-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LSP: New settings option to Disable server and Better Goto Definition for property and file paths (1/2) #2504
Conversation
5072476
to
acdb4fe
Compare
d962189
to
ca424a1
Compare
Code Climate has analyzed commit 92e616f and detected 0 issues on this pull request. The test coverage on the diff in this pull request is 88.4% (85% is the threshold). This pull request will bring the total coverage in the repository to 96.6% (-0.2% change). View more on Code Climate. |
Needs #2530 to be ready before merging. |
this.isRunning() && | ||
this.languageServerDisabled() | ||
) { | ||
this.stop() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we dispose of the onDidChangeConfiguration
here? We could get rid of the this.isRunning() && this.languageServerDisabled()
as well as this would only run once (when disabling the server the first time).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
|
||
private findLocationsForPropertySymbol(symbol: DocumentSymbol) { | ||
const propertyPath = symbol.detail | ||
const itIsHere = propertyPath && this.hasProperty(propertyPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick, but is it possible to rename isHere
as it follows our boolean naming conventions more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thanks!
visit | ||
} from 'yaml' | ||
import { BaseLanguageHelper } from './baseLanguageHelper' | ||
import * as RegExes from './regexes' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you can still import the regexes individually (ex.: filePaths
), I think it'd be better to rename the exported constants in regexes.ts
to identify them as regexes and simply import them individually. The other solution would be to wrap them all in a regexes
object and export that instead, but I think the first solution is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's what I tried first, but I worried if anyone would be annoyed about typing a prefix every time they create/use the constant.
But now that I'm writing this I realised that typing Regexes.something
is exactly the same thing and now I'm feeling really dumb.
I'll change it, thanks!
} | ||
|
||
protected toJSON(): unknown { | ||
return this.rootNode.toJS() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why toJS()
instead of toJSON()
? Might be worth a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes more sense, thanks!
@@ -1,3 +1,4 @@ | |||
export const variableTemplates = /\${([^}]+)}/g | |||
export const filePaths = /[\d/A-Za-z]+\.[A-Za-z]+/g | |||
export const alphadecimalWords = /[\dA-Za-z]+/g | |||
export const propertyPathLike = /[\d.A-Z[\]a-z]+/g |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any differences between this file and languageServer/src/languageHelpers/regexes.ts? They should be merged if so. Either way we should only have one file only for regexes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot about it, will delete it 👍
const textDocuments = files.map(filePath => { | ||
const uri = Uri.file(filePath).toString() | ||
const languageId = filePath.endsWith('yaml') ? 'yaml' : 'json' | ||
const text = readFileSync(filePath, 'utf8') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was very confused as to how the "ring-fenced" language server managed to bring down the extension host.
This would be what caused the crashes. A synchronous call to read every file would definitely bring down the thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The watcher would not have caused this issue. We already have at least one watcher which watches the entire workspace (and more).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The more I think about this the more I feel like the approach was backwards. We should be parsing each dvc.yaml
file when it is opened and checking to see which symbols are files. From there we read those files so that we can jump into them if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relevant: https://code.visualstudio.com/updates/v1_72#_improved-startup-performance
See "NO MORE SYNC FS CALLS"
await this.client.sendRequest('initialTextDocuments', { | ||
textDocuments | ||
}) | ||
workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the language server is on and I disable it in the settings, the server turns off without any need to reload. But if I try to turn it back on in settings, I need to reload the page to see the language server running again:
Screen.Recording.2022-10-05.at.4.13.12.PM.mov
Do we want it to be able to turn it back on without needing to reload?
import * as RegExes from './regexes' | ||
|
||
export class YamlHelper extends BaseLanguageHelper<Document> { | ||
protected rootNode!: Document |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never seen a !
used like this before! Learned something new today :)
@@ -10,16 +10,14 @@ import { | |||
Location, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File definitions inside of cmd
s don't seem to work correctly on my end:
Screen.Recording.2022-10-05.at.5.35.47.PM.mov
@@ -10,16 +10,14 @@ import { | |||
Location, | |||
Position, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What should be shown if a file hasn't been opened yet? Currently, it appears to take us somewhere that doesn't seem to make sense:
Screen.Recording.2022-10-05.at.5.39.18.PM.mov
await this.client.sendRequest('initialTextDocuments', { | ||
textDocuments | ||
}) | ||
workspace.onDidChangeConfiguration((event: ConfigurationChangeEvent) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[I] this is a disposable and should be tracked.
@@ -68,6 +54,14 @@ export class LanguageClientWrapper extends Disposable { | |||
this.client.stop() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Q] Are you sure that stopping the client stops the server?
@@ -0,0 +1,105 @@ | |||
import { has } from 'lodash' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be using lodash subpackages for consistency with the rest of the app.
@@ -94,18 +61,33 @@ export class LanguageServer { | |||
return new TextDocumentWrapper(doc) | |||
} | |||
|
|||
private isPossibleFilePath(symbol: DocumentSymbol) { | |||
const isFile = symbol.kind === SymbolKind.File |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Q] any ideas how symbol.kind
is set to SymbolKind.File
?
findLocationsFor(symbol: DocumentSymbol): Location[] | ||
} | ||
|
||
export abstract class BaseLanguageHelper<RootNode> implements LanguageHelper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's usual practice in the codebase to have this a <T>
. I was looking for where <RootNode>
is defined for a couple of minutes.
SymbolKind | ||
} from 'vscode-languageserver/node' | ||
|
||
export interface LanguageHelper { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[N] Probably don't need this interface on top of the abstract class.
const textDocuments = files.map(filePath => { | ||
const uri = Uri.file(filePath).toString() | ||
const languageId = filePath.endsWith('yaml') ? 'yaml' : 'json' | ||
const text = readFileSync(filePath, 'utf8') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The more I think about this the more I feel like the approach was backwards. We should be parsing each dvc.yaml
file when it is opened and checking to see which symbols are files. From there we read those files so that we can jump into them if needed.
@@ -45,132 +33,11 @@ export class TextDocumentWrapper implements ITextDocumentWrapper { | |||
return parseDocument(this.getText()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getYamlDocument
is no longer used anywhere (seems like it has been moved into the languageHelper
) it should be removed from this class and the interface.
This PR will allow the Goto Definition for feature for properties inside parameter files, and also for files referenced in the dvc.yaml.
It will also introduce an extension setting to disable the language server when needed.
Demo:
Screen.Recording.2022-10-04.at.14.15.38.mov