@@ -606,6 +606,7 @@ namespace ts {
606
606
getAllPossiblePropertiesOfTypes,
607
607
getSuggestedSymbolForNonexistentProperty,
608
608
getSuggestionForNonexistentProperty,
609
+ getSuggestedSymbolForNonexistentJSXAttribute,
609
610
getSuggestedSymbolForNonexistentSymbol: (location, name, meaning) => getSuggestedSymbolForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning),
610
611
getSuggestionForNonexistentSymbol: (location, name, meaning) => getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning),
611
612
getSuggestedSymbolForNonexistentModule,
@@ -24852,7 +24853,7 @@ namespace ts {
24852
24853
relatedInfo = createDiagnosticForNode(propNode, Diagnostics.Did_you_forget_to_use_await);
24853
24854
}
24854
24855
else {
24855
- const suggestion = getSuggestedSymbolForNonexistentProperty(propNode, containingType, /*isJsxAttr*/ false );
24856
+ const suggestion = getSuggestedSymbolForNonexistentProperty(propNode, containingType);
24856
24857
if (suggestion !== undefined) {
24857
24858
const suggestedName = symbolName(suggestion);
24858
24859
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, declarationNameToString(propNode), typeToString(containingType), suggestedName);
@@ -24875,12 +24876,24 @@ namespace ts {
24875
24876
return prop !== undefined && prop.valueDeclaration && hasSyntacticModifier(prop.valueDeclaration, ModifierFlags.Static);
24876
24877
}
24877
24878
24878
- function getSuggestedSymbolForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type, isJsxAttr: boolean ): Symbol | undefined {
24879
- return getSpellingSuggestionForName(isString(name) ? name : idText(name), getPropertiesOfType(containingType), SymbolFlags.Value, isJsxAttr );
24879
+ function getSuggestedSymbolForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type): Symbol | undefined {
24880
+ return getSpellingSuggestionForName(isString(name) ? name : idText(name), getPropertiesOfType(containingType), SymbolFlags.Value);
24880
24881
}
24881
24882
24883
+ function getSuggestedSymbolForNonexistentJSXAttribute(name: Identifier | PrivateIdentifier | string, containingType: Type): Symbol | undefined {
24884
+ const strName = isString(name) ? name : idText(name);
24885
+ const properties = getPropertiesOfType(containingType);
24886
+ const defaultSuggestion = () => getSpellingSuggestionForName(strName, properties, SymbolFlags.Value);
24887
+ const getCandidate = (expectedName: string) => properties.find(x => symbolName(x) === expectedName);
24888
+ switch (strName) {
24889
+ case "for": return getCandidate("htmlFor") || defaultSuggestion();
24890
+ case "class": return getCandidate("className") || defaultSuggestion();
24891
+ }
24892
+ return defaultSuggestion();
24893
+ }
24894
+
24882
24895
function getSuggestionForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type, isJsxAttr: boolean): string | undefined {
24883
- const suggestion = getSuggestedSymbolForNonexistentProperty(name, containingType, isJsxAttr );
24896
+ const suggestion = (isJsxAttr ? getSuggestedSymbolForNonexistentJSXAttribute : getSuggestedSymbolForNonexistentProperty) (name, containingType);
24884
24897
return suggestion && symbolName(suggestion);
24885
24898
}
24886
24899
@@ -24892,7 +24905,7 @@ namespace ts {
24892
24905
// Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function
24893
24906
// So the table *contains* `x` but `x` isn't actually in scope.
24894
24907
// However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion.
24895
- return symbol || getSpellingSuggestionForName(unescapeLeadingUnderscores(name), arrayFrom(symbols.values()), meaning, /*isJsxAttr*/ false );
24908
+ return symbol || getSpellingSuggestionForName(unescapeLeadingUnderscores(name), arrayFrom(symbols.values()), meaning);
24896
24909
});
24897
24910
return result;
24898
24911
}
@@ -24903,7 +24916,7 @@ namespace ts {
24903
24916
}
24904
24917
24905
24918
function getSuggestedSymbolForNonexistentModule(name: Identifier, targetModule: Symbol): Symbol | undefined {
24906
- return targetModule.exports && getSpellingSuggestionForName(idText(name), getExportsOfModuleAsArray(targetModule), SymbolFlags.ModuleMember, /*isJsxAttr*/ false );
24919
+ return targetModule.exports && getSpellingSuggestionForName(idText(name), getExportsOfModuleAsArray(targetModule), SymbolFlags.ModuleMember);
24907
24920
}
24908
24921
24909
24922
function getSuggestionForNonexistentExport(name: Identifier, targetModule: Symbol): string | undefined {
@@ -24953,8 +24966,8 @@ namespace ts {
24953
24966
* (0.4 allows 1 substitution/transposition for every 5 characters,
24954
24967
* and 1 insertion/deletion at 3 characters)
24955
24968
*/
24956
- function getSpellingSuggestionForName(name: string, symbols: Symbol[], meaning: SymbolFlags, isJsxAttr: boolean ): Symbol | undefined {
24957
- return getSpellingSuggestion(name, symbols, getCandidateName, isJsxAttr );
24969
+ function getSpellingSuggestionForName(name: string, symbols: Symbol[], meaning: SymbolFlags): Symbol | undefined {
24970
+ return getSpellingSuggestion(name, symbols, getCandidateName);
24958
24971
function getCandidateName(candidate: Symbol) {
24959
24972
const candidateName = symbolName(candidate);
24960
24973
if (startsWith(candidateName, "\"")) {
0 commit comments