From 707c5676a6ea3d573f14b1edde4ae222570b2213 Mon Sep 17 00:00:00 2001 From: Wolmir Nemitz Date: Thu, 22 Sep 2022 15:04:45 -0300 Subject: [PATCH 1/3] Send interesting files on initialisation --- extension/src/lspClient/languageClient.ts | 27 ++++++++-- languageServer/src/LanguageServer.ts | 62 +++++++++++++++++++---- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/extension/src/lspClient/languageClient.ts b/extension/src/lspClient/languageClient.ts index f6d26305f2..3873ccc95a 100644 --- a/extension/src/lspClient/languageClient.ts +++ b/extension/src/lspClient/languageClient.ts @@ -1,4 +1,4 @@ -import { workspace } from 'vscode' +import { Uri, workspace } from 'vscode' import { LanguageClient, LanguageClientOptions, @@ -6,7 +6,9 @@ import { TransportKind } from 'vscode-languageclient/node' import { documentSelector, serverModule } from 'dvc-vscode-lsp' +import { readFileSync } from 'fs-extra' import { Disposable } from '../class/dispose' +import { findFiles } from '../fileSystem/workspace' export class LanguageClientWrapper extends Disposable { private client: LanguageClient @@ -37,8 +39,27 @@ export class LanguageClientWrapper extends Disposable { this.start() } - start() { - this.client.start() + async start() { + await this.client.start() + + const files = await findFiles('**/*.{yaml,json}', '.??*') + + const textDocuments = files.map(filePath => { + const uri = Uri.file(filePath).toString() + const languageId = filePath.endsWith('yaml') ? 'yaml' : 'json' + const text = readFileSync(filePath, 'utf8') + + return { + languageId, + text, + uri, + version: 0 + } + }) + + await this.client.sendRequest('initialTextDocuments', { + textDocuments + }) return this } diff --git a/languageServer/src/LanguageServer.ts b/languageServer/src/LanguageServer.ts index 153944225a..b30b1afad7 100644 --- a/languageServer/src/LanguageServer.ts +++ b/languageServer/src/LanguageServer.ts @@ -10,17 +10,19 @@ import { Location, Position, Range, - DocumentSymbol + DocumentSymbol, + TextDocumentItem } from 'vscode-languageserver/node' import { TextDocument } from 'vscode-languageserver-textdocument' import { URI } from 'vscode-uri' import { TextDocumentWrapper } from './TextDocumentWrapper' export class LanguageServer { - private documents!: TextDocuments + private documentsKnownToEditor!: TextDocuments + private documentsFromDvcClient: TextDocumentWrapper[] = [] public listen(connection: _Connection) { - this.documents = new TextDocuments(TextDocument) + this.documentsKnownToEditor = new TextDocuments(TextDocument) connection.onInitialize(() => this.onInitialize()) @@ -32,20 +34,59 @@ export class LanguageServer { return this.onDefinition(params) }) - this.documents.listen(connection) + connection.onRequest( + 'initialTextDocuments', + (params: { textDocuments: TextDocumentItem[] }) => { + this.documentsFromDvcClient = params.textDocuments.map( + ({ uri, languageId, version, text: content }) => { + const textDocument = TextDocument.create( + uri, + languageId, + version, + content + ) + + return this.wrap(textDocument) + } + ) + } + ) + + this.documentsKnownToEditor.listen(connection) connection.listen() } + private getAllDocuments() { + const openDocuments = this.documentsKnownToEditor.all() + const acc: TextDocumentWrapper[] = openDocuments.map(doc => this.wrap(doc)) + + for (const textDocument of this.documentsFromDvcClient) { + const userAlreadyOpenedIt = this.documentsKnownToEditor.get( + textDocument.uri + ) + + if (!userAlreadyOpenedIt) { + acc.push(textDocument) + } + } + + return acc + } + private getDvcTextDocument( params: TextDocumentPositionParams | CodeActionParams ) { const uri = params.textDocument.uri - const doc = this.documents.get(uri) + const doc = this.documentsKnownToEditor.get(uri) if (!doc) { - return null + const alternative = this.documentsFromDvcClient.find( + txtDoc => txtDoc.uri === uri + ) + return alternative ?? null } + return this.wrap(doc) } @@ -55,7 +96,7 @@ export class LanguageServer { private getFilePathLocations( symbolUnderCursor: DocumentSymbol, - allDocs: TextDocument[] + allDocs: TextDocumentWrapper[] ) { if (symbolUnderCursor.kind !== SymbolKind.File) { return [] @@ -79,13 +120,12 @@ export class LanguageServer { private getLocationsFromOtherDocuments( symbolUnderCursor: DocumentSymbol, - allDocs: TextDocument[] + allDocs: TextDocumentWrapper[] ) { const locationsAccumulator = [] for (const txtDoc of allDocs) { - const finder = this.wrap(txtDoc) - const locations = finder.findLocationsFor(symbolUnderCursor) + const locations = txtDoc.findLocationsFor(symbolUnderCursor) locationsAccumulator.push(...locations) } @@ -97,7 +137,7 @@ export class LanguageServer { const symbolUnderCursor = document?.symbolAt(params.position) if (document && symbolUnderCursor) { - const allDocs = this.documents.all() + const allDocs = this.getAllDocuments() const locationsAccumulator = [] const fileLocations = this.getFilePathLocations( From 43b0e29959e0f4d834a8254ca5001017ab6dc4ca Mon Sep 17 00:00:00 2001 From: Wolmir Nemitz Date: Thu, 22 Sep 2022 15:26:15 -0300 Subject: [PATCH 2/3] Add test for the inital files request --- languageServer/src/test/definitions.test.ts | 3 ++- .../src/test/utils/sendTheseFilesToServer.ts | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 languageServer/src/test/utils/sendTheseFilesToServer.ts diff --git a/languageServer/src/test/definitions.test.ts b/languageServer/src/test/definitions.test.ts index 57433d8195..f6021183e7 100644 --- a/languageServer/src/test/definitions.test.ts +++ b/languageServer/src/test/definitions.test.ts @@ -11,6 +11,7 @@ import { disposeTestConnections, setupTestConnections } from './utils/setup-test-connections' +import { sendTheseFilesToServer } from './utils/sendTheseFilesToServer' describe('textDocument/definitions', () => { beforeEach(() => { @@ -75,7 +76,7 @@ describe('textDocument/definitions', () => { }) it('should provide a single location that points to the top of the file path symbol', async () => { - const [dvcYaml] = await openTheseFilesAndNotifyServer([ + const [dvcYaml] = await sendTheseFilesToServer([ { languageId: 'yaml', mockContents: vars_dvc_yaml, diff --git a/languageServer/src/test/utils/sendTheseFilesToServer.ts b/languageServer/src/test/utils/sendTheseFilesToServer.ts new file mode 100644 index 0000000000..8ff75626f3 --- /dev/null +++ b/languageServer/src/test/utils/sendTheseFilesToServer.ts @@ -0,0 +1,27 @@ +import { TextDocument } from 'vscode-languageserver-textdocument' +import { URI } from 'vscode-uri' +import { client } from './setup-test-connections' + +export const sendTheseFilesToServer = async ( + files: Array<{ mockPath: string; mockContents: string; languageId: string }> +) => { + const filesToReturn: TextDocument[] = [] + + for (const { mockPath, mockContents, languageId } of files) { + const uri = URI.file(mockPath).toString() + const textDocument = TextDocument.create(uri, languageId, 1, mockContents) + filesToReturn.push(textDocument) + } + await client.sendRequest('initialTextDocuments', { + textDocuments: filesToReturn.map(textDocument => { + return { + languageId: 'yaml', + text: textDocument.getText(), + uri: textDocument.uri, + version: textDocument.version + } + }) + }) + + return filesToReturn +} From 1f6a83b2fc6d030218a7c9e3a9af973d4aa5603c Mon Sep 17 00:00:00 2001 From: Wolmir Nemitz Date: Fri, 23 Sep 2022 16:44:02 -0300 Subject: [PATCH 3/3] Add more files for the initial load --- extension/src/lspClient/languageClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/src/lspClient/languageClient.ts b/extension/src/lspClient/languageClient.ts index 3873ccc95a..69ae685684 100644 --- a/extension/src/lspClient/languageClient.ts +++ b/extension/src/lspClient/languageClient.ts @@ -42,7 +42,7 @@ export class LanguageClientWrapper extends Disposable { async start() { await this.client.start() - const files = await findFiles('**/*.{yaml,json}', '.??*') + const files = await findFiles('**/*.{yaml,json,py,toml}', '.??*') const textDocuments = files.map(filePath => { const uri = Uri.file(filePath).toString()