mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-11 01:34:55 -06:00
refactor fix
This commit is contained in:
parent
3cfac081d5
commit
467381273e
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user