@travetto/transformer 3.0.0-rc.12 → 3.0.0-rc.14
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/package.json +2 -2
- package/src/importer.ts +14 -17
- package/src/manager.ts +13 -5
- package/src/resolver/builder.ts +23 -25
- package/src/resolver/service.ts +37 -5
- package/src/resolver/types.ts +3 -1
- package/src/state.ts +15 -21
- package/src/util/log.ts +2 -1
- package/src/manifest-index.ts +0 -36
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/transformer",
|
|
3
|
-
"version": "3.0.0-rc.
|
|
3
|
+
"version": "3.0.0-rc.14",
|
|
4
4
|
"description": "Functionality for AST transformations, with transformer registration, and general utils",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"directory": "module/transformer"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@travetto/manifest": "^3.0.0-rc.
|
|
27
|
+
"@travetto/manifest": "^3.0.0-rc.11",
|
|
28
28
|
"tslib": "^2.5.0",
|
|
29
29
|
"typescript": "^4.9.5"
|
|
30
30
|
},
|
package/src/importer.ts
CHANGED
|
@@ -2,13 +2,12 @@ import ts from 'typescript';
|
|
|
2
2
|
|
|
3
3
|
import { PackageUtil, path } from '@travetto/manifest';
|
|
4
4
|
|
|
5
|
-
import { AnyType, ExternalType } from './resolver/types';
|
|
5
|
+
import { AnyType, TransformResolver, ExternalType } from './resolver/types';
|
|
6
6
|
import { ImportUtil } from './util/import';
|
|
7
7
|
import { CoreUtil } from './util/core';
|
|
8
8
|
import { Import } from './types/shared';
|
|
9
9
|
import { LiteralUtil } from './util/literal';
|
|
10
10
|
import { DeclarationUtil } from './util/declaration';
|
|
11
|
-
import { TransformerIndex } from './manifest-index';
|
|
12
11
|
|
|
13
12
|
const D_OR_D_TS_EXT_RE = /[.]d([.]ts)?$/;
|
|
14
13
|
|
|
@@ -22,10 +21,12 @@ export class ImportManager {
|
|
|
22
21
|
#idx: Record<string, number> = {};
|
|
23
22
|
#ids = new Map<string, string>();
|
|
24
23
|
#importName: string;
|
|
24
|
+
#resolver: TransformResolver;
|
|
25
25
|
|
|
26
|
-
constructor(public source: ts.SourceFile, public factory: ts.NodeFactory) {
|
|
26
|
+
constructor(public source: ts.SourceFile, public factory: ts.NodeFactory, resolver: TransformResolver) {
|
|
27
27
|
this.#imports = ImportUtil.collectImports(source);
|
|
28
|
-
this.#
|
|
28
|
+
this.#resolver = resolver;
|
|
29
|
+
this.#importName = this.#resolver.getImportName(source.fileName);
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
#getImportFile(spec?: ts.Expression): string | undefined {
|
|
@@ -38,7 +39,7 @@ export class ImportManager {
|
|
|
38
39
|
const fileOrImport = this.#getImportFile(spec);
|
|
39
40
|
if (
|
|
40
41
|
fileOrImport &&
|
|
41
|
-
(fileOrImport.startsWith('.') ||
|
|
42
|
+
(fileOrImport.startsWith('.') || this.#resolver.isKnownFile(fileOrImport)) &&
|
|
42
43
|
!/[.]([mc]?js|ts|json)$/.test(fileOrImport)
|
|
43
44
|
) {
|
|
44
45
|
return LiteralUtil.fromLiteral(this.factory, `${fileOrImport}.js`);
|
|
@@ -46,17 +47,13 @@ export class ImportManager {
|
|
|
46
47
|
return spec;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
#rewriteImportClause(
|
|
50
|
-
spec: ts.Expression | undefined,
|
|
51
|
-
clause: ts.ImportClause | undefined,
|
|
52
|
-
checker: ts.TypeChecker
|
|
53
|
-
): ts.ImportClause | undefined {
|
|
50
|
+
#rewriteImportClause(spec: ts.Expression | undefined, clause: ts.ImportClause | undefined): ts.ImportClause | undefined {
|
|
54
51
|
if (!(spec && clause?.namedBindings && ts.isNamedImports(clause.namedBindings))) {
|
|
55
52
|
return clause;
|
|
56
53
|
}
|
|
57
54
|
|
|
58
55
|
const fileOrImport = this.#getImportFile(spec);
|
|
59
|
-
if (!(fileOrImport && (fileOrImport.startsWith('.') ||
|
|
56
|
+
if (!(fileOrImport && (fileOrImport.startsWith('.') || this.#resolver.isKnownFile(fileOrImport)))) {
|
|
60
57
|
return clause;
|
|
61
58
|
}
|
|
62
59
|
|
|
@@ -65,7 +62,7 @@ export class ImportManager {
|
|
|
65
62
|
// Remove all type only imports
|
|
66
63
|
for (const el of bindings.elements) {
|
|
67
64
|
if (!el.isTypeOnly) {
|
|
68
|
-
const type =
|
|
65
|
+
const type = this.#resolver.getType(el.name);
|
|
69
66
|
const objFlags = DeclarationUtil.getObjectFlags(type);
|
|
70
67
|
const typeFlags = type.getFlags();
|
|
71
68
|
if (objFlags || typeFlags !== 1) {
|
|
@@ -104,7 +101,7 @@ export class ImportManager {
|
|
|
104
101
|
* Import a file if needed, and record it's identifier
|
|
105
102
|
*/
|
|
106
103
|
importFile(file: string, name?: string): Import {
|
|
107
|
-
file =
|
|
104
|
+
file = this.#resolver.getImportName(file);
|
|
108
105
|
|
|
109
106
|
// Allow for node classes to be imported directly
|
|
110
107
|
if (/@types\/node/.test(file)) {
|
|
@@ -176,7 +173,7 @@ export class ImportManager {
|
|
|
176
173
|
}
|
|
177
174
|
}
|
|
178
175
|
|
|
179
|
-
finalizeImportExportExtension(ret: ts.SourceFile
|
|
176
|
+
finalizeImportExportExtension(ret: ts.SourceFile): ts.SourceFile {
|
|
180
177
|
const toAdd: ts.Statement[] = [];
|
|
181
178
|
|
|
182
179
|
for (const stmt of ret.statements) {
|
|
@@ -196,7 +193,7 @@ export class ImportManager {
|
|
|
196
193
|
toAdd.push(this.factory.updateImportDeclaration(
|
|
197
194
|
stmt,
|
|
198
195
|
stmt.modifiers,
|
|
199
|
-
this.#rewriteImportClause(stmt.moduleSpecifier, stmt.importClause
|
|
196
|
+
this.#rewriteImportClause(stmt.moduleSpecifier, stmt.importClause)!,
|
|
200
197
|
this.#rewriteModuleSpecifier(stmt.moduleSpecifier)!,
|
|
201
198
|
stmt.assertClause
|
|
202
199
|
));
|
|
@@ -211,9 +208,9 @@ export class ImportManager {
|
|
|
211
208
|
/**
|
|
212
209
|
* Reset the imports into the source file
|
|
213
210
|
*/
|
|
214
|
-
finalize(ret: ts.SourceFile
|
|
211
|
+
finalize(ret: ts.SourceFile): ts.SourceFile {
|
|
215
212
|
ret = this.finalizeNewImports(ret) ?? ret;
|
|
216
|
-
ret = this.finalizeImportExportExtension(ret
|
|
213
|
+
ret = this.finalizeImportExportExtension(ret) ?? ret;
|
|
217
214
|
return ret;
|
|
218
215
|
}
|
|
219
216
|
|
package/src/manager.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
|
|
3
|
-
import { RootIndex } from '@travetto/manifest';
|
|
3
|
+
import { ManifestIndex, path, RootIndex } from '@travetto/manifest';
|
|
4
4
|
|
|
5
5
|
import { NodeTransformer } from './types/visitor';
|
|
6
6
|
import { VisitorFactory } from './visitor';
|
|
@@ -18,7 +18,13 @@ export class TransformerManager {
|
|
|
18
18
|
* @param manifest
|
|
19
19
|
* @returns
|
|
20
20
|
*/
|
|
21
|
-
static async create(
|
|
21
|
+
static async create(manifestIndex: ManifestIndex): Promise<TransformerManager> {
|
|
22
|
+
const transformerFiles = Object.values(manifestIndex.manifest.modules).flatMap(
|
|
23
|
+
x => (x.files.$transformer ?? []).map(([f]) =>
|
|
24
|
+
path.resolve(manifestIndex.manifest.workspacePath, x.sourceFolder, f)
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
|
|
22
28
|
const transformers: NodeTransformer<TransformerState>[] = [];
|
|
23
29
|
|
|
24
30
|
for (const file of transformerFiles) { // Exclude based on blacklist
|
|
@@ -27,14 +33,16 @@ export class TransformerManager {
|
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
// Prepare a new visitor factory with a given type checker
|
|
30
|
-
return new TransformerManager(transformers);
|
|
36
|
+
return new TransformerManager(manifestIndex, transformers);
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
#cached: ts.CustomTransformers | undefined;
|
|
34
40
|
#transformers: NodeTransformer<TransformerState>[];
|
|
41
|
+
#manifestIndex: ManifestIndex;
|
|
35
42
|
|
|
36
|
-
constructor(transformers: NodeTransformer<TransformerState>[]) {
|
|
43
|
+
constructor(manifestIndex: ManifestIndex, transformers: NodeTransformer<TransformerState>[]) {
|
|
37
44
|
this.#transformers = transformers;
|
|
45
|
+
this.#manifestIndex = manifestIndex;
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
/**
|
|
@@ -43,7 +51,7 @@ export class TransformerManager {
|
|
|
43
51
|
*/
|
|
44
52
|
init(checker: ts.TypeChecker): void {
|
|
45
53
|
const visitor = new VisitorFactory(
|
|
46
|
-
(ctx, src) => new TransformerState(src, ctx.factory, checker),
|
|
54
|
+
(ctx, src) => new TransformerState(src, ctx.factory, checker, this.#manifestIndex),
|
|
47
55
|
this.#transformers
|
|
48
56
|
);
|
|
49
57
|
|
package/src/resolver/builder.ts
CHANGED
|
@@ -8,11 +8,9 @@ import { CoreUtil } from '../util/core';
|
|
|
8
8
|
import { DeclarationUtil } from '../util/declaration';
|
|
9
9
|
import { LiteralUtil } from '../util/literal';
|
|
10
10
|
|
|
11
|
-
import { Type, AnyType, UnionType,
|
|
11
|
+
import { Type, AnyType, UnionType, TransformResolver } from './types';
|
|
12
12
|
import { CoerceUtil } from './coerce';
|
|
13
13
|
|
|
14
|
-
import { TransformerIndex } from '../manifest-index';
|
|
15
|
-
|
|
16
14
|
/**
|
|
17
15
|
* List of global types that can be parameterized
|
|
18
16
|
*/
|
|
@@ -40,7 +38,7 @@ type Category = 'void' | 'undefined' | 'concrete' | 'unknown' | 'tuple' | 'shape
|
|
|
40
38
|
/**
|
|
41
39
|
* Type categorizer, input for builder
|
|
42
40
|
*/
|
|
43
|
-
export function TypeCategorize(
|
|
41
|
+
export function TypeCategorize(resolver: TransformResolver, type: ts.Type): { category: Category, type: ts.Type } {
|
|
44
42
|
const flags = type.getFlags();
|
|
45
43
|
const objectFlags = DeclarationUtil.getObjectFlags(type) ?? 0;
|
|
46
44
|
|
|
@@ -70,7 +68,7 @@ export function TypeCategorize(checker: ts.TypeChecker, type: ts.Type): { catego
|
|
|
70
68
|
const sourceFile = source.fileName;
|
|
71
69
|
if (sourceFile?.includes('@types/node/globals') || sourceFile?.includes('typescript/lib')) {
|
|
72
70
|
return { category: 'literal', type };
|
|
73
|
-
} else if (sourceFile?.endsWith('.d.ts') && !
|
|
71
|
+
} else if (sourceFile?.endsWith('.d.ts') && !resolver.isKnownFile(sourceFile)) {
|
|
74
72
|
return { category: 'unknown', type };
|
|
75
73
|
} else if (!resolvedType.isClass()) { // Not a real type
|
|
76
74
|
return { category: 'shape', type: resolvedType };
|
|
@@ -99,26 +97,26 @@ export function TypeCategorize(checker: ts.TypeChecker, type: ts.Type): { catego
|
|
|
99
97
|
*/
|
|
100
98
|
export const TypeBuilder: {
|
|
101
99
|
[K in Category]: {
|
|
102
|
-
build(
|
|
100
|
+
build(resolver: TransformResolver, type: ts.Type, alias?: ts.Symbol): AnyType | undefined;
|
|
103
101
|
finalize?(type: Type<K>): AnyType;
|
|
104
102
|
}
|
|
105
103
|
} = {
|
|
106
104
|
unknown: {
|
|
107
|
-
build: (
|
|
105
|
+
build: (resolver, type) => undefined
|
|
108
106
|
},
|
|
109
107
|
undefined: {
|
|
110
|
-
build: (
|
|
108
|
+
build: (resolver, type) => ({ key: 'literal', name: 'undefined', ctor: undefined })
|
|
111
109
|
},
|
|
112
110
|
void: {
|
|
113
|
-
build: (
|
|
111
|
+
build: (resolver, type) => ({ key: 'literal', name: 'void', ctor: undefined })
|
|
114
112
|
},
|
|
115
113
|
tuple: {
|
|
116
|
-
build: (
|
|
114
|
+
build: (resolver, type) => ({ key: 'tuple', tsTupleTypes: resolver.getAllTypeArguments(type), subTypes: [] })
|
|
117
115
|
},
|
|
118
116
|
literal: {
|
|
119
|
-
build: (
|
|
117
|
+
build: (resolver, type) => {
|
|
120
118
|
// Handle void/undefined
|
|
121
|
-
const name =
|
|
119
|
+
const name = resolver.getTypeAsString(type) ?? '';
|
|
122
120
|
const complexName = CoreUtil.getSymbol(type)?.getName() ?? '';
|
|
123
121
|
|
|
124
122
|
if (name in GLOBAL_SIMPLE) {
|
|
@@ -139,21 +137,21 @@ export const TypeBuilder: {
|
|
|
139
137
|
key: 'literal',
|
|
140
138
|
name: cons.name,
|
|
141
139
|
ctor: cons,
|
|
142
|
-
tsTypeArguments:
|
|
140
|
+
tsTypeArguments: resolver.getAllTypeArguments(type)
|
|
143
141
|
};
|
|
144
142
|
}
|
|
145
143
|
}
|
|
146
144
|
},
|
|
147
145
|
external: {
|
|
148
|
-
build: (
|
|
146
|
+
build: (resolver, type) => {
|
|
149
147
|
const name = CoreUtil.getSymbol(type)?.getName();
|
|
150
|
-
const importName =
|
|
151
|
-
const tsTypeArguments =
|
|
148
|
+
const importName = resolver.getImportName(type);
|
|
149
|
+
const tsTypeArguments = resolver.getAllTypeArguments(type);
|
|
152
150
|
return { key: 'external', name, importName, tsTypeArguments };
|
|
153
151
|
}
|
|
154
152
|
},
|
|
155
153
|
union: {
|
|
156
|
-
build: (
|
|
154
|
+
build: (resolver, uType: ts.UnionType) => {
|
|
157
155
|
let undefinable = false;
|
|
158
156
|
let nullable = false;
|
|
159
157
|
const remainder = uType.types.filter(ut => {
|
|
@@ -179,15 +177,15 @@ export const TypeBuilder: {
|
|
|
179
177
|
}
|
|
180
178
|
},
|
|
181
179
|
shape: {
|
|
182
|
-
build: (
|
|
180
|
+
build: (resolver, type, alias?) => {
|
|
183
181
|
const tsFieldTypes: Record<string, ts.Type> = {};
|
|
184
182
|
const name = CoreUtil.getSymbol(alias ?? type)?.getName();
|
|
185
|
-
const importName =
|
|
186
|
-
const tsTypeArguments =
|
|
187
|
-
for (const member of
|
|
183
|
+
const importName = resolver.getImportName(type);
|
|
184
|
+
const tsTypeArguments = resolver.getAllTypeArguments(type);
|
|
185
|
+
for (const member of resolver.getPropertiesOfType(type)) {
|
|
188
186
|
const dec = DeclarationUtil.getPrimaryDeclarationNode(member);
|
|
189
187
|
if (DeclarationUtil.isPublic(dec)) { // If public
|
|
190
|
-
const memberType =
|
|
188
|
+
const memberType = resolver.getType(dec);
|
|
191
189
|
if (
|
|
192
190
|
!member.getName().includes('@') && // if not a symbol
|
|
193
191
|
!memberType.getCallSignatures().length // if not a function
|
|
@@ -200,7 +198,7 @@ export const TypeBuilder: {
|
|
|
200
198
|
}
|
|
201
199
|
},
|
|
202
200
|
concrete: {
|
|
203
|
-
build: (
|
|
201
|
+
build: (resolver, type) => {
|
|
204
202
|
const [tag] = DocUtil.readDocTag(type, 'concrete');
|
|
205
203
|
if (tag) {
|
|
206
204
|
// eslint-disable-next-line prefer-const
|
|
@@ -217,10 +215,10 @@ export const TypeBuilder: {
|
|
|
217
215
|
?.getSourceFile().fileName ?? '';
|
|
218
216
|
|
|
219
217
|
if (importName === '.') {
|
|
220
|
-
importName =
|
|
218
|
+
importName = resolver.getImportName(rawSourceFile);
|
|
221
219
|
} else {
|
|
222
220
|
const base = path.dirname(rawSourceFile);
|
|
223
|
-
importName =
|
|
221
|
+
importName = resolver.getImportName(path.resolve(base, importName));
|
|
224
222
|
}
|
|
225
223
|
}
|
|
226
224
|
return { key: 'external', name, importName };
|
package/src/resolver/service.ts
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { ManifestIndex, path } from '@travetto/manifest';
|
|
4
|
+
|
|
5
|
+
import type { AnyType, TransformResolver } from './types';
|
|
4
6
|
import { TypeCategorize, TypeBuilder } from './builder';
|
|
5
7
|
import { VisitCache } from './cache';
|
|
6
8
|
import { DocUtil } from '../util/doc';
|
|
9
|
+
import { DeclarationUtil } from '../util/declaration';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
|
-
*
|
|
12
|
+
* Implementation of TransformResolver
|
|
10
13
|
*/
|
|
11
|
-
export class
|
|
14
|
+
export class SimpleResolver implements TransformResolver {
|
|
12
15
|
#tsChecker: ts.TypeChecker;
|
|
16
|
+
#manifestIndex: ManifestIndex;
|
|
13
17
|
|
|
14
|
-
constructor(tsChecker: ts.TypeChecker) {
|
|
18
|
+
constructor(tsChecker: ts.TypeChecker, manifestIndex: ManifestIndex) {
|
|
15
19
|
this.#tsChecker = tsChecker;
|
|
20
|
+
this.#manifestIndex = manifestIndex;
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
/**
|
|
@@ -23,6 +28,33 @@ export class TypeResolver implements Checker {
|
|
|
23
28
|
return this.#tsChecker;
|
|
24
29
|
}
|
|
25
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Resolve an import name (e.g. @module/path/file) for a given input or type
|
|
33
|
+
*/
|
|
34
|
+
getImportName(fileOrType: string | ts.Type, removeExt?: boolean): string {
|
|
35
|
+
const ogSource = typeof fileOrType === 'string' ? fileOrType : DeclarationUtil.getPrimaryDeclarationNode(fileOrType).getSourceFile().fileName;
|
|
36
|
+
let sourceFile = path.toPosix(ogSource);
|
|
37
|
+
|
|
38
|
+
if (!sourceFile.endsWith('.js') && !sourceFile.endsWith('.ts')) {
|
|
39
|
+
sourceFile = `${sourceFile}.ts`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const imp =
|
|
43
|
+
this.#manifestIndex.getEntry(/[.]ts$/.test(sourceFile) ? sourceFile : `${sourceFile}.js`)?.import ??
|
|
44
|
+
this.#manifestIndex.getFromImport(sourceFile.replace(/^.*node_modules\//, '').replace(/[.]ts$/, ''))?.import ??
|
|
45
|
+
ogSource;
|
|
46
|
+
|
|
47
|
+
return removeExt ? imp.replace(/[.]js$/, '') : imp;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Is the file/import known to the index, helpful for determine ownership
|
|
52
|
+
*/
|
|
53
|
+
isKnownFile(fileOrImport: string): boolean {
|
|
54
|
+
return (this.#manifestIndex.getFromSource(fileOrImport) !== undefined) ||
|
|
55
|
+
(this.#manifestIndex.getFromImport(fileOrImport) !== undefined);
|
|
56
|
+
}
|
|
57
|
+
|
|
26
58
|
/**
|
|
27
59
|
* Get type from element
|
|
28
60
|
* @param el
|
|
@@ -73,7 +105,7 @@ export class TypeResolver implements Checker {
|
|
|
73
105
|
throw new Error('Object structure too nested');
|
|
74
106
|
}
|
|
75
107
|
|
|
76
|
-
const { category, type } = TypeCategorize(this
|
|
108
|
+
const { category, type } = TypeCategorize(this, resType);
|
|
77
109
|
const { build, finalize } = TypeBuilder[category];
|
|
78
110
|
|
|
79
111
|
let result = build(this, type, alias);
|
package/src/resolver/types.ts
CHANGED
|
@@ -151,7 +151,9 @@ export type AnyType = TupleType | ShapeType | UnionType | LiteralType | External
|
|
|
151
151
|
/**
|
|
152
152
|
* Simple interface for checked methods
|
|
153
153
|
*/
|
|
154
|
-
export interface
|
|
154
|
+
export interface TransformResolver {
|
|
155
|
+
isKnownFile(file: string): boolean;
|
|
156
|
+
getImportName(fileOrType: string | ts.Type, removeExt?: boolean): string;
|
|
155
157
|
getAllTypeArguments(type: ts.Type): ts.Type[];
|
|
156
158
|
getPropertiesOfType(type: ts.Type): ts.Symbol[];
|
|
157
159
|
getTypeAsString(type: ts.Type): string | undefined;
|
package/src/state.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
|
|
3
|
-
import { path } from '@travetto/manifest';
|
|
3
|
+
import { ManifestIndex, path } from '@travetto/manifest';
|
|
4
4
|
|
|
5
5
|
import { ExternalType, AnyType } from './resolver/types';
|
|
6
6
|
import { State, DecoratorMeta, Transformer, ModuleNameⲐ } from './types/visitor';
|
|
7
|
-
import {
|
|
7
|
+
import { SimpleResolver } from './resolver/service';
|
|
8
8
|
import { ImportManager } from './importer';
|
|
9
9
|
import { Import } from './types/shared';
|
|
10
10
|
|
|
@@ -14,7 +14,6 @@ import { DeclarationUtil } from './util/declaration';
|
|
|
14
14
|
import { CoreUtil } from './util/core';
|
|
15
15
|
import { LiteralUtil } from './util/literal';
|
|
16
16
|
import { SystemUtil } from './util/system';
|
|
17
|
-
import { TransformerIndex } from './manifest-index';
|
|
18
17
|
|
|
19
18
|
function hasOriginal(n: unknown): n is { original: ts.Node } {
|
|
20
19
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
@@ -32,28 +31,23 @@ function hasEscapedName(n: unknown): n is { name: { escapedText: string } } {
|
|
|
32
31
|
export class TransformerState implements State {
|
|
33
32
|
static SYNTHETIC_EXT = 'Ⲑsyn';
|
|
34
33
|
|
|
35
|
-
#resolver:
|
|
34
|
+
#resolver: SimpleResolver;
|
|
36
35
|
#imports: ImportManager;
|
|
37
36
|
#fileIdent: ts.Identifier;
|
|
37
|
+
#manifestIndex: ManifestIndex;
|
|
38
38
|
#syntheticIdentifiers = new Map<string, ts.Identifier>();
|
|
39
39
|
#decorators = new Map<string, ts.PropertyAccessExpression>();
|
|
40
40
|
added = new Map<number, ts.Statement[]>();
|
|
41
41
|
importName: string;
|
|
42
42
|
file: string;
|
|
43
43
|
|
|
44
|
-
constructor(public source: ts.SourceFile, public factory: ts.NodeFactory, checker: ts.TypeChecker) {
|
|
45
|
-
this.#
|
|
46
|
-
this.#resolver = new
|
|
44
|
+
constructor(public source: ts.SourceFile, public factory: ts.NodeFactory, checker: ts.TypeChecker, manifestIndex: ManifestIndex) {
|
|
45
|
+
this.#manifestIndex = manifestIndex;
|
|
46
|
+
this.#resolver = new SimpleResolver(checker, manifestIndex);
|
|
47
|
+
this.#imports = new ImportManager(source, factory, this.#resolver);
|
|
47
48
|
this.file = path.toPosix(this.source.fileName);
|
|
48
|
-
this.importName = TransformerIndex.getImportName(this.file, true);
|
|
49
|
-
}
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
* Allow access to resolver
|
|
53
|
-
* @private
|
|
54
|
-
*/
|
|
55
|
-
getResolver(): TypeResolver {
|
|
56
|
-
return this.#resolver;
|
|
50
|
+
this.importName = this.#resolver.getImportName(this.file, true);
|
|
57
51
|
}
|
|
58
52
|
|
|
59
53
|
/**
|
|
@@ -86,7 +80,7 @@ export class TransformerState implements State {
|
|
|
86
80
|
const resolved = this.resolveType(node);
|
|
87
81
|
if (resolved.key !== 'external') {
|
|
88
82
|
const file = node.getSourceFile().fileName;
|
|
89
|
-
const src =
|
|
83
|
+
const src = this.#resolver.getImportName(file);
|
|
90
84
|
throw new Error(`Unable to import non-external type: ${node.getText()} ${resolved.key}: ${src}`);
|
|
91
85
|
}
|
|
92
86
|
return resolved;
|
|
@@ -153,8 +147,8 @@ export class TransformerState implements State {
|
|
|
153
147
|
this.#resolver.getType(ident)
|
|
154
148
|
);
|
|
155
149
|
const src = decl?.getSourceFile().fileName;
|
|
156
|
-
const mod = src ?
|
|
157
|
-
const file =
|
|
150
|
+
const mod = src ? this.#resolver.getImportName(src, true) : undefined;
|
|
151
|
+
const file = this.#manifestIndex.getFromImport(mod ?? '')?.outputFile;
|
|
158
152
|
const targets = DocUtil.readAugments(this.#resolver.getType(ident));
|
|
159
153
|
const module = file ? mod : undefined;
|
|
160
154
|
const name = ident ?
|
|
@@ -218,7 +212,7 @@ export class TransformerState implements State {
|
|
|
218
212
|
* Finalize the source file for emission
|
|
219
213
|
*/
|
|
220
214
|
finalize(ret: ts.SourceFile): ts.SourceFile {
|
|
221
|
-
ret = this.#imports.finalize(ret
|
|
215
|
+
ret = this.#imports.finalize(ret);
|
|
222
216
|
return ret;
|
|
223
217
|
}
|
|
224
218
|
|
|
@@ -272,7 +266,7 @@ export class TransformerState implements State {
|
|
|
272
266
|
if (this.#fileIdent === undefined) {
|
|
273
267
|
this.#fileIdent = this.createIdentifier('ᚕf');
|
|
274
268
|
const decl = this.factory.createVariableDeclaration(this.#fileIdent, undefined, undefined,
|
|
275
|
-
this.fromLiteral(
|
|
269
|
+
this.fromLiteral(this.#resolver.getImportName(this.source.fileName) ?? this.source.fileName)
|
|
276
270
|
);
|
|
277
271
|
this.addStatements([
|
|
278
272
|
this.factory.createVariableStatement([], this.factory.createVariableDeclarationList([decl]))
|
|
@@ -345,7 +339,7 @@ export class TransformerState implements State {
|
|
|
345
339
|
(m): m is ts.MethodDeclaration => ts.isMethodDeclaration(m) && ts.isIdentifier(m.name) && m.name.escapedText === method
|
|
346
340
|
);
|
|
347
341
|
} else {
|
|
348
|
-
const props = this.
|
|
342
|
+
const props = this.#resolver.getPropertiesOfType(cls);
|
|
349
343
|
for (const prop of props) {
|
|
350
344
|
const decl = prop.declarations?.[0];
|
|
351
345
|
if (decl && prop.escapedName === method && ts.isMethodDeclaration(decl)) {
|
package/src/util/log.ts
CHANGED
|
@@ -36,7 +36,8 @@ export class LogUtil {
|
|
|
36
36
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
37
37
|
const ox = x as object;
|
|
38
38
|
const out: Record<string, unknown> = {};
|
|
39
|
-
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
40
|
+
for (const key of Object.keys(ox) as (keyof typeof ox)[]) {
|
|
40
41
|
if (Object.getPrototypeOf(ox[key]) === Function.prototype || exclude.has(key) || ox[key] === undefined) {
|
|
41
42
|
continue;
|
|
42
43
|
}
|
package/src/manifest-index.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import ts from 'typescript';
|
|
2
|
-
|
|
3
|
-
import { RootIndex, IndexedFile, path } from '@travetto/manifest';
|
|
4
|
-
import { DeclarationUtil } from './util/declaration';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Specific logic for the transformer
|
|
8
|
-
*/
|
|
9
|
-
export class TransformerIndex {
|
|
10
|
-
/**
|
|
11
|
-
* Resolve import name for a given type
|
|
12
|
-
*/
|
|
13
|
-
static getImportName(type: ts.Type | string, removeExt = false): string {
|
|
14
|
-
const ogSource = typeof type === 'string' ? type : DeclarationUtil.getPrimaryDeclarationNode(type).getSourceFile().fileName;
|
|
15
|
-
let sourceFile = path.toPosix(ogSource);
|
|
16
|
-
|
|
17
|
-
if (!sourceFile.endsWith('.js') && !sourceFile.endsWith('.ts')) {
|
|
18
|
-
sourceFile = `${sourceFile}.ts`;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const imp =
|
|
22
|
-
RootIndex.getEntry(/[.]ts$/.test(sourceFile) ? sourceFile : `${sourceFile}.js`)?.import ??
|
|
23
|
-
RootIndex.getFromImport(sourceFile.replace(/^.*node_modules\//, '').replace(/[.]ts$/, ''))?.import ??
|
|
24
|
-
ogSource;
|
|
25
|
-
|
|
26
|
-
return removeExt ? imp.replace(/[.]js$/, '') : imp;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
static isKnown(fileOrImport: string): boolean {
|
|
30
|
-
return (RootIndex.getFromSource(fileOrImport) !== undefined) || (RootIndex.getFromImport(fileOrImport) !== undefined);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
static getFromImport(imp: string): IndexedFile | undefined {
|
|
34
|
-
return RootIndex.getFromImport(imp);
|
|
35
|
-
}
|
|
36
|
-
}
|