diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 9dae626d91e..9ff4f4ef9b8 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -2564,7 +2564,9 @@ namespace ts.server { externalProject.enableLanguageService(); } // external project already exists and not config files were added - update the project and return; + // The graph update here isnt postponed since any file open operation needs all updated external projects this.updateRootAndOptionsOfNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, compilerOptions, proj.typeAcquisition, proj.options.compileOnSave); + externalProject.updateGraph(); return; } // some config files were added to external project (that previously were not there) @@ -2622,8 +2624,11 @@ namespace ts.server { } else { // no config files - remove the item from the collection + // Create external project and update its graph, do not delay update since + // any file open operation needs all updated external projects this.externalProjectToConfiguredProjectMap.delete(proj.projectFileName); - this.createExternalProject(proj.projectFileName, rootFiles, proj.options, proj.typeAcquisition, excludedFiles); + const project = this.createExternalProject(proj.projectFileName, rootFiles, proj.options, proj.typeAcquisition, excludedFiles); + project.updateGraph(); } } diff --git a/src/testRunner/unittests/tsserverProjectSystem.ts b/src/testRunner/unittests/tsserverProjectSystem.ts index 6e7a41eee12..4f85cbf00b3 100644 --- a/src/testRunner/unittests/tsserverProjectSystem.ts +++ b/src/testRunner/unittests/tsserverProjectSystem.ts @@ -1776,11 +1776,8 @@ namespace ts.projectSystem { try { projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, office.path]) }); const proj = projectService.externalProjects[0]; - // Since the file is not yet open, the project wont have program yet - assert.deepEqual(proj.getFileNames(/*excludeFilesFromExternalLibraries*/ true), emptyArray); - assert.deepEqual(proj.getTypeAcquisition().include, ["duck-types"]); - projectService.openClientFile(file1.path); assert.deepEqual(proj.getFileNames(/*excludeFilesFromExternalLibraries*/ true), [file1.path]); + assert.deepEqual(proj.getTypeAcquisition().include, ["duck-types"]); } finally { projectService.resetSafeList(); } @@ -1821,11 +1818,8 @@ namespace ts.projectSystem { try { projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles(files.map(f => f.path)) }); const proj = projectService.externalProjects[0]; - // Since the file is not yet open, the project wont have program yet - assert.deepEqual(proj.getFileNames(/*excludeFilesFromExternalLibraries*/ true), emptyArray); - assert.deepEqual(proj.getTypeAcquisition().include, ["kendo-ui", "office"]); - projectService.openClientFile(file1.path); assert.deepEqual(proj.getFileNames(/*excludeFilesFromExternalLibraries*/ true), [file1.path]); + assert.deepEqual(proj.getTypeAcquisition().include, ["kendo-ui", "office"]); } finally { projectService.resetSafeList(); } @@ -1865,9 +1859,6 @@ namespace ts.projectSystem { try { projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]), typeAcquisition: { enable: true } }); const proj = projectService.externalProjects[0]; - // Since the file is not yet open, the project wont have program yet - assert.deepEqual(proj.getFileNames(), emptyArray); - projectService.openClientFile(file2.path); assert.deepEqual(proj.getFileNames(), [file2.path]); } finally { projectService.resetSafeList(); @@ -2083,9 +2074,6 @@ namespace ts.projectSystem { projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path]) }); checkNumberOfProjects(projectService, { externalProjects: 1 }); - // Since the file is not yet open, the project wont have program yet - assert.deepEqual(projectService.externalProjects[0].getFileNames(), emptyArray); - projectService.openClientFile(file1.path); checkProjectActualFiles(projectService.externalProjects[0], [file1.path]); projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]) }); @@ -2113,17 +2101,11 @@ namespace ts.projectSystem { projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ModuleResolutionKind.NodeJs }, rootFiles: toExternalFiles([file1.path, file2.path]) }); checkNumberOfProjects(projectService, { externalProjects: 1 }); checkProjectRootFiles(projectService.externalProjects[0], [file1.path, file2.path]); - // Since the file is not yet open, the project wont have program yet - checkProjectActualFiles(projectService.externalProjects[0], emptyArray); - projectService.openClientFile(file1.path); checkProjectActualFiles(projectService.externalProjects[0], [file1.path, file2.path]); projectService.openExternalProject({ projectFileName: "project", options: { moduleResolution: ModuleResolutionKind.Classic }, rootFiles: toExternalFiles([file1.path, file2.path]) }); checkNumberOfProjects(projectService, { externalProjects: 1 }); checkProjectRootFiles(projectService.externalProjects[0], [file1.path, file2.path]); - // The update doesnt happen right away until needed, so either open a file or ensure projects uptodate - checkProjectActualFiles(projectService.externalProjects[0], [file1.path, file2.path]); - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(projectService.externalProjects[0], [file1.path, file2.path, file3.path]); }); @@ -2425,10 +2407,6 @@ namespace ts.projectSystem { projectService.openExternalProject({ projectFileName, options: {}, rootFiles: [{ fileName: file1.path, scriptKind: ScriptKind.JS, hasMixedContent: true }] }); checkNumberOfProjects(projectService, { externalProjects: 1 }); - // Since the external project is not updated till needed (eg opening client file/ensuringProjectStructureUptodate) - // watched files will be empty at first - checkWatchedFiles(host, emptyArray); - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkWatchedFiles(host, [libFile.path]); // watching the "missing" lib file const project = projectService.externalProjects[0]; @@ -3013,9 +2991,6 @@ namespace ts.projectSystem { projectService.openExternalProjects([externalProject]); checkNumberOfProjects(projectService, { configuredProjects: 0, externalProjects: 1, inferredProjects: 0 }); - // Since the external project is not updated till needed (eg opening client file/ensuringProjectStructureUptodate) - checkProjectActualFiles(projectService.externalProjects[0], emptyArray); - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(projectService.externalProjects[0], [site.path, libFile.path]); }); @@ -4019,8 +3994,6 @@ namespace ts.projectSystem { }); projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(projectService.externalProjects[0], emptyArray); // external project created but not updated till actually needed - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(projectService.externalProjects[0], [f1.path, f2.path]); }); @@ -4058,8 +4031,6 @@ namespace ts.projectSystem { }); projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(projectService.externalProjects[0], emptyArray); // external project created but program is not created till its needed - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); // add two config file as root files @@ -4093,8 +4064,6 @@ namespace ts.projectSystem { }); projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(projectService.externalProjects[0], emptyArray); // external project created but program is not created till its needed - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(projectService.externalProjects[0], [f1.path]); // open two config files diff --git a/src/testRunner/unittests/typingsInstaller.ts b/src/testRunner/unittests/typingsInstaller.ts index 0b8a62239e2..6a7e76e15de 100644 --- a/src/testRunner/unittests/typingsInstaller.ts +++ b/src/testRunner/unittests/typingsInstaller.ts @@ -330,8 +330,6 @@ namespace ts.projectSystem { typeAcquisition: { enable: true, include: ["jquery"] } }); - assert.isFalse(enqueueIsCalled, "expected enqueueIsCalled to be false since external project isnt updated right away"); - projectService.ensureInferredProjectsUpToDate_TestOnly(); assert.isTrue(enqueueIsCalled, "expected enqueueIsCalled to be true"); installer.installAll(/*expectedCount*/ 1); @@ -388,8 +386,6 @@ namespace ts.projectSystem { const p = projectService.externalProjects[0]; projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(p, emptyArray); // external project created but not updated - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(p, [file2Jsx.path, file3dts.path]); installer.installAll(/*expectedCount*/ 1); @@ -434,8 +430,6 @@ namespace ts.projectSystem { const p = projectService.externalProjects[0]; projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(p, emptyArray); // external project created but not updated - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(p, [jqueryJs.path]); installer.checkPendingCommands(/*expectedCount*/ 0); @@ -479,8 +473,6 @@ namespace ts.projectSystem { const p = projectService.externalProjects[0]; projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(p, emptyArray); // external project created but not updated - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(p, [jqueryJs.path, file2Ts.path]); installer.checkPendingCommands(/*expectedCount*/ 0); @@ -556,8 +548,6 @@ namespace ts.projectSystem { const p = projectService.externalProjects[0]; projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(p, emptyArray); // external project created but not updated - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(p, [file3dts.path]); installer.installAll(/*expectedCount*/ 1); @@ -640,8 +630,6 @@ namespace ts.projectSystem { const p = projectService.externalProjects[0]; projectService.checkNumberOfProjects({ externalProjects: 1 }); - checkProjectActualFiles(p, emptyArray); // external project created but not updated - projectService.ensureInferredProjectsUpToDate_TestOnly(); checkProjectActualFiles(p, [file3.path]); installer.checkPendingCommands(/*expectedCount*/ 1); installer.executePendingCommands(); @@ -726,8 +714,6 @@ namespace ts.projectSystem { typeAcquisition: { include: ["jquery", "cordova"] } }); - checkProjectActualFiles(projectService.externalProjects[0], emptyArray); // external project created but not updated - projectService.ensureInferredProjectsUpToDate_TestOnly(); installer.checkPendingCommands(/*expectedCount*/ 1); assert.equal(installer.pendingRunRequests.length, 0, "expect no throttled requests"); @@ -739,8 +725,6 @@ namespace ts.projectSystem { rootFiles: [toExternalFile(file3.path)], typeAcquisition: { include: ["grunt", "gulp"] } }); - checkProjectActualFiles(projectService.externalProjects[1], emptyArray); // external project created but not updated - projectService.ensureInferredProjectsUpToDate_TestOnly(); assert.equal(installer.pendingRunRequests.length, 1, "expect one throttled request"); const p1 = projectService.externalProjects[0];