@@ -295,7 +295,7 @@ namespace ts {
295295 getAllPossiblePropertiesOfTypes,
296296 getSuggestionForNonexistentProperty: (node, type) => getSuggestionForNonexistentProperty(node, type),
297297 getSuggestionForNonexistentSymbol: (location, name, meaning) => getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning),
298- getSuggestionForNonexistentModule : (node, target) => getSuggestionForNonexistentModule (node, target),
298+ getSuggestionForNonexistentExport : (node, target) => getSuggestionForNonexistentExport (node, target),
299299 getBaseConstraintOfType,
300300 getDefaultFromTypeParameter: type => type && type.flags & TypeFlags.TypeParameter ? getDefaultFromTypeParameter(type as TypeParameter) : undefined,
301301 resolveName(name, location, meaning, excludeGlobals) {
@@ -710,7 +710,7 @@ namespace ts {
710710 }
711711 }
712712
713- function addRelatedInfo(diagnostic: Diagnostic, ...relatedInformation: DiagnosticRelatedInformation[ ]) {
713+ function addRelatedInfo(diagnostic: Diagnostic, ...relatedInformation: [ DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[] ]) {
714714 if (!diagnostic.relatedInformation) {
715715 diagnostic.relatedInformation = [];
716716 }
@@ -1434,11 +1434,18 @@ namespace ts {
14341434 !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) &&
14351435 !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) &&
14361436 !checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning)) {
1437- let suggestion: string | undefined;
1437+ let suggestion: Symbol | undefined;
14381438 if (suggestedNameNotFoundMessage && suggestionCount < maximumSuggestionCount) {
1439- suggestion = getSuggestionForNonexistentSymbol (originalLocation, name, meaning);
1439+ suggestion = getSuggestedSymbolForNonexistentSymbol (originalLocation, name, meaning);
14401440 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+ }
14421449 }
14431450 }
14441451 if (!suggestion) {
@@ -1674,7 +1681,7 @@ namespace ts {
16741681
16751682 if (diagnosticMessage) {
16761683 addRelatedInfo(diagnosticMessage,
1677- createDiagnosticForNode(declaration, Diagnostics._0_was_declared_here , declarationName)
1684+ createDiagnosticForNode(declaration, Diagnostics._0_is_declared_here , declarationName)
16781685 );
16791686 }
16801687 }
@@ -1866,9 +1873,15 @@ namespace ts {
18661873 if (!symbol) {
18671874 const moduleName = getFullyQualifiedName(moduleSymbol);
18681875 const declarationName = declarationNameToString(name);
1869- const suggestion = getSuggestionForNonexistentModule (name, targetSymbol);
1876+ const suggestion = getSuggestedSymbolForNonexistentModule (name, targetSymbol);
18701877 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+ }
18721885 }
18731886 else {
18741887 error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName);
@@ -17676,7 +17689,7 @@ namespace ts {
1767617689
1767717690 if (diagnosticMessage) {
1767817691 addRelatedInfo(diagnosticMessage,
17679- createDiagnosticForNode(valueDeclaration, Diagnostics._0_was_declared_here , declarationName)
17692+ createDiagnosticForNode(valueDeclaration, Diagnostics._0_is_declared_here , declarationName)
1768017693 );
1768117694 }
1768217695 }
@@ -17726,6 +17739,7 @@ namespace ts {
1772617739
1772717740 function reportNonexistentProperty(propNode: Identifier, containingType: Type) {
1772817741 let errorInfo: DiagnosticMessageChain | undefined;
17742+ let relatedInfo: Diagnostic | undefined;
1772917743 if (containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) {
1773017744 for (const subtype of (containingType as UnionType).types) {
1773117745 if (!getPropertyOfType(subtype, propNode.escapedText)) {
@@ -17739,30 +17753,34 @@ namespace ts {
1773917753 errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_forget_to_use_await, declarationNameToString(propNode), typeToString(containingType));
1774017754 }
1774117755 else {
17742- const suggestion = getSuggestionForNonexistentProperty (propNode, containingType);
17756+ const suggestion = getSuggestedSymbolForNonexistentProperty (propNode, containingType);
1774317757 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);
1774517761 }
1774617762 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));
1775417764 }
1775517765 }
1775617766
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);
1775817776 }
1775917777
1776017778 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);
1776217780 return suggestion && symbolName(suggestion);
1776317781 }
1776417782
17765- function getSuggestionForNonexistentSymbol (location: Node | undefined, outerName: __String, meaning: SymbolFlags): string | undefined {
17783+ function getSuggestedSymbolForNonexistentSymbol (location: Node | undefined, outerName: __String, meaning: SymbolFlags): Symbol | undefined {
1776617784 Debug.assert(outerName !== undefined, "outername should always be defined");
1776717785 const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, (symbols, name, meaning) => {
1776817786 Debug.assertEqual(outerName, name, "name should equal outerName");
@@ -17772,11 +17790,20 @@ namespace ts {
1777217790 // However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion.
1777317791 return symbol || getSpellingSuggestionForName(unescapeLeadingUnderscores(name), arrayFrom(symbols.values()), meaning);
1777417792 });
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);
1777617803 }
1777717804
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);
1778017807 return suggestion && symbolName(suggestion);
1778117808 }
1778217809
0 commit comments