Skip to content

Commit 4459730

Browse files
Give related error on declaration location for used-before-declared errors.
1 parent 7dc66e9 commit 4459730

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

src/compiler/checker.ts

+29-7
Original file line numberDiff line numberDiff line change
@@ -1655,18 +1655,34 @@ namespace ts {
16551655
if (declaration === undefined) return Debug.fail("Declaration to checkResolvedBlockScopedVariable is undefined");
16561656

16571657
if (!(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) {
1658+
let err;
1659+
const declarationName = declarationNameToString(getNameOfDeclaration(declaration));
16581660
if (result.flags & SymbolFlags.BlockScopedVariable) {
1659-
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration)));
1661+
err = error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationName);
16601662
}
16611663
else if (result.flags & SymbolFlags.Class) {
1662-
error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration)));
1664+
err = error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationName);
16631665
}
16641666
else if (result.flags & SymbolFlags.RegularEnum) {
1665-
error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationNameToString(getNameOfDeclaration(declaration)));
1667+
err = error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationName);
1668+
}
1669+
else {
1670+
Debug.assert(!!(result.flags & SymbolFlags.ConstEnum));
1671+
}
1672+
1673+
if (err) {
1674+
placeRelatedSpanOnLaterDeclaration(declarationName, declaration, err);
16661675
}
16671676
}
16681677
}
16691678

1679+
function placeRelatedSpanOnLaterDeclaration(declarationName: string, declarationLocation: Declaration, diagnostic: Diagnostic) {
1680+
Debug.assert(!diagnostic.relatedInformation);
1681+
diagnostic.relatedInformation = [
1682+
createDiagnosticForNode(declarationLocation, Diagnostics._0_was_declared_here, declarationName)
1683+
];
1684+
}
1685+
16701686
/* Starting from 'initial' node walk up the parent chain until 'stopAt' node is reached.
16711687
* If at any point current node is equal to 'parent' node - return true.
16721688
* Return false if 'stopAt' node is reached or isFunctionLike(current) === true.
@@ -17460,16 +17476,22 @@ namespace ts {
1746017476
return;
1746117477
}
1746217478

17479+
let err;
17480+
const declarationName = idText(right);
1746317481
if (isInPropertyInitializer(node) &&
1746417482
!isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)
1746517483
&& !isPropertyDeclaredInAncestorClass(prop)) {
17466-
error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, idText(right));
17484+
err = error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationName);
1746717485
}
1746817486
else if (valueDeclaration.kind === SyntaxKind.ClassDeclaration &&
1746917487
node.parent.kind !== SyntaxKind.TypeReference &&
1747017488
!(valueDeclaration.flags & NodeFlags.Ambient) &&
1747117489
!isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)) {
17472-
error(right, Diagnostics.Class_0_used_before_its_declaration, idText(right));
17490+
err = error(right, Diagnostics.Class_0_used_before_its_declaration, declarationName);
17491+
}
17492+
17493+
if (err) {
17494+
placeRelatedSpanOnLaterDeclaration(declarationName, valueDeclaration, err);
1747317495
}
1747417496
}
1747517497

@@ -19083,8 +19105,8 @@ namespace ts {
1908319105
if (importNode && !isImportCall(importNode)) {
1908419106
const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target!), kind);
1908519107
if (!sigs || !sigs.length) return;
19086-
diagnostic.relatedInformation = diagnostic.relatedInformation || [];
19087-
diagnostic.relatedInformation.push(createDiagnosticForNode(importNode, Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead));
19108+
Debug.assert(!diagnostic.relatedInformation);
19109+
diagnostic.relatedInformation = [createDiagnosticForNode(importNode, Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead)];
1908819110
}
1908919111
}
1909019112

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -2397,6 +2397,10 @@
23972397
"category": "Error",
23982398
"code": 2727
23992399
},
2400+
"'{0}' was declared here.": {
2401+
"category": "Error",
2402+
"code": 2728
2403+
},
24002404

24012405
"Import declaration '{0}' is using private name '{1}'.": {
24022406
"category": "Error",

0 commit comments

Comments
 (0)