Skip to content

Commit 7102de7

Browse files
committed
Consider JSX namespace imports when moving statements between files
Each of the old and new files should end up with a JSX namespace import iff it contains JSX. Fixes #27939
1 parent 41a7bf4 commit 7102de7

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

src/services/refactors/moveToNewFile.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,12 @@ namespace ts.refactor {
460460
const oldImportsNeededByNewFile = new SymbolSet();
461461
const newFileImportsFromOldFile = new SymbolSet();
462462

463+
const containsJsx = find(toMove, statement => !!(statement.transformFlags & TransformFlags.ContainsJsx));
464+
const jsxNamespaceSymbol = getJsxNamespaceSymbol(containsJsx);
465+
if (jsxNamespaceSymbol) { // Might not exist (e.g. in non-compiling code)
466+
oldImportsNeededByNewFile.add(jsxNamespaceSymbol);
467+
}
468+
463469
for (const statement of toMove) {
464470
forEachTopLevelDeclaration(statement, decl => {
465471
movedSymbols.add(Debug.assertDefined(isExpressionStatement(decl) ? checker.getSymbolAtLocation(decl.expression.left) : decl.symbol));
@@ -485,13 +491,30 @@ namespace ts.refactor {
485491
for (const statement of oldFile.statements) {
486492
if (contains(toMove, statement)) continue;
487493

494+
// jsxNamespaceSymbol will only be set iff it is in oldImportsNeededByNewFile.
495+
if (jsxNamespaceSymbol && !!(statement.transformFlags & TransformFlags.ContainsJsx)) {
496+
unusedImportsFromOldFile.delete(jsxNamespaceSymbol);
497+
}
498+
488499
forEachReference(statement, checker, symbol => {
489500
if (movedSymbols.has(symbol)) oldFileImportsFromNewFile.add(symbol);
490501
unusedImportsFromOldFile.delete(symbol);
491502
});
492503
}
493504

494505
return { movedSymbols, newFileImportsFromOldFile, oldFileImportsFromNewFile, oldImportsNeededByNewFile, unusedImportsFromOldFile };
506+
507+
function getJsxNamespaceSymbol(containsJsx: Node | undefined) {
508+
if (containsJsx === undefined) {
509+
return undefined;
510+
}
511+
512+
const jsxNamespace = checker.getJsxNamespace(containsJsx);
513+
const jsxNamespaceSymbol = checker.resolveName(jsxNamespace, containsJsx, SymbolFlags.Namespace, /*excludeGlobals*/ true);
514+
return !!jsxNamespaceSymbol && some(jsxNamespaceSymbol.declarations, isInImport)
515+
? jsxNamespaceSymbol
516+
: undefined;
517+
}
495518
}
496519

497520
// Below should all be utilities
@@ -512,7 +535,7 @@ namespace ts.refactor {
512535
}
513536
function isVariableDeclarationInImport(decl: VariableDeclaration) {
514537
return isSourceFile(decl.parent.parent.parent) &&
515-
decl.initializer && isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true);
538+
!!decl.initializer && isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true);
516539
}
517540

518541
function filterImport(i: SupportedImport, moduleSpecifier: StringLiteralLike, keep: (name: Identifier) => boolean): SupportedImportStatement | undefined {

0 commit comments

Comments
 (0)