Skip to content

Commit 02b07a1

Browse files
authored
Dont open composite projects to determine if script info is part of project (#59688)
1 parent 8230bc6 commit 02b07a1

File tree

1,079 files changed

+29994
-24432
lines changed

Some content is hidden

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

1,079 files changed

+29994
-24432
lines changed

src/compiler/commandLineParser.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3250,13 +3250,25 @@ function shouldReportNoInputFiles(fileNames: string[], canJsonReportNoInutFiles:
32503250
return fileNames.length === 0 && canJsonReportNoInutFiles && (!resolutionStack || resolutionStack.length === 0);
32513251
}
32523252

3253+
/** @internal */
3254+
export function isSolutionConfig(config: ParsedCommandLine): boolean {
3255+
return !config.fileNames.length &&
3256+
hasProperty(config.raw, "references");
3257+
}
3258+
32533259
/** @internal */
32543260
export function canJsonReportNoInputFiles(raw: any): boolean {
32553261
return !hasProperty(raw, "files") && !hasProperty(raw, "references");
32563262
}
32573263

32583264
/** @internal */
3259-
export function updateErrorForNoInputFiles(fileNames: string[], configFileName: string, configFileSpecs: ConfigFileSpecs, configParseDiagnostics: Diagnostic[], canJsonReportNoInutFiles: boolean): boolean {
3265+
export function updateErrorForNoInputFiles(
3266+
fileNames: string[],
3267+
configFileName: string,
3268+
configFileSpecs: ConfigFileSpecs,
3269+
configParseDiagnostics: Diagnostic[],
3270+
canJsonReportNoInutFiles: boolean,
3271+
): boolean {
32603272
const existingErrors = configParseDiagnostics.length;
32613273
if (shouldReportNoInputFiles(fileNames, canJsonReportNoInutFiles)) {
32623274
configParseDiagnostics.push(getErrorForNoInputFiles(configFileSpecs, configFileName));
@@ -3960,13 +3972,14 @@ export function matchesExclude(
39603972
);
39613973
}
39623974

3963-
function matchesExcludeWorker(
3975+
/** @internal */
3976+
export function matchesExcludeWorker(
39643977
pathToCheck: string,
39653978
excludeSpecs: readonly string[] | undefined,
39663979
useCaseSensitiveFileNames: boolean,
39673980
currentDirectory: string,
39683981
basePath?: string,
3969-
) {
3982+
): boolean {
39703983
const excludePattern = getRegularExpressionForWildcard(excludeSpecs, combinePaths(normalizePath(currentDirectory), basePath), "exclude");
39713984
const excludeRegex = excludePattern && getRegexFromPattern(excludePattern, useCaseSensitiveFileNames);
39723985
if (!excludeRegex) return false;

src/compiler/program.ts

Lines changed: 66 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,11 @@ export function forEachResolvedProjectReference<T>(
11501150
resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined,
11511151
cb: (resolvedProjectReference: ResolvedProjectReference, parent: ResolvedProjectReference | undefined) => T | undefined,
11521152
): T | undefined {
1153-
return forEachProjectReference(/*projectReferences*/ undefined, resolvedProjectReferences, (resolvedRef, parent) => resolvedRef && cb(resolvedRef, parent));
1153+
return forEachProjectReference(
1154+
/*projectReferences*/ undefined,
1155+
resolvedProjectReferences,
1156+
(resolvedRef, parent) => resolvedRef && cb(resolvedRef, parent),
1157+
);
11541158
}
11551159

11561160
function forEachProjectReference<T>(
@@ -1160,7 +1164,6 @@ function forEachProjectReference<T>(
11601164
cbRef?: (projectReferences: readonly ProjectReference[] | undefined, parent: ResolvedProjectReference | undefined) => T | undefined,
11611165
): T | undefined {
11621166
let seenResolvedRefs: Set<Path> | undefined;
1163-
11641167
return worker(projectReferences, resolvedProjectReferences, /*parent*/ undefined);
11651168

11661169
function worker(
@@ -1173,19 +1176,26 @@ function forEachProjectReference<T>(
11731176
const result = cbRef(projectReferences, parent);
11741177
if (result) return result;
11751178
}
1176-
1177-
return forEach(resolvedProjectReferences, (resolvedRef, index) => {
1178-
if (resolvedRef && seenResolvedRefs?.has(resolvedRef.sourceFile.path)) {
1179-
// ignore recursives
1180-
return undefined;
1181-
}
1182-
1183-
const result = cbResolvedRef(resolvedRef, parent, index);
1184-
if (result || !resolvedRef) return result;
1185-
1186-
(seenResolvedRefs ||= new Set()).add(resolvedRef.sourceFile.path);
1187-
return worker(resolvedRef.commandLine.projectReferences, resolvedRef.references, resolvedRef);
1188-
});
1179+
let skipChildren: Set<ResolvedProjectReference> | undefined;
1180+
return forEach(
1181+
resolvedProjectReferences,
1182+
(resolvedRef, index) => {
1183+
if (resolvedRef && seenResolvedRefs?.has(resolvedRef.sourceFile.path)) {
1184+
(skipChildren ??= new Set()).add(resolvedRef);
1185+
// ignore recursives
1186+
return undefined;
1187+
}
1188+
const result = cbResolvedRef(resolvedRef, parent, index);
1189+
if (result || !resolvedRef) return result;
1190+
(seenResolvedRefs ||= new Set()).add(resolvedRef.sourceFile.path);
1191+
},
1192+
) || forEach(
1193+
resolvedProjectReferences,
1194+
resolvedRef =>
1195+
resolvedRef && !skipChildren?.has(resolvedRef) ?
1196+
worker(resolvedRef.commandLine.projectReferences, resolvedRef.references, resolvedRef) :
1197+
undefined,
1198+
);
11891199
}
11901200
}
11911201

@@ -1367,7 +1377,14 @@ export function isProgramUptoDate(
13671377
(seenResolvedRefs || (seenResolvedRefs = [])).push(oldResolvedRef);
13681378

13691379
// If child project references are upto date, this project reference is uptodate
1370-
return !forEach(oldResolvedRef.references, (childResolvedRef, index) => !resolvedProjectReferenceUptoDate(childResolvedRef, oldResolvedRef.commandLine.projectReferences![index]));
1380+
return !forEach(
1381+
oldResolvedRef.references,
1382+
(childResolvedRef, index) =>
1383+
!resolvedProjectReferenceUptoDate(
1384+
childResolvedRef,
1385+
oldResolvedRef.commandLine.projectReferences![index],
1386+
),
1387+
);
13711388
}
13721389

13731390
// In old program, not able to resolve project reference path,
@@ -4905,7 +4922,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
49054922
case FileIncludeKind.SourceFromProjectReference:
49064923
case FileIncludeKind.OutputFromProjectReference:
49074924
const referencedResolvedRef = Debug.checkDefined(resolvedProjectReferences?.[reason.index]);
4908-
const referenceInfo = forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, parent, index) => resolvedRef === referencedResolvedRef ? { sourceFile: parent?.sourceFile || options.configFile!, index } : undefined);
4925+
const referenceInfo = forEachProjectReference(
4926+
projectReferences,
4927+
resolvedProjectReferences,
4928+
(resolvedRef, parent, index) =>
4929+
resolvedRef === referencedResolvedRef ?
4930+
{ sourceFile: parent?.sourceFile || options.configFile!, index } :
4931+
undefined,
4932+
);
49094933
if (!referenceInfo) return undefined;
49104934
const { sourceFile, index } = referenceInfo;
49114935
const referencesSyntax = forEachTsConfigPropArray(sourceFile as TsConfigSourceFile, "references", property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined);
@@ -4945,28 +4969,32 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
49454969

49464970
function verifyProjectReferences() {
49474971
const buildInfoPath = !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined;
4948-
forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, parent, index) => {
4949-
const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index];
4950-
const parentFile = parent && parent.sourceFile as JsonSourceFile;
4951-
verifyDeprecatedProjectReference(ref, parentFile, index);
4952-
if (!resolvedRef) {
4953-
createDiagnosticForReference(parentFile, index, Diagnostics.File_0_not_found, ref.path);
4954-
return;
4955-
}
4956-
const options = resolvedRef.commandLine.options;
4957-
if (!options.composite || options.noEmit) {
4958-
// ok to not have composite if the current program is container only
4959-
const inputs = parent ? parent.commandLine.fileNames : rootNames;
4960-
if (inputs.length) {
4961-
if (!options.composite) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path);
4962-
if (options.noEmit) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_may_not_disable_emit, ref.path);
4972+
forEachProjectReference(
4973+
projectReferences,
4974+
resolvedProjectReferences,
4975+
(resolvedRef, parent, index) => {
4976+
const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index];
4977+
const parentFile = parent && parent.sourceFile as JsonSourceFile;
4978+
verifyDeprecatedProjectReference(ref, parentFile, index);
4979+
if (!resolvedRef) {
4980+
createDiagnosticForReference(parentFile, index, Diagnostics.File_0_not_found, ref.path);
4981+
return;
49634982
}
4964-
}
4965-
if (!parent && buildInfoPath && buildInfoPath === getTsBuildInfoEmitOutputFilePath(options)) {
4966-
createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_write_file_0_because_it_will_overwrite_tsbuildinfo_file_generated_by_referenced_project_1, buildInfoPath, ref.path);
4967-
hasEmitBlockingDiagnostics.set(toPath(buildInfoPath), true);
4968-
}
4969-
});
4983+
const options = resolvedRef.commandLine.options;
4984+
if (!options.composite || options.noEmit) {
4985+
// ok to not have composite if the current program is container only
4986+
const inputs = parent ? parent.commandLine.fileNames : rootNames;
4987+
if (inputs.length) {
4988+
if (!options.composite) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path);
4989+
if (options.noEmit) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_may_not_disable_emit, ref.path);
4990+
}
4991+
}
4992+
if (!parent && buildInfoPath && buildInfoPath === getTsBuildInfoEmitOutputFilePath(options)) {
4993+
createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_write_file_0_because_it_will_overwrite_tsbuildinfo_file_generated_by_referenced_project_1, buildInfoPath, ref.path);
4994+
hasEmitBlockingDiagnostics.set(toPath(buildInfoPath), true);
4995+
}
4996+
},
4997+
);
49704998
}
49714999

49725000
function createDiagnosticForOptionPathKeyValue(key: string, valueIndex: number, message: DiagnosticMessage, ...args: DiagnosticArguments) {

src/compiler/tsbuildPublic.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ import {
8080
isIncrementalBuildInfo,
8181
isIncrementalCompilation,
8282
isPackageJsonInfo,
83+
isSolutionConfig,
8384
loadWithModeAwareCache,
8485
maybeBind,
8586
missingFileModifiedTime,
@@ -1236,7 +1237,13 @@ function getNextInvalidatedProjectCreateInfo<T extends BuilderProgram>(
12361237
else if (updateLevel === ProgramUpdateLevel.RootNamesAndUpdate) {
12371238
// Update file names
12381239
config.fileNames = getFileNamesFromConfigSpecs(config.options.configFile!.configFileSpecs!, getDirectoryPath(project), config.options, state.parseConfigFileHost);
1239-
updateErrorForNoInputFiles(config.fileNames, project, config.options.configFile!.configFileSpecs!, config.errors, canJsonReportNoInputFiles(config.raw));
1240+
updateErrorForNoInputFiles(
1241+
config.fileNames,
1242+
project,
1243+
config.options.configFile!.configFileSpecs!,
1244+
config.errors,
1245+
canJsonReportNoInputFiles(config.raw),
1246+
);
12401247
watchInputFiles(state, project, projectPath, config);
12411248
watchPackageJsonFiles(state, project, projectPath, config);
12421249
}
@@ -1461,11 +1468,7 @@ function checkConfigFileUpToDateStatus<T extends BuilderProgram>(state: Solution
14611468

14621469
function getUpToDateStatusWorker<T extends BuilderProgram>(state: SolutionBuilderState<T>, project: ParsedCommandLine, resolvedPath: ResolvedConfigFilePath): UpToDateStatus {
14631470
// Container if no files are specified in the project
1464-
if (!project.fileNames.length && !canJsonReportNoInputFiles(project.raw)) {
1465-
return {
1466-
type: UpToDateStatusType.ContainerOnly,
1467-
};
1468-
}
1471+
if (isSolutionConfig(project)) return { type: UpToDateStatusType.ContainerOnly };
14691472

14701473
// Fast check to see if reference projects are upto date and error free
14711474
let referenceStatuses;

src/compiler/watchPublic.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,15 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
925925

926926
updateLevel = ProgramUpdateLevel.Update;
927927
rootFileNames = getFileNamesFromConfigSpecs(compilerOptions.configFile!.configFileSpecs!, getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), compilerOptions, parseConfigFileHost, extraFileExtensions);
928-
if (updateErrorForNoInputFiles(rootFileNames, getNormalizedAbsolutePath(configFileName, currentDirectory), compilerOptions.configFile!.configFileSpecs!, configFileParsingDiagnostics!, canConfigFileJsonReportNoInputFiles)) {
928+
if (
929+
updateErrorForNoInputFiles(
930+
rootFileNames,
931+
getNormalizedAbsolutePath(configFileName, currentDirectory),
932+
compilerOptions.configFile!.configFileSpecs!,
933+
configFileParsingDiagnostics!,
934+
canConfigFileJsonReportNoInputFiles,
935+
)
936+
) {
929937
hasChangedConfigFileParsingErrors = true;
930938
}
931939

src/harness/client.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ import { protocol } from "./_namespaces/ts.server.js";
8282

8383
export interface SessionClientHost extends LanguageServiceHost {
8484
writeMessage(message: string): void;
85+
openFile(fileName: string): void;
8586
}
8687

8788
interface RenameEntry {
@@ -480,6 +481,7 @@ export class SessionClient implements LanguageService {
480481
}
481482

482483
getFileReferences(fileName: string): ReferenceEntry[] {
484+
this.host.openFile(fileName);
483485
const request = this.processRequest<protocol.FileReferencesRequest>(protocol.CommandTypes.FileReferences, { file: fileName });
484486
const response = this.processResponse<protocol.FileReferencesResponse>(request);
485487

src/harness/projectServiceStateLogger.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ interface ProjectData {
3131
projectStateVersion: Project["projectStateVersion"];
3232
projectProgramVersion: Project["projectProgramVersion"];
3333
dirty: Project["dirty"];
34+
initialLoadPending: Project["initialLoadPending"];
3435
isClosed: ReturnType<Project["isClosed"]>;
3536
isOrphan: ReturnType<Project["isOrphan"]>;
3637
noOpenRef: boolean;
@@ -123,6 +124,7 @@ export function patchServiceForStateBaseline(service: ProjectService): void {
123124
projectDiff = printProperty(PrintPropertyWhen.Always, data, "projectStateVersion", project.projectStateVersion, projectDiff, projectPropertyLogs);
124125
projectDiff = printProperty(PrintPropertyWhen.Always, data, "projectProgramVersion", project.projectProgramVersion, projectDiff, projectPropertyLogs);
125126
projectDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "dirty", project.dirty, projectDiff, projectPropertyLogs);
127+
projectDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "initialLoadPending", project.initialLoadPending, projectDiff, projectPropertyLogs);
126128
projectDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "isClosed", project.isClosed(), projectDiff, projectPropertyLogs);
127129
projectDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "isOrphan", !isBackgroundProject(project) && project.isOrphan(), projectDiff, projectPropertyLogs);
128130
projectDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "noOpenRef", noOpenRef(project), projectDiff, projectPropertyLogs);
@@ -154,6 +156,7 @@ export function patchServiceForStateBaseline(service: ProjectService): void {
154156
projectStateVersion: project.projectStateVersion,
155157
projectProgramVersion: project.projectProgramVersion,
156158
dirty: project.dirty,
159+
initialLoadPending: project.initialLoadPending,
157160
isClosed: project.isClosed(),
158161
isOrphan: !isBackgroundProject(project) && project.isOrphan(),
159162
noOpenRef: noOpenRef(project),

0 commit comments

Comments
 (0)