mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-16 15:44:16 -06:00
Get one fix per interface
This commit is contained in:
parent
d842a6f665
commit
b1e97b370f
@ -9,10 +9,13 @@ namespace ts.codefix {
|
||||
const checker = context.program.getTypeChecker();
|
||||
|
||||
if (token.kind === SyntaxKind.Identifier && isClassLike(token.parent)) {
|
||||
const classDeclaration = <ClassDeclaration>token.parent;
|
||||
const startPos = classDeclaration.members.pos;
|
||||
const classDecl = <ClassDeclaration>token.parent;
|
||||
const startPos = classDecl.members.pos;
|
||||
|
||||
const insertion = getMissingAbstractMemberInsertion(classDeclaration, checker, context.newLineCharacter);
|
||||
const InstantiatedExtendsType = <InterfaceType>checker.getTypeFromTypeReference(getClassExtendsHeritageClauseElement(classDecl));
|
||||
const resolvedExtendsType = checker.resolveStructuredTypeMembers(InstantiatedExtendsType);
|
||||
|
||||
const insertion = getMissingAbstractMembersInsertion(classDecl, resolvedExtendsType, checker, context.newLineCharacter);
|
||||
|
||||
if (insertion.length > 0) {
|
||||
return [{
|
||||
|
||||
@ -8,15 +8,40 @@ namespace ts.codefix {
|
||||
const token = getTokenAtPosition(sourceFile, start);
|
||||
const checker = context.program.getTypeChecker();
|
||||
|
||||
if (token.kind === SyntaxKind.Identifier && isClassLike(token.parent)) {
|
||||
const classDeclaration = <ClassDeclaration>token.parent;
|
||||
const startPos: number = classDeclaration.members.pos;
|
||||
if (!(token.kind === SyntaxKind.Identifier && isClassLike(token.parent))) {
|
||||
return undefined;
|
||||
}
|
||||
const classDecl = <ClassDeclaration>token.parent;
|
||||
const startPos: number = classDecl.members.pos;
|
||||
|
||||
const insertion = getMissingInterfaceMembersInsertion(classDeclaration, checker, context.newLineCharacter);
|
||||
const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl);
|
||||
const implementedTypes = implementedTypeNodes.map(checker.getTypeFromTypeReference);
|
||||
const resolvedImplementedTypes = implementedTypes.map(checker.resolveStructuredTypeMembers);
|
||||
|
||||
let result: CodeAction[] | undefined = undefined;
|
||||
|
||||
for (const resolvedType of resolvedImplementedTypes) {
|
||||
const insertion = getMissingMembersInsertion(classDecl, resolvedType, checker, context.newLineCharacter);
|
||||
result = pushAction(insertion, getLocaleSpecificMessage(Diagnostics.Implement_interface_on_class), result);
|
||||
}
|
||||
|
||||
// TODO: (arozga) Get this working and figure out how to test it reliably.
|
||||
/*
|
||||
// If there are multiple objects, we additionally try to generate a combined fix that simultaneously implements all types.
|
||||
const intersectionType = checker.getIntersectionType(implementedTypes);
|
||||
if(intersectionType.flags & TypeFlags.Intersection) {
|
||||
const resolvedIntersectionType = checker.resolveStructuredTypeMembers(<IntersectionType>intersectionType)
|
||||
const insertion = getMissingMembersInsertion(classDecl, resolvedIntersectionType, checker, context.newLineCharacter);
|
||||
result = pushAction(insertion, "stubbed locale message", result)
|
||||
}
|
||||
*/
|
||||
|
||||
return result;
|
||||
|
||||
function pushAction(insertion: string, description: string, result?: CodeAction[]): CodeAction[] {
|
||||
if (insertion && insertion.length) {
|
||||
return [{
|
||||
description: getLocaleSpecificMessage(Diagnostics.Implement_interface_on_class),
|
||||
const newAction: CodeAction = {
|
||||
description: description,
|
||||
changes: [{
|
||||
fileName: sourceFile.fileName,
|
||||
textChanges: [{
|
||||
@ -24,10 +49,16 @@ namespace ts.codefix {
|
||||
newText: insertion
|
||||
}]
|
||||
}]
|
||||
}];
|
||||
};
|
||||
if (result) {
|
||||
result.push(newAction);
|
||||
}
|
||||
else {
|
||||
result = [newAction];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1359,32 +1359,19 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function getMissingAbstractMemberInsertion(classDecl: ClassDeclaration, checker: TypeChecker, newlineChar: string): string {
|
||||
export function getMissingAbstractMembersInsertion(classDecl: ClassDeclaration, resolvedType: ResolvedType, checker: TypeChecker, newlineChar: string): string {
|
||||
const classSymbol = checker.getSymbolOfNode(classDecl);
|
||||
|
||||
const InstantiatedExtendsType = <InterfaceType>checker.getTypeFromTypeReference(getClassExtendsHeritageClauseElement(classDecl));
|
||||
const resolvedExtendsType = checker.resolveStructuredTypeMembers(InstantiatedExtendsType);
|
||||
|
||||
const missingMembers = filterMissingMembers(filterAbstract(filterNonPrivate(resolvedExtendsType.members)), classSymbol.members);
|
||||
|
||||
const missingMembers = filterMissingMembers(filterAbstract(filterNonPrivate(resolvedType.members)), classSymbol.members);
|
||||
return getInsertionsForMembers(missingMembers, classDecl, checker, newlineChar);
|
||||
}
|
||||
|
||||
export function getMissingInterfaceMembersInsertion(classDecl: ClassDeclaration, checker: TypeChecker, newlineChar: string): string {
|
||||
const implementedTypeNodes = getClassImplementsHeritageClauseElements(classDecl);
|
||||
|
||||
/**
|
||||
* Finds members of the resolved type that are missing in the class pointed to by class decl
|
||||
* and generates source code for the missing members.
|
||||
*/
|
||||
export function getMissingMembersInsertion(classDecl: ClassDeclaration, resolvedType: ResolvedType, checker: TypeChecker, newlineChar: string): string {
|
||||
const classSymbol = checker.getSymbolOfNode(classDecl);
|
||||
|
||||
let implementsIntersectionType: IntersectionType | InterfaceType;
|
||||
if (implementedTypeNodes.length > 1) {
|
||||
implementsIntersectionType = <IntersectionType>checker.getIntersectionType(implementedTypeNodes.map(checker.getTypeFromTypeReference));
|
||||
}
|
||||
else {
|
||||
implementsIntersectionType = <InterfaceType>checker.getTypeFromTypeReference(implementedTypeNodes[0]);
|
||||
}
|
||||
|
||||
const structuredType = checker.resolveStructuredTypeMembers(<IntersectionType | InterfaceType>implementsIntersectionType);
|
||||
const missingMembers = filterMissingMembers(filterNonPrivate(structuredType.members), classSymbol.members);
|
||||
const missingMembers = filterMissingMembers(filterNonPrivate(resolvedType.members), classSymbol.members);
|
||||
return getInsertionsForMembers(missingMembers, classDecl, checker, newlineChar);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user