Skip to content

Commit 5e21d52

Browse files
authored
Language Server for dvc.yaml files (#2408)
* Add a test and a definitions provider * Remove unused logic * Refactor getCompletions * Refactor yamlScalarNodeToDocumentSymbol * Refactor DvcYamlModel * Extract onInitialize handler to dedicated method * Remove dupes from DvcLanguageServer * Extract documentSelector constant * Add lspClient to Extension class * Restore disposable exports in extension.ts * Make ServerModule class into a method * Add prettier to languageServer * Remove commented out config * Remove unnecessary jest config entries * Add swc/jest to languageServer * Rename DvcLanguageServer->LanguageServer * Rename DvcTextDocument->TextDocumentWrapper * Rename IDvcTextDocument->ITextDocumentWrapper * Fix test coverage config in languageServer * Collect only from src folder * Refactor dependencies * Create onDefinition method * Create more connection handler methods * Add method access specifiers to TextDocumentWrapper * Remove unnecessary if * Remove await before return * Remove make script * Remove useless accessor * Remove constructor shorthands * Add a codeAction request test * Use a better fixture for the codeActions test * Drop DVC prefix from LanguageClient * Simplify lspClient track call * Add access prefixes in DvcYamlModel * Export documentSelector from languageServer * Export more regex for readability * Simplify Stage::toJSON * Simplify Stage::addDependencies * Make TextDocumentWrapper implement ITextDocumentWrapper * Move more logic from DocumentWrapper to DvcYaml * Commit lock file * Move definitions logic to languageServer * Simplify findLocationFor * More readability improvements * New PR with only the definitions provider * Add test-build script to languageServer * Fix document selector bug * Fix code styling issues * Fix definition bugs * Add test for definitions outside dvc.yamls * Add test for file path symbols
1 parent bb10bcc commit 5e21d52

32 files changed

+1320
-22
lines changed

.codeclimate.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"**/contract.ts",
88
"demo/**",
99
"extension/src/test/**",
10+
"languageServer/src/test/**",
1011
"webview/src/react-table-config.d.ts",
1112
"webview/src/shared/components/icons/**"
1213
],

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"prettier.configPath": ".prettierrc.json",
88
"editor.tabSize": 2,
99
"typescript.updateImportsOnFileMove.enabled": "prompt",
10+
"npm.exclude": ["**/{demo,.wdio*}/**"],
1011
"cSpell.words": [
1112
"appdirs",
1213
"camelcase",

.vscode/tasks.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,25 @@
2424
"path": "webview/",
2525
"group": "build"
2626
},
27+
{
28+
"type": "npm",
29+
"label": "npm: dev - languageServer",
30+
"script": "dev",
31+
"isBackground": true,
32+
"presentation": {
33+
"reveal": "never"
34+
},
35+
"path": "languageServer/",
36+
"group": "build"
37+
},
2738
{
2839
"label": "npm: dev - all",
2940
"isBackground": true,
30-
"dependsOn": ["npm: dev - extension", "npm: dev - webview"],
41+
"dependsOn": [
42+
"npm: dev - extension",
43+
"npm: dev - webview",
44+
"npm: dev - languageServer"
45+
],
3146
"group": {
3247
"kind": "build",
3348
"isDefault": true

extension/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1544,7 +1544,8 @@
15441544
"lodash.merge": "4.6.2",
15451545
"lodash.omit": "4.5.0",
15461546
"tree-kill": "1.2.2",
1547-
"uuid": "9.0.0"
1547+
"uuid": "9.0.0",
1548+
"vscode-languageclient": "8.0.2"
15481549
},
15491550
"devDependencies": {
15501551
"@swc/core": "1.3.1",

extension/src/extension.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import { collectWorkspaceScale } from './telemetry/collect'
5151
import { createFileSystemWatcher } from './fileSystem/watcher'
5252
import { GitExecutor } from './cli/git/executor'
5353
import { GitReader } from './cli/git/reader'
54+
import { LanguageClientWrapper } from './lspClient/languageClient'
5455

5556
export class Extension extends Disposable implements IExtension {
5657
protected readonly internalCommands: InternalCommands
@@ -92,6 +93,8 @@ export class Extension extends Disposable implements IExtension {
9293
this.setCommandsAvailability(false)
9394
this.setProjectAvailability()
9495

96+
this.dispose.track(new LanguageClientWrapper())
97+
9598
this.resourceLocator = this.dispose.track(
9699
new ResourceLocator(context.extensionUri)
97100
)
@@ -442,6 +445,7 @@ export class Extension extends Disposable implements IExtension {
442445
}
443446

444447
let extension: undefined | Extension
448+
445449
export function activate(context: ExtensionContext): void {
446450
extension = new Extension(context)
447451
context.subscriptions.push(extension)

extension/src/fileSystem/workspace.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ export const isInWorkspace = (pathOrGlob: string): boolean => {
2727
return definedAndNonEmpty(isContained)
2828
}
2929

30-
export const findFiles = async (relativeGlob: string): Promise<string[]> => {
31-
const files = await workspace.findFiles(relativeGlob)
30+
export const findFiles = async (
31+
relativeGlob: string,
32+
exclude?: string
33+
): Promise<string[]> => {
34+
const files = await workspace.findFiles(relativeGlob, exclude)
3235
return files.map(uri => uri.fsPath)
3336
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { workspace } from 'vscode'
2+
import {
3+
LanguageClient,
4+
LanguageClientOptions,
5+
ServerOptions,
6+
TransportKind
7+
} from 'vscode-languageclient/node'
8+
import { documentSelector, serverModule } from 'dvc-vscode-lsp'
9+
import { Disposable } from '../class/dispose'
10+
11+
export class LanguageClientWrapper extends Disposable {
12+
private client: LanguageClient
13+
14+
constructor() {
15+
super()
16+
17+
const clientOptions: LanguageClientOptions = {
18+
documentSelector,
19+
20+
synchronize: {
21+
fileEvents: workspace.createFileSystemWatcher(
22+
'**/*.{yaml,dvc,dvc.lock,json,toml}'
23+
)
24+
}
25+
}
26+
27+
this.client = this.dispose.track(
28+
new LanguageClient(
29+
'dvc-vscode-lsp',
30+
'DVC Language Server',
31+
this.getServerOptions(),
32+
clientOptions
33+
)
34+
)
35+
36+
// Start the client. This will also launch the server
37+
this.start()
38+
}
39+
40+
start() {
41+
this.client.start()
42+
43+
return this
44+
}
45+
46+
stop() {
47+
this.client.stop()
48+
}
49+
50+
private getServerOptions(): ServerOptions {
51+
const debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] }
52+
53+
return {
54+
debug: {
55+
module: serverModule,
56+
options: debugOptions,
57+
transport: TransportKind.ipc
58+
},
59+
run: { module: serverModule, transport: TransportKind.ipc }
60+
}
61+
}
62+
}

extension/webpack.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export default {
3333
devtool: 'source-map',
3434
entry: r('./src/extension'),
3535
externals: {
36+
'dvc-vscode-lsp': 'dvc-vscode-lsp',
3637
'dvc-vscode-webview': 'dvc-vscode-webview',
3738
fsevents: "require('fsevents')",
3839
vscode: 'commonjs vscode'
@@ -65,6 +66,7 @@ export default {
6566
plugins: [
6667
new CleanWebpackPlugin(),
6768
includeDependency(r('../webview/')),
69+
includeDependency(r('../languageServer/')),
6870
includeFiles(),
6971
new ForkTsCheckerWebpackPlugin()
7072
],

languageServer/.eslintrc.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const config = require('../.eslintrc')
2+
3+
module.exports = {
4+
...config,
5+
ignorePatterns: [...config.ignorePatterns, 'src/test/fixtures/**']
6+
}

languageServer/.lintstagedrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('../.lintstagedrc')

0 commit comments

Comments
 (0)