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)
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