From 6ed9badb564aa5e37e46695838264b3dd27f221b Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Wed, 20 Sep 2017 11:16:51 -0700 Subject: [PATCH] Port plugin fixes from master --- src/server/project.ts | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/server/project.ts b/src/server/project.ts index 6a7c0565614..5b32a83b48d 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -742,7 +742,8 @@ namespace ts.server { } // compute and return the difference const lastReportedFileNames = this.lastReportedFileNames; - const currentFiles = arrayToSet(this.getFileNames()); + const externalFiles = this.getExternalFiles().map(f => toNormalizedPath(f)); + const currentFiles = arrayToSet(this.getFileNames().concat(externalFiles)); const added: string[] = []; const removed: string[] = []; @@ -765,7 +766,8 @@ namespace ts.server { else { // unknown version - return everything const projectFileNames = this.getFileNames(); - this.lastReportedFileNames = arrayToSet(projectFileNames); + const externalFiles = this.getExternalFiles().map(f => toNormalizedPath(f)); + this.lastReportedFileNames = arrayToSet(projectFileNames.concat(externalFiles)); this.lastReportedVersion = this.projectStructureVersion; return { info, files: projectFileNames, projectErrors: this.getGlobalProjectErrors() }; } @@ -994,16 +996,22 @@ namespace ts.server { if (this.projectService.globalPlugins) { // Enable global plugins with synthetic configuration entries for (const globalPluginName of this.projectService.globalPlugins) { + // Skip empty names from odd commandline parses + if (!globalPluginName) continue; + // Skip already-locally-loaded plugins if (options.plugins && options.plugins.some(p => p.name === globalPluginName)) continue; // Provide global: true so plugins can detect why they can't find their config + this.projectService.logger.info(`Loading global plugin ${globalPluginName}`); this.enablePlugin({ name: globalPluginName, global: true } as PluginImport, searchPaths); } } } private enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[]) { + this.projectService.logger.info(`Enabling plugin ${pluginConfigEntry.name} from candidate paths: ${searchPaths.join(",")}`); + const log = (message: string) => { this.projectService.logger.info(message); }; @@ -1015,7 +1023,7 @@ namespace ts.server { return; } } - this.projectService.logger.info(`Couldn't find ${pluginConfigEntry.name} anywhere in paths: ${searchPaths.join(",")}`); + this.projectService.logger.info(`Couldn't find ${pluginConfigEntry.name}`); } private enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: PluginImport) { @@ -1034,7 +1042,15 @@ namespace ts.server { }; const pluginModule = pluginModuleFactory({ typescript: ts }); - this.languageService = pluginModule.create(info); + const newLS = pluginModule.create(info); + for (const k of Object.keys(this.languageService)) { + if (!(k in newLS)) { + this.projectService.logger.info(`Plugin activation warning: Missing proxied method ${k} in created LS. Patching.`); + (newLS as any)[k] = (this.languageService as any)[k]; + } + } + this.projectService.logger.info(`Plugin validation succeded`); + this.languageService = newLS; this.plugins.push(pluginModule); } catch (e) { @@ -1066,6 +1082,9 @@ namespace ts.server { } catch (e) { this.projectService.logger.info(`A plugin threw an exception in getExternalFiles: ${e}`); + if (e.stack) { + this.projectService.logger.info(e.stack); + } } })); } @@ -1174,6 +1193,7 @@ namespace ts.server { public compileOnSaveEnabled: boolean, private readonly projectFilePath?: string) { super(externalProjectName, ProjectKind.External, projectService, documentRegistry, /*hasExplicitListOfFiles*/ true, languageServiceEnabled, compilerOptions, compileOnSaveEnabled); + } getProjectRootPath() {