Improve positioning of the implement interface codefix (#34928)

This commit is contained in:
Orta
2019-11-19 12:13:50 -05:00
committed by GitHub
parent 6c59dc34ac
commit af0d5d33b6
4 changed files with 72 additions and 8 deletions
@@ -54,6 +54,7 @@ namespace ts.codefix {
const nonPrivateAndNotExistedInHeritageClauseMembers = implementedTypeSymbols.filter(and(symbolPointsToNonPrivateMember, symbol => !maybeHeritageClauseSymbol.has(symbol.escapedName)));
const classType = checker.getTypeAtLocation(classDeclaration);
const constructor = find(classDeclaration.members, m => isConstructorDeclaration(m));
if (!classType.getNumberIndexType()) {
createMissingIndexSignatureDeclaration(implementedType, IndexKind.Number);
@@ -62,12 +63,22 @@ namespace ts.codefix {
createMissingIndexSignatureDeclaration(implementedType, IndexKind.String);
}
createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, context, preferences, member => changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member));
createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, context, preferences, member => insertInterfaceMemberNode(sourceFile, classDeclaration, member));
function createMissingIndexSignatureDeclaration(type: InterfaceType, kind: IndexKind): void {
const indexInfoOfKind = checker.getIndexInfoOfType(type, kind);
if (indexInfoOfKind) {
changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context))!);
insertInterfaceMemberNode(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context))!);
}
}
// Either adds the node at the top of the class, or if there's a constructor right after that
function insertInterfaceMemberNode(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration, newElement: ClassElement): void {
if (constructor) {
changeTracker.insertNodeAfter(sourceFile, constructor, newElement);
}
else {
changeTracker.insertNodeAtClassStart(sourceFile, cls, newElement);
}
}
}
@@ -1,5 +1,6 @@
/// <reference path='fourslash.ts' />
////
//// interface I {
//// x: {};
//// }
@@ -8,6 +9,15 @@
//// |]constructor() { }
//// }
verify.rangeAfterCodeFix(`
x: {};
`);
verify.codeFix({
description: "Implement interface 'I'",
newFileContent:`
interface I {
x: {};
}
class C implements I {
constructor() { }
x: {};
}`,
});
@@ -1,5 +1,6 @@
/// <reference path='fourslash.ts' />
////
//// interface I {
//// x: number;
//// y: number;
@@ -11,6 +12,20 @@
//// y: number;
//// }
verify.rangeAfterCodeFix(`
z: number & { __iBrand: any; };
`);
verify.codeFix({
description: "Implement interface 'I'",
newFileContent:`
interface I {
x: number;
y: number;
z: number & { __iBrand: any };
}
class C implements I {
constructor(public x: number) { }
z: number & { __iBrand: any; };
y: number;
}`,
});
@@ -0,0 +1,28 @@
/// <reference path='fourslash.ts' />
// #34841
////interface IFoo {
//// bar(): void;
////}
////
////class Foo implements IFoo {
//// private x = 1;
//// constructor() { this.x = 2 }
////}
verify.codeFix({
description: "Implement interface 'IFoo'",
index: 0,
newFileContent:
`interface IFoo {
bar(): void;
}
class Foo implements IFoo {
private x = 1;
constructor() { this.x = 2 }
bar(): void {
throw new Error("Method not implemented.");
}
}`});