Skip to content

Commit 2690355

Browse files
committed
Improve insertion position of extracted methods
Old: End of target scope New: Before the first non-constructor function following the extracted range in the target scope
1 parent deefb01 commit 2690355

File tree

3 files changed

+56
-7
lines changed

3 files changed

+56
-7
lines changed

src/compiler/utilities.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ namespace ts {
505505
}
506506
}
507507

508-
function staticAssertNever(_: never): void {}
508+
export function staticAssertNever(_: never): void {}
509509

510510
// Gets the nearest enclosing block scope container that has the provided node
511511
// as a descendant, that is not the provided node.

src/services/refactors/extractMethod.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,8 +697,14 @@ namespace ts.refactor.extractMethod {
697697
}
698698

699699
const changeTracker = textChanges.ChangeTracker.fromContext(context);
700-
// insert function at the end of the scope
701-
changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter });
700+
const minInsertionPos = (isReadonlyArray(range.range) ? lastOrUndefined(range.range) : range.range).end;
701+
const nodeToInsertBefore = getNodeToInsertBefore(minInsertionPos, scope);
702+
if (nodeToInsertBefore) {
703+
changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, { suffix: context.newLineCharacter + context.newLineCharacter });
704+
}
705+
else {
706+
changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter });
707+
}
702708

703709
const newNodes: Node[] = [];
704710
// replace range with function call
@@ -831,6 +837,39 @@ namespace ts.refactor.extractMethod {
831837
return "__return";
832838
}
833839

840+
function getStatementsOrClassElements(scope: Scope): ReadonlyArray<Statement> | ReadonlyArray<ClassElement> {
841+
if (isFunctionLike(scope)) {
842+
const body = scope.body;
843+
if (isBlock(body)) {
844+
return body.statements;
845+
}
846+
}
847+
else if (isModuleBlock(scope) || isSourceFile(scope)) {
848+
return scope.statements;
849+
}
850+
else if (isClassLike(scope)) {
851+
return scope.members;
852+
}
853+
else {
854+
staticAssertNever(scope);
855+
}
856+
857+
return emptyArray;
858+
}
859+
860+
/**
861+
* If `scope` contains a function after `minPos`, then return the first such function.
862+
* Otherwise, return `undefined`.
863+
*/
864+
function getNodeToInsertBefore(minPos: number, scope: Scope): Node | undefined {
865+
const children = getStatementsOrClassElements(scope);
866+
for (const child of children) {
867+
if (child.pos >= minPos && isFunctionLike(child) && !isConstructorDeclaration(child)) {
868+
return child;
869+
}
870+
}
871+
}
872+
834873
function transformFunctionBody(body: Node) {
835874
if (isBlock(body) && !writes && substitutions.size === 0) {
836875
// already block, no writes to propagate back, no substitutions - can use node as is

tests/cases/fourslash/extract-method13.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ edit.applyRefactor({
1616
actionDescription: "Extract function into class 'C'",
1717
});
1818

19+
verify.currentFileContentIs(`class C {
20+
static j = 1 + 1;
21+
constructor(q: string = C.newFunction()) {
22+
}
23+
24+
private static newFunction(): string {
25+
return "a" + "b";
26+
}
27+
}`);
28+
1929
goTo.select('c', 'd');
2030
edit.applyRefactor({
2131
refactorName: "Extract Method",
@@ -28,11 +38,11 @@ verify.currentFileContentIs(`class C {
2838
constructor(q: string = C.newFunction()) {
2939
}
3040
31-
private static newFunction(): string {
32-
return "a" + "b";
33-
}
34-
3541
private static newFunction_1() {
3642
return 1 + 1;
3743
}
44+
45+
private static newFunction(): string {
46+
return "a" + "b";
47+
}
3848
}`);

0 commit comments

Comments
 (0)