@eliasku/ts-transformers 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/package.json +5 -4
- package/src/const-enum/evaluator.ts +0 -3
- package/src/const-enum/registry.ts +0 -16
- package/src/{mangler/exports → exports}/tracker.ts +1 -1
- package/src/{mangler/index.ts → index.ts} +97 -20
- package/src/{mangler/types.ts → types.ts} +8 -2
- package/src/const-enum/index.ts +0 -181
- /package/src/{mangler/typescript-helpers.ts → typescript-helpers.ts} +0 -0
- /package/src/{mangler/utils → utils}/ast-utils.ts +0 -0
- /package/src/{mangler/utils → utils}/symbol-utils.ts +0 -0
package/README.md
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @eliasku/ts-transformers
|
|
2
|
+
|
|
3
|
+
TypeScript transformer for code optimization.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { optimizer } from "@eliasku/ts-transformers";
|
|
9
|
+
|
|
10
|
+
transformers: (program) => ({
|
|
11
|
+
before: [
|
|
12
|
+
optimizer(program, {
|
|
13
|
+
entrySourceFiles: ["./src/index.ts"],
|
|
14
|
+
inlineConstEnums: true,
|
|
15
|
+
}),
|
|
16
|
+
],
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Options
|
|
21
|
+
|
|
22
|
+
### entrySourceFiles (required)
|
|
23
|
+
|
|
24
|
+
An array of entry source files which will be used to detect exported and internal fields. Basically it should be entry point(s) of the library/project.
|
|
25
|
+
|
|
26
|
+
### inlineConstEnums (optional, default: true)
|
|
27
|
+
|
|
28
|
+
Whether to inline const enum values and remove const enum declarations.
|
|
29
|
+
|
|
30
|
+
### privatePrefix (optional, default: "$p$")
|
|
31
|
+
|
|
32
|
+
Prefix of generated names for private fields.
|
|
33
|
+
|
|
34
|
+
### internalPrefix (optional, default: "$i$")
|
|
35
|
+
|
|
36
|
+
Prefix of generated names for internal fields.
|
|
37
|
+
|
|
38
|
+
### publicJSDocTag (optional, default: "public")
|
|
39
|
+
|
|
40
|
+
Comment which will treat a class/interface/type/property/etc and all its children as "public". Set it to empty string to disable using JSDoc comment to detect "visibility level".
|
|
41
|
+
|
|
42
|
+
### ignoreDecorated (optional, default: false)
|
|
43
|
+
|
|
44
|
+
Whether fields that were decorated should be renamed. A field is treated as "decorated" if itself or any its parent (on type level) has a decorator.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eliasku/ts-transformers",
|
|
3
|
-
"description": "",
|
|
4
|
-
"version": "0.0.
|
|
3
|
+
"description": "TypeScript transformer for code optimization",
|
|
4
|
+
"version": "0.0.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
@@ -22,9 +22,10 @@
|
|
|
22
22
|
"@rollup/plugin-typescript": "latest",
|
|
23
23
|
"tslib": "latest"
|
|
24
24
|
},
|
|
25
|
+
"module": "./src/index.ts",
|
|
26
|
+
"types": "./src/index.ts",
|
|
25
27
|
"exports": {
|
|
26
|
-
"
|
|
27
|
-
"./const-enum": "./src/const-enum/index.ts"
|
|
28
|
+
".": "./src/index.ts"
|
|
28
29
|
},
|
|
29
30
|
"repository": {
|
|
30
31
|
"type": "git",
|
|
@@ -58,7 +58,6 @@ export class EnumEvaluator {
|
|
|
58
58
|
|
|
59
59
|
private evaluateImplicitMember(member: ts.EnumMember): EnumValue {
|
|
60
60
|
const name = ts.isIdentifier(member.name) ? member.name.text : `<computed>`;
|
|
61
|
-
// unused
|
|
62
61
|
void name;
|
|
63
62
|
|
|
64
63
|
if (this.lastImplicitValue === -1) {
|
|
@@ -104,12 +103,10 @@ export class EnumEvaluator {
|
|
|
104
103
|
const left = this.evaluate(expr.left, context);
|
|
105
104
|
const right = this.evaluate(expr.right, context);
|
|
106
105
|
|
|
107
|
-
// String concatenation
|
|
108
106
|
if (typeof left === "string" && typeof right === "string" && expr.operatorToken.kind === ts.SyntaxKind.PlusToken) {
|
|
109
107
|
return left + right;
|
|
110
108
|
}
|
|
111
109
|
|
|
112
|
-
// Numeric operations
|
|
113
110
|
if (typeof left === "number" && typeof right === "number") {
|
|
114
111
|
switch (expr.operatorToken.kind) {
|
|
115
112
|
case ts.SyntaxKind.BarToken:
|
|
@@ -2,7 +2,6 @@ import ts from "typescript";
|
|
|
2
2
|
import { EnumValue, EvaluationContext } from "./evaluator";
|
|
3
3
|
import { EnumEvaluator } from "./evaluator";
|
|
4
4
|
import { hasModifier, isConstEnumSymbol } from "./utils";
|
|
5
|
-
import { LOGS } from "../config";
|
|
6
5
|
|
|
7
6
|
export interface ConstEnumInfo {
|
|
8
7
|
declaration: ts.EnumDeclaration;
|
|
@@ -56,29 +55,15 @@ export class ConstEnumRegistry {
|
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
private collectConstEnumsFromEntryPoints(): void {
|
|
59
|
-
if (LOGS) {
|
|
60
|
-
console.log(`[const-enum registry] Starting collection from ${this.entrySourceFiles.length} entry point(s)`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Collect all const enums from the entire program
|
|
64
58
|
const sourceFiles = this.program.getSourceFiles();
|
|
65
|
-
if (LOGS) {
|
|
66
|
-
console.log(`[const-enum registry] Program has ${sourceFiles.length} source files`);
|
|
67
|
-
}
|
|
68
59
|
|
|
69
60
|
for (const sourceFile of sourceFiles) {
|
|
70
|
-
// We are using typescript files from node_modules as well, so don't skip them
|
|
71
|
-
// but skip declaration files
|
|
72
61
|
if (sourceFile.isDeclarationFile) {
|
|
73
62
|
continue;
|
|
74
63
|
}
|
|
75
64
|
|
|
76
65
|
this.registerConstEnumFromSource(sourceFile);
|
|
77
66
|
}
|
|
78
|
-
|
|
79
|
-
if (LOGS) {
|
|
80
|
-
console.log(`[const-enum registry] Found ${this.enumDeclarations.size} const enum declarations`);
|
|
81
|
-
}
|
|
82
67
|
}
|
|
83
68
|
|
|
84
69
|
private registerConstEnumFromSource(sourceFile: ts.SourceFile): void {
|
|
@@ -96,7 +81,6 @@ export class ConstEnumRegistry {
|
|
|
96
81
|
const name = this.getEnumSymbolName(symbol);
|
|
97
82
|
|
|
98
83
|
if (this.enumDeclarations.has(name)) {
|
|
99
|
-
// Already registered (might be from different import)
|
|
100
84
|
return;
|
|
101
85
|
}
|
|
102
86
|
|
|
@@ -14,23 +14,26 @@ import {
|
|
|
14
14
|
isNodeNamedDeclaration,
|
|
15
15
|
} from "./utils/symbol-utils";
|
|
16
16
|
import { getNodeJSDocComment } from "./utils/ast-utils";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
17
|
+
import { OptimizerOptions, defaultOptions, VisibilityType } from "./types";
|
|
18
|
+
import { ConstEnumRegistry } from "./const-enum/registry";
|
|
19
|
+
import { EnumEvaluator } from "./const-enum/evaluator";
|
|
20
|
+
import { isConstEnumType } from "./const-enum/utils";
|
|
21
|
+
import { LOGS } from "./config";
|
|
19
22
|
|
|
20
|
-
export
|
|
23
|
+
export const optimizer = (
|
|
21
24
|
program: ts.Program,
|
|
22
|
-
config?: Partial<
|
|
23
|
-
): ts.TransformerFactory<ts.SourceFile>
|
|
24
|
-
return createTransformerFactory(program, config);
|
|
25
|
-
}
|
|
25
|
+
config?: Partial<OptimizerOptions>,
|
|
26
|
+
): ts.TransformerFactory<ts.SourceFile> => createTransformerFactory(program, config);
|
|
26
27
|
|
|
27
28
|
function createTransformerFactory(
|
|
28
29
|
program: ts.Program,
|
|
29
|
-
options?: Partial<
|
|
30
|
+
options?: Partial<OptimizerOptions>,
|
|
30
31
|
): ts.TransformerFactory<ts.SourceFile> {
|
|
31
|
-
const fullOptions:
|
|
32
|
+
const fullOptions: OptimizerOptions = { ...defaultOptions, ...options };
|
|
32
33
|
const typeChecker = program.getTypeChecker();
|
|
33
34
|
const exportsSymbolTree = new ExportsSymbolTree(program, fullOptions.entrySourceFiles);
|
|
35
|
+
const constEnumRegistry = new ConstEnumRegistry(program, fullOptions.entrySourceFiles);
|
|
36
|
+
const enumEvaluator = new EnumEvaluator(typeChecker);
|
|
34
37
|
|
|
35
38
|
const cache = new Map<ts.Symbol, VisibilityType>();
|
|
36
39
|
|
|
@@ -40,17 +43,24 @@ function createTransformerFactory(
|
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
return (context: ts.TransformationContext) => {
|
|
43
|
-
function transformNodeAndChildren(node: ts.SourceFile, ctx: ts.TransformationContext): ts.SourceFile;
|
|
44
|
-
function transformNodeAndChildren(node: ts.Node, ctx: ts.TransformationContext): ts.Node;
|
|
45
|
-
function transformNodeAndChildren(node: ts.Node, ctx: ts.TransformationContext): ts.Node {
|
|
46
|
-
return ts.visitEachChild(
|
|
47
|
-
transformNode(node),
|
|
48
|
-
(childNode: ts.Node) => transformNodeAndChildren(childNode, ctx),
|
|
49
|
-
ctx,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
46
|
function transformNode(node: ts.Node): ts.Node {
|
|
47
|
+
if (fullOptions.inlineConstEnums !== false) {
|
|
48
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
49
|
+
const inlined = tryInlineConstEnum(node);
|
|
50
|
+
if (inlined) return inlined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (ts.isImportSpecifier(node)) {
|
|
54
|
+
const removed = tryRemoveConstEnumImport(node);
|
|
55
|
+
if (removed === undefined) return undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (ts.isImportClause(node)) {
|
|
59
|
+
const removed = tryRemoveConstEnumImportClause(node);
|
|
60
|
+
if (removed === undefined) return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
54
64
|
// const a = { node }
|
|
55
65
|
if (ts.isShorthandPropertyAssignment(node)) {
|
|
56
66
|
return handleShorthandPropertyAssignment(node);
|
|
@@ -637,6 +647,73 @@ function createTransformerFactory(
|
|
|
637
647
|
return isSymbolClassMember(typeChecker.getSymbolAtLocation(node));
|
|
638
648
|
}
|
|
639
649
|
|
|
640
|
-
|
|
650
|
+
function tryInlineConstEnum(node: ts.PropertyAccessExpression): ts.Expression | null {
|
|
651
|
+
const expressionType = typeChecker.getTypeAtLocation(node.expression);
|
|
652
|
+
if (!isConstEnumType(expressionType)) return null;
|
|
653
|
+
|
|
654
|
+
const enumSymbol = expressionType.symbol || expressionType.aliasSymbol;
|
|
655
|
+
if (!enumSymbol) return null;
|
|
656
|
+
|
|
657
|
+
const enumInfo = constEnumRegistry.getEnumInfo(enumSymbol);
|
|
658
|
+
if (!enumInfo) return null;
|
|
659
|
+
|
|
660
|
+
const memberValue = enumInfo.members.get(node.name.text)?.value;
|
|
661
|
+
if (memberValue === undefined || memberValue === null) return null;
|
|
662
|
+
|
|
663
|
+
return enumEvaluator.createLiteral(memberValue);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function tryRemoveConstEnumImport(node: ts.ImportSpecifier): ts.ImportSpecifier | undefined {
|
|
667
|
+
const importedType = typeChecker.getTypeAtLocation(node);
|
|
668
|
+
if (isConstEnumType(importedType)) {
|
|
669
|
+
return undefined;
|
|
670
|
+
}
|
|
671
|
+
return node;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
function tryRemoveConstEnumImportClause(node: ts.ImportClause): ts.ImportClause | undefined {
|
|
675
|
+
if (!node.name) return node;
|
|
676
|
+
const type = typeChecker.getTypeAtLocation(node.name);
|
|
677
|
+
if (isConstEnumType(type)) {
|
|
678
|
+
return undefined;
|
|
679
|
+
}
|
|
680
|
+
return node;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
return (sourceFile: ts.SourceFile) => {
|
|
684
|
+
function handleEnumDeclaration(node: ts.EnumDeclaration): ts.EnumDeclaration | undefined {
|
|
685
|
+
if (fullOptions.inlineConstEnums === false) return node;
|
|
686
|
+
if (!hasModifier(node, ts.SyntaxKind.ConstKeyword)) return node;
|
|
687
|
+
|
|
688
|
+
if (sourceFile.isDeclarationFile) {
|
|
689
|
+
return ts.factory.updateEnumDeclaration(
|
|
690
|
+
node,
|
|
691
|
+
node.modifiers?.filter((m) => m.kind !== ts.SyntaxKind.ConstKeyword),
|
|
692
|
+
node.name,
|
|
693
|
+
node.members,
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
return undefined;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
function wrapTransformNode(node: ts.Node): ts.Node {
|
|
700
|
+
if (ts.isEnumDeclaration(node)) {
|
|
701
|
+
const result = handleEnumDeclaration(node);
|
|
702
|
+
if (result === undefined) return undefined;
|
|
703
|
+
if (result !== node) return result;
|
|
704
|
+
}
|
|
705
|
+
return transformNode(node);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
function wrappedTransformNodeAndChildren(node: ts.Node): ts.Node {
|
|
709
|
+
return ts.visitEachChild(
|
|
710
|
+
wrapTransformNode(node),
|
|
711
|
+
(childNode: ts.Node) => wrappedTransformNodeAndChildren(childNode),
|
|
712
|
+
context,
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return wrappedTransformNodeAndChildren(sourceFile) as ts.SourceFile;
|
|
717
|
+
};
|
|
641
718
|
};
|
|
642
719
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface OptimizerOptions {
|
|
2
2
|
/**
|
|
3
3
|
* An array of entry source files which will used to detect exported and internal fields.
|
|
4
4
|
* Basically it should be entry point(s) of the library/project.
|
|
@@ -34,6 +34,11 @@ export interface RenameOptions {
|
|
|
34
34
|
* A field is treated as "decorated" if itself or any its parent (on type level) has a decorator.
|
|
35
35
|
*/
|
|
36
36
|
ignoreDecorated: boolean;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Whether to inline const enum values.
|
|
40
|
+
*/
|
|
41
|
+
inlineConstEnums?: boolean;
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
export const enum VisibilityType {
|
|
@@ -42,10 +47,11 @@ export const enum VisibilityType {
|
|
|
42
47
|
External = 2,
|
|
43
48
|
}
|
|
44
49
|
|
|
45
|
-
export const defaultOptions:
|
|
50
|
+
export const defaultOptions: OptimizerOptions = {
|
|
46
51
|
entrySourceFiles: [],
|
|
47
52
|
privatePrefix: "$p$",
|
|
48
53
|
internalPrefix: "$i$",
|
|
49
54
|
publicJSDocTag: "public",
|
|
50
55
|
ignoreDecorated: false,
|
|
56
|
+
inlineConstEnums: true,
|
|
51
57
|
};
|
package/src/const-enum/index.ts
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
2
|
-
import { ConstEnumRegistry } from "./registry";
|
|
3
|
-
import { EnumEvaluator } from "./evaluator";
|
|
4
|
-
import { hasModifier, isConstEnumType } from "./utils";
|
|
5
|
-
import { LOGS } from "../config";
|
|
6
|
-
|
|
7
|
-
export const tsTransformConstEnums = (
|
|
8
|
-
program: ts.Program,
|
|
9
|
-
entrySourceFiles?: readonly string[],
|
|
10
|
-
): ts.TransformerFactory<ts.SourceFile> => {
|
|
11
|
-
if (LOGS) {
|
|
12
|
-
console.log("[const-enum] tsTransformConstEnums called!");
|
|
13
|
-
}
|
|
14
|
-
const startTime = performance.now();
|
|
15
|
-
const registry = new ConstEnumRegistry(program, entrySourceFiles);
|
|
16
|
-
const typeChecker = program.getTypeChecker();
|
|
17
|
-
const evaluator = new EnumEvaluator(typeChecker);
|
|
18
|
-
if (LOGS) {
|
|
19
|
-
console.log(
|
|
20
|
-
`[const-enum] Found ${registry.getEnumCount()} const enum declarations in ${performance.now() - startTime}ms`,
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return (context: ts.TransformationContext) => {
|
|
25
|
-
function transformNodeAndChildren(
|
|
26
|
-
node: ts.Node,
|
|
27
|
-
ctx: ts.TransformationContext,
|
|
28
|
-
sourceFile: ts.SourceFile,
|
|
29
|
-
): ts.Node {
|
|
30
|
-
return ts.visitEachChild(
|
|
31
|
-
transformNode(node, sourceFile, ctx, registry, evaluator, typeChecker),
|
|
32
|
-
(childNode: ts.Node) => transformNodeAndChildren(childNode, ctx, sourceFile),
|
|
33
|
-
ctx,
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
return (sourceFile: ts.SourceFile) => transformNodeAndChildren(sourceFile, context, sourceFile) as ts.SourceFile;
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
function transformNode(
|
|
41
|
-
node: ts.Node,
|
|
42
|
-
sourceFile: ts.SourceFile,
|
|
43
|
-
ctx: ts.TransformationContext,
|
|
44
|
-
registry: ConstEnumRegistry,
|
|
45
|
-
evaluator: EnumEvaluator,
|
|
46
|
-
typeChecker: ts.TypeChecker,
|
|
47
|
-
): ts.Node {
|
|
48
|
-
if (ts.isPropertyAccessExpression(node)) {
|
|
49
|
-
return transformPropertyAccess(node, ctx, registry, evaluator, typeChecker);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (ts.isEnumDeclaration(node)) {
|
|
53
|
-
return transformEnumDeclaration(node, sourceFile, ctx);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (ts.isImportSpecifier(node)) {
|
|
57
|
-
return transformImportSpecifier(node, ctx, registry, typeChecker);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (ts.isImportClause(node)) {
|
|
61
|
-
return transformImportClause(node, ctx, registry, typeChecker);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return ts.visitEachChild(
|
|
65
|
-
node,
|
|
66
|
-
(child) => transformNode(child, sourceFile, ctx, registry, evaluator, typeChecker),
|
|
67
|
-
ctx,
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function transformPropertyAccess(
|
|
72
|
-
node: ts.PropertyAccessExpression,
|
|
73
|
-
ctx: ts.TransformationContext,
|
|
74
|
-
registry: ConstEnumRegistry,
|
|
75
|
-
evaluator: EnumEvaluator,
|
|
76
|
-
typeChecker: ts.TypeChecker,
|
|
77
|
-
): ts.Expression | ts.PropertyAccessExpression {
|
|
78
|
-
const expressionType = typeChecker.getTypeAtLocation(node.expression);
|
|
79
|
-
|
|
80
|
-
if (!isConstEnumType(expressionType)) {
|
|
81
|
-
return node;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const enumSymbol = expressionType.symbol || expressionType.aliasSymbol;
|
|
85
|
-
if (!enumSymbol) {
|
|
86
|
-
return node;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const enumInfo = registry.getEnumInfo(enumSymbol);
|
|
90
|
-
if (!enumInfo) {
|
|
91
|
-
if (LOGS) {
|
|
92
|
-
console.warn(`[const-enum] Could not find const enum ${enumSymbol.name}`);
|
|
93
|
-
}
|
|
94
|
-
return node;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const memberValue = enumInfo.members.get(node.name.text)?.value;
|
|
98
|
-
if (memberValue === undefined || memberValue === null) {
|
|
99
|
-
if (LOGS) {
|
|
100
|
-
console.warn(`[const-enum] Could not find member ${enumSymbol.name}.${node.name.text}`);
|
|
101
|
-
}
|
|
102
|
-
return node;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const literal = evaluator.createLiteral(memberValue);
|
|
106
|
-
if (LOGS) {
|
|
107
|
-
console.log(`[const-enum] Inline ${enumSymbol.name}.${node.name.text} → ${JSON.stringify(memberValue)}`);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return literal;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function transformEnumDeclaration(
|
|
114
|
-
node: ts.EnumDeclaration,
|
|
115
|
-
sourceFile: ts.SourceFile,
|
|
116
|
-
ctx: ts.TransformationContext,
|
|
117
|
-
): ts.EnumDeclaration | undefined {
|
|
118
|
-
// unused
|
|
119
|
-
void ctx;
|
|
120
|
-
|
|
121
|
-
if (!hasModifier(node, ts.SyntaxKind.ConstKeyword)) {
|
|
122
|
-
return node;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (sourceFile.isDeclarationFile) {
|
|
126
|
-
if (LOGS) {
|
|
127
|
-
console.log(`[const-enum] Strip 'const' from ${node.name.text} in ${sourceFile.fileName}`);
|
|
128
|
-
}
|
|
129
|
-
return ts.factory.updateEnumDeclaration(
|
|
130
|
-
node,
|
|
131
|
-
node.modifiers?.filter((m) => m.kind !== ts.SyntaxKind.ConstKeyword),
|
|
132
|
-
node.name,
|
|
133
|
-
node.members,
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (LOGS) {
|
|
138
|
-
console.log(`[const-enum] Remove const enum declaration ${node.name.text} in ${sourceFile.fileName}`);
|
|
139
|
-
}
|
|
140
|
-
return undefined;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function transformImportSpecifier(
|
|
144
|
-
node: ts.ImportSpecifier,
|
|
145
|
-
ctx: ts.TransformationContext,
|
|
146
|
-
registry: ConstEnumRegistry,
|
|
147
|
-
typeChecker: ts.TypeChecker,
|
|
148
|
-
): ts.ImportSpecifier | undefined {
|
|
149
|
-
const importedType = typeChecker.getTypeAtLocation(node);
|
|
150
|
-
|
|
151
|
-
if (isConstEnumType(importedType)) {
|
|
152
|
-
if (LOGS) {
|
|
153
|
-
console.log(`[const-enum] Remove import of const enum ${importedType.symbol?.name}`);
|
|
154
|
-
}
|
|
155
|
-
return undefined;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return node;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function transformImportClause(
|
|
162
|
-
node: ts.ImportClause,
|
|
163
|
-
ctx: ts.TransformationContext,
|
|
164
|
-
registry: ConstEnumRegistry,
|
|
165
|
-
typeChecker: ts.TypeChecker,
|
|
166
|
-
): ts.ImportClause | undefined {
|
|
167
|
-
if (!node.name) {
|
|
168
|
-
return node;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
const type = typeChecker.getTypeAtLocation(node.name);
|
|
172
|
-
|
|
173
|
-
if (isConstEnumType(type)) {
|
|
174
|
-
if (LOGS) {
|
|
175
|
-
console.log(`[const-enum] Remove import clause for const enum ${type.symbol?.name}`);
|
|
176
|
-
}
|
|
177
|
-
return undefined;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return node;
|
|
181
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|