Skip to content

Commit 05666fc

Browse files
Fix move to file refactor issue with React components
Added proper check for SymbolFlags.Module before calling addImportForModuleSymbol to prevent debug assertion failure when moving non-module symbols like React components. Co-authored-by: RyanCavanaugh <[email protected]>
1 parent 917e69c commit 05666fc

2 files changed

Lines changed: 25 additions & 20 deletions

File tree

src/services/refactors/helpers.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,18 @@ export function addTargetFileImports(
7575
* but sometimes it fails because of unresolved imports from files, or when a source file is not available for the target file (in this case when creating a new file).
7676
* So in that case, fall back to copying the import verbatim.
7777
*/
78-
importsToCopy.forEach(([isValidTypeOnlyUseSite, declaration], symbol) => {
79-
const targetSymbol = skipAlias(symbol, checker);
80-
if (checker.isUnknownSymbol(targetSymbol)) {
81-
importAdder.addVerbatimImport(Debug.checkDefined(declaration ?? findAncestor(symbol.declarations?.[0], isAnyImportOrRequireStatement)));
82-
}
83-
else if (targetSymbol.parent === undefined) {
84-
Debug.assert(declaration !== undefined, "expected module symbol to have a declaration");
85-
importAdder.addImportForModuleSymbol(symbol, isValidTypeOnlyUseSite, declaration);
86-
}
87-
else {
88-
importAdder.addImportFromExportedSymbol(targetSymbol, isValidTypeOnlyUseSite, declaration);
89-
}
78+
importsToCopy.forEach(([isValidTypeOnlyUseSite, declaration], symbol) => {
79+
const targetSymbol = skipAlias(symbol, checker);
80+
if (checker.isUnknownSymbol(targetSymbol)) {
81+
importAdder.addVerbatimImport(Debug.checkDefined(declaration ?? findAncestor(symbol.declarations?.[0], isAnyImportOrRequireStatement)));
82+
}
83+
else if (targetSymbol.parent === undefined && (targetSymbol.flags & SymbolFlags.Module)) {
84+
Debug.assert(declaration !== undefined, "expected module symbol to have a declaration");
85+
importAdder.addImportForModuleSymbol(symbol, isValidTypeOnlyUseSite, declaration);
86+
}
87+
else {
88+
importAdder.addImportFromExportedSymbol(targetSymbol, isValidTypeOnlyUseSite, declaration);
89+
}
9090
});
9191

9292
addImportsForMovedSymbols(targetFileImportsFromOldFile, oldFile.fileName, importAdder, program);

tests/cases/fourslash/moveToNewFileReactComponent.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,36 @@
44

55
// @Filename: /Component.tsx
66
////import React from 'react';
7+
////import { useState } from 'react';
78
////
89
////export const ComponentA = () => {
9-
//// return <div>Component A</div>;
10+
//// const [count, setCount] = useState(0);
11+
//// return <div onClick={() => setCount(count + 1)}>Component A: {count}</div>;
1012
////};
1113
////
1214
////[|export const ComponentB = () => {
13-
//// return <div>Component B</div>;
15+
//// const [text, setText] = useState('Hello');
16+
//// return <div><input value={text} onChange={(e) => setText(e.target.value)} /><span>{text}</span></div>;
1417
////};|]
1518

1619
verify.moveToNewFile({
1720
newFileContents: {
1821
"/Component.tsx":
1922
`import React from 'react';
23+
import { useState } from 'react';
2024
2125
export const ComponentA = () => {
22-
return <div>Component A</div>;
23-
};
24-
`,
26+
const [count, setCount] = useState(0);
27+
return <div onClick={() => setCount(count + 1)}>Component A: {count}</div>;
28+
};`,
2529

2630
"/ComponentB.tsx":
2731
`import React from 'react';
32+
import { useState } from 'react';
2833
2934
export const ComponentB = () => {
30-
return <div>Component B</div>;
31-
};
32-
`,
35+
const [text, setText] = useState('Hello');
36+
return <div><input value={text} onChange={(e) => setText(e.target.value)} /><span>{text}</span></div>;
37+
};`,
3338
},
3439
});

0 commit comments

Comments
 (0)