Skip to content

Commit 3891c96

Browse files
committed
feat: support transformation of export outside enum modifier
1 parent 8bd8d10 commit 3891c96

File tree

3 files changed

+37
-29
lines changed

3 files changed

+37
-29
lines changed

README.md

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,3 @@ export default {
148148
],
149149
};
150150
```
151-
152-
# Caveats
153-
154-
Currently, only immediate export const enum works. For example:
155-
156-
```ts
157-
// The following works
158-
export const enum WorkingEnum {}
159-
160-
// The following doesn't work
161-
const enum FailingEnum {}
162-
export FailEnum;
163-
```
164-
165-
This may be fixed in future release.

src/transform.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
11
import ts from 'typescript';
2-
import { evaluate, getModifier } from './utils';
2+
import { evaluate, getExportedNamesOfSource, hasModifier } from './utils';
33

44
export default function(program: ts.Program, pluginOptions?: unknown) {
55
return (ctx: ts.TransformationContext) => {
66
return (sourceFile: ts.SourceFile) => {
7-
const ambient = sourceFile.isDeclarationFile;
8-
97
return ts.visitEachChild(sourceFile, visitor, ctx);
108

119
function visitor(node: ts.Node): ts.Node {
1210
if (!ts.isEnumDeclaration(node)) {
1311
return ts.visitEachChild(node, visitor, ctx);
1412
}
15-
const exportModifier = getModifier(node, ts.SyntaxKind.ExportKeyword);
16-
if (!exportModifier) return node;
17-
const constModifier = getModifier(node, ts.SyntaxKind.ConstKeyword);
18-
if (!constModifier) return node;
1913

20-
if (ambient) {
14+
if (!hasModifier(node, ts.SyntaxKind.ConstKeyword)) {
15+
return node;
16+
}
17+
18+
if (!hasModifier(node, ts.SyntaxKind.ExportKeyword)) {
19+
if (!getExportedNamesOfSource(program, sourceFile).includes(node.name.text)) {
20+
return node;
21+
}
22+
}
23+
24+
if (sourceFile.isDeclarationFile) {
2125
return ts.visitEachChild(node, stripConstKeyword, ctx);
2226
}
2327

24-
return transformEnum(node, [exportModifier, constModifier]);
28+
return transformEnum(node);
2529
}
2630
};
2731
};
@@ -30,7 +34,7 @@ export default function(program: ts.Program, pluginOptions?: unknown) {
3034
return node.kind === ts.SyntaxKind.ConstKeyword ? undefined : node;
3135
}
3236

33-
function transformEnum(node: ts.EnumDeclaration, modifiers: ts.Modifier[]) {
37+
function transformEnum(node: ts.EnumDeclaration) {
3438
const members = node.members;
3539
const known = new Map<string, number | string>();
3640
const properties: ts.PropertyAssignment[] = [];
@@ -78,7 +82,7 @@ export default function(program: ts.Program, pluginOptions?: unknown) {
7882
}
7983

8084
const result = ts.factory.createVariableStatement(
81-
modifiers,
85+
node.modifiers,
8286
ts.factory.createVariableDeclarationList(
8387
[
8488
ts.factory.createVariableDeclaration(

src/utils.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,28 @@ export function evaluate(
7070
throw new Error('unexpected evaluation for enum member: ' + expr.getText);
7171
}
7272

73-
export function getModifier(node: ts.Node, modifier: ts.SyntaxKind) {
73+
export function hasModifier(node: ts.Node, modifier: ts.SyntaxKind) {
7474
return (
75-
node.modifiers
76-
&& node.modifiers.find((mod: ts.Modifier) => mod.kind === modifier)
75+
node.modifiers?.some((mod: ts.Modifier) => mod.kind === modifier)
7776
);
7877
}
78+
79+
const cachedMap = new WeakMap<ts.SourceFile, string[]>();
80+
export function getExportedNamesOfSource(program: ts.Program, sourceFile: ts.SourceFile) {
81+
const cached = cachedMap.get(sourceFile);
82+
if (cached) return cached;
83+
84+
const typeChecker = program.getTypeChecker();
85+
const sourceSymbol = typeChecker.getSymbolAtLocation(sourceFile);
86+
if (!sourceSymbol) return [];
87+
88+
const symbols = typeChecker.getExportsOfModule(sourceSymbol).map(s => {
89+
if (s.flags & ts.SymbolFlags.Alias) {
90+
return typeChecker.getAliasedSymbol(s).name;
91+
}
92+
return s.name;
93+
});
94+
95+
cachedMap.set(sourceFile, symbols);
96+
return symbols;
97+
}

0 commit comments

Comments
 (0)