Skip to content

Commit 93ac5c6

Browse files
authored
fix(54463): Move to existing file — Error: Debug Failure. at doChange4 (#54482)
1 parent 324e61e commit 93ac5c6

File tree

4 files changed

+158
-3
lines changed

4 files changed

+158
-3
lines changed

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7628,6 +7628,10 @@
76287628
"category": "Message",
76297629
"code": 95182
76307630
},
7631+
"Cannot move statements to the selected file": {
7632+
"category": "Message",
7633+
"code": 95183
7634+
},
76317635

76327636
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
76337637
"category": "Error",

src/services/refactors/moveToFile.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,20 +167,28 @@ registerRefactor(refactorNameForMoveToFile, {
167167
getEditsForAction: function getRefactorEditsToMoveToFile(context, actionName, interactiveRefactorArguments): RefactorEditInfo | undefined {
168168
Debug.assert(actionName === refactorNameForMoveToFile, "Wrong refactor invoked");
169169
const statements = Debug.checkDefined(getStatementsToMove(context));
170+
const { host, program } = context;
170171
Debug.assert(interactiveRefactorArguments, "No interactive refactor arguments available");
171172
const targetFile = interactiveRefactorArguments.targetFile;
172173
if (hasJSFileExtension(targetFile) || hasTSFileExtension(targetFile)) {
173-
const edits = textChanges.ChangeTracker.with(context, t => doChange(context, context.file, interactiveRefactorArguments.targetFile, context.program, statements, t, context.host, context.preferences));
174+
if (host.fileExists(targetFile) && program.getSourceFile(targetFile) === undefined) {
175+
return error(getLocaleSpecificMessage(Diagnostics.Cannot_move_statements_to_the_selected_file));
176+
}
177+
const edits = textChanges.ChangeTracker.with(context, t => doChange(context, context.file, interactiveRefactorArguments.targetFile, program, statements, t, context.host, context.preferences));
174178
return { edits, renameFilename: undefined, renameLocation: undefined };
175179
}
176-
return { edits: [], renameFilename: undefined, renameLocation: undefined, notApplicableReason: getLocaleSpecificMessage(Diagnostics.Cannot_move_to_file_selected_file_is_invalid) };
180+
return error(getLocaleSpecificMessage(Diagnostics.Cannot_move_to_file_selected_file_is_invalid));
177181
}
178182
});
179183

184+
function error(notApplicableReason: string) {
185+
return { edits: [], renameFilename: undefined, renameLocation: undefined, notApplicableReason };
186+
}
187+
180188
function doChange(context: RefactorContext, oldFile: SourceFile, targetFile: string, program: Program, toMove: ToMove, changes: textChanges.ChangeTracker, host: LanguageServiceHost, preferences: UserPreferences): void {
181189
const checker = program.getTypeChecker();
182190
const usage = getUsageInfo(oldFile, toMove.all, checker);
183-
//For a new file
191+
// For a new file
184192
if (!host.fileExists(targetFile)) {
185193
changes.createNewFile(oldFile, targetFile, getNewStatementsAndRemoveFromOldFile(oldFile, targetFile, usage, changes, toMove, program, host, preferences));
186194
addNewFileToTsconfig(program, changes, oldFile.fileName, targetFile, hostGetCanonicalFileName(host));

src/testRunner/unittests/tsserver/refactors.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,46 @@ describe("unittests:: tsserver:: refactors", () => {
153153
});
154154
baselineTsserverLogs("refactors", "handles moving statements to a non-TS file", session);
155155
});
156+
157+
it("handles moving statements to a TS file that is not included in the TS project", () => {
158+
const fooATs: File = {
159+
path: "/Foo/a.ts",
160+
content: ""
161+
};
162+
const fooTsconfig: File = {
163+
path: "/Foo/tsconfig.json",
164+
content: `{ "files": ["./a.ts"] }`
165+
};
166+
167+
const barATs: File = {
168+
path: "/Bar/a.ts",
169+
content: [
170+
"const a = 1;",
171+
"const b = 2;",
172+
"console.log(a, b);",
173+
].join("\n")
174+
};
175+
const barTsconfig: File = {
176+
path: "/Bar/tsconfig.json",
177+
content: `{ "files": ["./a.ts"] }`
178+
};
179+
const host = createServerHost([fooATs, fooTsconfig, barATs, barTsconfig]);
180+
const session = createSession(host, { logger: createLoggerWithInMemoryLogs(host) });
181+
openFilesForSession([barATs], session);
182+
183+
session.executeCommandSeq<ts.server.protocol.GetEditsForRefactorRequest>({
184+
command: ts.server.protocol.CommandTypes.GetEditsForRefactor,
185+
arguments: {
186+
file: barATs.path,
187+
startLine: 1,
188+
startOffset: 1,
189+
endLine: 1,
190+
endOffset: 13,
191+
refactor: "Move to file",
192+
action: "Move to file",
193+
interactiveRefactorArguments: { targetFile: "/Foo/a.ts" },
194+
}
195+
});
196+
baselineTsserverLogs("refactors", "handles moving statements to a TS file that is not included in the TS project", session);
197+
});
156198
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
currentDirectory:: / useCaseSensitiveFileNames: false
2+
Info seq [hh:mm:ss:mss] Provided types map file "/a/lib/typesMap.json" doesn't exist
3+
Before request
4+
//// [/Foo/a.ts]
5+
6+
7+
//// [/Foo/tsconfig.json]
8+
{ "files": ["./a.ts"] }
9+
10+
//// [/Bar/a.ts]
11+
const a = 1;
12+
const b = 2;
13+
console.log(a, b);
14+
15+
//// [/Bar/tsconfig.json]
16+
{ "files": ["./a.ts"] }
17+
18+
19+
Info seq [hh:mm:ss:mss] request:
20+
{
21+
"command": "open",
22+
"arguments": {
23+
"file": "/Bar/a.ts"
24+
},
25+
"seq": 1,
26+
"type": "request"
27+
}
28+
Info seq [hh:mm:ss:mss] Search path: /Bar
29+
Info seq [hh:mm:ss:mss] For info: /Bar/a.ts :: Config file name: /Bar/tsconfig.json
30+
Info seq [hh:mm:ss:mss] Creating configuration project /Bar/tsconfig.json
31+
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /Bar/tsconfig.json 2000 undefined Project: /Bar/tsconfig.json WatchType: Config file
32+
Info seq [hh:mm:ss:mss] Config: /Bar/tsconfig.json : {
33+
"rootNames": [
34+
"/Bar/a.ts"
35+
],
36+
"options": {
37+
"configFilePath": "/Bar/tsconfig.json"
38+
}
39+
}
40+
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /Bar/tsconfig.json
41+
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined Project: /Bar/tsconfig.json WatchType: Missing file
42+
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /Bar/tsconfig.json Version: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms
43+
Info seq [hh:mm:ss:mss] Project '/Bar/tsconfig.json' (Configured)
44+
Info seq [hh:mm:ss:mss] Files (1)
45+
/Bar/a.ts SVC-1-0 "const a = 1;\nconst b = 2;\nconsole.log(a, b);"
46+
47+
48+
a.ts
49+
Part of 'files' list in tsconfig.json
50+
51+
Info seq [hh:mm:ss:mss] -----------------------------------------------
52+
Info seq [hh:mm:ss:mss] Project '/Bar/tsconfig.json' (Configured)
53+
Info seq [hh:mm:ss:mss] Files (1)
54+
55+
Info seq [hh:mm:ss:mss] -----------------------------------------------
56+
Info seq [hh:mm:ss:mss] Open files:
57+
Info seq [hh:mm:ss:mss] FileName: /Bar/a.ts ProjectRootPath: undefined
58+
Info seq [hh:mm:ss:mss] Projects: /Bar/tsconfig.json
59+
Info seq [hh:mm:ss:mss] response:
60+
{
61+
"responseRequired": false
62+
}
63+
After request
64+
65+
PolledWatches::
66+
/a/lib/lib.d.ts: *new*
67+
{"pollingInterval":500}
68+
69+
FsWatches::
70+
/bar/tsconfig.json: *new*
71+
{}
72+
73+
Before request
74+
75+
Info seq [hh:mm:ss:mss] request:
76+
{
77+
"command": "getEditsForRefactor",
78+
"arguments": {
79+
"file": "/Bar/a.ts",
80+
"startLine": 1,
81+
"startOffset": 1,
82+
"endLine": 1,
83+
"endOffset": 13,
84+
"refactor": "Move to file",
85+
"action": "Move to file",
86+
"interactiveRefactorArguments": {
87+
"targetFile": "/Foo/a.ts"
88+
}
89+
},
90+
"seq": 2,
91+
"type": "request"
92+
}
93+
Info seq [hh:mm:ss:mss] response:
94+
{
95+
"response": {
96+
"edits": [],
97+
"notApplicableReason": "Cannot move statements to the selected file"
98+
},
99+
"responseRequired": true
100+
}
101+
After request

0 commit comments

Comments
 (0)