diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 5b9d01c69d1..846c1a69d7c 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -685,6 +685,12 @@ "default": true, "description": "%configuration.tsserver.useSeparateSyntaxServer%", "scope": "window" + }, + "typescript.tsserver.maxTsServerMemory": { + "type": "number", + "default": 0, + "description": "%configuration.tsserver.maxTsServerMemory%", + "scope": "window" } } }, diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index 1282c67429d..fba54ea6c5c 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -54,6 +54,7 @@ "typescript.problemMatchers.tscWatch.label": "TypeScript problems (watch mode)", "configuration.suggest.paths": "Enable/disable suggestions for paths in import statements and require calls.", "configuration.tsserver.useSeparateSyntaxServer": "Enable/disable spawning a separate TypeScript server that can more quickly respond to syntax related operations, such as calculating folding or computing document symbols. Requires using TypeScript 3.4.0 or newer in the workspace.", + "configuration.tsserver.maxTsServerMemory": "Set the maximum amount of memory (in MB) to allocate to the TypeScript server process", "typescript.locale": "Sets the locale used to report JavaScript and TypeScript errors. Requires using TypeScript 2.6.0 or newer in the workspace. Default of `null` uses VS Code's locale.", "javascript.implicitProjectConfig.experimentalDecorators": "Enable/disable `experimentalDecorators` for JavaScript files that are not part of a project. Existing jsconfig.json or tsconfig.json files override this setting. Requires using TypeScript 2.3.1 or newer in the workspace.", "configuration.suggest.autoImports": "Enable/disable auto import suggestions. Requires using TypeScript 2.6.1 or newer in the workspace.", diff --git a/extensions/typescript-language-features/src/tsServer/spawner.ts b/extensions/typescript-language-features/src/tsServer/spawner.ts index de55136d020..5b50c22f142 100644 --- a/extensions/typescript-language-features/src/tsServer/spawner.ts +++ b/extensions/typescript-language-features/src/tsServer/spawner.ts @@ -72,7 +72,7 @@ export class TypeScriptServerSpawner { } this._logger.info(`<${kind}> Forking...`); - const childProcess = electron.fork(version.tsServerPath, args, this.getForkOptions(kind)); + const childProcess = electron.fork(version.tsServerPath, args, this.getForkOptions(kind, configuration)); this._logger.info(`<${kind}> Starting...`); return new ProcessBasedTsServer( @@ -85,10 +85,13 @@ export class TypeScriptServerSpawner { this._tracer); } - private getForkOptions(kind: ServerKind) { + private getForkOptions(kind: ServerKind, configuration: TypeScriptServiceConfiguration) { const debugPort = TypeScriptServerSpawner.getDebugPort(kind); const tsServerForkOptions: electron.ForkOptions = { - execArgv: debugPort ? [`--inspect=${debugPort}`] : [], + execArgv: [ + ...(debugPort ? [`--inspect=${debugPort}`] : []), + ...(configuration.maxTsServerMemory ? [`--max-old-space-size=${configuration.maxTsServerMemory}`] : []) + ] }; return tsServerForkOptions; } diff --git a/extensions/typescript-language-features/src/utils/configuration.ts b/extensions/typescript-language-features/src/utils/configuration.ts index f0e602e810a..bf9c9e7493f 100644 --- a/extensions/typescript-language-features/src/utils/configuration.ts +++ b/extensions/typescript-language-features/src/utils/configuration.ts @@ -55,6 +55,7 @@ export class TypeScriptServiceConfiguration { public readonly experimentalDecorators: boolean; public readonly disableAutomaticTypeAcquisition: boolean; public readonly useSeparateSyntaxServer: boolean; + public readonly maxTsServerMemory: number; public static loadFromWorkspace(): TypeScriptServiceConfiguration { return new TypeScriptServiceConfiguration(); @@ -73,6 +74,7 @@ export class TypeScriptServiceConfiguration { this.experimentalDecorators = TypeScriptServiceConfiguration.readExperimentalDecorators(configuration); this.disableAutomaticTypeAcquisition = TypeScriptServiceConfiguration.readDisableAutomaticTypeAcquisition(configuration); this.useSeparateSyntaxServer = TypeScriptServiceConfiguration.readUseSeparateSyntaxServer(configuration); + this.maxTsServerMemory = TypeScriptServiceConfiguration.readMaxTsServerMemory(configuration); } public isEqualTo(other: TypeScriptServiceConfiguration): boolean { @@ -85,7 +87,8 @@ export class TypeScriptServiceConfiguration { && this.experimentalDecorators === other.experimentalDecorators && this.disableAutomaticTypeAcquisition === other.disableAutomaticTypeAcquisition && arrays.equals(this.tsServerPluginPaths, other.tsServerPluginPaths) - && this.useSeparateSyntaxServer === other.useSeparateSyntaxServer; + && this.useSeparateSyntaxServer === other.useSeparateSyntaxServer + && this.maxTsServerMemory === other.maxTsServerMemory; } private static fixPathPrefixes(inspectValue: string): string { @@ -146,4 +149,12 @@ export class TypeScriptServiceConfiguration { private static readUseSeparateSyntaxServer(configuration: vscode.WorkspaceConfiguration): boolean { return configuration.get('typescript.tsserver.useSeparateSyntaxServer', true); } + + private static readMaxTsServerMemory(configuration: vscode.WorkspaceConfiguration): number { + const memoryInMB = configuration.get('typescript.tsserver.maxTsServerMemory', 0); + if (!Number.isSafeInteger(memoryInMB) || memoryInMB < 128) { + return 0; + } + return memoryInMB; + } }