-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
semantic-errors.ts
111 lines (107 loc) · 5.27 KB
/
semantic-errors.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import ts from 'typescript';
interface SemanticOrSyntacticError extends ts.Diagnostic {
message: string;
}
/**
* By default, diagnostics from the TypeScript compiler contain all errors - regardless of whether
* they are related to generic ECMAScript standards, or TypeScript-specific constructs.
*
* Therefore, we filter out all diagnostics, except for the ones we explicitly want to consider when
* the user opts in to throwing errors on semantic issues.
*/
export function getFirstSemanticOrSyntacticError(
program: ts.Program,
ast: ts.SourceFile,
): SemanticOrSyntacticError | undefined {
try {
const supportedSyntacticDiagnostics = whitelistSupportedDiagnostics(
program.getSyntacticDiagnostics(ast),
);
if (supportedSyntacticDiagnostics.length) {
return convertDiagnosticToSemanticOrSyntacticError(
supportedSyntacticDiagnostics[0],
);
}
const supportedSemanticDiagnostics = whitelistSupportedDiagnostics(
program.getSemanticDiagnostics(ast),
);
if (supportedSemanticDiagnostics.length) {
return convertDiagnosticToSemanticOrSyntacticError(
supportedSemanticDiagnostics[0],
);
}
return undefined;
} catch (e) {
/**
* TypeScript compiler has certain Debug.fail() statements in, which will cause the diagnostics
* retrieval above to throw.
*
* E.g. from ast-alignment-tests
* "Debug Failure. Shouldn't ever directly check a JsxOpeningElement"
*
* For our current use-cases this is undesired behavior, so we just suppress it
* and log a a warning.
*/
/* istanbul ignore next */
console.warn(`Warning From TSC: "${e.message}`);
/* istanbul ignore next */
return undefined;
}
}
function whitelistSupportedDiagnostics(
diagnostics: ReadonlyArray<ts.DiagnosticWithLocation | ts.Diagnostic>,
): ReadonlyArray<ts.DiagnosticWithLocation | ts.Diagnostic> {
return diagnostics.filter(diagnostic => {
switch (diagnostic.code) {
case 1013: // ts 3.2 "A rest parameter or binding pattern may not have a trailing comma."
case 1014: // ts 3.2 "A rest parameter must be last in a parameter list."
case 1044: // ts 3.2 "'{0}' modifier cannot appear on a module or namespace element."
case 1045: // ts 3.2 "A '{0}' modifier cannot be used with an interface declaration."
case 1048: // ts 3.2 "A rest parameter cannot have an initializer."
case 1049: // ts 3.2 "A 'set' accessor must have exactly one parameter."
case 1070: // ts 3.2 "'{0}' modifier cannot appear on a type member."
case 1071: // ts 3.2 "'{0}' modifier cannot appear on an index signature."
case 1085: // ts 3.2 "Octal literals are not available when targeting ECMAScript 5 and higher. Use the syntax '{0}'."
case 1090: // ts 3.2 "'{0}' modifier cannot appear on a parameter."
case 1096: // ts 3.2 "An index signature must have exactly one parameter."
case 1097: // ts 3.2 "'{0}' list cannot be empty."
case 1098: // ts 3.3 "Type parameter list cannot be empty."
case 1099: // ts 3.3 "Type argument list cannot be empty."
case 1117: // ts 3.2 "An object literal cannot have multiple properties with the same name in strict mode."
case 1121: // ts 3.2 "Octal literals are not allowed in strict mode."
case 1123: // ts 3.2: "Variable declaration list cannot be empty."
case 1141: // ts 3.2 "String literal expected."
case 1162: // ts 3.2 "An object member cannot be declared optional."
case 1172: // ts 3.2 "'extends' clause already seen."
case 1173: // ts 3.2 "'extends' clause must precede 'implements' clause."
case 1175: // ts 3.2 "'implements' clause already seen."
case 1176: // ts 3.2 "Interface declaration cannot have 'implements' clause."
case 1190: // ts 3.2 "The variable declaration of a 'for...of' statement cannot have an initializer."
case 1200: // ts 3.2 "Line terminator not permitted before arrow."
case 1206: // ts 3.2 "Decorators are not valid here."
case 1211: // ts 3.2 "A class declaration without the 'default' modifier must have a name."
case 1242: // ts 3.2 "'abstract' modifier can only appear on a class, method, or property declaration."
case 1246: // ts 3.2 "An interface property cannot have an initializer."
case 1255: // ts 3.2 "A definite assignment assertion '!' is not permitted in this context."
case 2364: // ts 3.2 "The left-hand side of an assignment expression must be a variable or a property access."
case 2369: // ts 3.2 "A parameter property is only allowed in a constructor implementation."
case 2462: // ts 3.2 "A rest element must be last in a destructuring pattern."
case 8017: // ts 3.2 "Octal literal types must use ES2015 syntax. Use the syntax '{0}'."
case 17012: // ts 3.2 "'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{2}'?"
case 17013: // ts 3.2 "Meta-property '{0}' is only allowed in the body of a function declaration, function expression, or constructor."
return true;
}
return false;
});
}
function convertDiagnosticToSemanticOrSyntacticError(
diagnostic: ts.Diagnostic,
): SemanticOrSyntacticError {
return {
...diagnostic,
message: ts.flattenDiagnosticMessageText(
diagnostic.messageText,
ts.sys.newLine,
),
};
}