Skip to content

Commit 8b1ecdb

Browse files
authoredOct 26, 2022
fix(50654): "Move to a new file" breaks the declaration of referenced variable (#50681)
* fix(50654): remove entire import require call instead of the name * handle require imports in ts files
1 parent 170a17f commit 8b1ecdb

File tree

4 files changed

+109
-3
lines changed

4 files changed

+109
-3
lines changed
 

‎src/services/refactors/moveToNewFile.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ namespace ts.refactor {
133133
) {
134134
const checker = program.getTypeChecker();
135135
const prologueDirectives = takeWhile(oldFile.statements, isPrologueDirective);
136-
if (!oldFile.externalModuleIndicator && !oldFile.commonJsModuleIndicator) {
136+
if (oldFile.externalModuleIndicator === undefined && oldFile.commonJsModuleIndicator === undefined && usage.oldImportsNeededByNewFile.size() === 0) {
137137
deleteMovedStatements(oldFile, toMove.ranges, changes);
138138
return [...prologueDirectives, ...toMove.all];
139139
}
@@ -402,7 +402,13 @@ namespace ts.refactor {
402402
switch (name.kind) {
403403
case SyntaxKind.Identifier:
404404
if (isUnused(name)) {
405-
changes.delete(sourceFile, name);
405+
if (varDecl.initializer && isRequireCall(varDecl.initializer, /*requireStringLiteralLikeArgument*/ true)) {
406+
changes.delete(sourceFile,
407+
isVariableDeclarationList(varDecl.parent) && length(varDecl.parent.declarations) === 1 ? varDecl.parent.parent : varDecl);
408+
}
409+
else {
410+
changes.delete(sourceFile, name);
411+
}
406412
}
407413
break;
408414
case SyntaxKind.ArrayBindingPattern:
@@ -641,10 +647,12 @@ namespace ts.refactor {
641647
}
642648

643649
interface ReadonlySymbolSet {
650+
size(): number;
644651
has(symbol: Symbol): boolean;
645652
forEach(cb: (symbol: Symbol) => void): void;
646653
forEachEntry<T>(cb: (symbol: Symbol) => T | undefined): T | undefined;
647654
}
655+
648656
class SymbolSet implements ReadonlySymbolSet {
649657
private map = new Map<string, Symbol>();
650658
add(symbol: Symbol): void {
@@ -667,6 +675,9 @@ namespace ts.refactor {
667675
copyEntries(this.map, clone.map);
668676
return clone;
669677
}
678+
size() {
679+
return this.map.size;
680+
}
670681
}
671682

672683
type TopLevelExpressionStatement = ExpressionStatement & { expression: BinaryExpression & { left: PropertyAccessExpression } }; // 'exports.x = ...'
@@ -775,7 +786,8 @@ namespace ts.refactor {
775786
if (useEs6Exports) {
776787
return !isExpressionStatement(decl) && hasSyntacticModifier(decl, ModifierFlags.Export) || !!(name && sourceFile.symbol.exports?.has(name.escapedText));
777788
}
778-
return getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports!.has(escapeLeadingUnderscores(name)));
789+
return !!sourceFile.symbol && !!sourceFile.symbol.exports &&
790+
getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports!.has(escapeLeadingUnderscores(name)));
779791
}
780792

781793
function addExport(decl: TopLevelDeclarationStatement, useEs6Exports: boolean): readonly Statement[] | undefined {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @allowJs: true
4+
5+
// @filename: /a.js
6+
////module.exports = 1;
7+
8+
// @filename: /b.js
9+
////var a = require("./a");
10+
////[|function f() {
11+
//// a;
12+
////}|]
13+
14+
verify.noErrors();
15+
16+
verify.moveToNewFile({
17+
newFileContents: {
18+
"/b.js": "",
19+
20+
"/f.js":
21+
`var a = require("./a");
22+
23+
function f() {
24+
a;
25+
}
26+
`,
27+
},
28+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @allowJs: true
4+
5+
// @filename: /a.js
6+
////module.exports = 1;
7+
8+
// @filename: /b.js
9+
////var a = require("./a"),
10+
//// b = require("./a"),
11+
//// c = require("./a");
12+
////[|function f() {
13+
//// b;
14+
////}|]
15+
16+
verify.noErrors();
17+
18+
verify.moveToNewFile({
19+
newFileContents: {
20+
"/b.js":
21+
`var a = require("./a"),
22+
c = require("./a");
23+
`,
24+
25+
"/f.js":
26+
`var b = require("./a");
27+
28+
function f() {
29+
b;
30+
}
31+
`,
32+
},
33+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @module: commonjs
4+
// @moduleResolution: node
5+
6+
// @filename: /node.d.ts
7+
////declare var module: any;
8+
////declare var require: any;
9+
10+
// @filename: /a.ts
11+
////module.exports = 1;
12+
13+
// @filename: /b.ts
14+
////var a = require("./a");
15+
////[|function f() {
16+
//// a;
17+
////}|]
18+
19+
verify.noErrors();
20+
21+
verify.moveToNewFile({
22+
newFileContents: {
23+
"/b.ts": "",
24+
25+
"/f.ts":
26+
`var a = require("./a");
27+
28+
function f() {
29+
a;
30+
}
31+
`,
32+
},
33+
});

0 commit comments

Comments
 (0)
Please sign in to comment.