@@ -295,7 +295,7 @@ namespace ts {
295
295
getAllPossiblePropertiesOfTypes,
296
296
getSuggestionForNonexistentProperty: (node, type) => getSuggestionForNonexistentProperty(node, type),
297
297
getSuggestionForNonexistentSymbol: (location, name, meaning) => getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning),
298
- getSuggestionForNonexistentModule : (node, target) => getSuggestionForNonexistentModule (node, target),
298
+ getSuggestionForNonexistentExport : (node, target) => getSuggestionForNonexistentExport (node, target),
299
299
getBaseConstraintOfType,
300
300
getDefaultFromTypeParameter: type => type && type.flags & TypeFlags.TypeParameter ? getDefaultFromTypeParameter(type as TypeParameter) : undefined,
301
301
resolveName(name, location, meaning, excludeGlobals) {
@@ -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);
@@ -17676,7 +17689,7 @@ namespace ts {
17676
17689
17677
17690
if (diagnosticMessage) {
17678
17691
addRelatedInfo(diagnosticMessage,
17679
- createDiagnosticForNode(valueDeclaration, Diagnostics._0_was_declared_here , declarationName)
17692
+ createDiagnosticForNode(valueDeclaration, Diagnostics._0_is_declared_here , declarationName)
17680
17693
);
17681
17694
}
17682
17695
}
@@ -17726,6 +17739,7 @@ namespace ts {
17726
17739
17727
17740
function reportNonexistentProperty(propNode: Identifier, containingType: Type) {
17728
17741
let errorInfo: DiagnosticMessageChain | undefined;
17742
+ let relatedInfo: Diagnostic | undefined;
17729
17743
if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) {
17730
17744
for (const subtype of (containingType as UnionType).types) {
17731
17745
if (!getPropertyOfType(subtype, propNode.escapedText)) {
@@ -17739,30 +17753,34 @@ namespace ts {
17739
17753
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_forget_to_use_await, declarationNameToString(propNode), typeToString(containingType));
17740
17754
}
17741
17755
else {
17742
- const suggestion = getSuggestionForNonexistentProperty (propNode, containingType);
17756
+ const suggestion = getSuggestedSymbolForNonexistentProperty (propNode, containingType);
17743
17757
if (suggestion !== undefined) {
17744
- errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
17758
+ const suggestedName = symbolName(suggestion);
17759
+ errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestedName);
17760
+ relatedInfo = suggestion.valueDeclaration && createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestedName);
17745
17761
}
17746
17762
else {
17747
- const suggestion = getSuggestionForNonexistentProperty(propNode, containingType);
17748
- if (suggestion !== undefined) {
17749
- errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestion);
17750
- }
17751
- else {
17752
- errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
17753
- }
17763
+ errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType));
17754
17764
}
17755
17765
}
17756
17766
17757
- diagnostics.add(createDiagnosticForNodeFromMessageChain(propNode, errorInfo));
17767
+ const resultDiagnostic = createDiagnosticForNodeFromMessageChain(propNode, errorInfo);
17768
+ if (relatedInfo) {
17769
+ addRelatedInfo(resultDiagnostic, relatedInfo);
17770
+ }
17771
+ diagnostics.add(resultDiagnostic);
17772
+ }
17773
+
17774
+ function getSuggestedSymbolForNonexistentProperty(name: Identifier | string, containingType: Type): Symbol | undefined {
17775
+ return getSpellingSuggestionForName(isString(name) ? name : idText(name), getPropertiesOfType(containingType), SymbolFlags.Value);
17758
17776
}
17759
17777
17760
17778
function getSuggestionForNonexistentProperty(name: Identifier | string, containingType: Type): string | undefined {
17761
- const suggestion = getSpellingSuggestionForName(isString( name) ? name : idText(name), getPropertiesOfType( containingType), SymbolFlags.Value );
17779
+ const suggestion = getSuggestedSymbolForNonexistentProperty( name, containingType);
17762
17780
return suggestion && symbolName(suggestion);
17763
17781
}
17764
17782
17765
- function getSuggestionForNonexistentSymbol (location: Node | undefined, outerName: __String, meaning: SymbolFlags): string | undefined {
17783
+ function getSuggestedSymbolForNonexistentSymbol (location: Node | undefined, outerName: __String, meaning: SymbolFlags): Symbol | undefined {
17766
17784
Debug.assert(outerName !== undefined, "outername should always be defined");
17767
17785
const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, (symbols, name, meaning) => {
17768
17786
Debug.assertEqual(outerName, name, "name should equal outerName");
@@ -17772,11 +17790,20 @@ namespace ts {
17772
17790
// However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion.
17773
17791
return symbol || getSpellingSuggestionForName(unescapeLeadingUnderscores(name), arrayFrom(symbols.values()), meaning);
17774
17792
});
17775
- return result && symbolName(result);
17793
+ return result;
17794
+ }
17795
+
17796
+ function getSuggestionForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): string | undefined {
17797
+ const symbolResult = getSuggestedSymbolForNonexistentSymbol(location, outerName, meaning);
17798
+ return symbolResult && symbolName(symbolResult);
17799
+ }
17800
+
17801
+ function getSuggestedSymbolForNonexistentModule(name: Identifier, targetModule: Symbol): Symbol | undefined {
17802
+ return targetModule.exports && getSpellingSuggestionForName(idText(name), getExportsOfModuleAsArray(targetModule), SymbolFlags.ModuleMember);
17776
17803
}
17777
17804
17778
- function getSuggestionForNonexistentModule (name: Identifier, targetModule: Symbol): string | undefined {
17779
- const suggestion = targetModule.exports && getSpellingSuggestionForName(idText( name), getExportsOfModuleAsArray( targetModule), SymbolFlags.ModuleMember );
17805
+ function getSuggestionForNonexistentExport (name: Identifier, targetModule: Symbol): string | undefined {
17806
+ const suggestion = getSuggestedSymbolForNonexistentModule( name, targetModule);
17780
17807
return suggestion && symbolName(suggestion);
17781
17808
}
17782
17809
0 commit comments