From 783538cd985856314a9cd94b39900ec916f0bf08 Mon Sep 17 00:00:00 2001 From: Benjamin Lichtman Date: Wed, 3 Apr 2019 13:55:33 -0700 Subject: [PATCH] VS IntelliCode-related changes (#30731) (#30737) * ensure configurePlugin gives a response * Update tests * Update baseline * Enable global plugin loading for external projects * Fix lint errors --- src/harness/client.ts | 8 ++- src/server/editorServices.ts | 3 +- src/server/project.ts | 4 +- src/server/protocol.ts | 3 + src/server/session.ts | 1 + .../unittests/tsserver/externalProjects.ts | 62 +++++++++++++++++++ .../reference/api/tsserverlibrary.d.ts | 2 + 7 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/harness/client.ts b/src/harness/client.ts index 1c7c0adb83450..03d5334461688 100644 --- a/src/harness/client.ts +++ b/src/harness/client.ts @@ -90,7 +90,7 @@ namespace ts.server { return request; } - private processResponse(request: protocol.Request): T { + private processResponse(request: protocol.Request, expectEmptyBody = false): T { let foundResponseMessage = false; let response!: T; while (!foundResponseMessage) { @@ -118,7 +118,8 @@ namespace ts.server { throw new Error("Error " + response.message); } - Debug.assert(!!response.body, "Malformed response: Unexpected empty response body."); + Debug.assert(expectEmptyBody || !!response.body, "Malformed response: Unexpected empty response body."); + Debug.assert(!expectEmptyBody || !response.body, "Malformed response: Unexpected non-empty response body."); return response; } @@ -696,7 +697,8 @@ namespace ts.server { } configurePlugin(pluginName: string, configuration: any): void { - this.processRequest("configurePlugin", { pluginName, configuration }); + const request = this.processRequest("configurePlugin", { pluginName, configuration }); + this.processResponse(request, /*expectEmptyBody*/ true); } getIndentationAtPosition(_fileName: string, _position: number, _options: EditorOptions): number { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 6c1ad386a05c9..6bfce902a049b 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1607,7 +1607,8 @@ namespace ts.server { this.documentRegistry, compilerOptions, /*lastFileExceededProgramSize*/ this.getFilenameForExceededTotalSizeLimitForNonTsFiles(projectFileName, compilerOptions, files, externalFilePropertyReader), - options.compileOnSave === undefined ? true : options.compileOnSave); + options.compileOnSave === undefined ? true : options.compileOnSave, + /*projectFilePath*/ undefined, this.currentPluginConfigOverrides); project.excludedFiles = excludedFiles; this.addFilesToNonInferredProject(project, files, externalFilePropertyReader, typeAcquisition); diff --git a/src/server/project.ts b/src/server/project.ts index 431c5664f3ad7..5a2c897e3863e 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1610,7 +1610,8 @@ namespace ts.server { compilerOptions: CompilerOptions, lastFileExceededProgramSize: string | undefined, public compileOnSaveEnabled: boolean, - projectFilePath?: string) { + projectFilePath?: string, + pluginConfigOverrides?: Map) { super(externalProjectName, ProjectKind.External, projectService, @@ -1621,6 +1622,7 @@ namespace ts.server { compileOnSaveEnabled, projectService.host, getDirectoryPath(projectFilePath || normalizeSlashes(externalProjectName))); + this.enableGlobalPlugins(this.getCompilerOptions(), pluginConfigOverrides); } updateGraph() { diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 3b7690e2c60dd..e5580874369e6 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1392,6 +1392,9 @@ namespace ts.server.protocol { arguments: ConfigurePluginRequestArguments; } + export interface ConfigurePluginResponse extends Response { + } + /** * Information found in an "open" request. */ diff --git a/src/server/session.ts b/src/server/session.ts index 6cf0619efd14e..3c202c9aecd02 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -2412,6 +2412,7 @@ namespace ts.server { }, [CommandNames.ConfigurePlugin]: (request: protocol.ConfigurePluginRequest) => { this.configurePlugin(request.arguments); + this.doOutput(/*info*/ undefined, CommandNames.ConfigurePlugin, request.seq, /*success*/ true); return this.notRequired(); } }); diff --git a/src/testRunner/unittests/tsserver/externalProjects.ts b/src/testRunner/unittests/tsserver/externalProjects.ts index 82c706500d37b..21d1290fc2e96 100644 --- a/src/testRunner/unittests/tsserver/externalProjects.ts +++ b/src/testRunner/unittests/tsserver/externalProjects.ts @@ -50,6 +50,68 @@ namespace ts.projectSystem { }); }); + it("load global plugins", () => { + const f1 = { + path: "/a/file1.ts", + content: "let x = [1, 2];" + }; + const p1 = { projectFileName: "/a/proj1.csproj", rootFiles: [toExternalFile(f1.path)], options: {} }; + + const host = createServerHost([f1]); + host.require = (_initialPath, moduleName) => { + assert.equal(moduleName, "myplugin"); + return { + module: () => ({ + create(info: server.PluginCreateInfo) { + const proxy = Harness.LanguageService.makeDefaultProxy(info); + proxy.getSemanticDiagnostics = filename => { + const prev = info.languageService.getSemanticDiagnostics(filename); + const sourceFile: SourceFile = info.project.getSourceFile(toPath(filename, /*basePath*/ undefined, createGetCanonicalFileName(info.serverHost.useCaseSensitiveFileNames)))!; + prev.push({ + category: DiagnosticCategory.Warning, + file: sourceFile, + code: 9999, + length: 3, + messageText: `Plugin diagnostic`, + start: 0 + }); + return prev; + }; + return proxy; + } + }), + error: undefined + }; + }; + const session = createSession(host, { globalPlugins: ["myplugin"] }); + + session.executeCommand({ + seq: 1, + type: "request", + command: "openExternalProjects", + arguments: { projects: [p1] } + }); + + const projectService = session.getProjectService(); + checkNumberOfProjects(projectService, { externalProjects: 1 }); + assert.equal(projectService.externalProjects[0].getProjectName(), p1.projectFileName); + + const handlerResponse = session.executeCommand({ + seq: 2, + type: "request", + command: "semanticDiagnosticsSync", + arguments: { + file: f1.path, + projectFileName: p1.projectFileName + } + }); + + assert.isDefined(handlerResponse.response); + const response = handlerResponse.response as protocol.Diagnostic[]; + assert.equal(response.length, 1); + assert.equal(response[0].text, "Plugin diagnostic"); + }); + it("remove not-listed external projects", () => { const f1 = { path: "/a/app.ts", diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 8208cdba2ab46..59fa706bf45b2 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -6748,6 +6748,8 @@ declare namespace ts.server.protocol { command: CommandTypes.ConfigurePlugin; arguments: ConfigurePluginRequestArguments; } + interface ConfigurePluginResponse extends Response { + } /** * Information found in an "open" request. */