Skip to content

Commit 96b2cf8

Browse files
authored
Merge pull request microsoft#23597 from Microsoft/inferredProjects
Do not remove inferred project till next file open so we can reuse them
2 parents cec5aaf + d6dfd9a commit 96b2cf8

File tree

8 files changed

+250
-121
lines changed

8 files changed

+250
-121
lines changed

src/compiler/core.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,10 @@ namespace ts {
17621762
return compareComparableValues(a, b);
17631763
}
17641764

1765+
export function getStringComparer(ignoreCase?: boolean) {
1766+
return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive;
1767+
}
1768+
17651769
/**
17661770
* Creates a string comparer for use with string collation in the UI.
17671771
*/
@@ -2274,7 +2278,7 @@ namespace ts {
22742278
const aComponents = getNormalizedPathComponents(a, currentDirectory);
22752279
const bComponents = getNormalizedPathComponents(b, currentDirectory);
22762280
const sharedLength = Math.min(aComponents.length, bComponents.length);
2277-
const comparer = ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive;
2281+
const comparer = getStringComparer(ignoreCase);
22782282
for (let i = 0; i < sharedLength; i++) {
22792283
const result = comparer(aComponents[i], bComponents[i]);
22802284
if (result !== Comparison.EqualTo) {
@@ -2615,7 +2619,7 @@ namespace ts {
26152619
}
26162620

26172621
// Sort the offsets array using either the literal or canonical path representations.
2618-
includeBasePaths.sort(useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive);
2622+
includeBasePaths.sort(getStringComparer(!useCaseSensitiveFileNames));
26192623

26202624
// Iterate over each include base path and include unique base paths that are not a
26212625
// subpath of an existing base path

src/compiler/sys.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ namespace ts {
698698
createWatchDirectoryUsing(dynamicPollingWatchFile || createDynamicPriorityPollingWatchFile({ getModifiedTime, setTimeout })) :
699699
watchDirectoryUsingFsWatch;
700700
const watchDirectoryRecursively = createRecursiveDirectoryWatcher({
701-
filePathComparer: useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive,
701+
filePathComparer: getStringComparer(!useCaseSensitiveFileNames),
702702
directoryExists,
703703
getAccessibleSortedChildDirectories: path => getAccessibleFileSystemEntries(path).directories,
704704
watchDirectory,

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 129 additions & 42 deletions
Large diffs are not rendered by default.

src/server/editorServices.ts

Lines changed: 87 additions & 70 deletions
Large diffs are not rendered by default.

src/server/project.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,11 @@ namespace ts.server {
591591
return this.rootFiles && this.rootFiles.length > 0;
592592
}
593593

594+
/*@internal*/
595+
isOrphan() {
596+
return false;
597+
}
598+
594599
getRootFiles() {
595600
return this.rootFiles && this.rootFiles.map(info => info.fileName);
596601
}
@@ -834,6 +839,10 @@ namespace ts.server {
834839

835840
/*@internal*/
836841
updateTypingFiles(typingFiles: SortedReadonlyArray<string>) {
842+
enumerateInsertsAndDeletes(typingFiles, this.typingFiles, getStringComparer(!this.useCaseSensitiveFileNames()),
843+
/*inserted*/ noop,
844+
removed => this.detachScriptInfoFromProject(removed)
845+
);
837846
this.typingFiles = typingFiles;
838847
// Invalidate files with unresolved imports
839848
this.resolutionCache.setFilesWithInvalidatedNonRelativeUnresolvedImports(this.cachedUnresolvedImportsPerFile);
@@ -894,7 +903,7 @@ namespace ts.server {
894903

895904
const oldExternalFiles = this.externalFiles || emptyArray as SortedReadonlyArray<string>;
896905
this.externalFiles = this.getExternalFiles();
897-
enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles, compareStringsCaseSensitive,
906+
enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles, getStringComparer(!this.useCaseSensitiveFileNames()),
898907
// Ensure a ScriptInfo is created for new external files. This is performed indirectly
899908
// by the LSHost for files in the program when the program is retrieved above but
900909
// the program doesn't contain external files so this must be done explicitly.
@@ -1169,6 +1178,10 @@ namespace ts.server {
11691178
/** this is canonical project root path */
11701179
readonly projectRootPath: string | undefined;
11711180

1181+
/*@internal*/
1182+
/** stored only if their is no projectRootPath and this isnt single inferred project */
1183+
readonly canonicalCurrentDirectory: string | undefined;
1184+
11721185
/*@internal*/
11731186
constructor(
11741187
projectService: ProjectService,
@@ -1187,12 +1200,15 @@ namespace ts.server {
11871200
projectService.host,
11881201
currentDirectory);
11891202
this.projectRootPath = projectRootPath && projectService.toCanonicalFileName(projectRootPath);
1203+
if (!projectRootPath && !projectService.useSingleInferredProject) {
1204+
this.canonicalCurrentDirectory = projectService.toCanonicalFileName(this.currentDirectory);
1205+
}
11901206
this.enableGlobalPlugins();
11911207
}
11921208

11931209
addRoot(info: ScriptInfo) {
11941210
Debug.assert(info.isScriptOpen());
1195-
this.projectService.startWatchingConfigFilesForInferredProjectRoot(info, this.projectService.openFiles.get(info.path));
1211+
this.projectService.startWatchingConfigFilesForInferredProjectRoot(info);
11961212
if (!this._isJsInferredProject && info.isJavaScript()) {
11971213
this.toggleJsInferredProject(/*isJsInferredProject*/ true);
11981214
}
@@ -1209,6 +1225,11 @@ namespace ts.server {
12091225
}
12101226
}
12111227

1228+
/*@internal*/
1229+
isOrphan() {
1230+
return !this.hasRoots();
1231+
}
1232+
12121233
isProjectWithSingleRoot() {
12131234
// - when useSingleInferredProject is not set and projectRootPath is not set,
12141235
// we can guarantee that this will be the only root

src/server/scriptInfo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ namespace ts.server {
460460
}
461461

462462
isOrphan() {
463-
return this.containingProjects.length === 0;
463+
return !forEach(this.containingProjects, p => !p.isOrphan());
464464
}
465465

466466
/**

src/server/session.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ namespace ts.server {
865865
symLinkedProjects = this.projectService.getSymlinkedProjects(scriptInfo);
866866
}
867867
// filter handles case when 'projects' is undefined
868-
projects = filter(projects, p => p.languageServiceEnabled);
868+
projects = filter(projects, p => p.languageServiceEnabled && !p.isOrphan());
869869
if ((!projects || !projects.length) && !symLinkedProjects) {
870870
return Errors.ThrowNoProject();
871871
}
@@ -1336,7 +1336,7 @@ namespace ts.server {
13361336
symLinkedProjects ? { projects, symLinkedProjects } : projects,
13371337
(project, info) => {
13381338
let result: protocol.CompileOnSaveAffectedFileListSingleProject;
1339-
if (project.compileOnSaveEnabled && project.languageServiceEnabled && !project.getCompilationSettings().noEmit) {
1339+
if (project.compileOnSaveEnabled && project.languageServiceEnabled && !project.isOrphan() && !project.getCompilationSettings().noEmit) {
13401340
result = {
13411341
projectFileName: project.getProjectName(),
13421342
fileNames: project.getCompileOnSaveAffectedFileList(info),

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8074,7 +8074,6 @@ declare namespace ts.server {
80748074
* @param info The file that has been closed or newly configured
80758075
*/
80768076
private closeOpenFile;
8077-
private deleteOrphanScriptInfoNotInAnyProject;
80788077
private deleteScriptInfo;
80798078
private configFileExists;
80808079
private setConfigFileExistenceByNewConfiguredProject;
@@ -8131,6 +8130,7 @@ declare namespace ts.server {
81318130
private sendConfigFileDiagEvent;
81328131
private getOrCreateInferredProjectForProjectRootPathIfEnabled;
81338132
private getOrCreateSingleInferredProjectIfEnabled;
8133+
private getOrCreateSingleInferredWithoutProjectRoot;
81348134
private createInferredProject;
81358135
getScriptInfo(uncheckedFileName: string): ScriptInfo;
81368136
private watchClosedScriptInfo;

0 commit comments

Comments
 (0)