mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-27 13:42:16 -05:00
Merge pull request #24442 from Kingwl/fix-implement-interface-with-extends-class
add lookup for extends class when implement interface
This commit is contained in:
@@ -32,6 +32,10 @@ namespace ts.codefix {
|
||||
return Debug.assertDefined(getContainingClass(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false)));
|
||||
}
|
||||
|
||||
function symbolPointsToNonPrivateMember (symbol: Symbol) {
|
||||
return !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private);
|
||||
}
|
||||
|
||||
function addMissingDeclarations(
|
||||
checker: TypeChecker,
|
||||
implementedTypeNode: ExpressionWithTypeArguments,
|
||||
@@ -40,11 +44,12 @@ namespace ts.codefix {
|
||||
changeTracker: textChanges.ChangeTracker,
|
||||
preferences: UserPreferences,
|
||||
): void {
|
||||
const maybeHeritageClauseSymbol = getHeritageClauseSymbolTable(classDeclaration, checker);
|
||||
// Note that this is ultimately derived from a map indexed by symbol names,
|
||||
// so duplicates cannot occur.
|
||||
const implementedType = checker.getTypeAtLocation(implementedTypeNode) as InterfaceType;
|
||||
const implementedTypeSymbols = checker.getPropertiesOfType(implementedType);
|
||||
const nonPrivateMembers = implementedTypeSymbols.filter(symbol => !(getModifierFlags(symbol.valueDeclaration) & ModifierFlags.Private));
|
||||
const nonPrivateAndNotExistedInHeritageClauseMembers = implementedTypeSymbols.filter(and(symbolPointsToNonPrivateMember, symbol => !maybeHeritageClauseSymbol.has(symbol.escapedName)));
|
||||
|
||||
const classType = checker.getTypeAtLocation(classDeclaration)!;
|
||||
|
||||
@@ -55,7 +60,7 @@ namespace ts.codefix {
|
||||
createMissingIndexSignatureDeclaration(implementedType, IndexKind.String);
|
||||
}
|
||||
|
||||
createMissingMemberNodes(classDeclaration, nonPrivateMembers, checker, preferences, member => changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member));
|
||||
createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, checker, preferences, member => changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member));
|
||||
|
||||
function createMissingIndexSignatureDeclaration(type: InterfaceType, kind: IndexKind): void {
|
||||
const indexInfoOfKind = checker.getIndexInfoOfType(type, kind);
|
||||
@@ -64,4 +69,12 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getHeritageClauseSymbolTable (classDeclaration: ClassLikeDeclaration, checker: TypeChecker): SymbolTable {
|
||||
const heritageClauseNode = getClassExtendsHeritageClauseElement(classDeclaration);
|
||||
if (!heritageClauseNode) return createSymbolTable();
|
||||
const heritageClauseType = checker.getTypeAtLocation(heritageClauseNode) as InterfaceType;
|
||||
const heritageClauseTypeSymbols = checker.getPropertiesOfType(heritageClauseType);
|
||||
return createSymbolTable(heritageClauseTypeSymbols.filter(symbolPointsToNonPrivateMember));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
//// class Base {
|
||||
//// foo: number;
|
||||
//// }
|
||||
////
|
||||
//// class D extends Base {
|
||||
//// bar: number;
|
||||
//// }
|
||||
////
|
||||
//// interface I {
|
||||
//// foo: number;
|
||||
//// bar: number;
|
||||
//// baz: number;
|
||||
//// }
|
||||
////
|
||||
//// class C extends D implements I { }
|
||||
|
||||
verify.codeFix({
|
||||
description: "Implement interface 'I'",
|
||||
newFileContent:
|
||||
`class Base {
|
||||
foo: number;
|
||||
}
|
||||
|
||||
class D extends Base {
|
||||
bar: number;
|
||||
}
|
||||
|
||||
interface I {
|
||||
foo: number;
|
||||
bar: number;
|
||||
baz: number;
|
||||
}
|
||||
|
||||
class C extends D implements I {
|
||||
baz: number;
|
||||
}`,
|
||||
});
|
||||
Reference in New Issue
Block a user