Skip to content

Commit af0d5d3

Browse files
author
Orta
authored
Improve positioning of the implement interface codefix (microsoft#34928)
1 parent 6c59dc3 commit af0d5d3

File tree

4 files changed

+72
-8
lines changed

4 files changed

+72
-8
lines changed

src/services/codefixes/fixClassIncorrectlyImplementsInterface.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ namespace ts.codefix {
5454
const nonPrivateAndNotExistedInHeritageClauseMembers = implementedTypeSymbols.filter(and(symbolPointsToNonPrivateMember, symbol => !maybeHeritageClauseSymbol.has(symbol.escapedName)));
5555

5656
const classType = checker.getTypeAtLocation(classDeclaration);
57+
const constructor = find(classDeclaration.members, m => isConstructorDeclaration(m));
5758

5859
if (!classType.getNumberIndexType()) {
5960
createMissingIndexSignatureDeclaration(implementedType, IndexKind.Number);
@@ -62,12 +63,22 @@ namespace ts.codefix {
6263
createMissingIndexSignatureDeclaration(implementedType, IndexKind.String);
6364
}
6465

65-
createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, context, preferences, member => changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member));
66+
createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, context, preferences, member => insertInterfaceMemberNode(sourceFile, classDeclaration, member));
6667

6768
function createMissingIndexSignatureDeclaration(type: InterfaceType, kind: IndexKind): void {
6869
const indexInfoOfKind = checker.getIndexInfoOfType(type, kind);
6970
if (indexInfoOfKind) {
70-
changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context))!);
71+
insertInterfaceMemberNode(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context))!);
72+
}
73+
}
74+
75+
// Either adds the node at the top of the class, or if there's a constructor right after that
76+
function insertInterfaceMemberNode(sourceFile: SourceFile, cls: ClassLikeDeclaration | InterfaceDeclaration, newElement: ClassElement): void {
77+
if (constructor) {
78+
changeTracker.insertNodeAfter(sourceFile, constructor, newElement);
79+
}
80+
else {
81+
changeTracker.insertNodeAtClassStart(sourceFile, cls, newElement);
7182
}
7283
}
7384
}
Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/// <reference path='fourslash.ts' />
22

3+
////
34
//// interface I {
45
//// x: {};
56
//// }
@@ -8,6 +9,15 @@
89
//// |]constructor() { }
910
//// }
1011

11-
verify.rangeAfterCodeFix(`
12-
x: {};
13-
`);
12+
verify.codeFix({
13+
description: "Implement interface 'I'",
14+
newFileContent:`
15+
interface I {
16+
x: {};
17+
}
18+
19+
class C implements I {
20+
constructor() { }
21+
x: {};
22+
}`,
23+
});

tests/cases/fourslash/codeFixClassImplementInterfaceSomePropertiesPresent.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/// <reference path='fourslash.ts' />
22

3+
////
34
//// interface I {
45
//// x: number;
56
//// y: number;
@@ -11,6 +12,20 @@
1112
//// y: number;
1213
//// }
1314

14-
verify.rangeAfterCodeFix(`
15-
z: number & { __iBrand: any; };
16-
`);
15+
16+
verify.codeFix({
17+
description: "Implement interface 'I'",
18+
newFileContent:`
19+
interface I {
20+
x: number;
21+
y: number;
22+
z: number & { __iBrand: any };
23+
}
24+
25+
class C implements I {
26+
constructor(public x: number) { }
27+
z: number & { __iBrand: any; };
28+
y: number;
29+
}`,
30+
});
31+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// #34841
4+
5+
////interface IFoo {
6+
//// bar(): void;
7+
////}
8+
////
9+
////class Foo implements IFoo {
10+
//// private x = 1;
11+
//// constructor() { this.x = 2 }
12+
////}
13+
14+
verify.codeFix({
15+
description: "Implement interface 'IFoo'",
16+
index: 0,
17+
newFileContent:
18+
`interface IFoo {
19+
bar(): void;
20+
}
21+
22+
class Foo implements IFoo {
23+
private x = 1;
24+
constructor() { this.x = 2 }
25+
bar(): void {
26+
throw new Error("Method not implemented.");
27+
}
28+
}`});

0 commit comments

Comments
 (0)