@eliasku/ts-transformers 0.0.8 → 0.0.10
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 +3 -23
- package/dist/index.d.ts +33 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/package.json +14 -7
- package/src/exports/tracker.ts +2 -20
- package/src/index.ts +53 -158
- package/src/types.ts +0 -6
- package/src/utils/ast-utils.ts +2 -2
- package/src/utils/symbol-utils.ts +39 -53
- package/src/const-enum/evaluator.ts +0 -158
- package/src/const-enum/registry.ts +0 -152
- package/src/const-enum/utils.ts +0 -13
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# @eliasku/ts-transformers
|
|
5
5
|
|
|
6
|
-
TypeScript transformer for aggressive code minification through type-aware property renaming
|
|
6
|
+
TypeScript transformer for aggressive code minification through type-aware property renaming.
|
|
7
7
|
|
|
8
8
|
## Important Requirement
|
|
9
9
|
|
|
@@ -24,7 +24,7 @@ Two-phase optimization pipeline:
|
|
|
24
24
|
|
|
25
25
|
Based on type analysis, properties are categorized as:
|
|
26
26
|
|
|
27
|
-
- **Public
|
|
27
|
+
- **Public**: Exported from entry points → **no prefix** (preserved)
|
|
28
28
|
- **Private**: Everything else → prefixed with `$_` (mangled by minifier)
|
|
29
29
|
|
|
30
30
|
**Example:**
|
|
@@ -52,23 +52,7 @@ class A{publicApi(){},a(){},b=1}
|
|
|
52
52
|
|
|
53
53
|
### Const Enum Inlining
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
// Before
|
|
59
|
-
const enum Status {
|
|
60
|
-
Active = 1,
|
|
61
|
-
Inactive = 0,
|
|
62
|
-
}
|
|
63
|
-
export const status = Status.Active;
|
|
64
|
-
|
|
65
|
-
// After transformer
|
|
66
|
-
export let Status: {};
|
|
67
|
-
export const status = 1;
|
|
68
|
-
|
|
69
|
-
// After minifier
|
|
70
|
-
export const status=1;
|
|
71
|
-
```
|
|
55
|
+
TypeScript currently inlines const enums, if you use traditional compiler for production build. Check if you have option `isolatedModules: false` disabled in `tsconfig.json`.
|
|
72
56
|
|
|
73
57
|
## Usage
|
|
74
58
|
|
|
@@ -165,10 +149,6 @@ class AppComponent {
|
|
|
165
149
|
}
|
|
166
150
|
```
|
|
167
151
|
|
|
168
|
-
### inlineConstEnums (optional, default: true)
|
|
169
|
-
|
|
170
|
-
Inline const enum values and transform declarations to preserve export/import flow.
|
|
171
|
-
|
|
172
152
|
## Complete Example
|
|
173
153
|
|
|
174
154
|
```typescript
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
interface OptimizerOptions {
|
|
4
|
+
/**
|
|
5
|
+
* An array of entry source files which will used to detect exported and internal fields.
|
|
6
|
+
* Basically it should be entry point(s) of the library/project.
|
|
7
|
+
* @example ['./src/index.ts']
|
|
8
|
+
*/
|
|
9
|
+
entrySourceFiles: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Prefix of generated names for private fields
|
|
12
|
+
* @example '_private_'
|
|
13
|
+
* @example '$_' // default
|
|
14
|
+
*/
|
|
15
|
+
privatePrefix: string;
|
|
16
|
+
/**
|
|
17
|
+
* Comment which will treat a class/interface/type/property/etc and all its children as "public".
|
|
18
|
+
* Set it to empty string to disable using JSDoc comment to detecting "visibility level".
|
|
19
|
+
* @example 'public' // default
|
|
20
|
+
* @example 'external'
|
|
21
|
+
* @example ''
|
|
22
|
+
*/
|
|
23
|
+
publicJSDocTag: string;
|
|
24
|
+
/**
|
|
25
|
+
* Whether fields that were decorated should be renamed.
|
|
26
|
+
* A field is treated as "decorated" if itself or any its parent (on type level) has a decorator.
|
|
27
|
+
*/
|
|
28
|
+
ignoreDecorated: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare const optimizer: (program: ts.Program, options?: Partial<OptimizerOptions>) => ts.TransformerFactory<ts.SourceFile>;
|
|
32
|
+
|
|
33
|
+
export { type OptimizerOptions, optimizer };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import e from"typescript";var t=(t,r)=>(t.flags&e.SymbolFlags.Alias&&(t=r.getAliasedSymbol(t)),t),r=(r,o)=>{if(0===(r.flags&e.SymbolFlags.Transient))return[r];const i=n(r),s=[];for(const e of i){if(!a(e)||void 0===e.name)continue;const r=o.getSymbolAtLocation(e.name);void 0!==r&&s.push(t(r,o))}return s},n=e=>{const t=[];return void 0!==e.declarations&&t.push(...e.declarations),void 0!==e.valueDeclaration&&(t.includes(e.valueDeclaration)||t.push(e.valueDeclaration)),t},o=(r,n)=>{if(void 0!==n.exports){const o=n.exports.get(e.InternalSymbolName.ExportEquals);if(void 0!==o)return[t(o,r)]}const o=r.getExportsOfModule(n);if(void 0!==n.exports){const t=n.exports.get(e.InternalSymbolName.Default);void 0!==t&&(o.includes(t)||o.push(t))}return o.map(e=>t(e,r))},i=[e.SyntaxKind.InterfaceDeclaration,e.SyntaxKind.ClassDeclaration,e.SyntaxKind.EnumDeclaration,e.SyntaxKind.TypeAliasDeclaration,e.SyntaxKind.ModuleDeclaration,e.SyntaxKind.FunctionDeclaration,e.SyntaxKind.VariableDeclaration,e.SyntaxKind.PropertySignature,e.SyntaxKind.Parameter],a=e=>-1!==i.indexOf(e.kind),s=t=>e.isMethodDeclaration(t)||e.isPropertyDeclaration(t)||e.isGetAccessor(t)||e.isSetAccessor(t),c=t=>l(t,e.SyntaxKind.PrivateKeyword),l=(t,r)=>(t=>d(e)?e.canHaveModifiers(t)&&e.getModifiers(t)||[]:t.modifiers||[])(t).some(e=>e.kind===r),p=t=>0!==(t=>d(e)?e.canHaveDecorators(t)&&e.getDecorators(t)||[]:t.decorators||[])(t).length,f=t=>e.isParameter(t)&&e.isConstructorDeclaration(t.parent)&&(l(t,e.SyntaxKind.PublicKeyword)||l(t,e.SyntaxKind.ProtectedKeyword)||l(t,e.SyntaxKind.PrivateKeyword)||l(t,e.SyntaxKind.ReadonlyKeyword)),u=e=>{if(void 0===e)return[];const t=e.getDeclarations();return void 0===t?[]:t.filter(e=>s(e)||f(e))},d=e=>"canHaveDecorators"in e,g=class{constructor(e,t){this.exportsTree=new Map,this.program=e,this.computeTreeForExports(t)}isSymbolAccessibleFromExports(e){e=this.getActualSymbol(e);for(const[,t]of this.exportsTree)if(t.has(e))return!0;return!1}computeTreeForExports(e){this.exportsTree.clear();const t=this.program.getTypeChecker();for(const r of e){const e=this.program.getSourceFile(r);if(void 0===e)throw new Error(`Cannot find source file ${r}`);const i=t.getSymbolAtLocation(e);if(void 0!==i)for(const e of o(t,i)){const t=new Set;this.exportsTree.set(e,t);for(const r of n(e))this.computeTreeForChildren(t,r,new Set)}}}computeTreeForChildren(r,o,i){if(e.isNamespaceExport(o)){const a=this.program.getTypeChecker(),s=a.getSymbolAtLocation(o.name);if(void 0!==s&&s.flags&e.SymbolFlags.Alias){const e=a.getAliasedSymbol(s),o=a.getExportsOfModule(e);if(o&&o.length>0)for(const e of o){const o=t(e,a);if(!i.has(o)){i.add(o),r.add(o);for(const e of n(o))this.computeTreeForChildren(r,e,i)}}else console.warn("[computeTreeForChildren] Could not get exports for aliased symbol")}return}if(e.isExportDeclaration(o)&&void 0!==o.exportClause&&e.isNamedExports(o.exportClause)){const a=this.program.getTypeChecker();for(const s of o.exportClause.elements){const o=a.getSymbolAtLocation(s.name);if(void 0!==o&&0!==(o.flags&e.SymbolFlags.Alias)){const s=a.getAliasedSymbol(o);if(0!==(s.flags&e.SymbolFlags.NamespaceModule)){const e=a.getExportsOfModule(s);for(const o of e){const e=t(o,a);if(!i.has(e)){i.add(e),r.add(e);for(const t of n(e))this.computeTreeForChildren(r,t,i)}}}}}}if(e.isVariableDeclaration(o)){const e=this.program.getTypeChecker().getTypeAtLocation(o).getSymbol();return void(void 0!==e&&r.add(e))}e.forEachChild(o,e=>this.computeTreeForNode(r,e,i))}computeTreeForNode(t,o,i){if(e.isVariableStatement(o))for(const e of o.declarationList.declarations)this.computeTreeForNode(t,e,i);else if(!(o.kind===e.SyntaxKind.JSDoc||e.isBlock(o)||s(o)&&c(o))){if(e.isIdentifier(o)){const e=this.getSymbol(o);if(null===e)return;if(i.has(e))return;i.add(e);for(const o of r(e,this.program.getTypeChecker())){t.add(o);for(const e of n(o))this.computeTreeForChildren(t,e,i)}}this.computeTreeForChildren(t,o,i)}}getSymbol(e){const t=this.program.getTypeChecker().getSymbolAtLocation(e);return void 0===t?null:this.getActualSymbol(t)}getActualSymbol(e){return t(e,this.program.getTypeChecker())}},m=e=>{const t=e.getStart(),r=e.getStart(void 0,!0);return e.getSourceFile().getFullText().substring(r,t).trim()},y={entrySourceFiles:[],privatePrefix:"$_",publicJSDocTag:"public",ignoreDecorated:!1},S=(t,o)=>{const i={...y,...o},d=t.getTypeChecker(),S=new g(t,i.entrySourceFiles),h=new Map,x=(e,t)=>(h.set(e,t),t);return o=>{const g=e=>{const t=e.parent,r=d.getTypeAtLocation(e);if(!r.isStringLiteral())throw new Error(`Can't get type for left expression in ${e.parent.getText()}`);const n=r.value;return M(d.getTypeAtLocation(t.right),n)?e:P(n,0,o.factory.createStringLiteral)},y=e=>K(e),b=e=>{const t=O(e);return 1===t?e:w(e,t,o.factory.createStringLiteral)},T=e=>K(e),A=e=>K(e),v=e=>K(e),F=e=>K(e),D=e=>K(e),E=e=>{const t=O(e.name);return 1===t?e:w(e.name,t,t=>o.factory.createPropertyAssignment(t,e.name))},C=t=>{if(!e.isIdentifier(t.name))return t;const r=O(t);return 1===r?t:w(t.name,r,e=>o.factory.createBindingElement(t.dotDotDotToken,e,t.name,t.initializer))},L=e=>K(e),K=e=>{const t=O(e);return 1===t?e:w(e,t,o.factory.createIdentifier)},w=(t,r,n)=>{const o=d.getSymbolAtLocation(t);if(void 0===o)throw new Error(`Cannot get symbol for node "${t.getText()}"`);const i=e.unescapeLeadingUnderscores(o.escapedName);return P(i,r,n)},P=(e,t,r)=>r(N(e)),N=e=>`${i.privatePrefix}${e}`,k=t=>(t.flags&e.SymbolFlags.Alias&&(t=d.getAliasedSymbol(t)),t),I=e=>{const t=d.getSymbolAtLocation(e);return void 0===t?null:k(t)},M=(t,o)=>{if(t.flags&e.TypeFlags.Unknown||t.flags&e.TypeFlags.Any)return!0;if(t.flags&e.TypeFlags.IndexedAccess)return M(d.getApparentType(t),o);const i=t.getSymbol(),a=d.getPropertyOfType(t,o);if(t.flags&e.TypeFlags.Object){const r=t;if(r.objectFlags&e.ObjectFlags.Tuple)return!0;if(r.objectFlags&e.ObjectFlags.Reference){const e=r.target;if(e!==r&&M(e,o))return!0}const s=void 0!==a&&0!==n(a).length;if(r.objectFlags&e.ObjectFlags.Mapped&&void 0!==i&&!s&&1===B(i))return!0}if(t.isUnionOrIntersection()){const e=t.types.some(e=>M(e,o));if(e)return e}if(void 0!==i){const t=n(i);for(const r of t)if((e.isClassDeclaration(r)||e.isInterfaceDeclaration(r))&&void 0!==r.heritageClauses){if(r.heritageClauses.some(e=>e.types.some(e=>M(d.getTypeAtLocation(e),o))))return!0}}return void 0!==a&&[a,...r(a,d)].some(e=>1===B(e))},O=t=>{if(e.isPropertyAssignment(t.parent)||e.isShorthandPropertyAssignment(t.parent)){let r=t.parent.parent,n=t.parent.parent,o=t.parent.parent.parent;for(;e.isParenthesizedExpression(o)||e.isAsExpression(o);)e.isAsExpression(o)&&(r=n,n=o),o=o.parent;const i=d.getContextualType(r);if(void 0!==i&&M(i,t.getText()))return 1}if(e.isPropertyAccessExpression(t.parent)||e.isElementAccessExpression(t.parent)){if(e.isIdentifier(t.parent.expression)){const r=d.getSymbolAtLocation(t.parent.expression);if(void 0!==r){const o=n(r);if(o.some(t=>e.isNamespaceImport(t)||e.isModuleDeclaration(t)))return 1;if(o.some(t=>e.isImportSpecifier(t))){const r=d.getTypeAtLocation(t.parent.expression);if(r){const t=r.getSymbol();if(t&&(0!==(t.flags&e.SymbolFlags.NamespaceModule)||0!==(t.flags&e.SymbolFlags.Module)))return 1}}}}const r=d.getTypeAtLocation(t.parent.expression),o=t.getText();if(M(r,o))return 1}if(e.isBindingElement(t)&&M(d.getTypeAtLocation(t.parent),t.getText()))return 1;if(e.isBindingElement(t.parent)&&M(d.getTypeAtLocation(t.parent.parent),t.getText()))return 1;if(e.isJsxAttribute(t.parent)){const e=d.getSymbolAtLocation(t.parent.parent.parent.tagName);if(void 0!==e&&void 0!==e.valueDeclaration){const r=d.getTypeOfSymbolAtLocation(e,e.valueDeclaration);if(M(r,t.getText()))return 1}}const r=I(t),o=null!==r?(e=>{const t=u(e);if(0!==t.length){const e=t[0];return f(e)?e.parent.parent:e.parent}return null})(r):null;if(null!==o&&M(d.getTypeAtLocation(o),t.getText()))return 1;const i=e.isBindingElement(t)?$(t):r;return null===i?1:B(i)},B=t=>{t=k(t);const r=h.get(t);if(void 0!==r)return r;const o=n(t);if(o.some(j))return x(t,1);if(o.some(t=>l(t,e.SyntaxKind.DeclareKeyword)))return x(t,1);if("prototype"===t.escapedName)return x(t,1);if(0!==i.publicJSDocTag.length||i.ignoreDecorated)for(const r of o){let n=r;for(;!e.isSourceFile(n);){if(0!==i.publicJSDocTag.length&&m(n).includes(`@${i.publicJSDocTag}`))return x(t,1);if(i.ignoreDecorated&&p(n))return x(t,1);if(e.isEnumDeclaration(n))return x(t,1);n=n.parent}}if(u(t).some(c))return x(t,0);if(S.isSymbolAccessibleFromExports(t))return x(t,1);for(const e of o){if(!a(e.parent)||void 0===e.parent.name)continue;const r=I(e.parent.name);if(null!==r&&1===B(r))return x(t,1)}return x(t,0)},$=t=>{if(void 0!==t.propertyName)throw new Error(`Cannot handle binding element with property name: ${t.getText()} in ${t.getSourceFile().fileName}`);if(!e.isIdentifier(t.name))return null;const r=d.getTypeAtLocation(t.parent);return r.isUnion()?null:r.getProperty(e.idText(t.name))||null},j=e=>{const r=e.getSourceFile();return r.isDeclarationFile||t.isSourceFileDefaultLibrary(r)||/[\\/]node_modules[\\/]/.test(r.fileName)},J=t=>{return!!e.isIdentifier(t)&&(r=d.getSymbolAtLocation(t),0!==u(r).length);var r},U=t=>e.visitEachChild((t=>{if(e.isShorthandPropertyAssignment(t))return E(t);if(e.isBindingElement(t)&&void 0===t.propertyName)return t.parent&&e.isObjectBindingPattern(t.parent)?C(t):t;if(t.parent&&e.isStringLiteral(t)&&e.isBinaryExpression(t.parent)&&t.parent.operatorToken.kind===e.SyntaxKind.InKeyword)return g(t);if(e.isIdentifier(t)&&t.parent){if(e.isPropertyAccessExpression(t.parent)&&t.parent.name===t)return y(t);if(s(t.parent)&&t.parent.name===t)return T(t);if(e.isEnumMember(t.parent)&&t.parent.name===t)return A(t);if(e.isPropertyAssignment(t.parent)&&t.parent.name===t)return D(t);if(e.isBindingElement(t.parent)&&t.parent.propertyName===t)return v(t);if(e.isJsxAttribute(t.parent)&&t.parent.name===t)return F(t);if(f(t.parent)&&t.parent.name===t||J(t))return L(t)}return t.parent&&e.isStringLiteral(t)&&e.isElementAccessExpression(t.parent)&&t.parent.argumentExpression===t?b(t):t})(t),U,o);return e=>U(e)}};export{S as optimizer};//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/symbol-utils.ts","../src/exports/tracker.ts","../src/utils/ast-utils.ts","../src/types.ts","../src/index.ts"],"names":["ts","getActualSymbol","expressionType"],"mappings":"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","file":"index.js","sourcesContent":["import ts from \"typescript\";\n\nexport const getActualSymbol = (symbol: ts.Symbol, typeChecker: ts.TypeChecker): ts.Symbol => {\n if (symbol.flags & ts.SymbolFlags.Alias) {\n symbol = typeChecker.getAliasedSymbol(symbol);\n }\n\n return symbol;\n};\n\nexport const splitTransientSymbol = (symbol: ts.Symbol, typeChecker: ts.TypeChecker): ts.Symbol[] => {\n // actually I think we even don't need to operate/use \"Transient\" symbols anywhere\n // it's kind of aliased symbol, but just merged\n // but it's hard to refractor everything to use array of symbols instead of just symbol\n // so let's fix it for some places\n if ((symbol.flags & ts.SymbolFlags.Transient) === 0) {\n return [symbol];\n }\n\n // \"Transient\" symbol is kinda \"merged\" symbol\n // I don't really know is this way to \"split\" is correct\n // but it seems that it works for now\n const declarations = getDeclarationsForSymbol(symbol);\n const result: ts.Symbol[] = [];\n for (const declaration of declarations) {\n if (!isNodeNamedDeclaration(declaration) || declaration.name === undefined) {\n continue;\n }\n\n const sym = typeChecker.getSymbolAtLocation(declaration.name);\n if (sym === undefined) {\n continue;\n }\n\n result.push(getActualSymbol(sym, typeChecker));\n }\n\n return result;\n};\n\nexport const getDeclarationsForSymbol = (symbol: ts.Symbol): ts.Declaration[] => {\n const result: ts.Declaration[] = [];\n\n if (symbol.declarations !== undefined) {\n result.push(...symbol.declarations);\n }\n\n if (symbol.valueDeclaration !== undefined) {\n // push valueDeclaration might be already in declarations array\n // so let's check first to avoid duplication nodes\n if (!result.includes(symbol.valueDeclaration)) {\n result.push(symbol.valueDeclaration);\n }\n }\n\n return result;\n};\n\nexport const getExportsForSourceFile = (typeChecker: ts.TypeChecker, sourceFileSymbol: ts.Symbol): ts.Symbol[] => {\n if (sourceFileSymbol.exports !== undefined) {\n const commonJsExport = sourceFileSymbol.exports.get(ts.InternalSymbolName.ExportEquals);\n if (commonJsExport !== undefined) {\n return [getActualSymbol(commonJsExport, typeChecker)];\n }\n }\n\n const result: ts.Symbol[] = typeChecker.getExportsOfModule(sourceFileSymbol);\n\n if (sourceFileSymbol.exports !== undefined) {\n const defaultExportSymbol = sourceFileSymbol.exports.get(ts.InternalSymbolName.Default);\n if (defaultExportSymbol !== undefined) {\n if (!result.includes(defaultExportSymbol)) {\n // it seems that default export is always returned by getExportsOfModule\n // but let's add it to be sure add if there is no such export\n result.push(defaultExportSymbol);\n }\n }\n }\n\n return result.map((symbol: ts.Symbol) => getActualSymbol(symbol, typeChecker));\n};\n\nconst namedDeclarationKinds = [\n ts.SyntaxKind.InterfaceDeclaration,\n ts.SyntaxKind.ClassDeclaration,\n ts.SyntaxKind.EnumDeclaration,\n ts.SyntaxKind.TypeAliasDeclaration,\n ts.SyntaxKind.ModuleDeclaration,\n ts.SyntaxKind.FunctionDeclaration,\n ts.SyntaxKind.VariableDeclaration,\n ts.SyntaxKind.PropertySignature,\n ts.SyntaxKind.Parameter,\n];\n\nexport const isNodeNamedDeclaration = (node: ts.Node): node is ts.NamedDeclaration =>\n namedDeclarationKinds.indexOf(node.kind) !== -1;\n\nexport type ClassMember =\n | ts.MethodDeclaration\n | ts.PropertyDeclaration\n | ts.GetAccessorDeclaration\n | ts.SetAccessorDeclaration;\n\nexport const isClassMember = (node: ts.Node): node is ClassMember =>\n ts.isMethodDeclaration(node) || ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node);\n\nexport const getClassOfMemberSymbol = (\n nodeSymbol: ts.Symbol,\n): ts.ClassLikeDeclaration | ts.ObjectLiteralExpression | ts.TypeLiteralNode | ts.InterfaceDeclaration | null => {\n const classMembers = getClassMemberDeclarations(nodeSymbol);\n if (classMembers.length !== 0) {\n // we need any member to get class' declaration\n const classMember = classMembers[0];\n if (isConstructorParameter(classMember)) {\n return (classMember.parent as ts.ConstructorDeclaration).parent;\n }\n\n // we're sure that it is a class, not interface\n return classMember.parent as ts.ClassLikeDeclaration | ts.ObjectLiteralExpression;\n }\n\n return null;\n};\n\nexport const hasPrivateKeyword = (node: ClassMember | ts.ParameterDeclaration): boolean =>\n hasModifier(node, ts.SyntaxKind.PrivateKeyword);\n\nconst getModifiers = (node: ts.Node): readonly ts.Modifier[] => {\n if (isBreakingTypeScriptApi(ts)) {\n if (!ts.canHaveModifiers(node)) {\n return [];\n }\n\n return ts.getModifiers(node) || [];\n }\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return node.modifiers || [];\n};\n\nexport const hasModifier = (node: ts.Node, modifier: ts.SyntaxKind): boolean =>\n getModifiers(node).some((mod) => mod.kind === modifier);\n\nconst getDecorators = (node: ts.Node): readonly unknown[] => {\n if (isBreakingTypeScriptApi(ts)) {\n if (!ts.canHaveDecorators(node)) {\n return [];\n }\n\n return ts.getDecorators(node) || [];\n }\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return node.decorators || [];\n};\n\nexport const hasDecorators = (node: ts.Node): boolean => getDecorators(node).length !== 0;\n\nexport const isConstructorParameter = (node: ts.Node): node is ts.ParameterDeclaration =>\n ts.isParameter(node) &&\n ts.isConstructorDeclaration(node.parent as ts.Node) &&\n (hasModifier(node, ts.SyntaxKind.PublicKeyword) ||\n hasModifier(node, ts.SyntaxKind.ProtectedKeyword) ||\n hasModifier(node, ts.SyntaxKind.PrivateKeyword) ||\n hasModifier(node, ts.SyntaxKind.ReadonlyKeyword));\n\nconst getClassMemberDeclarations = (symbol: ts.Symbol | undefined): (ClassMember | ts.ParameterDeclaration)[] => {\n if (symbol === undefined) {\n return [];\n }\n\n const declarations = symbol.getDeclarations();\n if (declarations === undefined) {\n return [];\n }\n\n return declarations.filter((x: ts.Declaration): x is ClassMember | ts.ParameterDeclaration => {\n return isClassMember(x) || isConstructorParameter(x);\n });\n};\n\nexport const isSymbolClassMember = (symbol: ts.Symbol | undefined): boolean =>\n getClassMemberDeclarations(symbol).length !== 0;\n\nexport const isPrivateClassMember = (symbol: ts.Symbol | undefined): boolean =>\n getClassMemberDeclarations(symbol).some(hasPrivateKeyword);\n\n// decorators and modifiers-related api added in ts 4.8\ninterface BreakingTypeScriptApi {\n canHaveDecorators(node: ts.Node): boolean;\n getDecorators(node: ts.Node): readonly ts.Decorator[] | undefined;\n canHaveModifiers(node: ts.Node): boolean;\n getModifiers(node: ts.Node): readonly ts.Modifier[] | undefined;\n}\n\nconst isBreakingTypeScriptApi = (compiler: object): compiler is BreakingTypeScriptApi =>\n \"canHaveDecorators\" in compiler;\n","import ts from \"typescript\";\n\nimport {\n getActualSymbol,\n splitTransientSymbol,\n isClassMember,\n hasPrivateKeyword,\n getExportsForSourceFile,\n getDeclarationsForSymbol,\n} from \"../utils/symbol-utils\";\nimport { LOGS } from \"../config\";\n\nexport class ExportsSymbolTree {\n private readonly program: ts.Program;\n private readonly exportsTree = new Map<ts.Symbol, Set<ts.Symbol>>();\n\n constructor(program: ts.Program, entrySourceFiles: readonly string[]) {\n this.program = program;\n this.computeTreeForExports(entrySourceFiles);\n }\n\n isSymbolAccessibleFromExports(symbol: ts.Symbol): boolean {\n symbol = this.getActualSymbol(symbol);\n for (const [, set] of this.exportsTree) {\n if (set.has(symbol)) {\n return true;\n }\n }\n return false;\n }\n\n private computeTreeForExports(entrySourceFiles: readonly string[]): void {\n this.exportsTree.clear();\n\n const typeChecker = this.program.getTypeChecker();\n for (const filePath of entrySourceFiles) {\n const sourceFile = this.program.getSourceFile(filePath);\n if (sourceFile === undefined) {\n throw new Error(`Cannot find source file ${filePath}`);\n }\n\n const entrySourceFile = typeChecker.getSymbolAtLocation(sourceFile);\n if (entrySourceFile === undefined) {\n // if a source file doesn't have any export - then it doesn't have a symbol as well\n // so just skip it here\n continue;\n }\n\n if (LOGS) {\n console.log(`[ExportsSymbolTree] Processing entry file: ${filePath}`);\n }\n for (const entryExportSymbol of getExportsForSourceFile(typeChecker, entrySourceFile)) {\n if (LOGS) {\n console.log(`[ExportsSymbolTree] Export symbol: ${entryExportSymbol.escapedName}`);\n }\n const exportSymbolsSet = new Set<ts.Symbol>();\n this.exportsTree.set(entryExportSymbol, exportSymbolsSet);\n\n for (const exportDeclaration of getDeclarationsForSymbol(entryExportSymbol)) {\n if (LOGS) {\n console.log(\n `[ExportsSymbolTree] Declaration: ${ts.SyntaxKind[exportDeclaration.kind]} - ${exportDeclaration.getText()}`,\n );\n }\n this.computeTreeForChildren(exportSymbolsSet, exportDeclaration, new Set<ts.Symbol>());\n }\n }\n }\n }\n\n private computeTreeForChildren(\n targetSymbolsSet: Set<ts.Symbol>,\n node: ts.Node,\n visitedSymbols: Set<ts.Symbol>,\n ): void {\n if (LOGS) {\n console.log(`[computeTreeForChildren] Processing: ${ts.SyntaxKind[node.kind]} - ${node.getText()}`);\n }\n\n // Handle namespace exports (export * as name from './module')\n // These create an alias symbol that points to the actual module symbol\n if (ts.isNamespaceExport(node)) {\n if (LOGS) {\n console.log(`[computeTreeForChildren] Found NamespaceExport!`);\n }\n const typeChecker = this.program.getTypeChecker();\n\n // Get the symbol at the namespace export's name (e.g., \"fun1\" in \"export * as fun1 from './module'\")\n const symbol = typeChecker.getSymbolAtLocation(node.name);\n if (LOGS) {\n console.log(\n `[computeTreeForChildren] Symbol: ${symbol?.name}, isAlias: ${symbol && (symbol.flags & ts.SymbolFlags.Alias) !== 0}`,\n );\n }\n if (symbol !== undefined && symbol.flags & ts.SymbolFlags.Alias) {\n // Resolve the alias to get the actual module symbol\n const aliasedSymbol = typeChecker.getAliasedSymbol(symbol);\n if (LOGS) {\n console.log(`[computeTreeForChildren] Aliased to: ${aliasedSymbol.escapedName}`);\n }\n\n // Get all exports from the referenced module\n const moduleExports = typeChecker.getExportsOfModule(aliasedSymbol);\n if (moduleExports && moduleExports.length > 0) {\n if (LOGS) {\n console.log(`[computeTreeForChildren] Module exports: ${moduleExports.map((e) => e.name).join(\", \")}`);\n }\n for (const exportSymbol of moduleExports) {\n const actualExport = getActualSymbol(exportSymbol, typeChecker);\n if (!visitedSymbols.has(actualExport)) {\n visitedSymbols.add(actualExport);\n targetSymbolsSet.add(actualExport);\n if (LOGS) {\n console.log(`[computeTreeForChildren] Adding: ${actualExport.escapedName}`);\n }\n\n for (const exportDeclaration of getDeclarationsForSymbol(actualExport)) {\n this.computeTreeForChildren(targetSymbolsSet, exportDeclaration, visitedSymbols);\n }\n }\n }\n } else {\n console.warn(`[computeTreeForChildren] Could not get exports for aliased symbol`);\n }\n }\n return;\n }\n\n // Handle re-export of namespace imports (import * as x from './module'; export { x })\n // This pattern creates an export that references a namespace import\n if (ts.isExportDeclaration(node) && node.exportClause !== undefined && ts.isNamedExports(node.exportClause)) {\n if (LOGS) {\n console.log(`[computeTreeForChildren] Found ExportDeclaration with named exports`);\n }\n const typeChecker = this.program.getTypeChecker();\n\n for (const exportSpecifier of node.exportClause.elements) {\n if (LOGS) {\n console.log(`[computeTreeForChildren] Export specifier: ${exportSpecifier.name.text}`);\n }\n // Get the symbol for this exported name\n const exportedSymbol = typeChecker.getSymbolAtLocation(exportSpecifier.name);\n if (exportedSymbol !== undefined) {\n if (LOGS) {\n console.log(\n `[computeTreeForChildren] Symbol: ${exportedSymbol.name}, flags: ${exportedSymbol.flags}`,\n );\n }\n\n // Check if this is an alias (e.g., from a namespace import)\n if ((exportedSymbol.flags & ts.SymbolFlags.Alias) !== 0) {\n const aliasedSymbol = typeChecker.getAliasedSymbol(exportedSymbol);\n if (LOGS) {\n console.log(\n `[computeTreeForChildren] Aliased to: ${aliasedSymbol.name}, flags: ${aliasedSymbol.flags}`,\n );\n }\n\n // Check if the aliased symbol is a namespace module\n if ((aliasedSymbol.flags & ts.SymbolFlags.NamespaceModule) !== 0) {\n if (LOGS) {\n console.log(`[computeTreeForChildren] Aliased symbol is a namespace module!`);\n }\n // Get all exports from this namespace module\n const moduleExports = typeChecker.getExportsOfModule(aliasedSymbol);\n if (LOGS) {\n console.log(\n `[computeTreeForChildren] Module exports: ${moduleExports.map((e) => e.name).join(\", \")}`,\n );\n }\n for (const exportSymbol of moduleExports) {\n const actualExport = getActualSymbol(exportSymbol, typeChecker);\n if (!visitedSymbols.has(actualExport)) {\n visitedSymbols.add(actualExport);\n targetSymbolsSet.add(actualExport);\n if (LOGS) {\n console.log(`[computeTreeForChildren] Adding: ${actualExport.escapedName}`);\n }\n\n // Recursively process the export's declarations\n for (const exportDeclaration of getDeclarationsForSymbol(actualExport)) {\n this.computeTreeForChildren(targetSymbolsSet, exportDeclaration, visitedSymbols);\n }\n }\n }\n }\n }\n }\n }\n // Don't return here - continue to process children\n }\n\n // it's similar to handling ts.Block node - both Block and variable's initializer are part of _implementation_\n // and we don't care about that implementation at all - we just only need to worry it's definition\n // for functions it is arguments and return type\n // for variables - the type of a variable\n if (ts.isVariableDeclaration(node)) {\n const typeChecker = this.program.getTypeChecker();\n const variableType = typeChecker.getTypeAtLocation(node);\n const variableTypeSymbol = variableType.getSymbol();\n if (variableTypeSymbol !== undefined) {\n targetSymbolsSet.add(variableTypeSymbol);\n if (LOGS) {\n console.log(`[computeTreeForChildren] Added variable type symbol: ${variableTypeSymbol.escapedName}`);\n }\n }\n\n return;\n }\n\n ts.forEachChild(node, (childNode: ts.Node) => this.computeTreeForNode(targetSymbolsSet, childNode, visitedSymbols));\n }\n\n private computeTreeForNode(targetSymbolsSet: Set<ts.Symbol>, node: ts.Node, visitedSymbols: Set<ts.Symbol>): void {\n if (ts.isVariableStatement(node)) {\n for (const varDeclaration of node.declarationList.declarations) {\n this.computeTreeForNode(targetSymbolsSet, varDeclaration, visitedSymbols);\n }\n\n return;\n }\n\n if (node.kind === ts.SyntaxKind.JSDoc || ts.isBlock(node)) {\n return;\n }\n\n if (isClassMember(node) && hasPrivateKeyword(node)) {\n return;\n }\n\n if (ts.isIdentifier(node)) {\n const symbol = this.getSymbol(node);\n if (symbol === null) {\n return;\n }\n\n if (visitedSymbols.has(symbol)) {\n return;\n }\n\n visitedSymbols.add(symbol);\n if (LOGS) {\n console.log(`[computeTreeForNode] Processing identifier: ${node.getText()} -> ${symbol.escapedName}`);\n }\n\n for (const childSymbol of splitTransientSymbol(symbol, this.program.getTypeChecker())) {\n targetSymbolsSet.add(childSymbol);\n if (LOGS) {\n console.log(`[computeTreeForNode] Added to set: ${childSymbol.escapedName}`);\n }\n\n for (const exportDeclaration of getDeclarationsForSymbol(childSymbol)) {\n this.computeTreeForChildren(targetSymbolsSet, exportDeclaration, visitedSymbols);\n }\n }\n }\n\n this.computeTreeForChildren(targetSymbolsSet, node, visitedSymbols);\n }\n\n private getSymbol(node: ts.Node): ts.Symbol | null {\n const nodeSymbol = this.program.getTypeChecker().getSymbolAtLocation(node);\n if (nodeSymbol === undefined) {\n return null;\n }\n\n return this.getActualSymbol(nodeSymbol);\n }\n\n private getActualSymbol(symbol: ts.Symbol): ts.Symbol {\n return getActualSymbol(symbol, this.program.getTypeChecker());\n }\n}\n","import ts from \"typescript\";\n\nexport const getNodeJSDocComment = (node: ts.Node): string => {\n const start = node.getStart();\n const jsDocStart = node.getStart(undefined, true);\n return node.getSourceFile().getFullText().substring(jsDocStart, start).trim();\n};\n","export interface OptimizerOptions {\n /**\n * An array of entry source files which will used to detect exported and internal fields.\n * Basically it should be entry point(s) of the library/project.\n * @example ['./src/index.ts']\n */\n entrySourceFiles: string[];\n\n /**\n * Prefix of generated names for private fields\n * @example '_private_'\n * @example '$_' // default\n */\n privatePrefix: string;\n\n /**\n * Comment which will treat a class/interface/type/property/etc and all its children as \"public\".\n * Set it to empty string to disable using JSDoc comment to detecting \"visibility level\".\n * @example 'public' // default\n * @example 'external'\n * @example ''\n */\n publicJSDocTag: string;\n\n /**\n * Whether fields that were decorated should be renamed.\n * A field is treated as \"decorated\" if itself or any its parent (on type level) has a decorator.\n */\n ignoreDecorated: boolean;\n}\n\nexport const enum VisibilityType {\n Private = 0,\n External = 1,\n}\n\nexport const defaultOptions: OptimizerOptions = {\n entrySourceFiles: [],\n privatePrefix: \"$_\",\n publicJSDocTag: \"public\",\n ignoreDecorated: false,\n};\n","import ts from \"typescript\";\nimport { ExportsSymbolTree } from \"./exports/tracker\";\nimport {\n getDeclarationsForSymbol,\n isClassMember,\n isConstructorParameter,\n isPrivateClassMember,\n isSymbolClassMember,\n getClassOfMemberSymbol,\n hasDecorators,\n hasModifier,\n splitTransientSymbol,\n isNodeNamedDeclaration,\n} from \"./utils/symbol-utils\";\nimport { getNodeJSDocComment } from \"./utils/ast-utils\";\nimport { OptimizerOptions, defaultOptions, VisibilityType } from \"./types\";\nimport { LOGS } from \"./config\";\n\nexport type { OptimizerOptions } from \"./types\";\n\nexport const optimizer = (\n program: ts.Program,\n options?: Partial<OptimizerOptions>,\n): ts.TransformerFactory<ts.SourceFile> => {\n const fullOptions: OptimizerOptions = { ...defaultOptions, ...options };\n const typeChecker = program.getTypeChecker();\n const exportsSymbolTree = new ExportsSymbolTree(program, fullOptions.entrySourceFiles);\n\n const cache = new Map<ts.Symbol, VisibilityType>();\n\n const putToCache = (nodeSymbol: ts.Symbol, val: VisibilityType): VisibilityType => {\n cache.set(nodeSymbol, val);\n return val;\n };\n\n return (context: ts.TransformationContext) => {\n const transformNode = (node: ts.Node): ts.Node | undefined => {\n // const a = { node }\n if (ts.isShorthandPropertyAssignment(node)) {\n return handleShorthandPropertyAssignment(node);\n }\n\n // const { node } = obj;\n if (ts.isBindingElement(node) && node.propertyName === undefined) {\n if (node.parent && ts.isObjectBindingPattern(node.parent)) {\n return handleShorthandObjectBindingElement(node);\n }\n return node;\n }\n\n // is not supported:\n // const { node = default_Value } = obj;\n\n // 'node' in obj\n if (\n node.parent &&\n ts.isStringLiteral(node) &&\n ts.isBinaryExpression(node.parent) &&\n node.parent.operatorToken.kind === ts.SyntaxKind.InKeyword\n ) {\n return handleInKeyword(node);\n }\n\n if (ts.isIdentifier(node) && node.parent) {\n // obj.node\n if (ts.isPropertyAccessExpression(node.parent) && node.parent.name === node) {\n return handlePropertyAccessIdentifier(node);\n }\n\n // private node\n // public node()\n if (isClassMember(node.parent) && node.parent.name === node) {\n return handleClassMember(node);\n }\n\n // enum Enum { node }\n if (ts.isEnumMember(node.parent) && node.parent.name === node) {\n return handleEnumMember(node);\n }\n\n // const a = { node: 123 }\n if (ts.isPropertyAssignment(node.parent) && node.parent.name === node) {\n return handlePropertyAssignment(node);\n }\n\n // const { node: localName } = obj;\n if (ts.isBindingElement(node.parent) && node.parent.propertyName === node) {\n return handleBindingElement(node);\n }\n\n // <Comp node={...} />\n if (ts.isJsxAttribute(node.parent) && node.parent.name === node) {\n return handleJsxAttributeName(node);\n }\n\n // constructor(public node: string) { // <--- this\n // console.log(node); // <--- and this\n // }\n if (\n (isConstructorParameter(node.parent) && node.parent.name === node) ||\n isConstructorParameterReference(node)\n ) {\n return handleCtorParameter(node);\n }\n }\n\n // obj['fooBar']\n if (\n node.parent &&\n ts.isStringLiteral(node) &&\n ts.isElementAccessExpression(node.parent) &&\n node.parent.argumentExpression === node\n ) {\n return handleElementAccessExpression(node);\n }\n\n return node;\n };\n\n const handleInKeyword = (node: ts.StringLiteral): ts.StringLiteral => {\n const parent = node.parent as ts.BinaryExpression;\n const nodeType = typeChecker.getTypeAtLocation(node);\n if (!nodeType.isStringLiteral()) {\n throw new Error(`Can't get type for left expression in ${node.parent.getText()}`);\n }\n\n const propertyName = nodeType.value;\n if (isTypePropertyExternal(typeChecker.getTypeAtLocation(parent.right), propertyName)) {\n return node;\n }\n\n return createNewNode(propertyName, VisibilityType.Private, context.factory.createStringLiteral);\n };\n\n // obj.node\n const handlePropertyAccessIdentifier = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);\n\n // obj['fooBar']\n const handleElementAccessExpression = (node: ts.StringLiteral): ts.StringLiteral => {\n const visibilityType = getNodeVisibilityType(node);\n if (visibilityType === VisibilityType.External) {\n return node;\n }\n\n return createNewNodeFromProperty(node, visibilityType, context.factory.createStringLiteral);\n };\n\n // private node\n // public node()\n const handleClassMember = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);\n\n // enum Enum { node }\n const handleEnumMember = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);\n\n // const { node: localName } = obj;\n const handleBindingElement = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);\n\n // <Comp node={...} />\n const handleJsxAttributeName = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);\n\n // const a = { node: 123 }\n const handlePropertyAssignment = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);\n\n // const a = { node }\n const handleShorthandPropertyAssignment = (\n node: ts.ShorthandPropertyAssignment,\n ): ts.PropertyAssignment | ts.ShorthandPropertyAssignment => {\n const visibilityType = getNodeVisibilityType(node.name);\n if (visibilityType === VisibilityType.External) {\n return node;\n }\n\n return createNewNodeFromProperty(node.name, visibilityType, (newName: string) => {\n return context.factory.createPropertyAssignment(newName, node.name);\n });\n };\n\n // const { node } = obj;\n const handleShorthandObjectBindingElement = (node: ts.BindingElement): ts.BindingElement => {\n if (!ts.isIdentifier(node.name)) {\n return node;\n }\n\n const visibilityType = getNodeVisibilityType(node);\n if (visibilityType === VisibilityType.External) {\n return node;\n }\n\n return createNewNodeFromProperty(node.name, visibilityType, (newName: string) => {\n return context.factory.createBindingElement(node.dotDotDotToken, newName, node.name, node.initializer);\n });\n };\n\n // constructor(public node: string) { // <--- this\n // console.log(node); // <--- and this\n // }\n const handleCtorParameter = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);\n\n const createNewIdentifier = (oldIdentifier: ts.Identifier): ts.Identifier => {\n const visibilityType = getNodeVisibilityType(oldIdentifier);\n if (visibilityType === VisibilityType.External) {\n return oldIdentifier;\n }\n\n return createNewNodeFromProperty(oldIdentifier, visibilityType, context.factory.createIdentifier);\n };\n\n const createNewNodeFromProperty = <T extends ts.Node>(\n oldProperty: ts.PropertyName,\n type: VisibilityType,\n createNode: (newName: string) => T,\n ): T => {\n const symbol = typeChecker.getSymbolAtLocation(oldProperty);\n if (symbol === undefined) {\n throw new Error(`Cannot get symbol for node \"${oldProperty.getText()}\"`);\n }\n\n const oldPropertyName = ts.unescapeLeadingUnderscores(symbol.escapedName);\n\n return createNewNode(oldPropertyName, type, createNode);\n };\n\n const createNewNode = <T extends ts.Node>(\n oldPropertyName: string,\n type: VisibilityType,\n createNode: (newName: string) => T,\n ): T => {\n const newPropertyName = getNewName(oldPropertyName);\n return createNode(newPropertyName);\n };\n\n const getNewName = (originalName: string): string => `${fullOptions.privatePrefix}${originalName}`;\n\n const getActualSymbol = (symbol: ts.Symbol): ts.Symbol => {\n if (symbol.flags & ts.SymbolFlags.Alias) {\n symbol = typeChecker.getAliasedSymbol(symbol);\n }\n\n return symbol;\n };\n\n const getNodeSymbol = (node: ts.Expression | ts.NamedDeclaration | ts.DeclarationName): ts.Symbol | null => {\n const symbol = typeChecker.getSymbolAtLocation(node);\n if (symbol === undefined) {\n return null;\n }\n\n return getActualSymbol(symbol);\n };\n\n const isTypePropertyExternal = (type: ts.Type, typePropertyName: string): boolean => {\n // if a type is unknown or any - they should be interpret as a public ones\n if (type.flags & ts.TypeFlags.Unknown || type.flags & ts.TypeFlags.Any) {\n return true;\n }\n\n if (type.flags & ts.TypeFlags.IndexedAccess) {\n return isTypePropertyExternal(typeChecker.getApparentType(type), typePropertyName);\n }\n\n const symbol = type.getSymbol();\n const propertySymbol = typeChecker.getPropertyOfType(type, typePropertyName);\n\n if (type.flags & ts.TypeFlags.Object) {\n const objectType = type as ts.ObjectType;\n\n // treat any tuple property as \"external\"\n if (objectType.objectFlags & ts.ObjectFlags.Tuple) {\n return true;\n }\n\n if (objectType.objectFlags & ts.ObjectFlags.Reference) {\n const target = (objectType as ts.TypeReference).target;\n if (target !== objectType && isTypePropertyExternal(target, typePropertyName)) {\n return true;\n }\n }\n\n // in case when we can't get where a property come from in mapped types\n // let's check the whole type explicitly\n // thus in case of when property doesn't have a declaration let's treat any property of a mapped type as \"external\" if its parent type is external\n // e.g. Readonly<Foo>.field will look for `field` in _Foo_ type (not in Readonly<Foo>), but { [K in 'foo' | 'bar']: any } won't\n // perhaps it would be awesome to handle exactly property we have, but ¯\\_(ツ)_/¯\n const propertyHasDeclarations =\n propertySymbol !== undefined ? getDeclarationsForSymbol(propertySymbol).length !== 0 : false;\n if (\n objectType.objectFlags & ts.ObjectFlags.Mapped &&\n symbol !== undefined &&\n !propertyHasDeclarations &&\n getSymbolVisibilityType(symbol) === VisibilityType.External\n ) {\n return true;\n }\n }\n\n if (type.isUnionOrIntersection()) {\n const hasExternalSubType = type.types.some((t: ts.Type) => isTypePropertyExternal(t, typePropertyName));\n if (hasExternalSubType) {\n return hasExternalSubType;\n }\n }\n\n if (symbol !== undefined) {\n const declarations = getDeclarationsForSymbol(symbol);\n for (const declaration of declarations) {\n if (\n (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) &&\n declaration.heritageClauses !== undefined\n ) {\n const hasHeritageClausesExternals = declaration.heritageClauses.some((clause: ts.HeritageClause) => {\n return clause.types.some((expr: ts.ExpressionWithTypeArguments) => {\n return isTypePropertyExternal(typeChecker.getTypeAtLocation(expr), typePropertyName);\n });\n });\n\n if (hasHeritageClausesExternals) {\n return true;\n }\n }\n }\n }\n\n if (propertySymbol === undefined) {\n return false;\n }\n\n return [propertySymbol, ...splitTransientSymbol(propertySymbol, typeChecker)].some(\n (sym: ts.Symbol) => getSymbolVisibilityType(sym) === VisibilityType.External,\n );\n };\n\n const getNodeVisibilityType = (\n node: ts.Expression | ts.Identifier | ts.StringLiteral | ts.BindingElement,\n ): VisibilityType => {\n if (ts.isPropertyAssignment(node.parent) || ts.isShorthandPropertyAssignment(node.parent)) {\n let expressionToGetTypeFrom: ts.Expression = node.parent.parent;\n let lastKnownExpression: ts.AsExpression | ts.ObjectLiteralExpression = node.parent.parent;\n let currentNode: ts.Node = node.parent.parent.parent;\n\n while (ts.isParenthesizedExpression(currentNode) || ts.isAsExpression(currentNode)) {\n if (ts.isAsExpression(currentNode)) {\n expressionToGetTypeFrom = lastKnownExpression;\n lastKnownExpression = currentNode;\n }\n\n currentNode = currentNode.parent;\n }\n\n // to get correct contextual type we need to provide the previous last expression rather than the last one\n const type = typeChecker.getContextualType(expressionToGetTypeFrom);\n if (type !== undefined && isTypePropertyExternal(type, node.getText())) {\n return VisibilityType.External;\n }\n }\n\n if (ts.isPropertyAccessExpression(node.parent) || ts.isElementAccessExpression(node.parent)) {\n if (ts.isIdentifier(node.parent.expression)) {\n const expressionSymbol = typeChecker.getSymbolAtLocation(node.parent.expression);\n if (LOGS) {\n console.log(\n `[transformer] PropertyAccess: expression=${node.parent.expression.getText()}, property=${node.getText()}`,\n );\n console.log(`[transformer] Expression symbol: ${expressionSymbol?.name}`);\n }\n if (expressionSymbol !== undefined) {\n // import * as foo from '...';\n // foo.node;\n // foo['node'];\n // or\n // namespace Foo { ... }\n // Foo.node\n // Foo['node'];\n const declarations = getDeclarationsForSymbol(expressionSymbol);\n if (LOGS) {\n console.log(`[transformer] Declarations: ${declarations.map((d) => ts.SyntaxKind[d.kind]).join(\", \")}`);\n }\n const isModuleOrStarImport = declarations.some(\n (decl: ts.Declaration) => ts.isNamespaceImport(decl) || ts.isModuleDeclaration(decl),\n );\n if (LOGS) {\n console.log(`[transformer] isModuleOrStarImport: ${isModuleOrStarImport}`);\n }\n if (isModuleOrStarImport) {\n // treat accessing to import-star or namespace as external one\n // because we can't rename them yet\n if (LOGS) {\n console.log(`[transformer] Returning External (module/star import)`);\n }\n return VisibilityType.External;\n }\n\n // import { foo } from '...';\n // where foo is a namespace re-export (export * as foo from './bar')\n // In this case, symbol for 'foo' is an alias to a module\n // Check if the symbol's type is a namespace module or regular module\n const hasImportSpecifier = declarations.some((decl) => ts.isImportSpecifier(decl));\n if (LOGS) {\n console.log(`[transformer] hasImportSpecifier: ${hasImportSpecifier}`);\n }\n if (hasImportSpecifier) {\n const expressionType = typeChecker.getTypeAtLocation(node.parent.expression);\n if (LOGS) {\n console.log(`[transformer] Expression type: ${expressionType?.flags}`);\n }\n if (expressionType) {\n const typeSymbol = expressionType.getSymbol();\n if (LOGS) {\n console.log(`[transformer] Type symbol: ${typeSymbol?.name}, flags: ${typeSymbol?.flags}`);\n }\n // Check if it's a module (NamespaceModule or regular Module)\n // NamespaceModule: 0x8000000, Module: 0x200\n const isModule =\n typeSymbol &&\n ((typeSymbol.flags & ts.SymbolFlags.NamespaceModule) !== 0 ||\n (typeSymbol.flags & ts.SymbolFlags.Module) !== 0);\n if (isModule) {\n // The expression's type is a module, so accessing its properties\n // means accessing exports from that module, which are external\n if (LOGS) {\n console.log(`[transformer] Returning External (module)`);\n }\n return VisibilityType.External;\n }\n }\n }\n }\n }\n\n const expressionType = typeChecker.getTypeAtLocation(node.parent.expression);\n const propertyText = node.getText();\n if (LOGS) {\n console.log(`[transformer] Checking isTypePropertyExternal for ${propertyText}`);\n }\n if (isTypePropertyExternal(expressionType, propertyText)) {\n if (LOGS) {\n console.log(`[transformer] Returning External (isTypePropertyExternal)`);\n }\n return VisibilityType.External;\n }\n }\n\n // shorthand binding element\n // const { node } = obj;\n if (\n ts.isBindingElement(node) &&\n isTypePropertyExternal(typeChecker.getTypeAtLocation(node.parent), node.getText())\n ) {\n return VisibilityType.External;\n }\n\n // full binding element\n // const { node: propName } = obj;\n if (\n ts.isBindingElement(node.parent) &&\n isTypePropertyExternal(typeChecker.getTypeAtLocation(node.parent.parent), node.getText())\n ) {\n return VisibilityType.External;\n }\n\n // <Comp node={...} />\n if (ts.isJsxAttribute(node.parent)) {\n const jsxTagSymbol = typeChecker.getSymbolAtLocation(node.parent.parent.parent.tagName);\n if (jsxTagSymbol !== undefined && jsxTagSymbol.valueDeclaration !== undefined) {\n const jsxPropsType = typeChecker.getTypeOfSymbolAtLocation(jsxTagSymbol, jsxTagSymbol.valueDeclaration);\n if (isTypePropertyExternal(jsxPropsType, node.getText())) {\n return VisibilityType.External;\n }\n }\n }\n\n const nodeSymbol = getNodeSymbol(node);\n const classOfMember = nodeSymbol !== null ? getClassOfMemberSymbol(nodeSymbol) : null;\n if (\n classOfMember !== null &&\n isTypePropertyExternal(typeChecker.getTypeAtLocation(classOfMember), node.getText())\n ) {\n return VisibilityType.External;\n }\n\n const symbol = ts.isBindingElement(node) ? getShorthandObjectBindingElementSymbol(node) : nodeSymbol;\n if (symbol === null) {\n return VisibilityType.External;\n }\n\n return getSymbolVisibilityType(symbol);\n };\n\n const getSymbolVisibilityType = (nodeSymbol: ts.Symbol): VisibilityType => {\n nodeSymbol = getActualSymbol(nodeSymbol);\n\n const cachedValue = cache.get(nodeSymbol);\n if (cachedValue !== undefined) {\n return cachedValue;\n }\n\n const symbolDeclarations = getDeclarationsForSymbol(nodeSymbol);\n if (symbolDeclarations.some(isDeclarationFromExternals)) {\n return putToCache(nodeSymbol, VisibilityType.External);\n }\n\n if (symbolDeclarations.some((decl: ts.Declaration) => hasModifier(decl, ts.SyntaxKind.DeclareKeyword))) {\n return putToCache(nodeSymbol, VisibilityType.External);\n }\n\n if (nodeSymbol.escapedName === \"prototype\") {\n return putToCache(nodeSymbol, VisibilityType.External);\n }\n\n if (fullOptions.publicJSDocTag.length !== 0 || fullOptions.ignoreDecorated) {\n for (const declaration of symbolDeclarations) {\n let currentNode: ts.Node = declaration;\n while (!ts.isSourceFile(currentNode)) {\n if (\n fullOptions.publicJSDocTag.length !== 0 &&\n getNodeJSDocComment(currentNode).includes(`@${fullOptions.publicJSDocTag}`)\n ) {\n return putToCache(nodeSymbol, VisibilityType.External);\n }\n\n if (fullOptions.ignoreDecorated && hasDecorators(currentNode)) {\n return putToCache(nodeSymbol, VisibilityType.External);\n }\n\n if (ts.isEnumDeclaration(currentNode)) {\n return putToCache(nodeSymbol, VisibilityType.External);\n }\n\n currentNode = currentNode.parent;\n }\n }\n }\n\n if (isPrivateClassMember(nodeSymbol)) {\n return putToCache(nodeSymbol, VisibilityType.Private);\n }\n\n if (exportsSymbolTree.isSymbolAccessibleFromExports(nodeSymbol)) {\n return putToCache(nodeSymbol, VisibilityType.External);\n }\n\n for (const declaration of symbolDeclarations) {\n if (!isNodeNamedDeclaration(declaration.parent) || declaration.parent.name === undefined) {\n continue;\n }\n\n const parentSymbol = getNodeSymbol(declaration.parent.name);\n if (parentSymbol === null) {\n continue;\n }\n\n if (getSymbolVisibilityType(parentSymbol) === VisibilityType.External) {\n return putToCache(nodeSymbol, VisibilityType.External);\n }\n }\n\n return putToCache(nodeSymbol, VisibilityType.Private);\n };\n\n const getShorthandObjectBindingElementSymbol = (element: ts.BindingElement): ts.Symbol | null => {\n if (element.propertyName !== undefined) {\n throw new Error(\n `Cannot handle binding element with property name: ${element.getText()} in ${\n element.getSourceFile().fileName\n }`,\n );\n }\n\n if (!ts.isIdentifier(element.name)) {\n return null;\n }\n\n // if no property name is set (const { a } = foo)\n // then node.propertyName is undefined and we need to find this property ourselves\n // so let's use go-to-definition algorithm from TSServer\n // see https://github.com/microsoft/TypeScript/blob/672b0e3e16ad18b422dbe0cec5a98fce49881b76/src/services/goToDefinition.ts#L58-L77\n const type = typeChecker.getTypeAtLocation(element.parent as ts.Node);\n if (type.isUnion()) {\n return null;\n }\n\n return type.getProperty(ts.idText(element.name)) || null;\n };\n\n const isDeclarationFromExternals = (declaration: ts.Declaration): boolean => {\n const sourceFile = declaration.getSourceFile();\n\n // all declarations from declaration source files are external by default\n return (\n sourceFile.isDeclarationFile ||\n program.isSourceFileDefaultLibrary(sourceFile) ||\n /[\\\\/]node_modules[\\\\/]/.test(sourceFile.fileName)\n );\n };\n\n const isConstructorParameterReference = (node: ts.Node): node is ts.Identifier => {\n if (!ts.isIdentifier(node)) {\n return false;\n }\n\n return isSymbolClassMember(typeChecker.getSymbolAtLocation(node));\n };\n const transformNodeAndChildren = (node: ts.Node): ts.Node | undefined =>\n ts.visitEachChild(transformNode(node), transformNodeAndChildren, context);\n\n return (sourceFile: ts.SourceFile) => transformNodeAndChildren(sourceFile) as ts.SourceFile;\n };\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eliasku/ts-transformers",
|
|
3
3
|
"description": "TypeScript transformer for code optimization",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.10",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
6
|
"scripts": {
|
|
7
|
+
"build": "tsup ./src/index.ts --target esnext --platform neutral --format esm --dts --sourcemap --minify terser --treeshake smallest --splitting false",
|
|
8
8
|
"test": "bun test",
|
|
9
9
|
"format": "prettier --write **/*.{ts,json,md,yml}",
|
|
10
10
|
"check": "tsc -p .",
|
|
@@ -22,12 +22,19 @@
|
|
|
22
22
|
"rollup": "latest",
|
|
23
23
|
"@rollup/plugin-typescript": "latest",
|
|
24
24
|
"tslib": "latest",
|
|
25
|
-
"esbuild": "latest"
|
|
25
|
+
"esbuild": "latest",
|
|
26
|
+
"tsup": "latest",
|
|
27
|
+
"terser": "latest"
|
|
26
28
|
},
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
+
"type": "module",
|
|
30
|
+
"module": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
29
32
|
"exports": {
|
|
30
|
-
".":
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./ts": "./scr/index.ts"
|
|
31
38
|
},
|
|
32
39
|
"repository": {
|
|
33
40
|
"type": "git",
|
|
@@ -40,7 +47,6 @@
|
|
|
40
47
|
"plugin",
|
|
41
48
|
"transformer",
|
|
42
49
|
"minify",
|
|
43
|
-
"const-enum",
|
|
44
50
|
"treeshake",
|
|
45
51
|
"mangle"
|
|
46
52
|
],
|
|
@@ -48,6 +54,7 @@
|
|
|
48
54
|
"access": "public"
|
|
49
55
|
},
|
|
50
56
|
"files": [
|
|
57
|
+
"dist",
|
|
51
58
|
"src"
|
|
52
59
|
]
|
|
53
60
|
}
|
package/src/exports/tracker.ts
CHANGED
|
@@ -14,12 +14,12 @@ export class ExportsSymbolTree {
|
|
|
14
14
|
private readonly program: ts.Program;
|
|
15
15
|
private readonly exportsTree = new Map<ts.Symbol, Set<ts.Symbol>>();
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
constructor(program: ts.Program, entrySourceFiles: readonly string[]) {
|
|
18
18
|
this.program = program;
|
|
19
19
|
this.computeTreeForExports(entrySourceFiles);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
isSymbolAccessibleFromExports(symbol: ts.Symbol): boolean {
|
|
23
23
|
symbol = this.getActualSymbol(symbol);
|
|
24
24
|
for (const [, set] of this.exportsTree) {
|
|
25
25
|
if (set.has(symbol)) {
|
|
@@ -122,24 +122,6 @@ export class ExportsSymbolTree {
|
|
|
122
122
|
} else {
|
|
123
123
|
console.warn(`[computeTreeForChildren] Could not get exports for aliased symbol`);
|
|
124
124
|
}
|
|
125
|
-
if (LOGS) {
|
|
126
|
-
console.log(`[computeTreeForChildren] Module exports: ${moduleExports.map((e) => e.name).join(", ")}`);
|
|
127
|
-
}
|
|
128
|
-
for (const exportSymbol of moduleExports) {
|
|
129
|
-
const actualExport = getActualSymbol(exportSymbol, typeChecker);
|
|
130
|
-
if (!visitedSymbols.has(actualExport)) {
|
|
131
|
-
visitedSymbols.add(actualExport);
|
|
132
|
-
targetSymbolsSet.add(actualExport);
|
|
133
|
-
if (LOGS) {
|
|
134
|
-
console.log(`[computeTreeForChildren] Adding: ${actualExport.escapedName}`);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Recursively process the export's declarations
|
|
138
|
-
for (const exportDeclaration of getDeclarationsForSymbol(actualExport)) {
|
|
139
|
-
this.computeTreeForChildren(targetSymbolsSet, exportDeclaration, visitedSymbols);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
125
|
}
|
|
144
126
|
return;
|
|
145
127
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
|
-
export type { OptimizerOptions } from "./types";
|
|
3
|
-
|
|
4
2
|
import { ExportsSymbolTree } from "./exports/tracker";
|
|
5
3
|
import {
|
|
6
4
|
getDeclarationsForSymbol,
|
|
@@ -16,45 +14,27 @@ import {
|
|
|
16
14
|
} from "./utils/symbol-utils";
|
|
17
15
|
import { getNodeJSDocComment } from "./utils/ast-utils";
|
|
18
16
|
import { OptimizerOptions, defaultOptions, VisibilityType } from "./types";
|
|
19
|
-
import { ConstEnumRegistry } from "./const-enum/registry";
|
|
20
|
-
import { EnumEvaluator } from "./const-enum/evaluator";
|
|
21
|
-
import { isConstEnumType } from "./const-enum/utils";
|
|
22
17
|
import { LOGS } from "./config";
|
|
23
18
|
|
|
24
|
-
export
|
|
25
|
-
program: ts.Program,
|
|
26
|
-
config?: Partial<OptimizerOptions>,
|
|
27
|
-
): ts.TransformerFactory<ts.SourceFile> => createTransformerFactory(program, config);
|
|
19
|
+
export type { OptimizerOptions } from "./types";
|
|
28
20
|
|
|
29
|
-
|
|
21
|
+
export const optimizer = (
|
|
30
22
|
program: ts.Program,
|
|
31
23
|
options?: Partial<OptimizerOptions>,
|
|
32
|
-
): ts.TransformerFactory<ts.SourceFile> {
|
|
24
|
+
): ts.TransformerFactory<ts.SourceFile> => {
|
|
33
25
|
const fullOptions: OptimizerOptions = { ...defaultOptions, ...options };
|
|
34
26
|
const typeChecker = program.getTypeChecker();
|
|
35
27
|
const exportsSymbolTree = new ExportsSymbolTree(program, fullOptions.entrySourceFiles);
|
|
36
|
-
const constEnumRegistry = new ConstEnumRegistry(program);
|
|
37
|
-
const enumEvaluator = new EnumEvaluator();
|
|
38
28
|
|
|
39
29
|
const cache = new Map<ts.Symbol, VisibilityType>();
|
|
40
30
|
|
|
41
|
-
|
|
31
|
+
const putToCache = (nodeSymbol: ts.Symbol, val: VisibilityType): VisibilityType => {
|
|
42
32
|
cache.set(nodeSymbol, val);
|
|
43
33
|
return val;
|
|
44
|
-
}
|
|
34
|
+
};
|
|
45
35
|
|
|
46
36
|
return (context: ts.TransformationContext) => {
|
|
47
|
-
|
|
48
|
-
if (fullOptions.inlineConstEnums !== false) {
|
|
49
|
-
if (ts.isPropertyAccessExpression(node)) {
|
|
50
|
-
const inlined = tryInlineConstEnum(node);
|
|
51
|
-
if (inlined) {
|
|
52
|
-
ts.setOriginalNode(inlined, node);
|
|
53
|
-
return inlined;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
37
|
+
const transformNode = (node: ts.Node): ts.Node | undefined => {
|
|
58
38
|
// const a = { node }
|
|
59
39
|
if (ts.isShorthandPropertyAssignment(node)) {
|
|
60
40
|
return handleShorthandPropertyAssignment(node);
|
|
@@ -135,9 +115,9 @@ function createTransformerFactory(
|
|
|
135
115
|
}
|
|
136
116
|
|
|
137
117
|
return node;
|
|
138
|
-
}
|
|
118
|
+
};
|
|
139
119
|
|
|
140
|
-
|
|
120
|
+
const handleInKeyword = (node: ts.StringLiteral): ts.StringLiteral => {
|
|
141
121
|
const parent = node.parent as ts.BinaryExpression;
|
|
142
122
|
const nodeType = typeChecker.getTypeAtLocation(node);
|
|
143
123
|
if (!nodeType.isStringLiteral()) {
|
|
@@ -150,53 +130,41 @@ function createTransformerFactory(
|
|
|
150
130
|
}
|
|
151
131
|
|
|
152
132
|
return createNewNode(propertyName, VisibilityType.Private, context.factory.createStringLiteral);
|
|
153
|
-
}
|
|
133
|
+
};
|
|
154
134
|
|
|
155
135
|
// obj.node
|
|
156
|
-
|
|
157
|
-
return createNewIdentifier(node);
|
|
158
|
-
}
|
|
136
|
+
const handlePropertyAccessIdentifier = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);
|
|
159
137
|
|
|
160
138
|
// obj['fooBar']
|
|
161
|
-
|
|
139
|
+
const handleElementAccessExpression = (node: ts.StringLiteral): ts.StringLiteral => {
|
|
162
140
|
const visibilityType = getNodeVisibilityType(node);
|
|
163
141
|
if (visibilityType === VisibilityType.External) {
|
|
164
142
|
return node;
|
|
165
143
|
}
|
|
166
144
|
|
|
167
145
|
return createNewNodeFromProperty(node, visibilityType, context.factory.createStringLiteral);
|
|
168
|
-
}
|
|
146
|
+
};
|
|
169
147
|
|
|
170
148
|
// private node
|
|
171
149
|
// public node()
|
|
172
|
-
|
|
173
|
-
return createNewIdentifier(node);
|
|
174
|
-
}
|
|
150
|
+
const handleClassMember = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);
|
|
175
151
|
|
|
176
152
|
// enum Enum { node }
|
|
177
|
-
|
|
178
|
-
return createNewIdentifier(node);
|
|
179
|
-
}
|
|
153
|
+
const handleEnumMember = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);
|
|
180
154
|
|
|
181
155
|
// const { node: localName } = obj;
|
|
182
|
-
|
|
183
|
-
return createNewIdentifier(node);
|
|
184
|
-
}
|
|
156
|
+
const handleBindingElement = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);
|
|
185
157
|
|
|
186
158
|
// <Comp node={...} />
|
|
187
|
-
|
|
188
|
-
return createNewIdentifier(node);
|
|
189
|
-
}
|
|
159
|
+
const handleJsxAttributeName = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);
|
|
190
160
|
|
|
191
161
|
// const a = { node: 123 }
|
|
192
|
-
|
|
193
|
-
return createNewIdentifier(node);
|
|
194
|
-
}
|
|
162
|
+
const handlePropertyAssignment = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);
|
|
195
163
|
|
|
196
164
|
// const a = { node }
|
|
197
|
-
|
|
165
|
+
const handleShorthandPropertyAssignment = (
|
|
198
166
|
node: ts.ShorthandPropertyAssignment,
|
|
199
|
-
): ts.PropertyAssignment | ts.ShorthandPropertyAssignment {
|
|
167
|
+
): ts.PropertyAssignment | ts.ShorthandPropertyAssignment => {
|
|
200
168
|
const visibilityType = getNodeVisibilityType(node.name);
|
|
201
169
|
if (visibilityType === VisibilityType.External) {
|
|
202
170
|
return node;
|
|
@@ -205,10 +173,10 @@ function createTransformerFactory(
|
|
|
205
173
|
return createNewNodeFromProperty(node.name, visibilityType, (newName: string) => {
|
|
206
174
|
return context.factory.createPropertyAssignment(newName, node.name);
|
|
207
175
|
});
|
|
208
|
-
}
|
|
176
|
+
};
|
|
209
177
|
|
|
210
178
|
// const { node } = obj;
|
|
211
|
-
|
|
179
|
+
const handleShorthandObjectBindingElement = (node: ts.BindingElement): ts.BindingElement => {
|
|
212
180
|
if (!ts.isIdentifier(node.name)) {
|
|
213
181
|
return node;
|
|
214
182
|
}
|
|
@@ -221,29 +189,27 @@ function createTransformerFactory(
|
|
|
221
189
|
return createNewNodeFromProperty(node.name, visibilityType, (newName: string) => {
|
|
222
190
|
return context.factory.createBindingElement(node.dotDotDotToken, newName, node.name, node.initializer);
|
|
223
191
|
});
|
|
224
|
-
}
|
|
192
|
+
};
|
|
225
193
|
|
|
226
194
|
// constructor(public node: string) { // <--- this
|
|
227
195
|
// console.log(node); // <--- and this
|
|
228
196
|
// }
|
|
229
|
-
|
|
230
|
-
return createNewIdentifier(node);
|
|
231
|
-
}
|
|
197
|
+
const handleCtorParameter = (node: ts.Identifier): ts.Identifier => createNewIdentifier(node);
|
|
232
198
|
|
|
233
|
-
|
|
199
|
+
const createNewIdentifier = (oldIdentifier: ts.Identifier): ts.Identifier => {
|
|
234
200
|
const visibilityType = getNodeVisibilityType(oldIdentifier);
|
|
235
201
|
if (visibilityType === VisibilityType.External) {
|
|
236
202
|
return oldIdentifier;
|
|
237
203
|
}
|
|
238
204
|
|
|
239
205
|
return createNewNodeFromProperty(oldIdentifier, visibilityType, context.factory.createIdentifier);
|
|
240
|
-
}
|
|
206
|
+
};
|
|
241
207
|
|
|
242
|
-
|
|
208
|
+
const createNewNodeFromProperty = <T extends ts.Node>(
|
|
243
209
|
oldProperty: ts.PropertyName,
|
|
244
210
|
type: VisibilityType,
|
|
245
211
|
createNode: (newName: string) => T,
|
|
246
|
-
): T {
|
|
212
|
+
): T => {
|
|
247
213
|
const symbol = typeChecker.getSymbolAtLocation(oldProperty);
|
|
248
214
|
if (symbol === undefined) {
|
|
249
215
|
throw new Error(`Cannot get symbol for node "${oldProperty.getText()}"`);
|
|
@@ -252,39 +218,37 @@ function createTransformerFactory(
|
|
|
252
218
|
const oldPropertyName = ts.unescapeLeadingUnderscores(symbol.escapedName);
|
|
253
219
|
|
|
254
220
|
return createNewNode(oldPropertyName, type, createNode);
|
|
255
|
-
}
|
|
221
|
+
};
|
|
256
222
|
|
|
257
|
-
|
|
223
|
+
const createNewNode = <T extends ts.Node>(
|
|
258
224
|
oldPropertyName: string,
|
|
259
225
|
type: VisibilityType,
|
|
260
226
|
createNode: (newName: string) => T,
|
|
261
|
-
): T {
|
|
227
|
+
): T => {
|
|
262
228
|
const newPropertyName = getNewName(oldPropertyName);
|
|
263
229
|
return createNode(newPropertyName);
|
|
264
|
-
}
|
|
230
|
+
};
|
|
265
231
|
|
|
266
|
-
|
|
267
|
-
return `${fullOptions.privatePrefix}${originalName}`;
|
|
268
|
-
}
|
|
232
|
+
const getNewName = (originalName: string): string => `${fullOptions.privatePrefix}${originalName}`;
|
|
269
233
|
|
|
270
|
-
|
|
234
|
+
const getActualSymbol = (symbol: ts.Symbol): ts.Symbol => {
|
|
271
235
|
if (symbol.flags & ts.SymbolFlags.Alias) {
|
|
272
236
|
symbol = typeChecker.getAliasedSymbol(symbol);
|
|
273
237
|
}
|
|
274
238
|
|
|
275
239
|
return symbol;
|
|
276
|
-
}
|
|
240
|
+
};
|
|
277
241
|
|
|
278
|
-
|
|
242
|
+
const getNodeSymbol = (node: ts.Expression | ts.NamedDeclaration | ts.DeclarationName): ts.Symbol | null => {
|
|
279
243
|
const symbol = typeChecker.getSymbolAtLocation(node);
|
|
280
244
|
if (symbol === undefined) {
|
|
281
245
|
return null;
|
|
282
246
|
}
|
|
283
247
|
|
|
284
248
|
return getActualSymbol(symbol);
|
|
285
|
-
}
|
|
249
|
+
};
|
|
286
250
|
|
|
287
|
-
|
|
251
|
+
const isTypePropertyExternal = (type: ts.Type, typePropertyName: string): boolean => {
|
|
288
252
|
// if a type is unknown or any - they should be interpret as a public ones
|
|
289
253
|
if (type.flags & ts.TypeFlags.Unknown || type.flags & ts.TypeFlags.Any) {
|
|
290
254
|
return true;
|
|
@@ -363,11 +327,11 @@ function createTransformerFactory(
|
|
|
363
327
|
return [propertySymbol, ...splitTransientSymbol(propertySymbol, typeChecker)].some(
|
|
364
328
|
(sym: ts.Symbol) => getSymbolVisibilityType(sym) === VisibilityType.External,
|
|
365
329
|
);
|
|
366
|
-
}
|
|
330
|
+
};
|
|
367
331
|
|
|
368
|
-
|
|
332
|
+
const getNodeVisibilityType = (
|
|
369
333
|
node: ts.Expression | ts.Identifier | ts.StringLiteral | ts.BindingElement,
|
|
370
|
-
): VisibilityType {
|
|
334
|
+
): VisibilityType => {
|
|
371
335
|
if (ts.isPropertyAssignment(node.parent) || ts.isShorthandPropertyAssignment(node.parent)) {
|
|
372
336
|
let expressionToGetTypeFrom: ts.Expression = node.parent.parent;
|
|
373
337
|
let lastKnownExpression: ts.AsExpression | ts.ObjectLiteralExpression = node.parent.parent;
|
|
@@ -519,9 +483,9 @@ function createTransformerFactory(
|
|
|
519
483
|
}
|
|
520
484
|
|
|
521
485
|
return getSymbolVisibilityType(symbol);
|
|
522
|
-
}
|
|
486
|
+
};
|
|
523
487
|
|
|
524
|
-
|
|
488
|
+
const getSymbolVisibilityType = (nodeSymbol: ts.Symbol): VisibilityType => {
|
|
525
489
|
nodeSymbol = getActualSymbol(nodeSymbol);
|
|
526
490
|
|
|
527
491
|
const cachedValue = cache.get(nodeSymbol);
|
|
@@ -590,9 +554,9 @@ function createTransformerFactory(
|
|
|
590
554
|
}
|
|
591
555
|
|
|
592
556
|
return putToCache(nodeSymbol, VisibilityType.Private);
|
|
593
|
-
}
|
|
557
|
+
};
|
|
594
558
|
|
|
595
|
-
|
|
559
|
+
const getShorthandObjectBindingElementSymbol = (element: ts.BindingElement): ts.Symbol | null => {
|
|
596
560
|
if (element.propertyName !== undefined) {
|
|
597
561
|
throw new Error(
|
|
598
562
|
`Cannot handle binding element with property name: ${element.getText()} in ${
|
|
@@ -615,9 +579,9 @@ function createTransformerFactory(
|
|
|
615
579
|
}
|
|
616
580
|
|
|
617
581
|
return type.getProperty(ts.idText(element.name)) || null;
|
|
618
|
-
}
|
|
582
|
+
};
|
|
619
583
|
|
|
620
|
-
|
|
584
|
+
const isDeclarationFromExternals = (declaration: ts.Declaration): boolean => {
|
|
621
585
|
const sourceFile = declaration.getSourceFile();
|
|
622
586
|
|
|
623
587
|
// all declarations from declaration source files are external by default
|
|
@@ -626,87 +590,18 @@ function createTransformerFactory(
|
|
|
626
590
|
program.isSourceFileDefaultLibrary(sourceFile) ||
|
|
627
591
|
/[\\/]node_modules[\\/]/.test(sourceFile.fileName)
|
|
628
592
|
);
|
|
629
|
-
}
|
|
593
|
+
};
|
|
630
594
|
|
|
631
|
-
|
|
595
|
+
const isConstructorParameterReference = (node: ts.Node): node is ts.Identifier => {
|
|
632
596
|
if (!ts.isIdentifier(node)) {
|
|
633
597
|
return false;
|
|
634
598
|
}
|
|
635
599
|
|
|
636
600
|
return isSymbolClassMember(typeChecker.getSymbolAtLocation(node));
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
function tryInlineConstEnum(node: ts.PropertyAccessExpression): ts.Expression | null {
|
|
640
|
-
const expressionType = typeChecker.getTypeAtLocation(node.expression);
|
|
641
|
-
if (!isConstEnumType(expressionType)) return null;
|
|
642
|
-
|
|
643
|
-
const enumSymbol = expressionType.symbol || expressionType.aliasSymbol;
|
|
644
|
-
if (!enumSymbol) return null;
|
|
645
|
-
|
|
646
|
-
const enumInfo = constEnumRegistry.getEnumInfo(enumSymbol);
|
|
647
|
-
if (!enumInfo) return null;
|
|
648
|
-
|
|
649
|
-
const memberValue = enumInfo.members.get(node.name.text)?.value;
|
|
650
|
-
if (memberValue === undefined || memberValue === null) return null;
|
|
651
|
-
const newNode = enumEvaluator.createLiteral(memberValue);
|
|
652
|
-
|
|
653
|
-
const r = ts.setOriginalNode(newNode, node);
|
|
654
|
-
ts.setSourceMapRange(newNode, ts.getSourceMapRange(node));
|
|
655
|
-
(newNode as any).symbol = (node as any).symbol; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
656
|
-
return r;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
return (sourceFile: ts.SourceFile) => {
|
|
660
|
-
function handleEnumDeclaration(node: ts.EnumDeclaration): ts.EnumDeclaration | undefined {
|
|
661
|
-
if (fullOptions.inlineConstEnums === false) {
|
|
662
|
-
return node;
|
|
663
|
-
}
|
|
664
|
-
if (!hasModifier(node, ts.SyntaxKind.ConstKeyword)) {
|
|
665
|
-
return node;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
if (sourceFile.isDeclarationFile) {
|
|
669
|
-
return ts.factory.updateEnumDeclaration(
|
|
670
|
-
node,
|
|
671
|
-
node.modifiers?.filter((m) => m.kind !== ts.SyntaxKind.ConstKeyword),
|
|
672
|
-
node.name,
|
|
673
|
-
node.members,
|
|
674
|
-
);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
return ts.factory.createVariableStatement(
|
|
678
|
-
[ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
|
|
679
|
-
ts.factory.createVariableDeclarationList(
|
|
680
|
-
[
|
|
681
|
-
ts.factory.createVariableDeclaration(
|
|
682
|
-
node.name, // Reuse enum name
|
|
683
|
-
undefined,
|
|
684
|
-
ts.factory.createTypeLiteralNode([]), // Empty object type: {}
|
|
685
|
-
undefined, // No initializer (empty declaration)
|
|
686
|
-
),
|
|
687
|
-
],
|
|
688
|
-
ts.NodeFlags.Let, // Sets the 'const' modifier
|
|
689
|
-
),
|
|
690
|
-
) as unknown as ts.EnumDeclaration;
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
function wrapTransformNode(node: ts.Node): ts.Node | undefined {
|
|
694
|
-
if (ts.isEnumDeclaration(node)) {
|
|
695
|
-
const result = handleEnumDeclaration(node);
|
|
696
|
-
if (result !== node) {
|
|
697
|
-
if (result) {
|
|
698
|
-
return transformNode(result);
|
|
699
|
-
}
|
|
700
|
-
return result;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
return transformNode(node);
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
const wrappedTransformNodeAndChildren = (node: ts.Node): ts.Node | undefined =>
|
|
707
|
-
ts.visitEachChild(wrapTransformNode(node), wrappedTransformNodeAndChildren, context);
|
|
708
|
-
|
|
709
|
-
return wrappedTransformNodeAndChildren(sourceFile) as ts.SourceFile;
|
|
710
601
|
};
|
|
602
|
+
const transformNodeAndChildren = (node: ts.Node): ts.Node | undefined =>
|
|
603
|
+
ts.visitEachChild(transformNode(node), transformNodeAndChildren, context);
|
|
604
|
+
|
|
605
|
+
return (sourceFile: ts.SourceFile) => transformNodeAndChildren(sourceFile) as ts.SourceFile;
|
|
711
606
|
};
|
|
712
|
-
}
|
|
607
|
+
};
|
package/src/types.ts
CHANGED
|
@@ -27,11 +27,6 @@ export interface OptimizerOptions {
|
|
|
27
27
|
* A field is treated as "decorated" if itself or any its parent (on type level) has a decorator.
|
|
28
28
|
*/
|
|
29
29
|
ignoreDecorated: boolean;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Whether to inline const enum values.
|
|
33
|
-
*/
|
|
34
|
-
inlineConstEnums?: boolean;
|
|
35
30
|
}
|
|
36
31
|
|
|
37
32
|
export const enum VisibilityType {
|
|
@@ -44,5 +39,4 @@ export const defaultOptions: OptimizerOptions = {
|
|
|
44
39
|
privatePrefix: "$_",
|
|
45
40
|
publicJSDocTag: "public",
|
|
46
41
|
ignoreDecorated: false,
|
|
47
|
-
inlineConstEnums: true,
|
|
48
42
|
};
|
package/src/utils/ast-utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export const getNodeJSDocComment = (node: ts.Node): string => {
|
|
4
4
|
const start = node.getStart();
|
|
5
5
|
const jsDocStart = node.getStart(undefined, true);
|
|
6
6
|
return node.getSourceFile().getFullText().substring(jsDocStart, start).trim();
|
|
7
|
-
}
|
|
7
|
+
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export const getActualSymbol = (symbol: ts.Symbol, typeChecker: ts.TypeChecker): ts.Symbol => {
|
|
4
4
|
if (symbol.flags & ts.SymbolFlags.Alias) {
|
|
5
5
|
symbol = typeChecker.getAliasedSymbol(symbol);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
return symbol;
|
|
9
|
-
}
|
|
9
|
+
};
|
|
10
10
|
|
|
11
|
-
export
|
|
11
|
+
export const splitTransientSymbol = (symbol: ts.Symbol, typeChecker: ts.TypeChecker): ts.Symbol[] => {
|
|
12
12
|
// actually I think we even don't need to operate/use "Transient" symbols anywhere
|
|
13
13
|
// it's kind of aliased symbol, but just merged
|
|
14
14
|
// but it's hard to refractor everything to use array of symbols instead of just symbol
|
|
@@ -36,9 +36,9 @@ export function splitTransientSymbol(symbol: ts.Symbol, typeChecker: ts.TypeChec
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
return result;
|
|
39
|
-
}
|
|
39
|
+
};
|
|
40
40
|
|
|
41
|
-
export
|
|
41
|
+
export const getDeclarationsForSymbol = (symbol: ts.Symbol): ts.Declaration[] => {
|
|
42
42
|
const result: ts.Declaration[] = [];
|
|
43
43
|
|
|
44
44
|
if (symbol.declarations !== undefined) {
|
|
@@ -54,9 +54,9 @@ export function getDeclarationsForSymbol(symbol: ts.Symbol): ts.Declaration[] {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
return result;
|
|
57
|
-
}
|
|
57
|
+
};
|
|
58
58
|
|
|
59
|
-
export
|
|
59
|
+
export const getExportsForSourceFile = (typeChecker: ts.TypeChecker, sourceFileSymbol: ts.Symbol): ts.Symbol[] => {
|
|
60
60
|
if (sourceFileSymbol.exports !== undefined) {
|
|
61
61
|
const commonJsExport = sourceFileSymbol.exports.get(ts.InternalSymbolName.ExportEquals);
|
|
62
62
|
if (commonJsExport !== undefined) {
|
|
@@ -78,7 +78,7 @@ export function getExportsForSourceFile(typeChecker: ts.TypeChecker, sourceFileS
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
return result.map((symbol: ts.Symbol) => getActualSymbol(symbol, typeChecker));
|
|
81
|
-
}
|
|
81
|
+
};
|
|
82
82
|
|
|
83
83
|
const namedDeclarationKinds = [
|
|
84
84
|
ts.SyntaxKind.InterfaceDeclaration,
|
|
@@ -92,9 +92,8 @@ const namedDeclarationKinds = [
|
|
|
92
92
|
ts.SyntaxKind.Parameter,
|
|
93
93
|
];
|
|
94
94
|
|
|
95
|
-
export
|
|
96
|
-
|
|
97
|
-
}
|
|
95
|
+
export const isNodeNamedDeclaration = (node: ts.Node): node is ts.NamedDeclaration =>
|
|
96
|
+
namedDeclarationKinds.indexOf(node.kind) !== -1;
|
|
98
97
|
|
|
99
98
|
export type ClassMember =
|
|
100
99
|
| ts.MethodDeclaration
|
|
@@ -102,15 +101,12 @@ export type ClassMember =
|
|
|
102
101
|
| ts.GetAccessorDeclaration
|
|
103
102
|
| ts.SetAccessorDeclaration;
|
|
104
103
|
|
|
105
|
-
export
|
|
106
|
-
|
|
107
|
-
ts.isMethodDeclaration(node) || ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node)
|
|
108
|
-
);
|
|
109
|
-
}
|
|
104
|
+
export const isClassMember = (node: ts.Node): node is ClassMember =>
|
|
105
|
+
ts.isMethodDeclaration(node) || ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node);
|
|
110
106
|
|
|
111
|
-
export
|
|
107
|
+
export const getClassOfMemberSymbol = (
|
|
112
108
|
nodeSymbol: ts.Symbol,
|
|
113
|
-
): ts.ClassLikeDeclaration | ts.ObjectLiteralExpression | ts.TypeLiteralNode | ts.InterfaceDeclaration | null {
|
|
109
|
+
): ts.ClassLikeDeclaration | ts.ObjectLiteralExpression | ts.TypeLiteralNode | ts.InterfaceDeclaration | null => {
|
|
114
110
|
const classMembers = getClassMemberDeclarations(nodeSymbol);
|
|
115
111
|
if (classMembers.length !== 0) {
|
|
116
112
|
// we need any member to get class' declaration
|
|
@@ -124,13 +120,12 @@ export function getClassOfMemberSymbol(
|
|
|
124
120
|
}
|
|
125
121
|
|
|
126
122
|
return null;
|
|
127
|
-
}
|
|
123
|
+
};
|
|
128
124
|
|
|
129
|
-
export
|
|
130
|
-
|
|
131
|
-
}
|
|
125
|
+
export const hasPrivateKeyword = (node: ClassMember | ts.ParameterDeclaration): boolean =>
|
|
126
|
+
hasModifier(node, ts.SyntaxKind.PrivateKeyword);
|
|
132
127
|
|
|
133
|
-
|
|
128
|
+
const getModifiers = (node: ts.Node): readonly ts.Modifier[] => {
|
|
134
129
|
if (isBreakingTypeScriptApi(ts)) {
|
|
135
130
|
if (!ts.canHaveModifiers(node)) {
|
|
136
131
|
return [];
|
|
@@ -142,13 +137,12 @@ function getModifiers(node: ts.Node): readonly ts.Modifier[] {
|
|
|
142
137
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
143
138
|
// @ts-ignore
|
|
144
139
|
return node.modifiers || [];
|
|
145
|
-
}
|
|
140
|
+
};
|
|
146
141
|
|
|
147
|
-
export
|
|
148
|
-
|
|
149
|
-
}
|
|
142
|
+
export const hasModifier = (node: ts.Node, modifier: ts.SyntaxKind): boolean =>
|
|
143
|
+
getModifiers(node).some((mod) => mod.kind === modifier);
|
|
150
144
|
|
|
151
|
-
|
|
145
|
+
const getDecorators = (node: ts.Node): readonly unknown[] => {
|
|
152
146
|
if (isBreakingTypeScriptApi(ts)) {
|
|
153
147
|
if (!ts.canHaveDecorators(node)) {
|
|
154
148
|
return [];
|
|
@@ -160,24 +154,19 @@ function getDecorators(node: ts.Node): readonly unknown[] {
|
|
|
160
154
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
161
155
|
// @ts-ignore
|
|
162
156
|
return node.decorators || [];
|
|
163
|
-
}
|
|
157
|
+
};
|
|
164
158
|
|
|
165
|
-
export
|
|
166
|
-
return getDecorators(node).length !== 0;
|
|
167
|
-
}
|
|
159
|
+
export const hasDecorators = (node: ts.Node): boolean => getDecorators(node).length !== 0;
|
|
168
160
|
|
|
169
|
-
export
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
hasModifier(node, ts.SyntaxKind.ReadonlyKeyword))
|
|
177
|
-
);
|
|
178
|
-
}
|
|
161
|
+
export const isConstructorParameter = (node: ts.Node): node is ts.ParameterDeclaration =>
|
|
162
|
+
ts.isParameter(node) &&
|
|
163
|
+
ts.isConstructorDeclaration(node.parent as ts.Node) &&
|
|
164
|
+
(hasModifier(node, ts.SyntaxKind.PublicKeyword) ||
|
|
165
|
+
hasModifier(node, ts.SyntaxKind.ProtectedKeyword) ||
|
|
166
|
+
hasModifier(node, ts.SyntaxKind.PrivateKeyword) ||
|
|
167
|
+
hasModifier(node, ts.SyntaxKind.ReadonlyKeyword));
|
|
179
168
|
|
|
180
|
-
|
|
169
|
+
const getClassMemberDeclarations = (symbol: ts.Symbol | undefined): (ClassMember | ts.ParameterDeclaration)[] => {
|
|
181
170
|
if (symbol === undefined) {
|
|
182
171
|
return [];
|
|
183
172
|
}
|
|
@@ -190,15 +179,13 @@ function getClassMemberDeclarations(symbol: ts.Symbol | undefined): (ClassMember
|
|
|
190
179
|
return declarations.filter((x: ts.Declaration): x is ClassMember | ts.ParameterDeclaration => {
|
|
191
180
|
return isClassMember(x) || isConstructorParameter(x);
|
|
192
181
|
});
|
|
193
|
-
}
|
|
182
|
+
};
|
|
194
183
|
|
|
195
|
-
export
|
|
196
|
-
|
|
197
|
-
}
|
|
184
|
+
export const isSymbolClassMember = (symbol: ts.Symbol | undefined): boolean =>
|
|
185
|
+
getClassMemberDeclarations(symbol).length !== 0;
|
|
198
186
|
|
|
199
|
-
export
|
|
200
|
-
|
|
201
|
-
}
|
|
187
|
+
export const isPrivateClassMember = (symbol: ts.Symbol | undefined): boolean =>
|
|
188
|
+
getClassMemberDeclarations(symbol).some(hasPrivateKeyword);
|
|
202
189
|
|
|
203
190
|
// decorators and modifiers-related api added in ts 4.8
|
|
204
191
|
interface BreakingTypeScriptApi {
|
|
@@ -208,6 +195,5 @@ interface BreakingTypeScriptApi {
|
|
|
208
195
|
getModifiers(node: ts.Node): readonly ts.Modifier[] | undefined;
|
|
209
196
|
}
|
|
210
197
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
198
|
+
const isBreakingTypeScriptApi = (compiler: object): compiler is BreakingTypeScriptApi =>
|
|
199
|
+
"canHaveDecorators" in compiler;
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
2
|
-
|
|
3
|
-
export type EnumValue = string | number;
|
|
4
|
-
|
|
5
|
-
export interface EvaluationContext {
|
|
6
|
-
localMembers: Map<string, EnumValue>;
|
|
7
|
-
allowEnumReferences: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class EnumEvaluator {
|
|
11
|
-
private lastImplicitValue = -1;
|
|
12
|
-
|
|
13
|
-
reset(): void {
|
|
14
|
-
this.lastImplicitValue = -1;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
evaluate(expr: ts.Expression, context: EvaluationContext): EnumValue {
|
|
18
|
-
if (ts.isPrefixUnaryExpression(expr)) {
|
|
19
|
-
return this.evaluateUnary(expr, context);
|
|
20
|
-
} else if (ts.isBinaryExpression(expr)) {
|
|
21
|
-
return this.evaluateBinary(expr, context);
|
|
22
|
-
} else if (ts.isStringLiteralLike(expr)) {
|
|
23
|
-
return expr.text;
|
|
24
|
-
} else if (ts.isNumericLiteral(expr)) {
|
|
25
|
-
return +expr.text;
|
|
26
|
-
} else if (ts.isParenthesizedExpression(expr)) {
|
|
27
|
-
return this.evaluate(expr.expression, context);
|
|
28
|
-
} else if (ts.isIdentifier(expr)) {
|
|
29
|
-
return this.evaluateIdentifier(expr, context);
|
|
30
|
-
} else if (
|
|
31
|
-
expr.kind === ts.SyntaxKind.TrueKeyword ||
|
|
32
|
-
expr.kind === ts.SyntaxKind.FalseKeyword ||
|
|
33
|
-
expr.kind === ts.SyntaxKind.NullKeyword
|
|
34
|
-
) {
|
|
35
|
-
throw this.createError(expr, `Unsupported literal: ${ts.SyntaxKind[expr.kind]}`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
throw this.createError(expr, `Cannot evaluate expression: ${expr.getText()}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
evaluateEnumMember(member: ts.EnumMember, context: EvaluationContext): EnumValue {
|
|
42
|
-
if (!member.initializer) {
|
|
43
|
-
return this.evaluateImplicitMember(member);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const value = this.evaluate(member.initializer, context);
|
|
47
|
-
|
|
48
|
-
if (typeof value === "number") {
|
|
49
|
-
this.lastImplicitValue = value;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return value;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private evaluateImplicitMember(member: ts.EnumMember): EnumValue {
|
|
56
|
-
const name = ts.isIdentifier(member.name) ? member.name.text : `<computed>`;
|
|
57
|
-
void name;
|
|
58
|
-
|
|
59
|
-
if (this.lastImplicitValue === -1) {
|
|
60
|
-
this.lastImplicitValue = 0;
|
|
61
|
-
return 0;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const nextValue = this.lastImplicitValue + 1;
|
|
65
|
-
this.lastImplicitValue = nextValue;
|
|
66
|
-
return nextValue;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
createLiteral(value: EnumValue): ts.Expression {
|
|
70
|
-
if (typeof value === "string") {
|
|
71
|
-
return ts.factory.createStringLiteral(value);
|
|
72
|
-
} else {
|
|
73
|
-
if (value < 0) {
|
|
74
|
-
return ts.factory.createPrefixMinus(ts.factory.createNumericLiteral(Math.abs(value).toString()));
|
|
75
|
-
}
|
|
76
|
-
return ts.factory.createNumericLiteral(value.toString());
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private evaluateUnary(expr: ts.PrefixUnaryExpression, context: EvaluationContext): number {
|
|
81
|
-
const value = this.evaluate(expr.operand, context);
|
|
82
|
-
if (typeof value !== "number") {
|
|
83
|
-
throw this.createError(expr, `Unary operator requires numeric value, got ${typeof value}`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
switch (expr.operator) {
|
|
87
|
-
case ts.SyntaxKind.PlusToken:
|
|
88
|
-
return value;
|
|
89
|
-
case ts.SyntaxKind.MinusToken:
|
|
90
|
-
return -value;
|
|
91
|
-
case ts.SyntaxKind.TildeToken:
|
|
92
|
-
return ~value;
|
|
93
|
-
default:
|
|
94
|
-
throw this.createError(expr, `Unsupported unary operator: ${ts.SyntaxKind[expr.operator]}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
private evaluateBinary(expr: ts.BinaryExpression, context: EvaluationContext): EnumValue {
|
|
99
|
-
const left = this.evaluate(expr.left, context);
|
|
100
|
-
const right = this.evaluate(expr.right, context);
|
|
101
|
-
|
|
102
|
-
if (typeof left === "string" && typeof right === "string" && expr.operatorToken.kind === ts.SyntaxKind.PlusToken) {
|
|
103
|
-
return left + right;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (typeof left === "number" && typeof right === "number") {
|
|
107
|
-
switch (expr.operatorToken.kind) {
|
|
108
|
-
case ts.SyntaxKind.BarToken:
|
|
109
|
-
return left | right;
|
|
110
|
-
case ts.SyntaxKind.AmpersandToken:
|
|
111
|
-
return left & right;
|
|
112
|
-
case ts.SyntaxKind.GreaterThanGreaterThanToken:
|
|
113
|
-
return left >> right;
|
|
114
|
-
case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
|
|
115
|
-
return left >>> right;
|
|
116
|
-
case ts.SyntaxKind.LessThanLessThanToken:
|
|
117
|
-
return left << right;
|
|
118
|
-
case ts.SyntaxKind.CaretToken:
|
|
119
|
-
return left ^ right;
|
|
120
|
-
case ts.SyntaxKind.AsteriskToken:
|
|
121
|
-
return left * right;
|
|
122
|
-
case ts.SyntaxKind.SlashToken:
|
|
123
|
-
return left / right;
|
|
124
|
-
case ts.SyntaxKind.PlusToken:
|
|
125
|
-
return left + right;
|
|
126
|
-
case ts.SyntaxKind.MinusToken:
|
|
127
|
-
return left - right;
|
|
128
|
-
case ts.SyntaxKind.PercentToken:
|
|
129
|
-
return left % right;
|
|
130
|
-
case ts.SyntaxKind.AsteriskAsteriskToken:
|
|
131
|
-
return left ** right;
|
|
132
|
-
default:
|
|
133
|
-
throw this.createError(expr, `Unsupported binary operator: ${ts.SyntaxKind[expr.operatorToken.kind]}`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
throw this.createError(expr, `Cannot evaluate binary expression with types ${typeof left} and ${typeof right}`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
private evaluateIdentifier(expr: ts.Identifier, context: EvaluationContext): EnumValue {
|
|
141
|
-
if (!context.allowEnumReferences) {
|
|
142
|
-
throw this.createError(expr, `Cannot reference enum member here`);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const value = context.localMembers.get(expr.text);
|
|
146
|
-
if (value === undefined) {
|
|
147
|
-
throw this.createError(expr, `Undefined enum member: ${expr.text}`);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return value;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
private createError(node: ts.Node, message: string): Error {
|
|
154
|
-
const sourceFile = node.getSourceFile();
|
|
155
|
-
const pos = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
156
|
-
return new Error(`${sourceFile.fileName}:${pos.line + 1}:${pos.character}: ${message}`);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
2
|
-
import { EnumValue, EvaluationContext } from "./evaluator";
|
|
3
|
-
import { EnumEvaluator } from "./evaluator";
|
|
4
|
-
import { isConstEnumSymbol } from "./utils";
|
|
5
|
-
import { hasModifier } from "../utils/symbol-utils";
|
|
6
|
-
|
|
7
|
-
export interface ConstEnumInfo {
|
|
8
|
-
declaration: ts.EnumDeclaration;
|
|
9
|
-
members: Map<string, ConstEnumMemberInfo>;
|
|
10
|
-
isExported: boolean;
|
|
11
|
-
sourceFile: ts.SourceFile;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ConstEnumMemberInfo {
|
|
15
|
-
declaration: ts.EnumMember;
|
|
16
|
-
name: string;
|
|
17
|
-
value: EnumValue | null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class ConstEnumRegistry {
|
|
21
|
-
private readonly program: ts.Program;
|
|
22
|
-
private readonly typeChecker: ts.TypeChecker;
|
|
23
|
-
private readonly enumDeclarations: Map<string, ConstEnumInfo>;
|
|
24
|
-
|
|
25
|
-
constructor(program: ts.Program) {
|
|
26
|
-
this.program = program;
|
|
27
|
-
this.typeChecker = program.getTypeChecker();
|
|
28
|
-
this.enumDeclarations = new Map();
|
|
29
|
-
this.collectConstEnumsFromEntryPoints();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
getEnum(enumName: string): ConstEnumInfo | undefined {
|
|
33
|
-
return this.enumDeclarations.get(enumName);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
getEnumInfo(symbol: ts.Symbol): ConstEnumInfo | undefined {
|
|
37
|
-
const name = this.getEnumSymbolName(symbol);
|
|
38
|
-
return this.enumDeclarations.get(name);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
getMemberValue(enumName: string, memberName: string): EnumValue | undefined {
|
|
42
|
-
const enumInfo = this.enumDeclarations.get(enumName);
|
|
43
|
-
if (!enumInfo) return undefined;
|
|
44
|
-
const memberInfo = enumInfo.members.get(memberName);
|
|
45
|
-
return memberInfo?.value ?? undefined;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
getAllEnums(): ConstEnumInfo[] {
|
|
49
|
-
return Array.from(this.enumDeclarations.values());
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
getEnumCount(): number {
|
|
53
|
-
return this.enumDeclarations.size;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
private collectConstEnumsFromEntryPoints(): void {
|
|
57
|
-
const sourceFiles = this.program.getSourceFiles();
|
|
58
|
-
|
|
59
|
-
for (const sourceFile of sourceFiles) {
|
|
60
|
-
if (sourceFile.isDeclarationFile) {
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
this.registerConstEnumFromSource(sourceFile);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private registerConstEnumFromSource(sourceFile: ts.SourceFile): void {
|
|
69
|
-
ts.forEachChild(sourceFile, (node) => {
|
|
70
|
-
if (ts.isEnumDeclaration(node) && hasModifier(node, ts.SyntaxKind.ConstKeyword)) {
|
|
71
|
-
const symbol = this.typeChecker.getSymbolAtLocation(node.name);
|
|
72
|
-
if (symbol && isConstEnumSymbol(symbol)) {
|
|
73
|
-
this.registerEnum(symbol, node, sourceFile);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
private registerEnum(symbol: ts.Symbol, declaration: ts.EnumDeclaration, sourceFile: ts.SourceFile): void {
|
|
80
|
-
const name = this.getEnumSymbolName(symbol);
|
|
81
|
-
|
|
82
|
-
if (this.enumDeclarations.has(name)) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const isExported = this.hasExportModifier(declaration);
|
|
87
|
-
|
|
88
|
-
const enumInfo: ConstEnumInfo = {
|
|
89
|
-
declaration,
|
|
90
|
-
members: new Map(),
|
|
91
|
-
isExported,
|
|
92
|
-
sourceFile,
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
this.evaluateEnumMembers(enumInfo);
|
|
96
|
-
|
|
97
|
-
this.enumDeclarations.set(name, enumInfo);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private hasExportModifier(node: ts.Node): boolean {
|
|
101
|
-
if (!ts.canHaveModifiers(node)) {
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
const modifiers = ts.getModifiers(node);
|
|
105
|
-
if (!modifiers) {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
return modifiers.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
private evaluateEnumMembers(enumInfo: ConstEnumInfo): void {
|
|
112
|
-
const evaluator = new EnumEvaluator();
|
|
113
|
-
evaluator.reset();
|
|
114
|
-
const context: EvaluationContext = {
|
|
115
|
-
localMembers: new Map(),
|
|
116
|
-
allowEnumReferences: true,
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
for (const member of enumInfo.declaration.members) {
|
|
120
|
-
if (!ts.isIdentifier(member.name)) continue;
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
const value = evaluator.evaluateEnumMember(member, context);
|
|
124
|
-
context.localMembers.set(member.name.text, value);
|
|
125
|
-
enumInfo.members.set(member.name.text, {
|
|
126
|
-
declaration: member,
|
|
127
|
-
name: member.name.text,
|
|
128
|
-
value,
|
|
129
|
-
});
|
|
130
|
-
} catch (error) {
|
|
131
|
-
throw new Error(
|
|
132
|
-
`Failed to evaluate const enum member ${enumInfo.declaration.name.text}.${member.name.text}: ${error}`,
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
private getEnumDeclaration(symbol: ts.Symbol): ts.EnumDeclaration | null {
|
|
139
|
-
const decl = symbol.declarations?.[0];
|
|
140
|
-
if (decl && ts.isEnumDeclaration(decl)) {
|
|
141
|
-
return decl;
|
|
142
|
-
}
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
private getEnumSymbolName(symbol: ts.Symbol): string {
|
|
147
|
-
if (symbol.flags & ts.SymbolFlags.Alias) {
|
|
148
|
-
return this.typeChecker.getAliasedSymbol(symbol).name;
|
|
149
|
-
}
|
|
150
|
-
return symbol.name;
|
|
151
|
-
}
|
|
152
|
-
}
|
package/src/const-enum/utils.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
2
|
-
|
|
3
|
-
export const isConstEnumSymbol = (symbol: ts.Symbol): boolean => (symbol.flags & ts.SymbolFlags.ConstEnum) !== 0;
|
|
4
|
-
|
|
5
|
-
export const isConstEnumType = (type: ts.Type | undefined): boolean => {
|
|
6
|
-
if (type) {
|
|
7
|
-
const symbol = type.symbol || type.aliasSymbol;
|
|
8
|
-
if (symbol) {
|
|
9
|
-
return (symbol.flags & ts.SymbolFlags.ConstEnum) !== 0;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
return false;
|
|
13
|
-
};
|