diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 9c5beffc61130..88fd5a43469e4 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -30116,7 +30116,7 @@ namespace ts {
const diags = max > 1 ? allDiagnostics[minIndex] : flatten(allDiagnostics);
Debug.assert(diags.length > 0, "No errors reported for 3 or fewer overload signatures");
const chain = chainDiagnosticMessages(
- map(diags, d => typeof d.messageText === "string" ? (d as DiagnosticMessageChain) : d.messageText),
+ map(diags, createDiagnosticMessageChainFromDiagnostic),
Diagnostics.No_overload_matches_this_call);
// The below is a spread to guarantee we get a new (mutable) array - our `flatMap` helper tries to do "smart" optimizations where it reuses input
// arrays and the emptyArray singleton where possible, which is decidedly not what we want while we're still constructing this diagnostic
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index ed8ddf17227a0..9e8fbcf756c5e 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -1071,6 +1071,15 @@ namespace ts {
};
}
+ export function createDiagnosticMessageChainFromDiagnostic(diagnostic: DiagnosticRelatedInformation): DiagnosticMessageChain {
+ return typeof diagnostic.messageText === "string" ? {
+ code: diagnostic.code,
+ category: diagnostic.category,
+ messageText: diagnostic.messageText,
+ next: (diagnostic as DiagnosticMessageChain).next,
+ } : diagnostic.messageText;
+ }
+
export function createDiagnosticForRange(sourceFile: SourceFile, range: TextRange, message: DiagnosticMessage): DiagnosticWithLocation {
return {
file: sourceFile,
diff --git a/src/testRunner/unittests/tsc/incremental.ts b/src/testRunner/unittests/tsc/incremental.ts
index a8fe334de7c7f..13a644a62082a 100644
--- a/src/testRunner/unittests/tsc/incremental.ts
+++ b/src/testRunner/unittests/tsc/incremental.ts
@@ -418,5 +418,36 @@ declare global {
incrementalScenarios: noChangeOnlyRuns,
baselinePrograms: true
});
+
+ verifyTscSerializedIncrementalEdits({
+ scenario: "incremental",
+ subScenario: "serializing error chains",
+ commandLineArgs: ["-p", `src/project`],
+ fs: () => loadProjectFromFiles({
+ "/src/project/tsconfig.json": JSON.stringify({
+ compilerOptions: {
+ incremental: true,
+ strict: true,
+ jsx: "react",
+ module: "esnext",
+ },
+ }),
+ "/src/project/index.tsx": Utils.dedent`
+ declare namespace JSX {
+ interface ElementChildrenAttribute { children: {}; }
+ interface IntrinsicElements { div: {} }
+ }
+
+ declare var React: any;
+
+ declare function Component(props: never): any;
+ declare function Component(props: { children?: number }): any;
+ (
+
+
+ )`
+ }, `\ninterface ReadonlyArray { readonly length: number }`),
+ incrementalScenarios: noChangeOnlyRuns,
+ });
});
}
diff --git a/tests/baselines/reference/tsc/incremental/initial-build/serializing-error-chains.js b/tests/baselines/reference/tsc/incremental/initial-build/serializing-error-chains.js
new file mode 100644
index 0000000000000..6cf4aaf5a3c1f
--- /dev/null
+++ b/tests/baselines/reference/tsc/incremental/initial-build/serializing-error-chains.js
@@ -0,0 +1,185 @@
+Input::
+//// [/lib/lib.d.ts]
+///
+interface Boolean {}
+interface Function {}
+interface CallableFunction {}
+interface NewableFunction {}
+interface IArguments {}
+interface Number { toExponential: any; }
+interface Object {}
+interface RegExp {}
+interface String { charAt: any; }
+interface Array { length: number; [n: number]: T; }
+interface ReadonlyArray {}
+declare const console: { log(msg: any): void; };
+interface ReadonlyArray { readonly length: number }
+
+//// [/src/project/index.tsx]
+declare namespace JSX {
+ interface ElementChildrenAttribute { children: {}; }
+ interface IntrinsicElements { div: {} }
+}
+
+declare var React: any;
+
+declare function Component(props: never): any;
+declare function Component(props: { children?: number }): any;
+(
+
+
+)
+
+//// [/src/project/tsconfig.json]
+{"compilerOptions":{"incremental":true,"strict":true,"jsx":"react","module":"esnext"}}
+
+
+
+Output::
+/lib/tsc -p src/project
+[96msrc/project/index.tsx[0m:[93m10[0m:[93m3[0m - [91merror[0m[90m TS2746: [0mThis JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided.
+
+[7m10[0m (
+[7m [0m [91m ~~~~~~~~~[0m
+
+[96msrc/project/index.tsx[0m:[93m10[0m:[93m3[0m - [91merror[0m[90m TS2746: [0mThis JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided.
+
+[7m10[0m (
+[7m [0m [91m ~~~~~~~~~[0m
+
+[96msrc/project/index.tsx[0m:[93m10[0m:[93m3[0m - [91merror[0m[90m TS2769: [0mNo overload matches this call.
+ This JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided.
+ This JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided.
+
+[7m10[0m (
+[7m [0m [91m ~~~~~~~~~[0m
+
+
+
+Found 3 errors in the same file, starting at: src/project/index.tsx[90m:10[0m
+
+exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated
+
+
+//// [/src/project/index.js]
+"use strict";
+(React.createElement(Component, null,
+ React.createElement("div", null),
+ React.createElement("div", null)));
+
+
+//// [/src/project/tsconfig.tsbuildinfo]
+{"program":{"fileNames":["../../lib/lib.d.ts","./index.tsx"],"fileInfos":[{"version":"7198220534-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };\ninterface ReadonlyArray { readonly length: number }","affectsGlobalScope":true},{"version":"42569361247-declare namespace JSX {\n interface ElementChildrenAttribute { children: {}; }\n interface IntrinsicElements { div: {} }\n}\n\ndeclare var React: any;\n\ndeclare function Component(props: never): any;\ndeclare function Component(props: { children?: number }): any;\n(\n \n \n)","affectsGlobalScope":true}],"options":{"jsx":2,"module":99,"strict":true},"referencedMap":[],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,[2,[{"file":"./index.tsx","start":265,"length":9,"messageText":"This JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided.","category":1,"code":2746},{"file":"./index.tsx","start":265,"length":9,"messageText":"This JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided.","category":1,"code":2746},{"file":"./index.tsx","start":265,"length":9,"code":2769,"category":1,"messageText":{"messageText":"No overload matches this call.","category":1,"code":2769,"next":[{"code":2746,"category":1,"messageText":"This JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided."},{"code":2746,"category":1,"messageText":"This JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided."}]},"relatedInformation":[]}]]]},"version":"FakeTSVersion"}
+
+//// [/src/project/tsconfig.tsbuildinfo.readable.baseline.txt]
+{
+ "program": {
+ "fileNames": [
+ "../../lib/lib.d.ts",
+ "./index.tsx"
+ ],
+ "fileInfos": {
+ "../../lib/lib.d.ts": {
+ "version": "7198220534-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };\ninterface ReadonlyArray { readonly length: number }",
+ "signature": "7198220534-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };\ninterface ReadonlyArray { readonly length: number }",
+ "affectsGlobalScope": true
+ },
+ "./index.tsx": {
+ "version": "42569361247-declare namespace JSX {\n interface ElementChildrenAttribute { children: {}; }\n interface IntrinsicElements { div: {} }\n}\n\ndeclare var React: any;\n\ndeclare function Component(props: never): any;\ndeclare function Component(props: { children?: number }): any;\n(\n \n \n)",
+ "signature": "42569361247-declare namespace JSX {\n interface ElementChildrenAttribute { children: {}; }\n interface IntrinsicElements { div: {} }\n}\n\ndeclare var React: any;\n\ndeclare function Component(props: never): any;\ndeclare function Component(props: { children?: number }): any;\n(\n \n \n)",
+ "affectsGlobalScope": true
+ }
+ },
+ "options": {
+ "jsx": 2,
+ "module": 99,
+ "strict": true
+ },
+ "referencedMap": {},
+ "exportedModulesMap": {},
+ "semanticDiagnosticsPerFile": [
+ "../../lib/lib.d.ts",
+ [
+ "./index.tsx",
+ [
+ {
+ "file": "./index.tsx",
+ "start": 265,
+ "length": 9,
+ "messageText": "This JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided.",
+ "category": 1,
+ "code": 2746
+ },
+ {
+ "file": "./index.tsx",
+ "start": 265,
+ "length": 9,
+ "messageText": "This JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided.",
+ "category": 1,
+ "code": 2746
+ },
+ {
+ "file": "./index.tsx",
+ "start": 265,
+ "length": 9,
+ "code": 2769,
+ "category": 1,
+ "messageText": {
+ "messageText": "No overload matches this call.",
+ "category": 1,
+ "code": 2769,
+ "next": [
+ {
+ "code": 2746,
+ "category": 1,
+ "messageText": "This JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided."
+ },
+ {
+ "code": 2746,
+ "category": 1,
+ "messageText": "This JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided."
+ }
+ ]
+ },
+ "relatedInformation": []
+ }
+ ]
+ ]
+ ]
+ },
+ "version": "FakeTSVersion",
+ "size": 2053
+}
+
+
+
+Change:: no-change-run
+Input::
+
+
+Output::
+/lib/tsc -p src/project
+[96msrc/project/index.tsx[0m:[93m10[0m:[93m3[0m - [91merror[0m[90m TS2746: [0mThis JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided.
+
+[7m10[0m (
+[7m [0m [91m ~~~~~~~~~[0m
+
+[96msrc/project/index.tsx[0m:[93m10[0m:[93m3[0m - [91merror[0m[90m TS2746: [0mThis JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided.
+
+[7m10[0m (
+[7m [0m [91m ~~~~~~~~~[0m
+
+[96msrc/project/index.tsx[0m:[93m10[0m:[93m3[0m - [91merror[0m[90m TS2769: [0mNo overload matches this call.
+ This JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided.
+ This JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided.
+
+[7m10[0m (
+[7m [0m [91m ~~~~~~~~~[0m
+
+
+
+Found 3 errors in the same file, starting at: src/project/index.tsx[90m:10[0m
+
+exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated
+
+