Skip to content

Commit 2cb4640

Browse files
author
Andy
authored
moveToNewFile: Remove newlines after last moved statement (microsoft#24503)
1 parent bfa3b95 commit 2cb4640

File tree

3 files changed

+23
-13
lines changed

3 files changed

+23
-13
lines changed

src/services/refactors/moveToNewFile.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ namespace ts.refactor {
1515
}
1616
});
1717

18-
function getRangeToMove(context: RefactorContext): ReadonlyArray<Statement> | undefined {
18+
interface RangeToMove { readonly toMove: ReadonlyArray<Statement>; readonly afterLast: Statement | undefined; }
19+
function getRangeToMove(context: RefactorContext): RangeToMove | undefined {
1920
const { file } = context;
2021
const range = createTextRangeFromSpan(getRefactorContextSpan(context));
2122
const { statements } = file;
@@ -25,7 +26,7 @@ namespace ts.refactor {
2526

2627
const startStatement = statements[startNodeIndex];
2728
if (isNamedDeclaration(startStatement) && startStatement.name && rangeContainsRange(startStatement.name, range)) {
28-
return [statements[startNodeIndex]];
29+
return { toMove: [statements[startNodeIndex]], afterLast: statements[startNodeIndex + 1] };
2930
}
3031

3132
// Can't only partially include the start node or be partially into the next node
@@ -34,7 +35,10 @@ namespace ts.refactor {
3435
// Can't be partially into the next node
3536
if (afterEndNodeIndex !== -1 && (afterEndNodeIndex === 0 || statements[afterEndNodeIndex].getStart(file) < range.end)) return undefined;
3637

37-
return statements.slice(startNodeIndex, afterEndNodeIndex === -1 ? statements.length : afterEndNodeIndex);
38+
return {
39+
toMove: statements.slice(startNodeIndex, afterEndNodeIndex === -1 ? statements.length : afterEndNodeIndex),
40+
afterLast: afterEndNodeIndex === -1 ? undefined : statements[afterEndNodeIndex],
41+
};
3842
}
3943

4044
function doChange(oldFile: SourceFile, program: Program, toMove: ToMove, changes: textChanges.ChangeTracker, host: LanguageServiceHost, preferences: UserPreferences): void {
@@ -47,14 +51,14 @@ namespace ts.refactor {
4751
const newFileNameWithExtension = newModuleName + extension;
4852

4953
// If previous file was global, this is easy.
50-
changes.createNewFile(oldFile, combinePaths(currentDirectory, newFileNameWithExtension), getNewStatements(oldFile, usage, changes, toMove, program, newModuleName, preferences));
54+
changes.createNewFile(oldFile, combinePaths(currentDirectory, newFileNameWithExtension), getNewStatementsAndRemoveFromOldFile(oldFile, usage, changes, toMove, program, newModuleName, preferences));
5155

5256
addNewFileToTsconfig(program, changes, oldFile.fileName, newFileNameWithExtension, hostGetCanonicalFileName(host));
5357
}
5458

5559
interface StatementRange {
5660
readonly first: Statement;
57-
readonly last: Statement;
61+
readonly afterLast: Statement | undefined;
5862
}
5963
interface ToMove {
6064
readonly all: ReadonlyArray<Statement>;
@@ -67,9 +71,10 @@ namespace ts.refactor {
6771
if (rangeToMove === undefined) return undefined;
6872
const all: Statement[] = [];
6973
const ranges: StatementRange[] = [];
70-
getRangesWhere(rangeToMove, s => !isPureImport(s), (start, afterEnd) => {
71-
for (let i = start; i < afterEnd; i++) all.push(rangeToMove[i]);
72-
ranges.push({ first: rangeToMove[start], last: rangeToMove[afterEnd - 1] });
74+
const { toMove, afterLast } = rangeToMove;
75+
getRangesWhere(toMove, s => !isPureImport(s), (start, afterEndIndex) => {
76+
for (let i = start; i < afterEndIndex; i++) all.push(toMove[i]);
77+
ranges.push({ first: toMove[start], afterLast });
7378
});
7479
return all.length === 0 ? undefined : { all, ranges };
7580
}
@@ -102,7 +107,7 @@ namespace ts.refactor {
102107
}
103108
}
104109

105-
function getNewStatements(
110+
function getNewStatementsAndRemoveFromOldFile(
106111
oldFile: SourceFile, usage: UsageInfo, changes: textChanges.ChangeTracker, toMove: ToMove, program: Program, newModuleName: string, preferences: UserPreferences,
107112
): ReadonlyArray<Statement> {
108113
const checker = program.getTypeChecker();
@@ -130,8 +135,8 @@ namespace ts.refactor {
130135
}
131136

132137
function deleteMovedStatements(sourceFile: SourceFile, moved: ReadonlyArray<StatementRange>, changes: textChanges.ChangeTracker) {
133-
for (const { first, last } of moved) {
134-
changes.deleteNodeRange(sourceFile, first, last);
138+
for (const { first, afterLast } of moved) {
139+
changes.deleteNodeRangeExcludingEnd(sourceFile, first, afterLast);
135140
}
136141
}
137142

src/services/textChanges.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ namespace ts.textChanges {
248248
return this;
249249
}
250250

251+
public deleteNodeRangeExcludingEnd(sourceFile: SourceFile, startNode: Node, afterEndNode: Node | undefined, options: ConfigurableStartEnd = {}): void {
252+
const startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart);
253+
const endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options, Position.FullStart);
254+
this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
255+
}
256+
251257
public deleteNodeInList(sourceFile: SourceFile, node: Node) {
252258
const containingList = formatting.SmartIndenter.getContainingList(node, sourceFile);
253259
if (!containingList) {

tests/cases/fourslash/moveToNewFile_rangeSemiValid.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
verify.moveToNewFile({
1010
newFileContents: {
1111
"/a.ts":
12-
`
13-
/** Comment */
12+
`/** Comment */
1413
const y = 0;`,
1514

1615
"/x.ts":

0 commit comments

Comments
 (0)