Skip to content

Commit 4648d6a

Browse files
committed
Revise error messages + related spans + no errors on never-returning functions
1 parent a13f862 commit 4648d6a

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

src/compiler/checker.ts

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17191,30 +17191,38 @@ namespace ts {
1719117191
getEffectiveTypeAnnotationNode(declaration as VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature));
1719217192
}
1719317193

17194-
function getExplicitTypeOfSymbol(symbol: Symbol) {
17195-
return symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.ValueModule) ||
17196-
symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property) && isDeclarationWithExplicitTypeAnnotation(symbol.valueDeclaration) ?
17197-
getTypeOfSymbol(symbol) : undefined;
17194+
function getExplicitTypeOfSymbol(symbol: Symbol, diagnostic?: Diagnostic) {
17195+
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.ValueModule)) {
17196+
return getTypeOfSymbol(symbol);
17197+
}
17198+
if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) {
17199+
if (isDeclarationWithExplicitTypeAnnotation(symbol.valueDeclaration)) {
17200+
return getTypeOfSymbol(symbol);
17201+
}
17202+
if (diagnostic && symbol.valueDeclaration) {
17203+
addRelatedInfo(diagnostic, createDiagnosticForNode(symbol.valueDeclaration, Diagnostics._0_is_declared_here, symbolToString(symbol)));
17204+
}
17205+
}
1719817206
}
1719917207

1720017208
// We require the dotted function name in an assertion expression to be comprised of identifiers
1720117209
// that reference function, method, class or value module symbols; or variable, property or
1720217210
// parameter symbols with declarations that have explicit type annotations. Such references are
1720317211
// resolvable with no possibility of triggering circularities in control flow analysis.
17204-
function getTypeOfDottedName(node: Expression): Type | undefined {
17212+
function getTypeOfDottedName(node: Expression, diagnostic: Diagnostic | undefined): Type | undefined {
1720517213
if (!(node.flags & NodeFlags.InWithStatement)) {
1720617214
switch (node.kind) {
1720717215
case SyntaxKind.Identifier:
1720817216
const symbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(<Identifier>node));
17209-
return getExplicitTypeOfSymbol(symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol);
17217+
return getExplicitTypeOfSymbol(symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol, diagnostic);
1721017218
case SyntaxKind.ThisKeyword:
1721117219
return getExplicitThisType(node);
1721217220
case SyntaxKind.PropertyAccessExpression:
17213-
const type = getTypeOfDottedName((<PropertyAccessExpression>node).expression);
17221+
const type = getTypeOfDottedName((<PropertyAccessExpression>node).expression, diagnostic);
1721417222
const prop = type && getPropertyOfType(type, (<PropertyAccessExpression>node).name.escapedText);
17215-
return prop && getExplicitTypeOfSymbol(prop);
17223+
return prop && getExplicitTypeOfSymbol(prop, diagnostic);
1721617224
case SyntaxKind.ParenthesizedExpression:
17217-
return getTypeOfDottedName((<ParenthesizedExpression>node).expression);
17225+
return getTypeOfDottedName((<ParenthesizedExpression>node).expression, diagnostic);
1721817226
}
1721917227
}
1722017228
}
@@ -17227,7 +17235,7 @@ namespace ts {
1722717235
// expressions are potential type predicate function calls. In order to avoid triggering
1722817236
// circularities in control flow analysis, we use getTypeOfDottedName when resolving the call
1722917237
// target expression of an assertion.
17230-
const funcType = node.parent.kind === SyntaxKind.ExpressionStatement ? getTypeOfDottedName(node.expression) :
17238+
const funcType = node.parent.kind === SyntaxKind.ExpressionStatement ? getTypeOfDottedName(node.expression, /*diagnostic*/ undefined) :
1723117239
node.expression.kind !== SyntaxKind.SuperKeyword ? checkNonNullExpression(node.expression) :
1723217240
undefined;
1723317241
const signatures = getSignaturesOfType(funcType && getApparentType(funcType) || unknownType, SignatureKind.Call);
@@ -23417,12 +23425,13 @@ namespace ts {
2341723425
return getESSymbolLikeTypeForNode(walkUpParenthesizedExpressions(node.parent));
2341823426
}
2341923427
if (node.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.ExpressionStatement &&
23420-
returnType.flags & (TypeFlags.Void | TypeFlags.Never) && hasTypePredicateOrNeverReturnType(signature)) {
23428+
returnType.flags & TypeFlags.Void && getTypePredicateOfSignature(signature)) {
2342123429
if (!isDottedName(node.expression)) {
23422-
error(node.expression, Diagnostics.Control_flow_effects_of_calls_to_assertion_and_never_returning_functions_are_reflected_only_when_the_function_expression_is_an_identifier_or_qualified_name);
23430+
error(node.expression, Diagnostics.Assertions_require_the_call_target_to_be_an_identifier_or_qualified_name);
2342323431
}
2342423432
else if (!getEffectsSignature(node)) {
23425-
error(node.expression, Diagnostics.Control_flow_effects_of_calls_to_assertion_and_never_returning_functions_are_reflected_only_when_every_variable_or_property_referenced_in_the_function_expression_is_declared_with_an_explicit_type_annotation);
23433+
const diagnostic = error(node.expression, Diagnostics.Assertions_require_every_name_in_the_call_target_to_be_declared_with_an_explicit_type_annotation);
23434+
getTypeOfDottedName(node.expression, diagnostic);
2342623435
}
2342723436
}
2342823437
let jsAssignmentType: Type | undefined;

src/compiler/diagnosticMessages.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2726,11 +2726,11 @@
27262726
"category": "Error",
27272727
"code": 2774
27282728
},
2729-
"Control flow effects of calls to assertion and never-returning functions are reflected only when every variable or property referenced in the function expression is declared with an explicit type annotation.": {
2729+
"Assertions require every name in the call target to be declared with an explicit type annotation.": {
27302730
"category": "Error",
27312731
"code": 2775
27322732
},
2733-
"Control flow effects of calls to assertion and never-returning functions are reflected only when the function expression is an identifier or qualified-name.": {
2733+
"Assertions require the call target to be an identifier or qualified-name.": {
27342734
"category": "Error",
27352735
"code": 2776
27362736
},

0 commit comments

Comments
 (0)