Skip to content

Commit 0708a7e

Browse files
committed
Revert "Revert of Search ancestor and its references for default projects #57196 (#59634)"
This reverts commit 5fd6a6f.
1 parent e9222d3 commit 0708a7e

File tree

121 files changed

+8234
-3880
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

+8234
-3880
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,
@@ -644,10 +645,37 @@ export interface ProjectServiceOptions {
644645
*/
645646
export type ConfigFileName = NormalizedPath | false;
646647

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

653681
/** @internal */
@@ -662,6 +690,7 @@ export interface AncestorConfigFileInfo {
662690
/** path of open file so we can look at correct root */
663691
path: Path;
664692
configFileInfo: true;
693+
isForDefaultProject: boolean;
665694
}
666695
/** @internal */
667696
export type OpenScriptInfoOrClosedFileInfo = ScriptInfo | OriginalFileInfo;
@@ -710,6 +739,8 @@ function forEachAncestorProject<T>(
710739
allowDeferredClosed: boolean | undefined,
711740
/** Used with ConfiguredProjectLoadKind.Reload to check if this project was already reloaded */
712741
reloadedProjects: Set<ConfiguredProject> | undefined,
742+
/** true means we are looking for solution, so we can stop if found project is not composite to go into parent solution */
743+
searchOnlyPotentialSolution: boolean,
713744
/** Used with ConfiguredProjectLoadKind.Reload to specify delay reload, and also a set of configured projects already marked for delay load */
714745
delayReloadedConfiguredProjects?: Set<ConfiguredProject>,
715746
): T | undefined {
@@ -719,7 +750,10 @@ function forEachAncestorProject<T>(
719750
if (
720751
!project.initialLoadPending &&
721752
(
722-
!project.getCompilerOptions().composite ||
753+
(searchOnlyPotentialSolution && !project.getCompilerOptions().composite) ||
754+
// Currently disableSolutionSearching is shared for finding solution/project when
755+
// - loading solution for find all references
756+
// - trying to find default project
723757
project.getCompilerOptions().disableSolutionSearching
724758
)
725759
) return;
@@ -729,6 +763,7 @@ function forEachAncestorProject<T>(
729763
fileName: project.getConfigFilePath(),
730764
path: info.path,
731765
configFileInfo: true,
766+
isForDefaultProject: !searchOnlyPotentialSolution,
732767
}, kind === ConfiguredProjectLoadKind.Find);
733768
if (!configFileName) return;
734769

@@ -738,9 +773,9 @@ function forEachAncestorProject<T>(
738773
kind,
739774
reason,
740775
allowDeferredClosed,
741-
/*triggerFile*/ undefined,
776+
!searchOnlyPotentialSolution ? info.fileName : undefined, // Config Diag event for project if its for default project
742777
reloadedProjects,
743-
/*delayLoad*/ true,
778+
searchOnlyPotentialSolution, // Delay load if we are searching for solution
744779
delayReloadedConfiguredProjects,
745780
);
746781
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

@@ -2268,7 +2303,7 @@ export class ProjectService {
22682303
const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
22692304

22702305
let openFilesImpactedByConfigFile: Set<Path> | undefined;
2271-
if (this.openFiles.has(info.path) && !isAncestorConfigFileInfo(info)) {
2306+
if (this.openFiles.has(info.path) && (!isAncestorConfigFileInfo(info) || info.isForDefaultProject)) {
22722307
// By default the info would get impacted by presence of config file since its in the detection path
22732308
// Only adding the info as a root to inferred project will need the existence to be watched by file watcher
22742309
if (configFileExistenceInfo) (configFileExistenceInfo.openFilesImpactedByConfigFile ??= new Set()).add(info.path);
@@ -2461,31 +2496,39 @@ export class ProjectService {
24612496

24622497
// If projectRootPath doesn't contain info.path, then do normal search for config file
24632498
const anySearchPathOk = !projectRootPath || !isSearchPathInProjectRoot();
2464-
// For ancestor of config file always ignore its own directory since its going to result in itself
2465-
let searchInDirectory = !isAncestorConfigFileInfo(info);
2499+
2500+
let searchTsconfig = true;
2501+
let searchJsconfig = true;
2502+
if (isAncestorConfigFileInfo(info)) {
2503+
// For ancestor of config file always ignore itself
2504+
if (endsWith(info.fileName, "tsconfig.json")) searchTsconfig = false;
2505+
else searchTsconfig = searchJsconfig = false;
2506+
}
24662507
do {
2467-
if (searchInDirectory) {
2468-
const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName);
2508+
const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName);
2509+
if (searchTsconfig) {
24692510
const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json"));
2470-
let result = action(combinePaths(canonicalSearchPath, "tsconfig.json") as NormalizedPath, tsconfigFileName);
2511+
const result = action(combinePaths(canonicalSearchPath, "tsconfig.json") as NormalizedPath, tsconfigFileName);
24712512
if (result) return tsconfigFileName;
2513+
}
24722514

2515+
if (searchJsconfig) {
24732516
const jsconfigFileName = asNormalizedPath(combinePaths(searchPath, "jsconfig.json"));
2474-
result = action(combinePaths(canonicalSearchPath, "jsconfig.json") as NormalizedPath, jsconfigFileName);
2517+
const result = action(combinePaths(canonicalSearchPath, "jsconfig.json") as NormalizedPath, jsconfigFileName);
24752518
if (result) return jsconfigFileName;
2519+
}
24762520

2477-
// If we started within node_modules, don't look outside node_modules.
2478-
// Otherwise, we might pick up a very large project and pull in the world,
2479-
// causing an editor delay.
2480-
if (isNodeModulesDirectory(canonicalSearchPath)) {
2481-
break;
2482-
}
2521+
// If we started within node_modules, don't look outside node_modules.
2522+
// Otherwise, we might pick up a very large project and pull in the world,
2523+
// causing an editor delay.
2524+
if (isNodeModulesDirectory(canonicalSearchPath)) {
2525+
break;
24832526
}
24842527

24852528
const parentPath = asNormalizedPath(getDirectoryPath(searchPath));
24862529
if (parentPath === searchPath) break;
24872530
searchPath = parentPath;
2488-
searchInDirectory = true;
2531+
searchTsconfig = searchJsconfig = true;
24892532
}
24902533
while (anySearchPathOk || isSearchPathInProjectRoot());
24912534

@@ -2520,8 +2563,24 @@ export class ProjectService {
25202563
configFileName: NormalizedPath | undefined,
25212564
) {
25222565
if (!this.openFiles.has(info.path)) return; // Dont cache for closed script infos
2523-
if (isAncestorConfigFileInfo(info)) return; // Dont cache for ancestors
2524-
this.configFileForOpenFiles.set(info.path, configFileName || false);
2566+
const config = configFileName || false;
2567+
if (!isAncestorConfigFileInfo(info)) {
2568+
// Set value for open script info
2569+
this.configFileForOpenFiles.set(info.path, config);
2570+
}
2571+
else {
2572+
// Need to set value for ancestor in ConfigFileMapForOpenFile
2573+
let configFileForOpenFile = this.configFileForOpenFiles.get(info.path)!;
2574+
if (!configFileForOpenFile || isString(configFileForOpenFile)) {
2575+
// We have value for open script info in cache, make a map with that as false key and set new vlaue
2576+
this.configFileForOpenFiles.set(
2577+
info.path,
2578+
configFileForOpenFile = new Map().set(false, configFileForOpenFile),
2579+
);
2580+
}
2581+
// Set value of for ancestor in the map
2582+
configFileForOpenFile.set(info.fileName, config);
2583+
}
25252584
}
25262585

25272586
/**
@@ -4247,7 +4306,8 @@ export class ProjectService {
42474306
function tryFindDefaultConfiguredProject(project: ConfiguredProject): ConfiguredProject | undefined {
42484307
return isDefaultProject(project) ?
42494308
defaultProject :
4250-
tryFindDefaultConfiguredProjectFromReferences(project);
4309+
(tryFindDefaultConfiguredProjectFromReferences(project) ??
4310+
tryFindDefaultConfiguredProjectFromAncestor(project));
42514311
}
42524312

42534313
function isDefaultProject(project: ConfiguredProject): ConfiguredProject | undefined {
@@ -4277,6 +4337,19 @@ export class ProjectService {
42774337
reloadedProjects,
42784338
);
42794339
}
4340+
4341+
function tryFindDefaultConfiguredProjectFromAncestor(project: ConfiguredProject) {
4342+
return forEachAncestorProject( // If not in referenced projects, try ancestors and its references
4343+
info,
4344+
project,
4345+
tryFindDefaultConfiguredProject,
4346+
kind,
4347+
`Creating possible configured project for ${info.fileName} to open`,
4348+
allowDeferredClosed,
4349+
reloadedProjects,
4350+
/*searchOnlyPotentialSolution*/ false,
4351+
);
4352+
}
42804353
}
42814354

42824355
/**
@@ -4321,6 +4394,7 @@ export class ProjectService {
43214394
`Creating project possibly referencing default composite project ${defaultProject.getProjectName()} of open file ${info.fileName}`,
43224395
allowDeferredClosed,
43234396
reloadedProjects,
4397+
/*searchOnlyPotentialSolution*/ true,
43244398
delayReloadedConfiguredProjects,
43254399
);
43264400
}

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
@@ -233,6 +233,7 @@ Info seq [hh:mm:ss:mss] request:
233233
"type": "request"
234234
}
235235
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a/b/src/file2.ts ProjectRootPath: undefined:: Result: /a/b/tsconfig.json
236+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a/b/tsconfig.json ProjectRootPath: undefined:: Result: undefined
236237
Info seq [hh:mm:ss:mss] event:
237238
{
238239
"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
@@ -233,6 +233,7 @@ Info seq [hh:mm:ss:mss] request:
233233
"type": "request"
234234
}
235235
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a/b/src/file2.ts ProjectRootPath: undefined:: Result: /a/b/tsconfig.json
236+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /a/b/tsconfig.json ProjectRootPath: undefined:: Result: undefined
236237
Info seq [hh:mm:ss:mss] event:
237238
{
238239
"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
@@ -355,6 +355,7 @@ Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile
355355
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
356356
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile2.ts ProjectRootPath: undefined
357357
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject2*
358+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/myproject/tsconfig.json ProjectRootPath: undefined:: Result: undefined
358359
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
359360
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* projectStateVersion: 2 projectProgramVersion: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms
360361
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
@@ -647,6 +648,7 @@ Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile
647648
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject1*,/user/username/projects/myproject/tsconfig.json
648649
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile2.ts ProjectRootPath: undefined
649650
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject2*
651+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/myproject/tsconfig.json ProjectRootPath: undefined:: Result: undefined
650652
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /dev/null/inferredProject1*
651653
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /dev/null/inferredProject1* projectStateVersion: 4 projectProgramVersion: 3 structureChanged: true structureIsReused:: Not Elapsed:: *ms
652654
Info seq [hh:mm:ss:mss] Project '/dev/null/inferredProject1*' (Inferred)
@@ -1596,6 +1598,7 @@ Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile
15961598
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
15971599
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/commonFile2.ts ProjectRootPath: undefined
15981600
Info seq [hh:mm:ss:mss] Projects: /dev/null/inferredProject4*
1601+
Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /user/username/projects/myproject/tsconfig.json ProjectRootPath: undefined:: Result: undefined
15991602
Info seq [hh:mm:ss:mss] After ensureProjectForOpenFiles:
16001603
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
16011604
Info seq [hh:mm:ss:mss] Files (2)

0 commit comments

Comments
 (0)