From dda4bd0d0b47bac0edf2c2626c0ccffb67e22b30 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 21 Feb 2018 10:03:02 -0800 Subject: [PATCH] fixClassDoesnotImplementInheritedAbstractMember: Don't perform fix for same class twice (#22073) --- ...ssDoesntImplementInheritedAbstractMember.ts | 18 +++++++++++------- .../fixClassIncorrectlyImplementsInterface.ts | 4 +--- .../codeFixClassExtendAbstractMethod_all.ts | 8 ++++++++ .../codeFixClassImplementInterface_all.ts | 1 - 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts index da3685339ab..786d61d798d 100644 --- a/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts +++ b/src/services/codefixes/fixClassDoesntImplementInheritedAbstractMember.ts @@ -14,18 +14,22 @@ namespace ts.codefix { return changes.length === 0 ? undefined : [{ description: getLocaleSpecificMessage(Diagnostics.Implement_inherited_abstract_class), changes, fixId }]; }, fixIds: [fixId], - getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => { - addMissingMembers(getClass(diag.file!, diag.start!), context.sourceFile, context.program.getTypeChecker(), changes); - }), + getAllCodeActions: context => { + const seenClassDeclarations = createMap(); + return codeFixAll(context, errorCodes, (changes, diag) => { + const classDeclaration = getClass(diag.file!, diag.start!); + if (addToSeen(seenClassDeclarations, getNodeId(classDeclaration))) { + addMissingMembers(classDeclaration, context.sourceFile, context.program.getTypeChecker(), changes); + } + }); + }, }); function getClass(sourceFile: SourceFile, pos: number): ClassLikeDeclaration { - // This is the identifier in the case of a class declaration + // Token is the identifier in the case of a class declaration // or the class keyword token in the case of a class expression. const token = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); - const classDeclaration = token.parent; - Debug.assert(isClassLike(classDeclaration)); - return classDeclaration as ClassLikeDeclaration; + return cast(token.parent, isClassLike); } function addMissingMembers(classDeclaration: ClassLikeDeclaration, sourceFile: SourceFile, checker: TypeChecker, changeTracker: textChanges.ChangeTracker): void { diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 0236b0c79b7..c295d4fb3c7 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -31,9 +31,7 @@ namespace ts.codefix { }); function getClass(sourceFile: SourceFile, pos: number): ClassLikeDeclaration { - const classDeclaration = getContainingClass(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false)); - Debug.assert(!!classDeclaration); - return classDeclaration!; + return Debug.assertDefined(getContainingClass(getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false))); } function addMissingDeclarations( diff --git a/tests/cases/fourslash/codeFixClassExtendAbstractMethod_all.ts b/tests/cases/fourslash/codeFixClassExtendAbstractMethod_all.ts index 9521173ad89..b158a215ca1 100644 --- a/tests/cases/fourslash/codeFixClassExtendAbstractMethod_all.ts +++ b/tests/cases/fourslash/codeFixClassExtendAbstractMethod_all.ts @@ -2,6 +2,7 @@ ////abstract class A { //// abstract m(): void; +//// abstract n(): void; ////} ////class B extends A {} ////class C extends A {} @@ -11,15 +12,22 @@ verify.codeFixAll({ newFileContent: `abstract class A { abstract m(): void; + abstract n(): void; } class B extends A { m(): void { throw new Error("Method not implemented."); } + n(): void { + throw new Error("Method not implemented."); + } } class C extends A { m(): void { throw new Error("Method not implemented."); } + n(): void { + throw new Error("Method not implemented."); + } }`, }); diff --git a/tests/cases/fourslash/codeFixClassImplementInterface_all.ts b/tests/cases/fourslash/codeFixClassImplementInterface_all.ts index cc27e395ed7..ae70d6fb422 100644 --- a/tests/cases/fourslash/codeFixClassImplementInterface_all.ts +++ b/tests/cases/fourslash/codeFixClassImplementInterface_all.ts @@ -7,7 +7,6 @@ verify.codeFixAll({ fixId: "fixClassIncorrectlyImplementsInterface", - // TODO: GH#20073 newFileContent: `interface I { i(): void; } interface J { j(): void; }