From 25d8367aaf5b79b5852c80d2387e9809b0e5e377 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Tue, 21 Mar 2017 14:49:20 -0700 Subject: [PATCH 1/9] Suppress semantic errors in JS only configured projects (cherry picked from commit 4ee8bdb762f870351da9be51d13dae6c9328e72f) --- src/server/session.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/server/session.ts b/src/server/session.ts index 8dd0411d07..11c99dfe46 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -25,8 +25,14 @@ namespace ts.server { return ((1e9 * seconds) + nanoseconds) / 1000000.0; } - function shouldSkipSematicCheck(project: Project) { - return (project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) && project.isJsOnlyProject(); + function shouldSkipSemanticCheck(project: Project) { + if (project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) { + return project.isJsOnlyProject(); + } + else { + // For configured projects, require that skipLibCheck be set also + return project.getCompilerOptions().skipLibCheck && project.isJsOnlyProject(); + } } interface FileStart { @@ -447,7 +453,7 @@ namespace ts.server { private semanticCheck(file: NormalizedPath, project: Project) { try { let diags: Diagnostic[] = []; - if (!shouldSkipSematicCheck(project)) { + if (!shouldSkipSemanticCheck(project)) { diags = project.getLanguageService().getSemanticDiagnostics(file); } @@ -555,7 +561,7 @@ namespace ts.server { private getDiagnosticsWorker(args: protocol.FileRequestArgs, isSemantic: boolean, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) { const { project, file } = this.getFileAndProject(args); - if (isSemantic && shouldSkipSematicCheck(project)) { + if (isSemantic && shouldSkipSemanticCheck(project)) { return []; } const scriptInfo = project.getScriptInfoForNormalizedPath(file); From 71e296042aa4495308456d2797837dd543bd450f Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 17 Mar 2017 12:56:31 -0700 Subject: [PATCH 2/9] Apply the 20 MB non-TS source limit across all projects (cherry picked from commit cc8ce5975cbda492834d43ec1b743126a3334df4) (cherry picked from commit de8fb9e8335d9bf34d0bbd5e61fee4df40cb5222) --- 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 397de9ead3..3252e2114a 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; @@ -563,9 +564,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); @@ -852,10 +855,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); @@ -863,10 +873,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; } @@ -877,7 +890,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); @@ -897,7 +910,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, @@ -1050,7 +1063,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 @@ -1414,7 +1427,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 385816b102..e57e605d65 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1031,7 +1031,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 afbe63ae990577a4d3ce603b4ab78f7095636a29 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 17 Mar 2017 15:36:15 -0700 Subject: [PATCH 3/9] Make compatible with 2.1 maps # Conflicts: # src/server/editorServices.ts # src/server/project.ts (cherry picked from commit 456614f7e0d8ac0f5d420a6caf42f57cf5dda313) (cherry picked from commit be30adc77f450a4871045c48d7d614c196fe37a5) --- 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 3252e2114a..196df1a2cb 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -564,11 +564,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); @@ -861,10 +861,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) { @@ -874,12 +874,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 d69a18d9d971872fe14341755e1259e988a49117 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 11:37:22 -0700 Subject: [PATCH 4/9] Store the size of the project properly (cherry picked from commit 16c7bcfebbeb8490a86dd994167283414d9d43a0) (cherry picked from commit 8b3c54dbfb04c084061c287a342e7e6ffa0f0612) --- 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 196df1a2cb..5c7dfcae64 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -873,14 +873,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 5b7a099aa6ad568a57347f1cd4c3b0f37979a74a Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 11:41:58 -0700 Subject: [PATCH 5/9] Math (cherry picked from commit 7b17f6affecd6fb5e478607bf43e4cc29edf3f45) (cherry picked from commit 63aeacb83f2c00eef903bb6d2f39d3aa6b72254d) --- 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 5c7dfcae64..1bdf68fe08 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -880,7 +880,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 390e63200a85dd52649f7fad509555e3e7117d2d Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 12:08:51 -0700 Subject: [PATCH 6/9] Add unit test (cherry picked from commit ff0947996c03c07a7d2c1d8fdaf25e60dce6039c) (cherry picked from commit c66a5359e2bdc45b0a37941f614dda40661ae2cd) --- .../unittests/tsserverProjectSystem.ts | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 5ea0df91ca..356a7a8962 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1007,6 +1007,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 e5313bda21180a6bad7023e258d7b27b64d9197d Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 13:01:06 -0700 Subject: [PATCH 7/9] Don't add in size of disabled projects (cherry picked from commit 2721a8c8b4fcacc551e68594964ea581b713f83c) (cherry picked from commit 1696df6c9eca388b72b73a1e1897ab9b85080a7e) --- 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 1bdf68fe08..c4c299a067 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -874,7 +874,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 eef0505f55b37999d8d37f22dfd4a142b5372950 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Tue, 21 Mar 2017 16:02:54 -0700 Subject: [PATCH 8/9] Store diabled projects as 0 (cherry picked from commit e9e7271fc3ab50654cb234c813e46fc90d70a736) (cherry picked from commit 35e77171e98d134c64ae1000d94b1be317879a05) --- 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 c4c299a067..291fa83d60 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -879,8 +879,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) { From 21c954717c6cdafa2d689f88d63aff572ad5d38d Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Wed, 22 Mar 2017 19:48:20 -0700 Subject: [PATCH 9/9] Changes for Map implementation (cherry picked from commit 8a67b6ddd43bdb33c89c1877d2755b738cb4c4c1) --- src/server/editorServices.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 291fa83d60..8af6fe5d34 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -564,11 +564,11 @@ namespace ts.server { switch (project.projectKind) { case ProjectKind.External: removeItemFromSet(this.externalProjects, project); - delete this.projectToSizeMap[(project as ExternalProject).externalProjectName]; + this.projectToSizeMap.delete((project as ExternalProject).externalProjectName); break; case ProjectKind.Configured: removeItemFromSet(this.configuredProjects, project); - delete this.projectToSizeMap[(project as ConfiguredProject).canonicalConfigFilePath]; + this.projectToSizeMap.delete((project as ConfiguredProject).canonicalConfigFilePath); break; case ProjectKind.Inferred: removeItemFromSet(this.inferredProjects, project); @@ -861,10 +861,8 @@ namespace ts.server { } let availableSpace = maxProgramSizeForNonTsFiles; - this.projectToSizeMap[name] = 0; - for (const key in this.projectToSizeMap) { - availableSpace -= (this.projectToSizeMap[key] || 0); - } + this.projectToSizeMap.set(name, 0); + this.projectToSizeMap.forEach(val => (availableSpace -= (val || 0))); let totalNonTsFileSize = 0; for (const f of fileNames) { @@ -883,7 +881,7 @@ namespace ts.server { return true; } - this.projectToSizeMap[name] = totalNonTsFileSize; + this.projectToSizeMap.set(name, totalNonTsFileSize); return false; }