@@ -710,7 +710,7 @@ namespace ts {
710
710
}
711
711
}
712
712
713
- function addRelatedInfo(diagnostic: Diagnostic, ...relatedInformation: DiagnosticRelatedInformation[ ]) {
713
+ function addRelatedInfo(diagnostic: Diagnostic, ...relatedInformation: [ DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[] ]) {
714
714
if (!diagnostic.relatedInformation) {
715
715
diagnostic.relatedInformation = [];
716
716
}
@@ -1434,11 +1434,18 @@ namespace ts {
1434
1434
!checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) &&
1435
1435
!checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) &&
1436
1436
!checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning)) {
1437
- let suggestion: string | undefined;
1437
+ let suggestion: Symbol | undefined;
1438
1438
if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) {
1439
- suggestion = getSuggestionForNonexistentSymbol (originalLocation, name, meaning);
1439
+ suggestion = getSuggestedSymbolForNonexistentSymbol (originalLocation, name, meaning);
1440
1440
if (suggestion) {
1441
- error(errorLocation, suggestedNameNotFoundMessage, diagnosticName(nameArg!), suggestion);
1441
+ const suggestionName = symbolToString(suggestion);
1442
+ const diagnostic = error(errorLocation, suggestedNameNotFoundMessage, diagnosticName(nameArg!), suggestionName);
1443
+ if (suggestion.valueDeclaration) {
1444
+ addRelatedInfo(
1445
+ diagnostic,
1446
+ createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName)
1447
+ );
1448
+ }
1442
1449
}
1443
1450
}
1444
1451
if (!suggestion) {
@@ -1674,7 +1681,7 @@ namespace ts {
1674
1681
1675
1682
if (diagnosticMessage) {
1676
1683
addRelatedInfo(diagnosticMessage,
1677
- createDiagnosticForNode(declaration, Diagnostics._0_was_declared_here , declarationName)
1684
+ createDiagnosticForNode(declaration, Diagnostics._0_is_declared_here , declarationName)
1678
1685
);
1679
1686
}
1680
1687
}
@@ -1866,9 +1873,15 @@ namespace ts {
1866
1873
if (!symbol) {
1867
1874
const moduleName = getFullyQualifiedName(moduleSymbol);
1868
1875
const declarationName = declarationNameToString(name);
1869
- const suggestion = getSuggestionForNonexistentModule (name, targetSymbol);
1876
+ const suggestion = getSuggestedSymbolForNonexistentModule (name, targetSymbol);
1870
1877
if (suggestion !== undefined) {
1871
- error(name, Diagnostics.Module_0_has_no_exported_member_1_Did_you_mean_2, moduleName, declarationName, suggestion);
1878
+ const suggestionName = symbolToString(suggestion);
1879
+ const diagnostic = error(name, Diagnostics.Module_0_has_no_exported_member_1_Did_you_mean_2, moduleName, declarationName, suggestionName);
1880
+ if (suggestion.valueDeclaration) {
1881
+ addRelatedInfo(diagnostic,
1882
+ createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName)
1883
+ );
1884
+ }
1872
1885
}
1873
1886
else {
1874
1887
error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName);
@@ -17661,7 +17674,7 @@ namespace ts {
17661
17674
17662
17675
if (diagnosticMessage) {
17663
17676
addRelatedInfo(diagnosticMessage,
17664
- createDiagnosticForNode(valueDeclaration, Diagnostics._0_was_declared_here , declarationName)
17677
+ createDiagnosticForNode(valueDeclaration, Diagnostics._0_is_declared_here , declarationName)
17665
17678
);
17666
17679
}
17667
17680
}
@@ -17711,6 +17724,7 @@ namespace ts {
17711
17724
17712
17725
function reportNonexistentProperty(propNode: Identifier, containingType: Type) {
17713
17726
let errorInfo: DiagnosticMessageChain | undefined;
17727
+ let relatedInfo: Diagnostic | undefined;
17714
17728
if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) {
17715
17729
for (const subtype of (containingType as UnionType).types) {
17716
17730
if (!getPropertyOfType(subtype, propNode.escapedText)) {
@@ -17724,30 +17738,34 @@ namespace ts {
17724
17738
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_forget_to_use_await, declarationNameToString(propNode), typeToString(containingType));
17725
17739
}
17726
17740
else {
17727
- const suggestion = getSuggestionForNonexistentProperty (propNode, containingType);
17741
+ const suggestion = getSuggestedSymbolForNonexistentProperty (propNode, containingType);
17728
17742
if (suggestion !== undefined) {
17729
- errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
17743
+ const suggestedName = symbolName(suggestion);
17744
+ errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestedName);
17745
+ relatedInfo = suggestion.valueDeclaration && createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestedName);
17730
17746
}
17731
17747
else {
17732
- const suggestion = getSuggestionForNonexistentProperty(propNode, containingType);
17733
- if (suggestion !== undefined) {
17734
- errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
17735
- }
17736
- else {
17737
- errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
17738
- }
17748
+ errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
17739
17749
}
17740
17750
}
17741
17751
17742
- diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo));
17752
+ const resultDiagnostic = createDiagnosticForNodeFromMessageChain(propNode, errorInfo);
17753
+ if (relatedInfo) {
17754
+ addRelatedInfo(resultDiagnostic, relatedInfo);
17755
+ }
17756
+ diagnostics.add(resultDiagnostic);
17757
+ }
17758
+
17759
+ function getSuggestedSymbolForNonexistentProperty(name: Identifier | string, containingType: Type): Symbol | undefined {
17760
+ return getSpellingSuggestionForName(isString(name) ? name : idText(name), getPropertiesOfType(containingType), SymbolFlags.Value);
17743
17761
}
17744
17762
17745
17763
function getSuggestionForNonexistentProperty(name: Identifier | string, containingType: Type): string | undefined {
17746
- const suggestion = getSpellingSuggestionForName(isString( name) ? name : idText(name), getPropertiesOfType( containingType), SymbolFlags.Value );
17764
+ const suggestion = getSuggestedSymbolForNonexistentProperty( name, containingType);
17747
17765
return suggestion && symbolName(suggestion);
17748
17766
}
17749
17767
17750
- function getSuggestionForNonexistentSymbol (location: Node | undefined, outerName: __String, meaning: SymbolFlags): string | undefined {
17768
+ function getSuggestedSymbolForNonexistentSymbol (location: Node | undefined, outerName: __String, meaning: SymbolFlags): Symbol | undefined {
17751
17769
Debug.assert(outerName !== undefined, "outername should always be defined");
17752
17770
const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, (symbols, name, meaning) => {
17753
17771
Debug.assertEqual(outerName, name, "name should equal outerName");
@@ -17757,11 +17775,20 @@ namespace ts {
17757
17775
// However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion.
17758
17776
return symbol || getSpellingSuggestionForName(unescapeLeadingUnderscores(name), arrayFrom(symbols.values()), meaning);
17759
17777
});
17760
- return result && symbolName(result);
17778
+ return result;
17779
+ }
17780
+
17781
+ function getSuggestionForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): string | undefined {
17782
+ const symbolResult = getSuggestedSymbolForNonexistentSymbol(location, outerName, meaning);
17783
+ return symbolResult && symbolName(symbolResult)
17784
+ }
17785
+
17786
+ function getSuggestedSymbolForNonexistentModule(name: Identifier, targetModule: Symbol): Symbol | undefined {
17787
+ return targetModule.exports && getSpellingSuggestionForName(idText(name), getExportsOfModuleAsArray(targetModule), SymbolFlags.ModuleMember);
17761
17788
}
17762
17789
17763
17790
function getSuggestionForNonexistentModule(name: Identifier, targetModule: Symbol): string | undefined {
17764
- const suggestion = targetModule.exports && getSpellingSuggestionForName(idText( name), getExportsOfModuleAsArray( targetModule), SymbolFlags.ModuleMember );
17791
+ const suggestion = getSuggestedSymbolForNonexistentModule( name, targetModule);
17765
17792
return suggestion && symbolName(suggestion);
17766
17793
}
17767
17794
0 commit comments