Handle dts emit time errors for incremental scenarios and buildInfo (#56295)

This commit is contained in:
Sheetal Nandi
2023-11-02 18:35:28 -07:00
committed by GitHub
parent d86bddec5e
commit e58d8fd635
15 changed files with 1477 additions and 194 deletions
+12 -6
View File
@@ -180,13 +180,14 @@ export type ReadableProgramBuildInfoFileInfo<T> = Omit<ts.BuilderState.FileInfo,
export type ReadableProgramBuildInfoRoot =
| [original: ts.ProgramBuildInfoFileId, readable: string]
| [original: ts.ProgramBuildInfoRootStartEnd, readable: readonly string[]];
export type ReadableProgramMultiFileEmitBuildInfo = Omit<ts.ProgramMultiFileEmitBuildInfo, "fileIdsList" | "fileInfos" | "root" | "referencedMap" | "exportedModulesMap" | "semanticDiagnosticsPerFile" | "affectedFilesPendingEmit" | "changeFileSet" | "emitSignatures"> & {
export type ReadableProgramMultiFileEmitBuildInfo = Omit<ts.ProgramMultiFileEmitBuildInfo, "fileIdsList" | "fileInfos" | "root" | "referencedMap" | "exportedModulesMap" | "semanticDiagnosticsPerFile" | "emitDiagnosticsPerFile" | "affectedFilesPendingEmit" | "changeFileSet" | "emitSignatures"> & {
fileNamesList: readonly (readonly string[])[] | undefined;
fileInfos: ts.MapLike<ReadableProgramBuildInfoFileInfo<ts.ProgramMultiFileEmitBuildInfoFileInfo>>;
root: readonly ReadableProgramBuildInfoRoot[];
referencedMap: ts.MapLike<string[]> | undefined;
exportedModulesMap: ts.MapLike<string[]> | undefined;
semanticDiagnosticsPerFile: readonly ReadableProgramBuildInfoDiagnostic[] | undefined;
emitDiagnosticsPerFile: readonly ReadableProgramBuildInfoDiagnostic[] | undefined;
affectedFilesPendingEmit: readonly ReadableProgramBuilderInfoFilePendingEmit[] | undefined;
changeFileSet: readonly string[] | undefined;
emitSignatures: readonly ReadableProgramBuildInfoEmitSignature[] | undefined;
@@ -240,11 +241,8 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string,
options: buildInfo.program.options,
referencedMap: toMapOfReferencedSet(buildInfo.program.referencedMap),
exportedModulesMap: toMapOfReferencedSet(buildInfo.program.exportedModulesMap),
semanticDiagnosticsPerFile: buildInfo.program.semanticDiagnosticsPerFile?.map(d =>
ts.isNumber(d) ?
toFileName(d) :
[toFileName(d[0]), d[1]]
),
semanticDiagnosticsPerFile: toReadableProgramBuildInfoDiagnosticsPerFile(buildInfo.program.semanticDiagnosticsPerFile),
emitDiagnosticsPerFile: toReadableProgramBuildInfoDiagnosticsPerFile(buildInfo.program.emitDiagnosticsPerFile),
affectedFilesPendingEmit: buildInfo.program.affectedFilesPendingEmit?.map(value => toReadableProgramBuilderInfoFilePendingEmit(value, fullEmitForOptions!)),
changeFileSet: buildInfo.program.changeFileSet?.map(toFileName),
emitSignatures: buildInfo.program.emitSignatures?.map(s =>
@@ -334,6 +332,14 @@ function generateBuildInfoProgramBaseline(sys: ts.System, buildInfoPath: string,
result = result ? `${result} | ${flag}` : flag;
}
}
function toReadableProgramBuildInfoDiagnosticsPerFile(diagnostics: ts.ProgramBuildInfoDiagnostic[] | undefined): readonly ReadableProgramBuildInfoDiagnostic[] | undefined {
return diagnostics?.map(d =>
ts.isNumber(d) ?
toFileName(d) :
[toFileName(d[0]), d[1]]
);
}
}
export function toPathWithSystem(sys: ts.System, fileName: string): ts.Path {
+21
View File
@@ -364,6 +364,26 @@ function verifyTscEditDiscrepancies({
expectedIndex++;
});
}
if (incrementalReadableBuildInfo?.program?.emitDiagnosticsPerFile) {
incrementalReadableBuildInfo.program.emitDiagnosticsPerFile.forEach(([actualFileOrArray]) => {
const actualFile = ts.isString(actualFileOrArray) ? actualFileOrArray : actualFileOrArray[0];
if (
!ts.find(
(cleanReadableBuildInfo!.program! as ReadableProgramMultiFileEmitBuildInfo).emitDiagnosticsPerFile,
([expectedFileOrArray]) => actualFile === (ts.isString(expectedFileOrArray) ? expectedFileOrArray : expectedFileOrArray[0]),
) && !ts.find(
(cleanReadableBuildInfo!.program! as ReadableProgramMultiFileEmitBuildInfo).affectedFilesPendingEmit,
([expectedFileOrArray]) => actualFile === (ts.isString(expectedFileOrArray) ? expectedFileOrArray : expectedFileOrArray[0]),
)
) {
addBaseline(
`Incremental build contains ${actualFile} file has errors, clean build does not have errors or does not mark is as pending emit: ${outputFile}::`,
`Incremental buildInfoText:: ${incrementalBuildText}`,
`Clean buildInfoText:: ${cleanBuildText}`,
);
}
});
}
}
}
}
@@ -453,6 +473,7 @@ function getBuildInfoForIncrementalCorrectnessCheck(text: string | undefined): {
options: { ...readableBuildInfo.program.options, noEmit: undefined },
exportedModulesMap: undefined,
affectedFilesPendingEmit: undefined,
emitDiagnosticsPerFile: undefined,
latestChangedDtsFile: readableBuildInfo.program.latestChangedDtsFile ? "FakeFileName" : undefined,
},
size: undefined, // Size doesnt need to be equal
@@ -8,6 +8,10 @@ import {
jsonToReadableText,
} from "../helpers";
import {
libContent,
} from "../helpers/contents";
import {
noChangeOnlyRuns,
verifyTsc,
} from "../helpers/tsc";
import {
@@ -132,3 +136,43 @@ export function fn4() {
commandLineArgs: ["--b", "/src/packages/pkg2/tsconfig.json", "--verbose"],
});
});
verifyTsc({
scenario: "declarationEmit",
subScenario: "reports dts generation errors with incremental",
commandLineArgs: ["-b", `/src/project`, "--explainFiles", "--listEmittedFiles", "--v"],
fs: () =>
loadProjectFromFiles({
"/src/project/tsconfig.json": jsonToReadableText({
compilerOptions: {
module: "NodeNext",
moduleResolution: "NodeNext",
incremental: true,
declaration: true,
skipLibCheck: true,
skipDefaultLibCheck: true,
},
}),
"/src/project/index.ts": dedent`
import ky from 'ky';
export const api = ky.extend({});
`,
"/src/project/package.json": jsonToReadableText({
type: "module",
}),
"/src/project/node_modules/ky/distribution/index.d.ts": dedent`
type KyInstance = {
extend(options: Record<string,unknown>): KyInstance;
}
declare const ky: KyInstance;
export default ky;
`,
"/src/project/node_modules/ky/package.json": jsonToReadableText({
name: "ky",
type: "module",
main: "./distribution/index.js",
}),
"/lib/lib.esnext.full.d.ts": libContent,
}),
edits: noChangeOnlyRuns,
});
@@ -618,14 +618,17 @@ console.log(a);`,
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;`,
),
edits: [
noChangeRun,
{
caption: "modify public to protected",
edit: fs => replaceText(fs, "/src/project/MessageablePerson.ts", "public", "protected"),
},
noChangeRun,
{
caption: "modify protected to public",
edit: fs => replaceText(fs, "/src/project/MessageablePerson.ts", "protected", "public"),
},
noChangeRun,
],
});
}
@@ -959,4 +962,49 @@ console.log(a);`,
edit: fs => appendText(fs, "/src/project/src/bug.js", `export const something = 1;`),
}],
});
verifyTsc({
scenario: "incremental",
subScenario: "reports dts generation errors",
commandLineArgs: ["-p", `/src/project`, "--explainFiles", "--listEmittedFiles"],
fs: () =>
loadProjectFromFiles({
"/src/project/tsconfig.json": jsonToReadableText({
compilerOptions: {
module: "NodeNext",
moduleResolution: "NodeNext",
composite: true,
skipLibCheck: true,
skipDefaultLibCheck: true,
},
}),
"/src/project/index.ts": Utils.dedent`
import ky from 'ky';
export const api = ky.extend({});
`,
"/src/project/package.json": jsonToReadableText({
type: "module",
}),
"/src/project/node_modules/ky/distribution/index.d.ts": Utils.dedent`
type KyInstance = {
extend(options: Record<string,unknown>): KyInstance;
}
declare const ky: KyInstance;
export default ky;
`,
"/src/project/node_modules/ky/package.json": jsonToReadableText({
name: "ky",
type: "module",
main: "./distribution/index.js",
}),
"/lib/lib.esnext.full.d.ts": libContent,
}),
edits: [
noChangeRun,
{
...noChangeRun,
commandLineArgs: ["-b", `/src/project`, "--explainFiles", "--listEmittedFiles", "-v"],
},
],
});
});