已开启
补充 getBuilderCreationParameters 和 getOldProgram 的 [SIR] 诊断日志 #871
liyancheng创建于 13 天前
补充 getBuilderCreationParameters 和 getOldProgram 的 [SIR] 诊断日志 #871
已开启
共 4 个文件变更+44-6
| @@ -1339,14 +1339,18 @@ export function getBuilderCreationParameters(newProgramOrRootNames: Program | re | |||
| 1339 | oldProgram = configFileParsingDiagnosticsOrOldProgram as BuilderProgram; | 1339 | oldProgram = configFileParsingDiagnosticsOrOldProgram as BuilderProgram; |
| 1340 | Debug.assert(!!oldProgram); | 1340 | Debug.assert(!!oldProgram); |
| 1341 | newProgram = oldProgram.getProgram(); | 1341 | newProgram = oldProgram.getProgram(); |
| 1342 | + console.warn(`[SIR] getBuilderCreationParameters(case1-undefined): reusing program from oldProgram.getProgram(), no createProgram call, oldProgram=${!!oldProgram}`); | ||
| 1342 | } | 1343 | } |
| 1343 | else if (isArray(newProgramOrRootNames)) { | 1344 | else if (isArray(newProgramOrRootNames)) { |
| 1344 | oldProgram = configFileParsingDiagnosticsOrOldProgram as BuilderProgram; | 1345 | oldProgram = configFileParsingDiagnosticsOrOldProgram as BuilderProgram; |
| 1346 | + const oldProgramForCreate = oldProgram && oldProgram.getProgramOrUndefined(); | ||
| 1347 | + console.warn(`[SIR] getBuilderCreationParameters: oldProgram=${!!oldProgram}, ` + | ||
| 1348 | + `oldProgram.getProgramOrUndefined()=${!!oldProgramForCreate}, rootNames.length=${(newProgramOrRootNames as readonly string[]).length}`); | ||
| 1345 | newProgram = createProgram({ | 1349 | newProgram = createProgram({ |
| 1346 | rootNames: newProgramOrRootNames, | 1350 | rootNames: newProgramOrRootNames, |
| 1347 | options: hostOrOptions as CompilerOptions, | 1351 | options: hostOrOptions as CompilerOptions, |
| 1348 | host: oldProgramOrHost as CompilerHost, | 1352 | host: oldProgramOrHost as CompilerHost, |
| 1349 | - oldProgram: oldProgram && oldProgram.getProgramOrUndefined(), | 1353 | + oldProgram: oldProgramForCreate, |
| 1350 | configFileParsingDiagnostics, | 1354 | configFileParsingDiagnostics, |
| 1351 | projectReferences | 1355 | projectReferences |
| 1352 | }); | 1356 | }); |
| @@ -1357,6 +1361,7 @@ export function getBuilderCreationParameters(newProgramOrRootNames: Program | re | |||
| 1357 | host = hostOrOptions as BuilderProgramHost; | 1361 | host = hostOrOptions as BuilderProgramHost; |
| 1358 | oldProgram = oldProgramOrHost as BuilderProgram; | 1362 | oldProgram = oldProgramOrHost as BuilderProgram; |
| 1359 | configFileParsingDiagnostics = configFileParsingDiagnosticsOrOldProgram as readonly Diagnostic[]; | 1363 | configFileParsingDiagnostics = configFileParsingDiagnosticsOrOldProgram as readonly Diagnostic[]; |
| 1364 | + console.warn(`[SIR] getBuilderCreationParameters(case3-Program): program already created externally, no createProgram call, oldProgram=${!!oldProgram}`); | ||
| 1360 | } | 1365 | } |
| 1361 | return { host, newProgram, oldProgram, configFileParsingDiagnostics: configFileParsingDiagnostics || emptyArray }; | 1366 | return { host, newProgram, oldProgram, configFileParsingDiagnostics: configFileParsingDiagnostics || emptyArray }; |
| 1362 | } | 1367 | } |
| @@ -2064,6 +2064,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2064 | 2064 | ||
| 2065 | function tryReuseStructureFromOldProgram(): StructureIsReused { | 2065 | function tryReuseStructureFromOldProgram(): StructureIsReused { |
| 2066 | if (!oldProgram) { | 2066 | if (!oldProgram) { |
| 2067 | + console.warn('[SIR] Not #1: oldProgram is null/undefined (first build or .tsbuildinfo missing/deleted/corrupt)'); | ||
| 2067 | return StructureIsReused.Not; | 2068 | return StructureIsReused.Not; |
| 2068 | } | 2069 | } |
| 2069 | 2070 | ||
| @@ -2071,17 +2072,22 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2071 | // if any of these properties has changed - structure cannot be reused | 2072 | // if any of these properties has changed - structure cannot be reused |
| 2072 | const oldOptions = oldProgram.getCompilerOptions(); | 2073 | const oldOptions = oldProgram.getCompilerOptions(); |
| 2073 | if (changesAffectModuleResolution(oldOptions, options)) { | 2074 | if (changesAffectModuleResolution(oldOptions, options)) { |
| 2075 | + console.warn('[SIR] Not #2: changesAffectModuleResolution - ' + | ||
| 2076 | + `configFilePath: ${oldOptions.configFilePath} -> ${options.configFilePath}`); | ||
| 2074 | return StructureIsReused.Not; | 2077 | return StructureIsReused.Not; |
| 2075 | } | 2078 | } |
| 2076 | 2079 | ||
| 2077 | // there is an old program, check if we can reuse its structure | 2080 | // there is an old program, check if we can reuse its structure |
| 2078 | const oldRootNames = oldProgram.getRootFileNames(); | 2081 | const oldRootNames = oldProgram.getRootFileNames(); |
| 2079 | if (!arrayIsEqualTo(oldRootNames, rootNames)) { | 2082 | if (!arrayIsEqualTo(oldRootNames, rootNames)) { |
| 2083 | + console.warn('[SIR] Not #3: rootFileNames changed - ' + | ||
| 2084 | + `oldCount=${oldRootNames.length}, newCount=${rootNames.length}`); | ||
| 2080 | return StructureIsReused.Not; | 2085 | return StructureIsReused.Not; |
| 2081 | } | 2086 | } |
| 2082 | 2087 | ||
| 2083 | // Check if any referenced project tsconfig files are different | 2088 | // Check if any referenced project tsconfig files are different |
| 2084 | if (!canReuseProjectReferences()) { | 2089 | if (!canReuseProjectReferences()) { |
| 2090 | + console.warn('[SIR] Not #4: canReuseProjectReferences returned false (project references changed)'); | ||
| 2085 | return StructureIsReused.Not; | 2091 | return StructureIsReused.Not; |
| 2086 | } | 2092 | } |
| 2087 | if (projectReferences) { | 2093 | if (projectReferences) { |
| @@ -2097,6 +2103,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2097 | // and hence cant reuse the structure. | 2103 | // and hence cant reuse the structure. |
| 2098 | // This is same as how we dont reuse the structure if one of the file from old program is now missing | 2104 | // This is same as how we dont reuse the structure if one of the file from old program is now missing |
| 2099 | if (oldProgram.getMissingFilePaths().some(missingFilePath => host.fileExists(missingFilePath))) { | 2105 | if (oldProgram.getMissingFilePaths().some(missingFilePath => host.fileExists(missingFilePath))) { |
| 2106 | + console.warn('[SIR] Not #5: a previously missing file now exists'); | ||
| 2100 | return StructureIsReused.Not; | 2107 | return StructureIsReused.Not; |
| 2101 | } | 2108 | } |
| 2102 | 2109 | ||
| @@ -2111,6 +2118,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2111 | : host.getSourceFile(oldSourceFile.fileName, sourceFileOptions, /*onError*/ undefined, shouldCreateNewSourceFile || sourceFileOptions.impliedNodeFormat !== oldSourceFile.impliedNodeFormat); // TODO: GH#18217 | 2118 | : host.getSourceFile(oldSourceFile.fileName, sourceFileOptions, /*onError*/ undefined, shouldCreateNewSourceFile || sourceFileOptions.impliedNodeFormat !== oldSourceFile.impliedNodeFormat); // TODO: GH#18217 |
| 2112 | 2119 | ||
| 2113 | if (!newSourceFile) { | 2120 | if (!newSourceFile) { |
| 2121 | + console.warn(`[SIR] Not #6: source file no longer exists: ${oldSourceFile.fileName}`); | ||
| 2114 | return StructureIsReused.Not; | 2122 | return StructureIsReused.Not; |
| 2115 | } | 2123 | } |
| 2116 | newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined; | 2124 | newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined; |
| @@ -2124,6 +2132,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2124 | // This lets us know if the unredirected file has changed. If it has we should break the redirect. | 2132 | // This lets us know if the unredirected file has changed. If it has we should break the redirect. |
| 2125 | if (newSourceFile !== oldSourceFile.redirectInfo.unredirected) { | 2133 | if (newSourceFile !== oldSourceFile.redirectInfo.unredirected) { |
| 2126 | // Underlying file has changed. Might not redirect anymore. Must rebuild program. | 2134 | // Underlying file has changed. Might not redirect anymore. Must rebuild program. |
| 2135 | + console.warn(`[SIR] Not #7: redirect underlying file changed: ${oldSourceFile.fileName}`); | ||
| 2127 | return StructureIsReused.Not; | 2136 | return StructureIsReused.Not; |
| 2128 | } | 2137 | } |
| 2129 | fileChanged = false; | 2138 | fileChanged = false; |
| @@ -2132,6 +2141,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2132 | else if (oldProgram.redirectTargetsMap.has(oldSourceFile.path)) { | 2141 | else if (oldProgram.redirectTargetsMap.has(oldSourceFile.path)) { |
| 2133 | // If a redirected-to source file changes, the redirect may be broken. | 2142 | // If a redirected-to source file changes, the redirect may be broken. |
| 2134 | if (newSourceFile !== oldSourceFile) { | 2143 | if (newSourceFile !== oldSourceFile) { |
| 2144 | + console.warn(`[SIR] Not #8: redirected-to file changed: ${oldSourceFile.fileName}`); | ||
| 2135 | return StructureIsReused.Not; | 2145 | return StructureIsReused.Not; |
| 2136 | } | 2146 | } |
| 2137 | fileChanged = false; | 2147 | fileChanged = false; |
| @@ -2153,6 +2163,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2153 | const prevKind = seenPackageNames.get(packageName); | 2163 | const prevKind = seenPackageNames.get(packageName); |
| 2154 | const newKind = fileChanged ? SeenPackageName.Modified : SeenPackageName.Exists; | 2164 | const newKind = fileChanged ? SeenPackageName.Modified : SeenPackageName.Exists; |
| 2155 | if ((prevKind !== undefined && newKind === SeenPackageName.Modified) || prevKind === SeenPackageName.Modified) { | 2165 | if ((prevKind !== undefined && newKind === SeenPackageName.Modified) || prevKind === SeenPackageName.Modified) { |
| 2166 | + console.warn(`[SIR] Not #9: package name conflict (two files for package "${packageName}", at least one changed): ${oldSourceFile.fileName}`); | ||
| 2156 | return StructureIsReused.Not; | 2167 | return StructureIsReused.Not; |
| 2157 | } | 2168 | } |
| 2158 | seenPackageNames.set(packageName, newKind); | 2169 | seenPackageNames.set(packageName, newKind); |
| @@ -2214,6 +2225,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2214 | } | 2225 | } |
| 2215 | 2226 | ||
| 2216 | if (structureIsReused !== StructureIsReused.Completely) { | 2227 | if (structureIsReused !== StructureIsReused.Completely) { |
| 2228 | + console.warn(`[SIR] SafeModules: file content changed but module resolution reusable (${structureIsReused === StructureIsReused.SafeModules ? 'SafeModules' : 'unknown'}), modifiedFiles=${modifiedSourceFiles.length}`); | ||
| 2217 | return structureIsReused; | 2229 | return structureIsReused; |
| 2218 | } | 2230 | } |
| 2219 | 2231 | ||
| @@ -2252,10 +2264,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2252 | } | 2264 | } |
| 2253 | 2265 | ||
| 2254 | if (structureIsReused !== StructureIsReused.Completely) { | 2266 | if (structureIsReused !== StructureIsReused.Completely) { |
| 2267 | + console.warn(`[SIR] SafeModules: module resolution changed for modified files, modifiedFiles=${modifiedSourceFiles.length}`); | ||
| 2255 | return structureIsReused; | 2268 | return structureIsReused; |
| 2256 | } | 2269 | } |
| 2257 | 2270 | ||
| 2258 | if (changesAffectingProgramStructure(oldOptions, options) || host.hasChangedAutomaticTypeDirectiveNames?.()) { | 2271 | if (changesAffectingProgramStructure(oldOptions, options) || host.hasChangedAutomaticTypeDirectiveNames?.()) { |
| 2272 | + console.warn('[SIR] SafeModules: changesAffectingProgramStructure or hasChangedAutomaticTypeDirectiveNames'); | ||
| 2259 | return StructureIsReused.SafeModules; | 2273 | return StructureIsReused.SafeModules; |
| 2260 | } | 2274 | } |
| 2261 | 2275 | ||
| @@ -2291,6 +2305,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg | |||
| 2291 | redirectTargetsMap = oldProgram.redirectTargetsMap; | 2305 | redirectTargetsMap = oldProgram.redirectTargetsMap; |
| 2292 | usesUriStyleNodeCoreModules = oldProgram.usesUriStyleNodeCoreModules; | 2306 | usesUriStyleNodeCoreModules = oldProgram.usesUriStyleNodeCoreModules; |
| 2293 | 2307 | ||
| 2308 | + console.warn('[SIR] Completely: structure fully reused from old program'); | ||
| 2294 | return StructureIsReused.Completely; | 2309 | return StructureIsReused.Completely; |
| 2295 | } | 2310 | } |
| 2296 | 2311 | ||
| @@ -1494,9 +1494,15 @@ function listEmittedFile({ write }: SolutionBuilderState, proj: ParsedCommandLin | |||
| 1494 | } | 1494 | } |
| 1495 | 1495 | ||
| 1496 | function getOldProgram<T extends BuilderProgram>({ options, builderPrograms, compilerHost }: SolutionBuilderState<T>, proj: ResolvedConfigFilePath, parsed: ParsedCommandLine) { | 1496 | function getOldProgram<T extends BuilderProgram>({ options, builderPrograms, compilerHost }: SolutionBuilderState<T>, proj: ResolvedConfigFilePath, parsed: ParsedCommandLine) { |
| 1497 | - if (options.force) return undefined; | 1497 | + if (options.force) { |
| 1498 | + console.warn(`[SIR] getOldProgram: --force flag set, returning undefined for ${proj}`); | ||
| 1499 | + return undefined; | ||
| 1500 | + } | ||
| 1498 | const value = builderPrograms.get(proj); | 1501 | const value = builderPrograms.get(proj); |
| 1499 | - if (value) return value; | 1502 | + if (value) { |
| 1503 | + console.warn(`[SIR] getOldProgram: reused cached builderProgram from builderPrograms map for ${proj}`); | ||
| 1504 | + return value; | ||
| 1505 | + } | ||
| 1500 | return readBuilderProgram(parsed.options, compilerHost) as any as T; | 1506 | return readBuilderProgram(parsed.options, compilerHost) as any as T; |
| 1501 | } | 1507 | } |
| 1502 | 1508 | ||
| @@ -106,7 +106,10 @@ export interface ReadBuildProgramHost { | |||
| 106 | export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost, isForLinter?: boolean) { | 106 | export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost, isForLinter?: boolean) { |
| 107 | let buildInfoPath = getTsBuildInfoEmitOutputFilePath(compilerOptions); | 107 | let buildInfoPath = getTsBuildInfoEmitOutputFilePath(compilerOptions); |
| 108 | 108 | ||
| 109 | - if (!buildInfoPath) return undefined; | 109 | + if (!buildInfoPath) { |
| 110 | + console.warn('[SIR] readBuilderProgram: buildInfoPath is empty (tsBuildInfoFile not set in compilerOptions)'); | ||
| 111 | + return undefined; | ||
| 112 | + } | ||
| 110 | 113 | ||
| 111 | if (isForLinter) { | 114 | if (isForLinter) { |
| 112 | buildInfoPath = getTsBuildInfoEmitOutputFilePathForLinter(buildInfoPath); | 115 | buildInfoPath = getTsBuildInfoEmitOutputFilePathForLinter(buildInfoPath); |
| @@ -119,10 +122,19 @@ export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadB | |||
| 119 | } | 122 | } |
| 120 | else { | 123 | else { |
| 121 | const content = host.readFile(buildInfoPath); | 124 | const content = host.readFile(buildInfoPath); |
| 122 | - if (!content) return undefined; | 125 | + if (!content) { |
| 126 | + console.warn(`[SIR] readBuilderProgram: .tsbuildinfo file not found or empty: ${buildInfoPath}`); | ||
| 127 | + return undefined; | ||
| 128 | + } | ||
| 123 | buildInfo = getBuildInfo(buildInfoPath, content); | 129 | buildInfo = getBuildInfo(buildInfoPath, content); |
| 124 | } | 130 | } |
| 125 | - if (!buildInfo || buildInfo.version !== version || !buildInfo.program) return undefined; | 131 | + if (!buildInfo || buildInfo.version !== version || !buildInfo.program) { |
| 132 | + console.warn(`[SIR] readBuilderProgram: buildInfo invalid - ` + | ||
| 133 | + `buildInfo=${!!buildInfo}, versionMatch=${buildInfo?.version === version}, hasProgram=${!!buildInfo?.program}, ` + | ||
| 134 | + `expectedVersion=${version}, actualVersion=${buildInfo?.version}, path=${buildInfoPath}`); | ||
| 135 | + return undefined; | ||
| 136 | + } | ||
| 137 | + console.warn(`[SIR] readBuilderProgram: SUCCESS - loaded oldProgram from ${buildInfoPath}`); | ||
| 126 | return createBuilderProgramUsingProgramBuildInfo(buildInfo.program, buildInfoPath, host); | 138 | return createBuilderProgramUsingProgramBuildInfo(buildInfo.program, buildInfoPath, host); |
| 127 | } | 139 | } |
| 128 | 140 | ||