Fix diagnostic serialization crash (#47604)

* Add crashing test

* Fix unsafe cast to DiagnosticMessageChain
This commit is contained in:
Andrew Branch 2022-01-26 10:41:47 -08:00 committed by GitHub
parent 3206df8e6d
commit c191e7c942
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 226 additions and 1 deletions

View File

@ -30121,7 +30121,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

View File

@ -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,

View File

@ -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;
(<Component>
<div />
<div />
</Component>)`
}, `\ninterface ReadonlyArray<T> { readonly length: number }`),
incrementalScenarios: noChangeOnlyRuns,
});
});
}

View File

@ -0,0 +1,185 @@
Input::
//// [/lib/lib.d.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }
interface ReadonlyArray<T> {}
declare const console: { log(msg: any): void; };
interface ReadonlyArray<T> { 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;
(<Component>
<div />
<div />
</Component>)
//// [/src/project/tsconfig.json]
{"compilerOptions":{"incremental":true,"strict":true,"jsx":"react","module":"esnext"}}
Output::
/lib/tsc -p src/project
src/project/index.tsx:10:3 - error TS2746: This JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided.
10 (<Component>
   ~~~~~~~~~
src/project/index.tsx:10:3 - error TS2746: This JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided.
10 (<Component>
   ~~~~~~~~~
src/project/index.tsx:10:3 - error TS2769: No 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.
10 (<Component>
   ~~~~~~~~~
Found 3 errors in the same file, starting at: src/project/index.tsx:10
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-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };\ninterface ReadonlyArray<T> { 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(<Component>\n <div />\n <div />\n</Component>)","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-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };\ninterface ReadonlyArray<T> { readonly length: number }",
"signature": "7198220534-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };\ninterface ReadonlyArray<T> { 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(<Component>\n <div />\n <div />\n</Component>)",
"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(<Component>\n <div />\n <div />\n</Component>)",
"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
src/project/index.tsx:10:3 - error TS2746: This JSX tag's 'children' prop expects a single child of type 'never', but multiple children were provided.
10 (<Component>
   ~~~~~~~~~
src/project/index.tsx:10:3 - error TS2746: This JSX tag's 'children' prop expects a single child of type 'number | undefined', but multiple children were provided.
10 (<Component>
   ~~~~~~~~~
src/project/index.tsx:10:3 - error TS2769: No 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.
10 (<Component>
   ~~~~~~~~~
Found 3 errors in the same file, starting at: src/project/index.tsx:10
exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated