From cc8ce5975cbda492834d43ec1b743126a3334df4 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 17 Mar 2017 12:56:31 -0700 Subject: [PATCH 1/7] Apply the 20 MB non-TS source limit across all projects --- src/server/editorServices.ts | 25 +++++++++++++++++++------ src/server/project.ts | 2 +- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 00df53e1e35..140988d4933 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -254,6 +254,7 @@ namespace ts.server { private compilerOptionsForInferredProjects: CompilerOptions; private compileOnSaveForInferredProjects: boolean; + private readonly projectToSizeMap: Map = createMap(); private readonly directoryWatchers: DirectoryWatchers; private readonly throttledOperations: ThrottledOperations; @@ -562,9 +563,11 @@ namespace ts.server { switch (project.projectKind) { case ProjectKind.External: removeItemFromSet(this.externalProjects, project); + this.projectToSizeMap.delete((project as ExternalProject).externalProjectName); break; case ProjectKind.Configured: removeItemFromSet(this.configuredProjects, project); + this.projectToSizeMap.delete((project as ConfiguredProject).canonicalConfigFilePath); break; case ProjectKind.Inferred: removeItemFromSet(this.inferredProjects, project); @@ -851,10 +854,17 @@ namespace ts.server { return { success: true, projectOptions, configFileErrors: errors }; } - private exceededTotalSizeLimitForNonTsFiles(options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader) { + private exceededTotalSizeLimitForNonTsFiles(name: string, options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader) { if (options && options.disableSizeLimit || !this.host.getFileSize) { return false; } + + let availableSpace = maxProgramSizeForNonTsFiles; + this.projectToSizeMap.set(name, 0); + this.projectToSizeMap.forEach(size => { + availableSpace -= size; + }); + let totalNonTsFileSize = 0; for (const f of fileNames) { const fileName = propertyReader.getFileName(f); @@ -862,10 +872,13 @@ namespace ts.server { continue; } totalNonTsFileSize += this.host.getFileSize(fileName); - if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) { + if (totalNonTsFileSize > availableSpace) { + this.projectToSizeMap.set(name, totalNonTsFileSize); return true; } } + + this.projectToSizeMap.set(name, totalNonTsFileSize); return false; } @@ -876,7 +889,7 @@ namespace ts.server { this, this.documentRegistry, compilerOptions, - /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(compilerOptions, files, externalFilePropertyReader), + /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(projectFileName, compilerOptions, files, externalFilePropertyReader), options.compileOnSave === undefined ? true : options.compileOnSave); this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typeAcquisition, /*configFileErrors*/ undefined); @@ -896,7 +909,7 @@ namespace ts.server { } private createAndAddConfiguredProject(configFileName: NormalizedPath, projectOptions: ProjectOptions, configFileErrors: Diagnostic[], clientFileName?: string) { - const sizeLimitExceeded = this.exceededTotalSizeLimitForNonTsFiles(projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader); + const sizeLimitExceeded = this.exceededTotalSizeLimitForNonTsFiles(configFileName, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader); const project = new ConfiguredProject( configFileName, this, @@ -1049,7 +1062,7 @@ namespace ts.server { return configFileErrors; } - if (this.exceededTotalSizeLimitForNonTsFiles(projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader)) { + if (this.exceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader)) { project.setCompilerOptions(projectOptions.compilerOptions); if (!project.languageServiceEnabled) { // language service is already disabled @@ -1411,7 +1424,7 @@ namespace ts.server { if (externalProject) { if (!tsConfigFiles) { const compilerOptions = convertCompilerOptions(proj.options); - if (this.exceededTotalSizeLimitForNonTsFiles(compilerOptions, proj.rootFiles, externalFilePropertyReader)) { + if (this.exceededTotalSizeLimitForNonTsFiles(proj.projectFileName, compilerOptions, proj.rootFiles, externalFilePropertyReader)) { externalProject.disableLanguageService(); } else { diff --git a/src/server/project.ts b/src/server/project.ts index 6085ee05159..bd214f8426d 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -886,7 +886,7 @@ namespace ts.server { export class ExternalProject extends Project { private typeAcquisition: TypeAcquisition; - constructor(externalProjectName: string, + constructor(public externalProjectName: string, projectService: ProjectService, documentRegistry: ts.DocumentRegistry, compilerOptions: CompilerOptions, From 456614f7e0d8ac0f5d420a6caf42f57cf5dda313 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 17 Mar 2017 15:36:15 -0700 Subject: [PATCH 2/7] Make compatible with 2.1 maps # Conflicts: # src/server/editorServices.ts # src/server/project.ts --- src/server/editorServices.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 140988d4933..c48946a2af8 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -563,11 +563,11 @@ namespace ts.server { switch (project.projectKind) { case ProjectKind.External: removeItemFromSet(this.externalProjects, project); - this.projectToSizeMap.delete((project as ExternalProject).externalProjectName); + delete this.projectToSizeMap[(project as ExternalProject).externalProjectName]; break; case ProjectKind.Configured: removeItemFromSet(this.configuredProjects, project); - this.projectToSizeMap.delete((project as ConfiguredProject).canonicalConfigFilePath); + delete this.projectToSizeMap[(project as ConfiguredProject).canonicalConfigFilePath]; break; case ProjectKind.Inferred: removeItemFromSet(this.inferredProjects, project); @@ -860,10 +860,10 @@ namespace ts.server { } let availableSpace = maxProgramSizeForNonTsFiles; - this.projectToSizeMap.set(name, 0); - this.projectToSizeMap.forEach(size => { - availableSpace -= size; - }); + this.projectToSizeMap[name] = 0; + for (const key in this.projectToSizeMap) { + availableSpace -= (this.projectToSizeMap[key] || 0); + } let totalNonTsFileSize = 0; for (const f of fileNames) { @@ -873,12 +873,12 @@ namespace ts.server { } totalNonTsFileSize += this.host.getFileSize(fileName); if (totalNonTsFileSize > availableSpace) { - this.projectToSizeMap.set(name, totalNonTsFileSize); + this.projectToSizeMap[name] = totalNonTsFileSize; return true; } } - this.projectToSizeMap.set(name, totalNonTsFileSize); + this.projectToSizeMap[name] = totalNonTsFileSize; return false; } From 16c7bcfebbeb8490a86dd994167283414d9d43a0 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 11:37:22 -0700 Subject: [PATCH 3/7] Store the size of the project properly --- src/server/editorServices.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index c48946a2af8..69f5a2cce4b 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -872,14 +872,14 @@ namespace ts.server { continue; } totalNonTsFileSize += this.host.getFileSize(fileName); - if (totalNonTsFileSize > availableSpace) { + if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) { this.projectToSizeMap[name] = totalNonTsFileSize; return true; } } this.projectToSizeMap[name] = totalNonTsFileSize; - return false; + return totalNonTsFileSize < availableSpace; } private createAndAddExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typeAcquisition: TypeAcquisition) { From 7b17f6affecd6fb5e478607bf43e4cc29edf3f45 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 11:41:58 -0700 Subject: [PATCH 4/7] Math --- src/server/editorServices.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 69f5a2cce4b..2d9e7166073 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -879,7 +879,7 @@ namespace ts.server { } this.projectToSizeMap[name] = totalNonTsFileSize; - return totalNonTsFileSize < availableSpace; + return totalNonTsFileSize > availableSpace; } private createAndAddExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typeAcquisition: TypeAcquisition) { From ff0947996c03c07a7d2c1d8fdaf25e60dce6039c Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 12:08:51 -0700 Subject: [PATCH 5/7] Add unit test --- .../unittests/tsserverProjectSystem.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 5b9f4332359..aa086dc03e5 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -983,6 +983,41 @@ namespace ts.projectSystem { checkProjectRootFiles(projectService.configuredProjects[0], [commonFile1.path, commonFile2.path]); }); + it("should disable features when the files are too large", () => { + const file1 = { + path: "/a/b/f1.js", + content: "let x =1;", + fileSize: 10 * 1024 * 1024 + }; + const file2 = { + path: "/a/b/f2.js", + content: "let y =1;", + fileSize: 6 * 1024 * 1024 + }; + const file3 = { + path: "/a/b/f3.js", + content: "let y =1;", + fileSize: 6 * 1024 * 1024 + }; + + const proj1name = "proj1", proj2name = "proj2", proj3name = "proj3"; + + const host = createServerHost([file1, file2, file3]); + const projectService = createProjectService(host); + + projectService.openExternalProject({ rootFiles: toExternalFiles([file1.path]), options: {}, projectFileName: proj1name }); + const proj1 = projectService.findProject(proj1name); + assert.isTrue(proj1.languageServiceEnabled); + + projectService.openExternalProject({ rootFiles: toExternalFiles([file2.path]), options: {}, projectFileName: proj2name }); + const proj2 = projectService.findProject(proj2name); + assert.isTrue(proj2.languageServiceEnabled); + + projectService.openExternalProject({ rootFiles: toExternalFiles([file3.path]), options: {}, projectFileName: proj3name }); + const proj3 = projectService.findProject(proj3name); + assert.isFalse(proj3.languageServiceEnabled); + }); + it("should use only one inferred project if 'useOneInferredProject' is set", () => { const file1 = { path: "/a/b/main.ts", From 2721a8c8b4fcacc551e68594964ea581b713f83c Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 13:01:06 -0700 Subject: [PATCH 6/7] Don't add in size of disabled projects --- src/server/editorServices.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 2d9e7166073..271b8fefb64 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -873,7 +873,7 @@ namespace ts.server { } totalNonTsFileSize += this.host.getFileSize(fileName); if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) { - this.projectToSizeMap[name] = totalNonTsFileSize; + // Keep the size as zero since it's disabled return true; } } From e9e7271fc3ab50654cb234c813e46fc90d70a736 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 16:02:54 -0700 Subject: [PATCH 7/7] Store diabled projects as 0 --- src/server/editorServices.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 271b8fefb64..c27a14fc440 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -878,8 +878,12 @@ namespace ts.server { } } + if (totalNonTsFileSize > availableSpace) { + return true; + } + this.projectToSizeMap[name] = totalNonTsFileSize; - return totalNonTsFileSize > availableSpace; + return false; } private createAndAddExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typeAcquisition: TypeAcquisition) {