diff --git a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts index 900b2c21720..7afbbbfd6a1 100644 --- a/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts +++ b/src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts @@ -2,73 +2,75 @@ namespace ts.codefix { registerCodeFix({ errorCodes: [Diagnostics.Class_0_incorrectly_implements_interface_1.code], - getCodeActions: (context: CodeFixContext) => { - const sourceFile = context.sourceFile; - const start = context.span.start; - const token = getTokenAtPosition(sourceFile, start); - const checker = context.program.getTypeChecker(); + getCodeActions: getActionForClassLikeIncorrectImplementsInterface + }); - const classDecl = getContainingClass(token); - if (!classDecl) { - return undefined; - } + function getActionForClassLikeIncorrectImplementsInterface(context: CodeFixContext): CodeAction[] | undefined { + const sourceFile = context.sourceFile; + const start = context.span.start; + const token = getTokenAtPosition(sourceFile, start); + const checker = context.program.getTypeChecker(); - const startPos: number = classDecl.members.pos; - const classType = checker.getTypeAtLocation(classDecl); - const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl); - const result: CodeAction[] = []; + const classDecl = getContainingClass(token); + if (!classDecl) { + return undefined; + } - const hasNumericIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.Number); - const hasStringIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.String); + const startPos: number = classDecl.members.pos; + const classType = checker.getTypeAtLocation(classDecl); + const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl); - for (const implementedTypeNode of implementedTypeNodes) { - const implementedType = checker.getTypeFromTypeReference(implementedTypeNode) as InterfaceType; - // Note that this is ultimately derived from a map indexed by symbol names, - // so duplicates cannot occur. - const implementedTypeSymbols = checker.getPropertiesOfType(implementedType); - const nonPrivateMembers = implementedTypeSymbols.filter(symbolRefersToNonPrivateMember); + const hasNumericIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.Number); + const hasStringIndexSignature = !!checker.getIndexTypeOfType(classType, IndexKind.String); - let insertion = getMissingIndexSignatureInsertion(implementedType, IndexKind.Number, classDecl, hasNumericIndexSignature); - insertion += getMissingIndexSignatureInsertion(implementedType, IndexKind.String, classDecl, hasStringIndexSignature); - insertion += getMissingMembersInsertion(classDecl, nonPrivateMembers, checker, context.newLineCharacter); + const result: CodeAction[] = []; + for (const implementedTypeNode of implementedTypeNodes) { + const implementedType = checker.getTypeFromTypeReference(implementedTypeNode) as InterfaceType; + // Note that this is ultimately derived from a map indexed by symbol names, + // so duplicates cannot occur. + const implementedTypeSymbols = checker.getPropertiesOfType(implementedType); + const nonPrivateMembers = implementedTypeSymbols.filter(symbolRefersToNonPrivateMember); - const message = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Implement_interface_0), [implementedTypeNode.getText()]); - if (insertion) { - pushAction(result, insertion, message); - } - } + let insertion = getMissingIndexSignatureInsertion(implementedType, IndexKind.Number, classDecl, hasNumericIndexSignature); + insertion += getMissingIndexSignatureInsertion(implementedType, IndexKind.String, classDecl, hasStringIndexSignature); + insertion += getMissingMembersInsertion(classDecl, nonPrivateMembers, checker, context.newLineCharacter); - return result; - - function getMissingIndexSignatureInsertion(type: InterfaceType, kind: IndexKind, enclosingDeclaration: ClassLikeDeclaration, hasIndexSigOfKind: boolean) { - if (!hasIndexSigOfKind) { - const IndexInfoOfKind = checker.getIndexInfoOfType(type, kind); - if (IndexInfoOfKind) { - return checker.indexSignatureToString(IndexInfoOfKind, kind, enclosingDeclaration); - } - } - return ""; - } - - function symbolRefersToNonPrivateMember(symbol: Symbol): boolean { - const decls = symbol.getDeclarations(); - Debug.assert(!!(decls && decls.length > 0)); - return !(getModifierFlags(decls[0]) & ModifierFlags.Private); - } - - function pushAction(result: CodeAction[], insertion: string, description: string): void { - const newAction: CodeAction = { - description: description, - changes: [{ - fileName: sourceFile.fileName, - textChanges: [{ - span: { start: startPos, length: 0 }, - newText: insertion - }] - }] - }; - result.push(newAction); + const message = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Implement_interface_0), [implementedTypeNode.getText()]); + if (insertion) { + pushAction(result, insertion, message); } } - }); + + return result; + + function getMissingIndexSignatureInsertion(type: InterfaceType, kind: IndexKind, enclosingDeclaration: ClassLikeDeclaration, hasIndexSigOfKind: boolean) { + if (!hasIndexSigOfKind) { + const IndexInfoOfKind = checker.getIndexInfoOfType(type, kind); + if (IndexInfoOfKind) { + return checker.indexSignatureToString(IndexInfoOfKind, kind, enclosingDeclaration); + } + } + return ""; + } + + function symbolRefersToNonPrivateMember(symbol: Symbol): boolean { + const decls = symbol.getDeclarations(); + Debug.assert(!!(decls && decls.length > 0)); + return !(getModifierFlags(decls[0]) & ModifierFlags.Private); + } + + function pushAction(result: CodeAction[], insertion: string, description: string): void { + const newAction: CodeAction = { + description: description, + changes: [{ + fileName: sourceFile.fileName, + textChanges: [{ + span: { start: startPos, length: 0 }, + newText: insertion + }] + }] + }; + result.push(newAction); + } + } } \ No newline at end of file