mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 02:33:53 -06:00
feat(44263): add quick fix for misspelled override error (#44266)
This commit is contained in:
parent
703c1bc69d
commit
591be7bece
@ -635,6 +635,7 @@ namespace ts {
|
||||
getSuggestionForNonexistentSymbol: (location, name, meaning) => getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning),
|
||||
getSuggestedSymbolForNonexistentModule,
|
||||
getSuggestionForNonexistentExport,
|
||||
getSuggestedSymbolForNonexistentClassMember,
|
||||
getBaseConstraintOfType,
|
||||
getDefaultFromTypeParameter: type => type && type.flags & TypeFlags.TypeParameter ? getDefaultFromTypeParameter(type as TypeParameter) : undefined,
|
||||
resolveName(name, location, meaning, excludeGlobals) {
|
||||
@ -27720,6 +27721,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getSuggestedSymbolForNonexistentClassMember(name: string, baseType: Type): Symbol | undefined {
|
||||
return getSpellingSuggestionForName(name, arrayFrom(getMembersOfSymbol(baseType.symbol).values()), SymbolFlags.ClassMember);
|
||||
}
|
||||
|
||||
function getSuggestedSymbolForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type): Symbol | undefined {
|
||||
let props = getPropertiesOfType(containingType);
|
||||
if (typeof name !== "string") {
|
||||
@ -27739,7 +27744,7 @@ namespace ts {
|
||||
: strName === "class" ? find(properties, x => symbolName(x) === "className")
|
||||
: undefined;
|
||||
return jsxSpecific ?? getSpellingSuggestionForName(strName, properties, SymbolFlags.Value);
|
||||
}
|
||||
}
|
||||
|
||||
function getSuggestionForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type): string | undefined {
|
||||
const suggestion = getSuggestedSymbolForNonexistentProperty(name, containingType);
|
||||
@ -37346,7 +37351,7 @@ namespace ts {
|
||||
|
||||
const baseClassName = typeToString(baseWithThis);
|
||||
if (prop && !baseProp && hasOverride) {
|
||||
const suggestion = getSpellingSuggestionForName(symbolName(declaredProp), arrayFrom(getMembersOfSymbol(baseType.symbol).values()), SymbolFlags.ClassMember);
|
||||
const suggestion = getSuggestedSymbolForNonexistentClassMember(symbolName(declaredProp), baseType);
|
||||
suggestion ?
|
||||
error(member, Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1, baseClassName, symbolToString(suggestion)) :
|
||||
error(member, Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0, baseClassName);
|
||||
|
||||
@ -4218,6 +4218,7 @@ namespace ts {
|
||||
/* @internal */ getSuggestedSymbolForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined;
|
||||
/* @internal */ getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined;
|
||||
/* @internal */ getSuggestedSymbolForNonexistentModule(node: Identifier, target: Symbol): Symbol | undefined;
|
||||
/* @internal */ getSuggestedSymbolForNonexistentClassMember(name: string, baseType: Type): Symbol | undefined;
|
||||
/* @internal */ getSuggestionForNonexistentExport(node: Identifier, target: Symbol): string | undefined;
|
||||
getBaseConstraintOfType(type: Type): Type | undefined;
|
||||
getDefaultFromTypeParameter(type: Type): Type | undefined;
|
||||
|
||||
@ -7,6 +7,7 @@ namespace ts.codefix {
|
||||
Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code,
|
||||
Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0.code,
|
||||
Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2.code,
|
||||
Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1.code,
|
||||
// for JSX class components
|
||||
Diagnostics.No_overload_matches_this_call.code,
|
||||
// for JSX FC
|
||||
@ -73,6 +74,14 @@ namespace ts.codefix {
|
||||
const props = checker.getContextualTypeForArgumentAtIndex(tag, 0);
|
||||
suggestedSymbol = checker.getSuggestedSymbolForNonexistentJSXAttribute(node, props!);
|
||||
}
|
||||
else if (hasSyntacticModifier(parent, ModifierFlags.Override) && isClassElement(parent) && parent.name === node) {
|
||||
const baseDeclaration = findAncestor(node, isClassLike);
|
||||
const baseTypeNode = baseDeclaration ? getEffectiveBaseTypeNode(baseDeclaration) : undefined;
|
||||
const baseType = baseTypeNode ? checker.getTypeAtLocation(baseTypeNode) : undefined;
|
||||
if (baseType) {
|
||||
suggestedSymbol = checker.getSuggestedSymbolForNonexistentClassMember(getTextOfNode(node), baseType);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const meaning = getMeaningFromLocation(node);
|
||||
const name = getTextOfNode(node);
|
||||
|
||||
15
tests/baselines/reference/override_js4.errors.txt
Normal file
15
tests/baselines/reference/override_js4.errors.txt
Normal file
@ -0,0 +1,15 @@
|
||||
tests/cases/conformance/override/a.js(7,5): error TS4117: This member cannot have an 'override' modifier because it is not declared in the base class 'A'. Did you mean 'doSomething'?
|
||||
|
||||
|
||||
==== tests/cases/conformance/override/a.js (1 errors) ====
|
||||
class A {
|
||||
doSomething() {}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
/** @override */
|
||||
doSomethang() {}
|
||||
~~~~~~~~~~~
|
||||
!!! error TS4117: This member cannot have an 'override' modifier because it is not declared in the base class 'A'. Did you mean 'doSomething'?
|
||||
}
|
||||
|
||||
17
tests/baselines/reference/override_js4.symbols
Normal file
17
tests/baselines/reference/override_js4.symbols
Normal file
@ -0,0 +1,17 @@
|
||||
=== tests/cases/conformance/override/a.js ===
|
||||
class A {
|
||||
>A : Symbol(A, Decl(a.js, 0, 0))
|
||||
|
||||
doSomething() {}
|
||||
>doSomething : Symbol(A.doSomething, Decl(a.js, 0, 9))
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
>B : Symbol(B, Decl(a.js, 2, 1))
|
||||
>A : Symbol(A, Decl(a.js, 0, 0))
|
||||
|
||||
/** @override */
|
||||
doSomethang() {}
|
||||
>doSomethang : Symbol(B.doSomethang, Decl(a.js, 4, 19))
|
||||
}
|
||||
|
||||
17
tests/baselines/reference/override_js4.types
Normal file
17
tests/baselines/reference/override_js4.types
Normal file
@ -0,0 +1,17 @@
|
||||
=== tests/cases/conformance/override/a.js ===
|
||||
class A {
|
||||
>A : A
|
||||
|
||||
doSomething() {}
|
||||
>doSomething : () => void
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
>B : B
|
||||
>A : A
|
||||
|
||||
/** @override */
|
||||
doSomethang() {}
|
||||
>doSomethang : () => void
|
||||
}
|
||||
|
||||
14
tests/cases/conformance/override/override_js4.ts
Normal file
14
tests/cases/conformance/override/override_js4.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// @noImplicitOverride: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noEmit: true
|
||||
|
||||
// @Filename: a.js
|
||||
class A {
|
||||
doSomething() {}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
/** @override */
|
||||
doSomethang() {}
|
||||
}
|
||||
16
tests/cases/fourslash/codeFixSpelling10.ts
Normal file
16
tests/cases/fourslash/codeFixSpelling10.ts
Normal file
@ -0,0 +1,16 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitOverride: true
|
||||
////class A {
|
||||
//// doSomething() {}
|
||||
////}
|
||||
////
|
||||
////class B extends A {
|
||||
//// override [|doSomethang|]() {}
|
||||
////}
|
||||
|
||||
verify.codeFix({
|
||||
index: 0,
|
||||
description: [ts.Diagnostics.Change_spelling_to_0.message, "doSomething"],
|
||||
newRangeContent: "doSomething"
|
||||
});
|
||||
15
tests/cases/fourslash/codeFixSpelling11.ts
Normal file
15
tests/cases/fourslash/codeFixSpelling11.ts
Normal file
@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitOverride: true
|
||||
////abstract class A {
|
||||
//// abstract doSomething(): void;
|
||||
////}
|
||||
////abstract class B extends A {
|
||||
//// abstract override [|doSomethang|](): number;
|
||||
////}
|
||||
|
||||
verify.codeFix({
|
||||
index: 0,
|
||||
description: [ts.Diagnostics.Change_spelling_to_0.message, "doSomething"],
|
||||
newRangeContent: "doSomething"
|
||||
});
|
||||
20
tests/cases/fourslash/codeFixSpelling12.ts
Normal file
20
tests/cases/fourslash/codeFixSpelling12.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noImplicitOverride: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
|
||||
// @Filename: a.js
|
||||
////class A {
|
||||
//// doSomething() {}
|
||||
////}
|
||||
////class B extends A {
|
||||
//// /** @override */
|
||||
//// [|doSomethang|]() {}
|
||||
////}
|
||||
|
||||
verify.codeFix({
|
||||
index: 0,
|
||||
description: [ts.Diagnostics.Change_spelling_to_0.message, "doSomething"],
|
||||
newRangeContent: "doSomething"
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user