diff --git a/src/services/refactors/moveToFile.ts b/src/services/refactors/moveToFile.ts index 3b0a0c22ab8..b595f6cdfa3 100644 --- a/src/services/refactors/moveToFile.ts +++ b/src/services/refactors/moveToFile.ts @@ -35,6 +35,7 @@ import { find, FindAllReferences, findIndex, + findLastIndex, firstDefined, flatMap, forEachKey, @@ -51,6 +52,7 @@ import { getRangesWhere, getRefactorContextSpan, getRelativePathFromFile, + getSourceFileOfNode, getSynthesizedDeepClone, getUniqueName, hasJSFileExtension, @@ -69,6 +71,7 @@ import { isDeclarationName, isExpressionStatement, isExternalModuleReference, + isFunctionLikeDeclaration, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, @@ -80,6 +83,7 @@ import { isPropertyAssignment, isRequireCall, isSourceFile, + isStatement, isStringLiteral, isStringLiteralLike, isValidTypeOnlyAliasUseSite, @@ -901,6 +905,11 @@ function getRangeToMove(context: RefactorContext): RangeToMove | undefined { return { toMove: [statements[startNodeIndex]], afterLast: statements[startNodeIndex + 1] }; } + const overloadRangeToMove = getOverloadRangeToMove(file, startStatement); + if (overloadRangeToMove) { + return overloadRangeToMove; + } + // Can't only partially include the start node or be partially into the next node if (range.pos > startStatement.getStart(file)) return undefined; const afterEndNodeIndex = findIndex(statements, s => s.end > range.end, startNodeIndex); @@ -1120,4 +1129,16 @@ function isNonVariableTopLevelDeclaration(node: Node): node is NonVariableTopLev } } - +function getOverloadRangeToMove(sourceFile: SourceFile, statement: Statement) { + if (isFunctionLikeDeclaration(statement)) { + const declarations = statement.symbol.declarations; + if (declarations === undefined || length(declarations) <= 1 || !contains(declarations, statement)) { + return undefined; + } + const lastDecl = declarations[length(declarations) - 1]; + const statementsToMove = mapDefined(declarations, d => getSourceFileOfNode(d) === sourceFile && isStatement(d) ? d : undefined); + const end = findLastIndex(sourceFile.statements, s => s.end > lastDecl.end); + return { toMove: statementsToMove, afterLast: end >= 0 ? sourceFile.statements[end] : undefined }; + } + return undefined; +} diff --git a/tests/cases/fourslash/moveToFile_overloads1.ts b/tests/cases/fourslash/moveToFile_overloads1.ts new file mode 100644 index 00000000000..c30bba2d9a1 --- /dev/null +++ b/tests/cases/fourslash/moveToFile_overloads1.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /add.ts +//// + +// @Filename: /a.ts +////[|function add(x: number, y: number): number;|] +////function add(x: string, y: string): string; +////function add(x: any, y: any) { +//// return x + y; +////} + +verify.moveToFile({ + newFileContents: { + "/a.ts": "", + "/add.ts": +`function add(x: number, y: number): number; +function add(x: string, y: string): string; +function add(x: any, y: any) { + return x + y; +} +` + }, + interactiveRefactorArguments: { targetFile: "/add.ts" } +}); diff --git a/tests/cases/fourslash/moveToFile_overloads2.ts b/tests/cases/fourslash/moveToFile_overloads2.ts new file mode 100644 index 00000000000..71108801dd6 --- /dev/null +++ b/tests/cases/fourslash/moveToFile_overloads2.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /add.ts +//// + +// @Filename: /a.ts +////function add(x: number, y: number): number; +////function add(x: string, y: string): string; +////[|function add(x: any, y: any) { +//// return x + y; +////}|] + +verify.moveToFile({ + newFileContents: { + "/a.ts": "", + "/add.ts": +`function add(x: number, y: number): number; +function add(x: string, y: string): string; +function add(x: any, y: any) { + return x + y; +} +` + }, + interactiveRefactorArguments: { targetFile: "/add.ts" } +}); diff --git a/tests/cases/fourslash/moveToFile_overloads3.ts b/tests/cases/fourslash/moveToFile_overloads3.ts new file mode 100644 index 00000000000..ea2df5986fb --- /dev/null +++ b/tests/cases/fourslash/moveToFile_overloads3.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /add.ts +//// + +// @Filename: /a.ts +////function add(x: number, y: number): number; +////[|function add(x: string, y: string): string; +////function add(x: any, y: any) { +//// return x + y; +////}|] + +verify.moveToFile({ + newFileContents: { + "/a.ts": "", + "/add.ts": +`function add(x: number, y: number): number; +function add(x: string, y: string): string; +function add(x: any, y: any) { + return x + y; +} +` + }, + interactiveRefactorArguments: { targetFile: "/add.ts" }, +}); diff --git a/tests/cases/fourslash/moveToFile_overloads4.ts b/tests/cases/fourslash/moveToFile_overloads4.ts new file mode 100644 index 00000000000..a846773a1ea --- /dev/null +++ b/tests/cases/fourslash/moveToFile_overloads4.ts @@ -0,0 +1,26 @@ +/// + +// @Filename: /add.ts +//// + +// @Filename: /a.ts +////function add(x: number, y: number): number; +////[|function add(x: string, y: string): string; +////function add(x: any, y: any) { +//// return x + y; +////}|] +////function remove() {} + +verify.moveToFile({ + newFileContents: { + "/a.ts": "function remove() {}", + "/add.ts": +`function add(x: number, y: number): number; +function add(x: string, y: string): string; +function add(x: any, y: any) { + return x + y; +} +` + }, + interactiveRefactorArguments: { targetFile: "/add.ts" }, +}); diff --git a/tests/cases/fourslash/moveToFile_overloads5.ts b/tests/cases/fourslash/moveToFile_overloads5.ts new file mode 100644 index 00000000000..d45914df719 --- /dev/null +++ b/tests/cases/fourslash/moveToFile_overloads5.ts @@ -0,0 +1,29 @@ +/// + +// @Filename: /add.ts +//// + +// @Filename: /a.ts +////function add(x: number, y: number): number; +////[|function add(x: string, y: string): string; +////function add(x: any, y: any) { +//// return x + y; +////}|] +////export const a = add(); + +verify.moveToFile({ + newFileContents: { + "/a.ts": +`import { add } from "./add"; + +export const a = add();`, + "/add.ts": +`export function add(x: number, y: number): number; +export function add(x: string, y: string): string; +export function add(x: any, y: any) { + return x + y; +} +` + }, + interactiveRefactorArguments: { targetFile: "/add.ts" }, +}); diff --git a/tests/cases/fourslash/moveToNewFile_overloads1.ts b/tests/cases/fourslash/moveToNewFile_overloads1.ts new file mode 100644 index 00000000000..7a7bc748ccc --- /dev/null +++ b/tests/cases/fourslash/moveToNewFile_overloads1.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: /a.ts +////[|function add(x: number, y: number): number;|] +////function add(x: string, y: string): string; +////function add(x: any, y: any) { +//// return x + y; +////} + +verify.moveToNewFile({ + newFileContents: { + "/a.ts": "", + "/add.ts": +`function add(x: number, y: number): number; +function add(x: string, y: string): string; +function add(x: any, y: any) { + return x + y; +} +` + }, +}); diff --git a/tests/cases/fourslash/moveToNewFile_overloads2.ts b/tests/cases/fourslash/moveToNewFile_overloads2.ts new file mode 100644 index 00000000000..318f088c89b --- /dev/null +++ b/tests/cases/fourslash/moveToNewFile_overloads2.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: /a.ts +////function add(x: number, y: number): number; +////function add(x: string, y: string): string; +////[|function add(x: any, y: any) { +//// return x + y; +////}|] + +verify.moveToNewFile({ + newFileContents: { + "/a.ts": "", + "/add.ts": +`function add(x: number, y: number): number; +function add(x: string, y: string): string; +function add(x: any, y: any) { + return x + y; +} +` + }, +}); diff --git a/tests/cases/fourslash/moveToNewFile_overloads3.ts b/tests/cases/fourslash/moveToNewFile_overloads3.ts new file mode 100644 index 00000000000..f3b99addcba --- /dev/null +++ b/tests/cases/fourslash/moveToNewFile_overloads3.ts @@ -0,0 +1,21 @@ +/// + +// @Filename: /a.ts +////function add(x: number, y: number): number; +////[|function add(x: string, y: string): string; +////function add(x: any, y: any) { +//// return x + y; +////}|] + +verify.moveToNewFile({ + newFileContents: { + "/a.ts": "", + "/add.ts": +`function add(x: number, y: number): number; +function add(x: string, y: string): string; +function add(x: any, y: any) { + return x + y; +} +` + }, +}); diff --git a/tests/cases/fourslash/moveToNewFile_overloads4.ts b/tests/cases/fourslash/moveToNewFile_overloads4.ts new file mode 100644 index 00000000000..abf881ca57a --- /dev/null +++ b/tests/cases/fourslash/moveToNewFile_overloads4.ts @@ -0,0 +1,22 @@ +/// + +// @Filename: /a.ts +////function add(x: number, y: number): number; +////[|function add(x: string, y: string): string; +////function add(x: any, y: any) { +//// return x + y; +////}|] +////function remove() {} + +verify.moveToNewFile({ + newFileContents: { + "/a.ts": "function remove() {}", + "/add.ts": +`function add(x: number, y: number): number; +function add(x: string, y: string): string; +function add(x: any, y: any) { + return x + y; +} +` + }, +});