Skip to content

Commit c937666

Browse files
committed
Revert "Revert of Search ancestor and its references for default projects #57196 (#59634)"
1 parent 0228b37 commit c937666

File tree

121 files changed

+8465
-3895
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+8465
-3895
lines changed

src/server/editorServices.ts

Lines changed: 99 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
DocumentRegistry,
3232
DocumentRegistryBucketKeyWithMode,
3333
emptyOptions,
34+
endsWith,
3435
ensureTrailingDirectorySeparator,
3536
equateStringsCaseInsensitive,
3637
equateStringsCaseSensitive,
@@ -643,10 +644,37 @@ export interface ProjectServiceOptions {
643644
*/
644645
export type ConfigFileName = NormalizedPath | false;
645646

647+
/**
648+
* Stores cached config file name for info as well as ancestor so is a map
649+
* Key is false for Open ScriptInfo
650+
* Key is NormalizedPath for Config file name
651+
* @internal
652+
*/
653+
export type ConfigFileMapForOpenFile = Map<ConfigFileName, ConfigFileName>;
654+
655+
/**
656+
* The cache for open script info will have
657+
* ConfigFileName or false if ancestors are not looked up
658+
* Map if ancestors are looked up
659+
* @internal
660+
*/
661+
export type ConfigFileForOpenFile = ConfigFileName | ConfigFileMapForOpenFile;
662+
646663
/** Gets cached value of config file name based on open script info or ancestor script info */
647-
function getConfigFileNameFromCache(info: OpenScriptInfoOrClosedOrConfigFileInfo, cache: Map<Path, ConfigFileName> | undefined): ConfigFileName | undefined {
648-
if (!cache || isAncestorConfigFileInfo(info)) return undefined;
649-
return cache.get(info.path);
664+
function getConfigFileNameFromCache(info: OpenScriptInfoOrClosedOrConfigFileInfo, cache: Map<Path, ConfigFileForOpenFile> | undefined): ConfigFileName | undefined {
665+
if (!cache) return undefined;
666+
const configFileForOpenFile = cache.get(info.path);
667+
if (configFileForOpenFile === undefined) return undefined;
668+
if (!isAncestorConfigFileInfo(info)) {
669+
return isString(configFileForOpenFile) || !configFileForOpenFile ?
670+
configFileForOpenFile : // direct result
671+
configFileForOpenFile.get(/*key*/ false); // Its a map, use false as the key for the info's config file name
672+
}
673+
else {
674+
return configFileForOpenFile && !isString(configFileForOpenFile) ? // Map with fileName as key
675+
configFileForOpenFile.get(info.fileName) :
676+
undefined; // No result for the config file name
677+
}
650678
}
651679

652680
/** @internal */
@@ -661,6 +689,7 @@ export interface AncestorConfigFileInfo {
661689
/** path of open file so we can look at correct root */
662690
path: Path;
663691
configFileInfo: true;
692+
isForDefaultProject: boolean;
664693
}
665694
/** @internal */
666695
export type OpenScriptInfoOrClosedFileInfo = ScriptInfo | OriginalFileInfo;
@@ -709,6 +738,8 @@ function forEachAncestorProject<T>(
709738
allowDeferredClosed: boolean | undefined,
710739
/** Used with ConfiguredProjectLoadKind.Reload to check if this project was already reloaded */
711740
reloadedProjects: Set<ConfiguredProject> | undefined,
741+
/** true means we are looking for solution, so we can stop if found project is not composite to go into parent solution */
742+
searchOnlyPotentialSolution: boolean,
712743
/** Used with ConfiguredProjectLoadKind.Reload to specify delay reload, and also a set of configured projects already marked for delay load */
713744
delayReloadedConfiguredProjects?: Set<ConfiguredProject>,
714745
): T | undefined {
@@ -718,7 +749,10 @@ function forEachAncestorProject<T>(
718749
if (
719750
!project.initialLoadPending &&
720751
(
721-
!project.getCompilerOptions().composite ||
752+
(searchOnlyPotentialSolution && !project.getCompilerOptions().composite) ||
753+
// Currently disableSolutionSearching is shared for finding solution/project when
754+
// - loading solution for find all references
755+
// - trying to find default project
722756
project.getCompilerOptions().disableSolutionSearching
723757
)
724758
) return;
@@ -728,6 +762,7 @@ function forEachAncestorProject<T>(
728762
fileName: project.getConfigFilePath(),
729763
path: info.path,
730764
configFileInfo: true,
765+
isForDefaultProject: !searchOnlyPotentialSolution,
731766
}, kind === ConfiguredProjectLoadKind.Find);
732767
if (!configFileName) return;
733768

@@ -737,9 +772,9 @@ function forEachAncestorProject<T>(
737772
kind,
738773
reason,
739774
allowDeferredClosed,
740-
/*triggerFile*/ undefined,
775+
!searchOnlyPotentialSolution ? info.fileName : undefined, // Config Diag event for project if its for default project
741776
reloadedProjects,
742-
/*delayLoad*/ true,
777+
searchOnlyPotentialSolution, // Delay load if we are searching for solution
743778
delayReloadedConfiguredProjects,
744779
);
745780
if (!ancestor) return;
@@ -1219,7 +1254,7 @@ export class ProjectService {
12191254
*/
12201255
readonly openFiles: Map<Path, NormalizedPath | undefined> = new Map<Path, NormalizedPath | undefined>();
12211256
/** Config files looked up and cached config files for open script info */
1222-
private readonly configFileForOpenFiles = new Map<Path, ConfigFileName>();
1257+
private readonly configFileForOpenFiles = new Map<Path, ConfigFileForOpenFile>();
12231258
/** Set of open script infos that are root of inferred project */
12241259
private rootOfInferredProjects = new Set<ScriptInfo>();
12251260
/**
@@ -1258,7 +1293,7 @@ export class ProjectService {
12581293
* All the open script info that needs recalculation of the default project,
12591294
* this also caches config file info before config file change was detected to use it in case projects are not updated yet
12601295
*/
1261-
private pendingOpenFileProjectUpdates?: Map<Path, ConfigFileName>;
1296+
private pendingOpenFileProjectUpdates?: Map<Path, ConfigFileForOpenFile>;
12621297
/** @internal */
12631298
pendingEnsureProjectForOpenFiles = false;
12641299

@@ -2277,7 +2312,7 @@ export class ProjectService {
22772312
const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
22782313

22792314
let openFilesImpactedByConfigFile: Set<Path> | undefined;
2280-
if (this.openFiles.has(info.path) && !isAncestorConfigFileInfo(info)) {
2315+
if (this.openFiles.has(info.path) && (!isAncestorConfigFileInfo(info) || info.isForDefaultProject)) {
22812316
// By default the info would get impacted by presence of config file since its in the detection path
22822317
// Only adding the info as a root to inferred project will need the existence to be watched by file watcher
22832318
if (configFileExistenceInfo) (configFileExistenceInfo.openFilesImpactedByConfigFile ??= new Set()).add(info.path);
@@ -2470,31 +2505,39 @@ export class ProjectService {
24702505

24712506
// If projectRootPath doesn't contain info.path, then do normal search for config file
24722507
const anySearchPathOk = !projectRootPath || !isSearchPathInProjectRoot();
2473-
// For ancestor of config file always ignore its own directory since its going to result in itself
2474-
let searchInDirectory = !isAncestorConfigFileInfo(info);
2508+
2509+
let searchTsconfig = true;
2510+
let searchJsconfig = true;
2511+
if (isAncestorConfigFileInfo(info)) {
2512+
// For ancestor of config file always ignore itself
2513+
if (endsWith(info.fileName, "tsconfig.json")) searchTsconfig = false;
2514+
else searchTsconfig = searchJsconfig = false;
2515+
}
24752516
do {
2476-
if (searchInDirectory) {
2477-
const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName);
2517+
const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName);
2518+
if (searchTsconfig) {
24782519
const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json"));
2479-
let result = action(combinePaths(canonicalSearchPath, "tsconfig.json") as NormalizedPath, tsconfigFileName);
2520+
const result = action(combinePaths(canonicalSearchPath, "tsconfig.json") as NormalizedPath, tsconfigFileName);
24802521
if (result) return tsconfigFileName;
2522+
}
24812523

2524+
if (searchJsconfig) {
24822525
const jsconfigFileName = asNormalizedPath(combinePaths(searchPath, "jsconfig.json"));
2483-
result = action(combinePaths(canonicalSearchPath, "jsconfig.json") as NormalizedPath, jsconfigFileName);
2526+
const result = action(combinePaths(canonicalSearchPath, "jsconfig.json") as NormalizedPath, jsconfigFileName);
24842527
if (result) return jsconfigFileName;
2528+
}
24852529

2486-
// If we started within node_modules, don't look outside node_modules.
2487-
// Otherwise, we might pick up a very large project and pull in the world,
2488-
// causing an editor delay.
2489-
if (isNodeModulesDirectory(canonicalSearchPath)) {
2490-
break;
2491-
}
2530+
// If we started within node_modules, don't look outside node_modules.
2531+
// Otherwise, we might pick up a very large project and pull in the world,
2532+
// causing an editor delay.
2533+
if (isNodeModulesDirectory(canonicalSearchPath)) {
2534+
break;
24922535
}
24932536

24942537
const parentPath = asNormalizedPath(getDirectoryPath(searchPath));
24952538
if (parentPath === searchPath) break;
24962539
searchPath = parentPath;
2497-
searchInDirectory = true;
2540+
searchTsconfig = searchJsconfig = true;
24982541
}
24992542
while (anySearchPathOk || isSearchPathInProjectRoot());
25002543

@@ -2529,8 +2572,24 @@ export class ProjectService {
25292572
configFileName: NormalizedPath | undefined,
25302573
) {
25312574
if (!this.openFiles.has(info.path)) return; // Dont cache for closed script infos
2532-
if (isAncestorConfigFileInfo(info)) return; // Dont cache for ancestors
2533-
this.configFileForOpenFiles.set(info.path, configFileName || false);
2575+
const config = configFileName || false;
2576+
if (!isAncestorConfigFileInfo(info)) {
2577+
// Set value for open script info
2578+
this.configFileForOpenFiles.set(info.path, config);
2579+
}
2580+
else {
2581+
// Need to set value for ancestor in ConfigFileMapForOpenFile
2582+
let configFileForOpenFile = this.configFileForOpenFiles.get(info.path)!;
2583+
if (!configFileForOpenFile || isString(configFileForOpenFile)) {
2584+
// We have value for open script info in cache, make a map with that as false key and set new vlaue
2585+
this.configFileForOpenFiles.set(
2586+
info.path,
2587+
configFileForOpenFile = new Map().set(false, configFileForOpenFile),
2588+
);
2589+
}
2590+
// Set value of for ancestor in the map
2591+
configFileForOpenFile.set(info.fileName, config);
2592+
}
25342593
}
25352594

25362595
/**
@@ -4275,7 +4334,8 @@ export class ProjectService {
42754334
function tryFindDefaultConfiguredProject(project: ConfiguredProject): ConfiguredProject | undefined {
42764335
return isDefaultProject(project) ?
42774336
defaultProject :
4278-
tryFindDefaultConfiguredProjectFromReferences(project);
4337+
(tryFindDefaultConfiguredProjectFromReferences(project) ??
4338+
tryFindDefaultConfiguredProjectFromAncestor(project));
42794339
}
42804340

42814341
function isDefaultProject(project: ConfiguredProject): ConfiguredProject | undefined {
@@ -4305,6 +4365,19 @@ export class ProjectService {
43054365
reloadedProjects,
43064366
);
43074367
}
4368+
4369+
function tryFindDefaultConfiguredProjectFromAncestor(project: ConfiguredProject) {
4370+
return forEachAncestorProject( // If not in referenced projects, try ancestors and its references
4371+
info,
4372+
project,
4373+
tryFindDefaultConfiguredProject,
4374+
kind,
4375+
`Creating possible configured project for ${info.fileName} to open`,
4376+
allowDeferredClosed,
4377+
reloadedProjects,
4378+
/*searchOnlyPotentialSolution*/ false,
4379+
);
4380+
}
43084381
}
43094382

43104383
/**
@@ -4349,6 +4422,7 @@ export class ProjectService {
43494422
`Creating project possibly referencing default composite project ${defaultProject.getProjectName()} of open file ${info.fileName}`,
43504423
allowDeferredClosed,
43514424
reloadedProjects,
4425+
/*searchOnlyPotentialSolution*/ true,
43524426
delayReloadedConfiguredProjects,
43534427
);
43544428
}

tests/baselines/reference/tsserver/configuredProjects/Open-ref-of-configured-project-when-open-file-gets-added-to-the-project-as-part-of-configured-file-update-buts-its-open-file-references-are-all-closed-when-the-update-happens.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ Info seq [hh:mm:ss:mss] request:
228228
"type": "request"
229229
}
230230
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/project/a/b/src/file2.ts ProjectRootPath: undefined:: Result: /user/username/projects/project/a/b/tsconfig.json
231+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/project/a/b/tsconfig.json ProjectRootPath: undefined:: Result: undefined
231232
Info seq [hh:mm:ss:mss] event:
232233
{
233234
"seq": 0,

tests/baselines/reference/tsserver/configuredProjects/Open-ref-of-configured-project-when-open-file-gets-added-to-the-project-as-part-of-configured-file-update.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ Info seq [hh:mm:ss:mss] request:
228228
"type": "request"
229229
}
230230
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/project/a/b/src/file2.ts ProjectRootPath: undefined:: Result: /user/username/projects/project/a/b/tsconfig.json
231+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/project/a/b/tsconfig.json ProjectRootPath: undefined:: Result: undefined
231232
Info seq [hh:mm:ss:mss] event:
232233
{
233234
"seq": 0,

tests/baselines/reference/tsserver/configuredProjects/add-and-then-remove-a-config-file-in-a-folder-with-loose-files.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile
366366
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
367367
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile2.ts ProjectRootPath: undefined
368368
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject2*
369+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/myproject/tsconfig.json ProjectRootPath: undefined:: Result: undefined
369370
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
370371
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* projectStateVersion: 2 projectProgramVersion: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms
371372
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
@@ -665,6 +666,7 @@ Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile
665666
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject1*,/user/username/projects/myproject/tsconfig.json
666667
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile2.ts ProjectRootPath: undefined
667668
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject2*
669+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/myproject/tsconfig.json ProjectRootPath: undefined:: Result: undefined
668670
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
669671
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* projectStateVersion: 4 projectProgramVersion: 3 structureChanged: true structureIsReused:: Not Elapsed:: *ms
670672
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
@@ -1731,6 +1733,7 @@ Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile
17311733
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
17321734
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile2.ts ProjectRootPath: undefined
17331735
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject4*
1736+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/myproject/tsconfig.json ProjectRootPath: undefined:: Result: undefined
17341737
Info seq [hh:mm:ss:mss] After ensureProjectForOpenFiles:
17351738
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
17361739
Info seq [hh:mm:ss:mss] Files (2)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy