Skip to content

Commit f621d67

Browse files
authored
fix(42605): support refactoring for export default assignment without equal (#42936)
1 parent cf8798d commit f621d67

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

src/services/findAllReferences.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,9 @@ namespace ts.FindAllReferences {
11801180
for (const indirectUser of indirectUsers) {
11811181
for (const node of getPossibleSymbolReferenceNodes(indirectUser, isDefaultExport ? "default" : exportName)) {
11821182
// Import specifiers should be handled by importSearches
1183-
if (isIdentifier(node) && !isImportOrExportSpecifier(node.parent) && checker.getSymbolAtLocation(node) === exportSymbol) {
1183+
const symbol = checker.getSymbolAtLocation(node);
1184+
const hasExportAssignmentDeclaration = some(symbol?.declarations, d => tryCast(d, isExportAssignment) ? true : false);
1185+
if (isIdentifier(node) && !isImportOrExportSpecifier(node.parent) && (symbol === exportSymbol || hasExportAssignmentDeclaration)) {
11841186
cb(node);
11851187
}
11861188
}

src/services/refactors/convertExport.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ namespace ts.refactor {
4848
});
4949

5050
// If a VariableStatement, will have exactly one VariableDeclaration, with an Identifier for a name.
51-
type ExportToConvert = FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | EnumDeclaration | NamespaceDeclaration | TypeAliasDeclaration | VariableStatement;
51+
type ExportToConvert = FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | EnumDeclaration | NamespaceDeclaration | TypeAliasDeclaration | VariableStatement | ExportAssignment;
5252
interface ExportInfo {
5353
readonly exportNode: ExportToConvert;
5454
readonly exportName: Identifier; // This is exportNode.name except for VariableStatement_s.
@@ -67,7 +67,8 @@ namespace ts.refactor {
6767

6868
const exportingModuleSymbol = isSourceFile(exportNode.parent) ? exportNode.parent.symbol : exportNode.parent.parent.symbol;
6969

70-
const flags = getSyntacticModifierFlags(exportNode);
70+
const flags = getSyntacticModifierFlags(exportNode) || ((isExportAssignment(exportNode) && !exportNode.isExportEquals) ? ModifierFlags.ExportDefault : ModifierFlags.None);
71+
7172
const wasDefault = !!(flags & ModifierFlags.Default);
7273
// If source file already has a default export, don't offer refactor.
7374
if (!(flags & ModifierFlags.Export) || !wasDefault && exportingModuleSymbol.exports!.has(InternalSymbolName.Default)) {
@@ -95,6 +96,11 @@ namespace ts.refactor {
9596
Debug.assert(!wasDefault, "Can't have a default flag here");
9697
return isIdentifier(decl.name) ? { exportNode: vs, exportName: decl.name, wasDefault, exportingModuleSymbol } : undefined;
9798
}
99+
case SyntaxKind.ExportAssignment: {
100+
const node = exportNode as ExportAssignment;
101+
const exp = node.expression as Identifier;
102+
return node.isExportEquals ? undefined : { exportNode: node, exportName: exp, wasDefault, exportingModuleSymbol };
103+
}
98104
default:
99105
return undefined;
100106
}
@@ -107,7 +113,14 @@ namespace ts.refactor {
107113

108114
function changeExport(exportingSourceFile: SourceFile, { wasDefault, exportNode, exportName }: ExportInfo, changes: textChanges.ChangeTracker, checker: TypeChecker): void {
109115
if (wasDefault) {
110-
changes.delete(exportingSourceFile, Debug.checkDefined(findModifier(exportNode, SyntaxKind.DefaultKeyword), "Should find a default keyword in modifier list"));
116+
if (isExportAssignment(exportNode) && !exportNode.isExportEquals) {
117+
const exp = exportNode.expression as Identifier;
118+
const spec = makeExportSpecifier(exp.text, exp.text);
119+
changes.replaceNode(exportingSourceFile, exportNode, factory.createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, factory.createNamedExports([spec])));
120+
}
121+
else {
122+
changes.delete(exportingSourceFile, Debug.checkDefined(findModifier(exportNode, SyntaxKind.DefaultKeyword), "Should find a default keyword in modifier list"));
123+
}
111124
}
112125
else {
113126
const exportKeyword = Debug.checkDefined(findModifier(exportNode, SyntaxKind.ExportKeyword), "Should find an export keyword in modifier list");
@@ -134,7 +147,7 @@ namespace ts.refactor {
134147
changes.insertNodeAfter(exportingSourceFile, exportNode, factory.createExportDefault(factory.createIdentifier(exportName.text)));
135148
break;
136149
default:
137-
Debug.assertNever(exportNode, `Unexpected exportNode kind ${(exportNode as ExportToConvert).kind}`);
150+
Debug.fail(`Unexpected exportNode kind ${(exportNode as ExportToConvert).kind}`);
138151
}
139152
}
140153
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @Filename: /a.ts
4+
////const f = () => {};
5+
/////*a*/export default f;/*b*/
6+
7+
// @Filename: /b.ts
8+
////import f from "./a";
9+
////import { default as f } from "./a";
10+
////import { default as g } from "./a";
11+
////import f, * as a from "./a";
12+
////
13+
////export { default } from "./a";
14+
////export { default as f } from "./a";
15+
////export { default as i } from "./a";
16+
////
17+
////import * as a from "./a";
18+
////a.default();
19+
20+
goTo.select("a", "b");
21+
edit.applyRefactor({
22+
refactorName: "Convert export",
23+
actionName: "Convert default export to named export",
24+
actionDescription: "Convert default export to named export",
25+
newContent: {
26+
"/a.ts":
27+
`const f = () => {};
28+
export { f };`,
29+
30+
"/b.ts":
31+
`import { f } from "./a";
32+
import { f } from "./a";
33+
import { f as g } from "./a";
34+
import * as a from "./a";
35+
import { f } from "./a";
36+
37+
export { f as default } from "./a";
38+
export { f } from "./a";
39+
export { f as i } from "./a";
40+
41+
import * as a from "./a";
42+
a.f();`,
43+
},
44+
});

0 commit comments

Comments
 (0)