Skip to content

Commit

Permalink
Rename interface after extraction
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoespeon committed Jan 31, 2020
1 parent 3bb51df commit 3c02e10
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/editor/adapters/in-memory-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ class InMemoryEditor implements Editor {
return Promise.resolve(choices[0]);
}

moveCursorTo(_position: Position) {
return Promise.resolve();
}

private setCodeMatrix(code: Code) {
this.codeMatrix = code
.split(LINE_SEPARATOR)
Expand Down
5 changes: 5 additions & 0 deletions src/editor/adapters/vscode-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ class VSCodeEditor implements Editor {
async askUser<T>(choices: Choice<T>[]) {
return await vscode.window.showQuickPick(choices);
}

moveCursorTo(position: Position) {
this.editor.selection = toVSCodeCursor(position);
return Promise.resolve();
}
}

function createSelectionFromVSCode(
Expand Down
1 change: 1 addition & 0 deletions src/editor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface Editor {
delegate(command: Command): Promise<void>;
showError(reason: ErrorReason): Promise<void>;
askUser<T>(choices: Choice<T>[]): Promise<Choice<T> | undefined>;
moveCursorTo(position: Position): Promise<void>;
}

type Modification = {
Expand Down
4 changes: 4 additions & 0 deletions src/editor/position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ class Position {
return new Position(this.line + lines, this.character);
}

addCharacters(characters: number): Position {
return new Position(this.line, this.character + characters);
}

putAtSameCharacter(position: Position): Position {
return new Position(this.line, position.character);
}
Expand Down
20 changes: 20 additions & 0 deletions src/refactorings/extract-interface/extract-interface.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Editor, ErrorReason, Code } from "../../editor/editor";
import { Position } from "../../editor/position";
import { Selection } from "../../editor/selection";
import { InMemoryEditor } from "../../editor/adapters/in-memory-editor";
import { testEach } from "../../tests-helpers";
Expand Down Expand Up @@ -215,6 +216,25 @@ interface Extracted {
);
});

it("should move cursor to extracted interface name", async () => {
const code = `class Position {
constructor(name: string) {
this.name = name;
}
isEqualTo(position: Position): boolean {
return true;
}
}`;
const editor = new InMemoryEditor(code);
const selection = Selection.cursorAt(0, 0);
const moveCursorTo = jest.spyOn(editor, "moveCursorTo");

await extractInterface(code, selection, editor);

expect(moveCursorTo).toBeCalledWith(new Position(10, 10));
});

async function doExtractInterface(
code: Code,
selection: Selection
Expand Down
29 changes: 27 additions & 2 deletions src/refactorings/extract-interface/extract-interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Editor, Code, ErrorReason } from "../../editor/editor";
import { Position } from "../../editor/position";
import { Selection } from "../../editor/selection";
import * as t from "../../ast";
import { renameSymbol } from "../rename-symbol/rename-symbol";

export { extractInterface, canExtractInterface };

Expand All @@ -17,6 +19,10 @@ async function extractInterface(
}

await editor.write(updatedCode.code);

await editor.moveCursorTo(updatedCode.interfaceIdentifierPosition);

await renameSymbol(editor);
}

function canExtractInterface(ast: t.AST, selection: Selection): boolean {
Expand All @@ -26,14 +32,33 @@ function canExtractInterface(ast: t.AST, selection: Selection): boolean {
return result;
}

function updateCode(ast: t.AST, selection: Selection): t.Transformed {
return t.transformAST(
function updateCode(
ast: t.AST,
selection: Selection
): t.Transformed & { interfaceIdentifierPosition: Position } {
let interfaceIdentifierPosition: Position = selection.start;

const result = t.transformAST(
ast,
createVisitor(selection, (path, id, declaration) => {
if (t.isSelectableNode(path.node)) {
// "interface X" => 10 characters before "X"
const interfaceIdentifierOffset = 10;

interfaceIdentifierPosition = Position.fromAST(path.node.loc.end)
.putAtStartOfLine()
// New interface starts 2 lines after class declaration
.putAtNextLine()
.putAtNextLine()
.addCharacters(interfaceIdentifierOffset);
}

path.node.implements = [t.classImplements(id)];
path.insertAfter(declaration);
})
);

return { ...result, interfaceIdentifierPosition };
}

function createVisitor(
Expand Down

0 comments on commit 3c02e10

Please sign in to comment.