Skip to content

Commit ad01270

Browse files
authored
Fix(54284) (#54973)
1 parent 83f3abd commit ad01270

19 files changed

+469
-50
lines changed

Diff for: src/services/refactors/moveToFile.ts

+24-20
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import {
4040
FindAllReferences,
4141
findIndex,
4242
findLast,
43-
findLastIndex,
4443
firstDefined,
4544
flatMap,
4645
forEachKey,
@@ -82,7 +81,6 @@ import {
8281
isIdentifier,
8382
isImportDeclaration,
8483
isImportEqualsDeclaration,
85-
isNamedDeclaration,
8684
isNamedExports,
8785
isObjectLiteralExpression,
8886
isOmittedExpression,
@@ -117,7 +115,6 @@ import {
117115
PropertyAccessExpression,
118116
PropertyAssignment,
119117
QuotePreference,
120-
rangeContainsRange,
121118
RefactorContext,
122119
RefactorEditInfo,
123120
RequireOrImportCall,
@@ -182,7 +179,7 @@ registerRefactor(refactorNameForMoveToFile, {
182179
if (host.fileExists(targetFile) && program.getSourceFile(targetFile) === undefined) {
183180
return error(getLocaleSpecificMessage(Diagnostics.Cannot_move_statements_to_the_selected_file));
184181
}
185-
const edits = textChanges.ChangeTracker.with(context, t => doChange(context, context.file, interactiveRefactorArguments.targetFile, program, statements, t, context.host, context.preferences));
182+
const edits = textChanges.ChangeTracker.with(context, t => doChange(context, context.file, interactiveRefactorArguments.targetFile, context.program, statements, t, context.host, context.preferences));
186183
return { edits, renameFilename: undefined, renameLocation: undefined };
187184
}
188185
return error(getLocaleSpecificMessage(Diagnostics.Cannot_move_to_file_selected_file_is_invalid));
@@ -196,7 +193,7 @@ function error(notApplicableReason: string) {
196193
function doChange(context: RefactorContext, oldFile: SourceFile, targetFile: string, program: Program, toMove: ToMove, changes: textChanges.ChangeTracker, host: LanguageServiceHost, preferences: UserPreferences): void {
197194
const checker = program.getTypeChecker();
198195
const usage = getUsageInfo(oldFile, toMove.all, checker);
199-
// For a new file
196+
//For a new file
200197
if (!host.fileExists(targetFile)) {
201198
changes.createNewFile(oldFile, targetFile, getNewStatementsAndRemoveFromOldFile(oldFile, targetFile, usage, changes, toMove, program, host, preferences));
202199
addNewFileToTsconfig(program, changes, oldFile.fileName, targetFile, hostGetCanonicalFileName(host));
@@ -913,28 +910,33 @@ function getRangeToMove(context: RefactorContext): RangeToMove | undefined {
913910
const range = createTextRangeFromSpan(getRefactorContextSpan(context));
914911
const { statements } = file;
915912

916-
const startNodeIndex = findIndex(statements, s => s.end > range.pos);
913+
let startNodeIndex = findIndex(statements, s => s.end > range.pos);
917914
if (startNodeIndex === -1) return undefined;
918-
919915
const startStatement = statements[startNodeIndex];
920-
if (isNamedDeclaration(startStatement) && startStatement.name && rangeContainsRange(startStatement.name, range)) {
921-
return { toMove: [statements[startNodeIndex]], afterLast: statements[startNodeIndex + 1] };
922-
}
923916

924917
const overloadRangeToMove = getOverloadRangeToMove(file, startStatement);
925918
if (overloadRangeToMove) {
926-
return overloadRangeToMove;
919+
startNodeIndex = overloadRangeToMove.start;
927920
}
928921

929-
// Can't only partially include the start node or be partially into the next node
930-
if (range.pos > startStatement.getStart(file)) return undefined;
931-
const afterEndNodeIndex = findIndex(statements, s => s.end > range.end, startNodeIndex);
932-
// Can't be partially into the next node
933-
if (afterEndNodeIndex !== -1 && (afterEndNodeIndex === 0 || statements[afterEndNodeIndex].getStart(file) < range.end)) return undefined;
922+
let endNodeIndex = findIndex(statements, s => s.end >= range.end, startNodeIndex);
923+
/**
924+
* [|const a = 2;
925+
* function foo() {
926+
* }
927+
* |]
928+
*/
929+
if (endNodeIndex !== -1 && range.end <= statements[endNodeIndex].getStart()) {
930+
endNodeIndex--;
931+
}
932+
const endingOverloadRangeToMove = getOverloadRangeToMove(file, statements[endNodeIndex]);
933+
if (endingOverloadRangeToMove) {
934+
endNodeIndex = endingOverloadRangeToMove.end;
935+
}
934936

935937
return {
936-
toMove: statements.slice(startNodeIndex, afterEndNodeIndex === -1 ? statements.length : afterEndNodeIndex),
937-
afterLast: afterEndNodeIndex === -1 ? undefined : statements[afterEndNodeIndex],
938+
toMove: statements.slice(startNodeIndex, endNodeIndex === -1 ? statements.length : endNodeIndex + 1),
939+
afterLast: endNodeIndex === -1 ? undefined : statements[endNodeIndex + 1]
938940
};
939941
}
940942

@@ -1204,10 +1206,12 @@ function getOverloadRangeToMove(sourceFile: SourceFile, statement: Statement) {
12041206
if (declarations === undefined || length(declarations) <= 1 || !contains(declarations, statement)) {
12051207
return undefined;
12061208
}
1209+
const firstDecl = declarations[0];
12071210
const lastDecl = declarations[length(declarations) - 1];
12081211
const statementsToMove = mapDefined(declarations, d => getSourceFileOfNode(d) === sourceFile && isStatement(d) ? d : undefined);
1209-
const end = findLastIndex(sourceFile.statements, s => s.end > lastDecl.end);
1210-
return { toMove: statementsToMove, afterLast: end >= 0 ? sourceFile.statements[end] : undefined };
1212+
const end = findIndex(sourceFile.statements, s => s.end >= lastDecl.end);
1213+
const start = findIndex(sourceFile.statements, s => s.end >= firstDecl.end);
1214+
return { toMove: statementsToMove, start, end };
12111215
}
12121216
return undefined;
12131217
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: /bar.ts
4+
////
5+
6+
// @Filename: /a.ts
7+
////co[|nst a = 1|]23;
8+
////function foo() { }
9+
10+
verify.moveToFile({
11+
newFileContents: {
12+
"/a.ts":
13+
`function foo() { }`,
14+
15+
"/bar.ts":
16+
`
17+
const a = 123;
18+
`,
19+
},
20+
interactiveRefactorArguments: { targetFile: "/bar.ts" }
21+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: /bar.ts
4+
////
5+
6+
// @Filename: /a.ts
7+
////const b = 2;[|
8+
////const a = 1;
9+
////function add(x: number, y: number): number;
10+
////function add(x: string, y: string): string;
11+
////function add(x: any, y: any) {
12+
//// return x + y;
13+
////}
14+
////|]
15+
////const c = 3;
16+
17+
18+
verify.moveToFile({
19+
newFileContents: {
20+
"/a.ts":
21+
`const b = 2;
22+
const c = 3;`,
23+
24+
"/bar.ts":
25+
`
26+
const a = 1;
27+
function add(x: number, y: number): number;
28+
function add(x: string, y: string): string;
29+
function add(x: any, y: any) {
30+
return x + y;
31+
}
32+
`,
33+
},
34+
interactiveRefactorArguments: { targetFile: "/bar.ts" }
35+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: /bar.ts
4+
////const b = 2;
5+
6+
// @Filename: /a.ts
7+
////const a = 1;
8+
////function[| add(x: number, y: number): number;
9+
////function add(x: string, y: string): string;
10+
////function add(x: any, y: any) {
11+
//// return x + y;
12+
////}
13+
////
14+
//// |]const b = 2;
15+
////const c = 3;
16+
17+
verify.moveToFile({
18+
newFileContents: {
19+
"/a.ts":
20+
`const a = 1;
21+
const b = 2;
22+
const c = 3;`,
23+
24+
"/bar.ts":
25+
`const b = 2;
26+
function add(x: number, y: number): number;
27+
function add(x: string, y: string): string;
28+
function add(x: any, y: any) {
29+
return x + y;
30+
}
31+
`,
32+
},
33+
interactiveRefactorArguments: { targetFile: "/bar.ts" }
34+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: /bar.ts
4+
////const b = 2;
5+
6+
// @Filename: /a.ts
7+
////const a = 1;[|
8+
////function add(x: number, y: number): number;
9+
////function add(x: string, y: string): string;
10+
////function add(x: any, y: any) {
11+
//// return x + y;
12+
////}
13+
////function foo() {}
14+
////|]
15+
16+
17+
verify.moveToFile({
18+
newFileContents: {
19+
"/a.ts":
20+
`const a = 1;
21+
`,
22+
23+
"/bar.ts":
24+
`const b = 2;
25+
function add(x: number, y: number): number;
26+
function add(x: string, y: string): string;
27+
function add(x: any, y: any) {
28+
return x + y;
29+
}
30+
function foo() { }
31+
`,
32+
},
33+
interactiveRefactorArguments: { targetFile: "/bar.ts" }
34+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: /bar.ts
4+
////const b = 2;
5+
6+
// @Filename: /a.ts
7+
////const a = 1;
8+
////function add1(x: number, y: number): number;
9+
////functi[|on add1(x: string, y: string): string;
10+
////function add1(x: any, y: any) {
11+
//// return x + y;
12+
////}
13+
////function foo() {}
14+
////function add2(x: number, y: number): number;
15+
////function add2(x: string, y: string): string;
16+
////function add2(x: any, y: any) {
17+
//// return x + y;
18+
////}|]
19+
////const c = 3;
20+
21+
verify.moveToFile({
22+
newFileContents: {
23+
"/a.ts":
24+
`const a = 1;
25+
const c = 3;`,
26+
27+
"/bar.ts":
28+
`const b = 2;
29+
function add1(x: number, y: number): number;
30+
function add1(x: string, y: string): string;
31+
function add1(x: any, y: any) {
32+
return x + y;
33+
}
34+
function foo() { }
35+
function add2(x: number, y: number): number;
36+
function add2(x: string, y: string): string;
37+
function add2(x: any, y: any) {
38+
return x + y;
39+
}
40+
`,
41+
},
42+
interactiveRefactorArguments: { targetFile: "/bar.ts" }
43+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: /bar.ts
4+
////
5+
6+
// @Filename: /a.ts
7+
////export [|default class {
8+
//// run()|] {}
9+
////}
10+
11+
verify.moveToFile({
12+
newFileContents: {
13+
"/a.ts":
14+
``,
15+
16+
"/bar.ts":
17+
`
18+
export default class {
19+
run() { }
20+
}
21+
`,
22+
},
23+
interactiveRefactorArguments: { targetFile: "/bar.ts" }
24+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: /bar.ts
4+
////const a = 1;
5+
6+
// @Filename: /a.ts
7+
////let [|message: string, count: number = 10, functional|]: boolean = true;
8+
9+
verify.moveToFile({
10+
newFileContents: {
11+
"/a.ts":
12+
``,
13+
14+
"/bar.ts":
15+
`const a = 1;
16+
let message: string, count: number = 10, functional: boolean = true;
17+
`,
18+
},
19+
interactiveRefactorArguments: { targetFile: "/bar.ts" }
20+
});
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: /bar.ts
4+
////import { b } from './other';
5+
////const t = b;
6+
7+
// @Filename: /a.ts
8+
////co[|nst a = 1;
9+
////cons|]t b = 1;
10+
////function foo() { }
11+
12+
// @Filename: /other.ts
13+
////export const b = 2;
14+
15+
verify.moveToFile({
16+
newFileContents: {
17+
"/a.ts":
18+
`function foo() { }`,
19+
20+
"/bar.ts":
21+
`import { b } from './other';
22+
const t = b;
23+
const a = 1;
24+
const b = 1;
25+
`,
26+
},
27+
interactiveRefactorArguments: { targetFile: "/bar.ts" }
28+
});
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//@Filename: /bar.ts
4+
////import { b } from './other';
5+
////const t = b;
6+
7+
// @Filename: /a.ts
8+
////[|const a = 1;
9+
////const b = 1;|]
10+
////function foo() { }
11+
12+
// @Filename: /other.ts
13+
////export const b = 2;
14+
15+
verify.moveToFile({
16+
newFileContents: {
17+
"/a.ts":
18+
`function foo() { }`,
19+
20+
"/bar.ts":
21+
`import { b } from './other';
22+
const t = b;
23+
const a = 1;
24+
const b = 1;
25+
`,
26+
},
27+
interactiveRefactorArguments: { targetFile: "/bar.ts" }
28+
});

0 commit comments

Comments
 (0)