@travetto/transformer 3.0.0-rc.2 → 3.0.0-rc.21

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/src/state.ts CHANGED
@@ -1,18 +1,19 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
- import { SystemUtil } from '@travetto/boot/src/internal/system';
4
- import { ModuleUtil } from '@travetto/boot/src/internal/module-util';
5
- import { Util } from '@travetto/base';
3
+ import { ManifestIndex, path } from '@travetto/manifest';
6
4
 
7
5
  import { ExternalType, AnyType } from './resolver/types';
8
- import { State, DecoratorMeta, Transformer, TransformerId } from './types/visitor';
9
- import { TypeResolver } from './resolver/service';
6
+ import { State, DecoratorMeta, Transformer, ModuleNameⲐ } from './types/visitor';
7
+ import { SimpleResolver } from './resolver/service';
10
8
  import { ImportManager } from './importer';
9
+ import { Import } from './types/shared';
10
+
11
11
  import { DocUtil } from './util/doc';
12
12
  import { DecoratorUtil } from './util/decorator';
13
13
  import { DeclarationUtil } from './util/declaration';
14
- import { CoreUtil, LiteralUtil } from './util';
15
- import { Import } from './types/shared';
14
+ import { CoreUtil } from './util/core';
15
+ import { LiteralUtil } from './util/literal';
16
+ import { SystemUtil } from './util/system';
16
17
 
17
18
  function hasOriginal(n: unknown): n is { original: ts.Node } {
18
19
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -28,28 +29,25 @@ function hasEscapedName(n: unknown): n is { name: { escapedText: string } } {
28
29
  * Transformer runtime state
29
30
  */
30
31
  export class TransformerState implements State {
31
- static SYNTHETIC_EXT = 'syn';
32
+ static SYNTHETIC_EXT = 'syn';
32
33
 
33
- #resolver: TypeResolver;
34
+ #resolver: SimpleResolver;
34
35
  #imports: ImportManager;
36
+ #fileIdent: ts.Identifier;
37
+ #manifestIndex: ManifestIndex;
35
38
  #syntheticIdentifiers = new Map<string, ts.Identifier>();
36
39
  #decorators = new Map<string, ts.PropertyAccessExpression>();
37
-
38
40
  added = new Map<number, ts.Statement[]>();
39
- module: string;
41
+ importName: string;
42
+ file: string;
40
43
 
41
- constructor(public source: ts.SourceFile, public factory: ts.NodeFactory, checker: ts.TypeChecker) {
42
- this.#imports = new ImportManager(source, factory);
43
- this.#resolver = new TypeResolver(checker);
44
- this.module = ModuleUtil.normalizePath(this.source.fileName);
45
- }
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);
48
+ this.file = path.toPosix(this.source.fileName);
46
49
 
47
- /**
48
- * Allow access to resolver
49
- * @private
50
- */
51
- getResolver(): TypeResolver {
52
- return this.#resolver;
50
+ this.importName = this.#resolver.getFileImportName(this.file, true);
53
51
  }
54
52
 
55
53
  /**
@@ -62,15 +60,15 @@ export class TransformerState implements State {
62
60
  /**
63
61
  * Import a given file
64
62
  */
65
- importFile(file: string): Import {
66
- return this.#imports.importFile(file);
63
+ importFile(file: string, name?: string): Import {
64
+ return this.#imports.importFile(file, name);
67
65
  }
68
66
 
69
67
  /**
70
68
  * Resolve an `AnyType` from a `ts.Type` or `ts.Node`
71
69
  */
72
70
  resolveType(node: ts.Type | ts.Node): AnyType {
73
- const resolved = this.#resolver.resolveType(node);
71
+ const resolved = this.#resolver.resolveType(node, this.importName);
74
72
  this.#imports.importFromResolved(resolved);
75
73
  return resolved;
76
74
  }
@@ -81,7 +79,9 @@ export class TransformerState implements State {
81
79
  resolveExternalType(node: ts.Node): ExternalType {
82
80
  const resolved = this.resolveType(node);
83
81
  if (resolved.key !== 'external') {
84
- throw new Error(`Unable to import non-external type: ${node.getText()} ${resolved.key}: ${node.getSourceFile().fileName}`);
82
+ const file = node.getSourceFile().fileName;
83
+ const src = this.#resolver.getFileImportName(file);
84
+ throw new Error(`Unable to import non-external type: ${node.getText()} ${resolved.key}: ${src}`);
85
85
  }
86
86
  return resolved;
87
87
  }
@@ -141,23 +141,24 @@ export class TransformerState implements State {
141
141
  /**
142
142
  * Read a decorator's metadata
143
143
  */
144
- getDecoratorMeta(dec: ts.Decorator): DecoratorMeta {
144
+ getDecoratorMeta(dec: ts.Decorator): DecoratorMeta | undefined {
145
145
  const ident = DecoratorUtil.getDecoratorIdent(dec);
146
146
  const decl = DeclarationUtil.getPrimaryDeclarationNode(
147
147
  this.#resolver.getType(ident)
148
148
  );
149
-
150
- return {
151
- dec,
152
- ident,
153
- file: decl?.getSourceFile().fileName,
154
- module: decl ? ModuleUtil.normalizePath(decl.getSourceFile().fileName) : undefined, // All #decorators will be absolute
155
- targets: DocUtil.readAugments(this.#resolver.getType(ident)),
156
- name: ident ?
157
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
158
- ident.escapedText! as string :
159
- undefined
160
- };
149
+ const src = decl?.getSourceFile().fileName;
150
+ const mod = src ? this.#resolver.getFileImportName(src, true) : undefined;
151
+ const file = this.#manifestIndex.getFromImport(mod ?? '')?.outputFile;
152
+ const targets = DocUtil.readAugments(this.#resolver.getType(ident));
153
+ const module = file ? mod : undefined;
154
+ const name = ident ?
155
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
156
+ ident.escapedText! as string :
157
+ undefined;
158
+
159
+ if (ident && name) {
160
+ return { dec, ident, file, module, targets, name };
161
+ }
161
162
  }
162
163
 
163
164
  /**
@@ -166,7 +167,7 @@ export class TransformerState implements State {
166
167
  getDecoratorList(node: ts.Node): DecoratorMeta[] {
167
168
  return ts.canHaveDecorators(node) ? (ts.getDecorators(node) ?? [])
168
169
  .map(dec => this.getDecoratorMeta(dec))
169
- .filter(x => !!x.ident) : [];
170
+ .filter((x): x is DecoratorMeta => !!x) : [];
170
171
  }
171
172
 
172
173
  /**
@@ -181,25 +182,30 @@ export class TransformerState implements State {
181
182
  * @param stmt
182
183
  * @param before
183
184
  */
184
- addStatement(stmt: ts.Statement, before?: ts.Node): void {
185
+ addStatements(added: ts.Statement[], before?: ts.Node | number): void {
185
186
  const stmts = this.source.statements.slice(0);
186
- let idx = stmts.length;
187
- let n = before;
188
- if (hasOriginal(n)) {
189
- n = n.original;
190
- }
191
- while (n && !ts.isSourceFile(n.parent)) {
192
- n = n.parent;
193
- }
194
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
195
- const nStmt: ts.Statement = n as ts.Statement;
196
- if (n && ts.isSourceFile(n.parent) && stmts.indexOf(nStmt) >= 0) {
197
- idx = stmts.indexOf(nStmt) - 1;
187
+ let idx = stmts.length + 1000;
188
+
189
+ if (before && typeof before !== 'number') {
190
+ let n = before;
191
+ if (hasOriginal(n)) {
192
+ n = n.original;
193
+ }
194
+ while (n && !ts.isSourceFile(n.parent) && n !== n.parent) {
195
+ n = n.parent;
196
+ }
197
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
198
+ const nStmt: ts.Statement = n as ts.Statement;
199
+ if (n && ts.isSourceFile(n.parent) && stmts.indexOf(nStmt) >= 0) {
200
+ idx = stmts.indexOf(nStmt) - 1;
201
+ }
202
+ } else if (before !== undefined) {
203
+ idx = before;
198
204
  }
199
205
  if (!this.added.has(idx)) {
200
206
  this.added.set(idx, []);
201
207
  }
202
- this.added.get(idx)!.push(stmt);
208
+ this.added.get(idx)!.push(...added);
203
209
  }
204
210
 
205
211
  /**
@@ -210,15 +216,6 @@ export class TransformerState implements State {
210
216
  return ret;
211
217
  }
212
218
 
213
- /**
214
- * Get Filename as ᚕsrc
215
- */
216
- getFilenameAsSrc(): ts.CallExpression {
217
- const ident = this.factory.createIdentifier('ᚕsrc');
218
- ident.getSourceFile = (): ts.SourceFile => this.source;
219
- return this.factory.createCallExpression(ident, [], [this.createIdentifier('__filename')]);
220
- }
221
-
222
219
  /**
223
220
  * From literal
224
221
  */
@@ -243,7 +240,7 @@ export class TransformerState implements State {
243
240
  /**
244
241
  * Create property access
245
242
  */
246
- createAccess(first: string | ts.Expression, second: string | ts.Identifier, ...items: (string | ts.Identifier)[]): ts.PropertyAccessExpression {
243
+ createAccess(first: string | ts.Expression, second: string | ts.Identifier, ...items: (string | number | ts.Identifier)[]): ts.Expression {
247
244
  return CoreUtil.createAccess(this.factory, first, second, ...items);
248
245
  }
249
246
 
@@ -262,6 +259,22 @@ export class TransformerState implements State {
262
259
  return this.factory.createIdentifier(typeof name === 'string' ? name : name.getText());
263
260
  }
264
261
 
262
+ /**
263
+ * Get filename identifier, regardless of module system
264
+ */
265
+ getFilenameIdentifier(): ts.Expression {
266
+ if (this.#fileIdent === undefined) {
267
+ this.#fileIdent = this.createIdentifier('ᚕf');
268
+ const decl = this.factory.createVariableDeclaration(this.#fileIdent, undefined, undefined,
269
+ this.fromLiteral(this.#resolver.getFileImportName(this.source.fileName) ?? this.source.fileName)
270
+ );
271
+ this.addStatements([
272
+ this.factory.createVariableStatement([], this.factory.createVariableDeclarationList([decl]))
273
+ ], -1);
274
+ }
275
+ return this.#fileIdent;
276
+ }
277
+
265
278
  /**
266
279
  * Find decorator, relative to registered key
267
280
  * @param state
@@ -269,10 +282,11 @@ export class TransformerState implements State {
269
282
  * @param name
270
283
  * @param module
271
284
  */
272
- findDecorator(cls: Transformer, node: ts.Node, name: string, module?: string): ts.Decorator | undefined {
273
- const target = `${cls[TransformerId]}/${name}`;
274
- return this.getDecoratorList(node)
275
- .find(x => x.targets?.includes(target) && (!module || x.name === name && x.module === module))?.dec;
285
+ findDecorator(mod: string | Transformer, node: ts.Node, name: string, module?: string): ts.Decorator | undefined {
286
+ mod = typeof mod === 'string' ? mod : mod[ModuleNameⲐ]!;
287
+ const target = `${mod}:${name}`;
288
+ const list = this.getDecoratorList(node);
289
+ return list.find(x => x.targets?.includes(target) && (!module || x.name === name && x.module === module))?.dec;
276
290
  }
277
291
 
278
292
  /**
@@ -291,7 +305,7 @@ export class TransformerState implements State {
291
305
  }
292
306
  } catch {
293
307
  // Determine type unique ident
294
- unique = Util.uuid(type.name ? 5 : 10);
308
+ unique = SystemUtil.uuid(type.name ? 5 : 10);
295
309
  }
296
310
  // Otherwise read name with uuid
297
311
  let name = type.name && !type.name.startsWith('_') ? type.name : '';
@@ -325,7 +339,7 @@ export class TransformerState implements State {
325
339
  (m): m is ts.MethodDeclaration => ts.isMethodDeclaration(m) && ts.isIdentifier(m.name) && m.name.escapedText === method
326
340
  );
327
341
  } else {
328
- const props = this.getResolver().getPropertiesOfType(cls);
342
+ const props = this.#resolver.getPropertiesOfType(cls);
329
343
  for (const prop of props) {
330
344
  const decl = prop.declarations?.[0];
331
345
  if (decl && prop.escapedName === method && ts.isMethodDeclaration(decl)) {
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import type ts from 'typescript';
2
2
 
3
3
  /**
4
4
  * Param documentation
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
3
  /**
4
4
  * Decorator metadata
@@ -14,7 +14,7 @@ export type DecoratorMeta = {
14
14
 
15
15
  export type State = {
16
16
  source: ts.SourceFile;
17
- module: string;
17
+ importName: string;
18
18
  added: Map<number, ts.Statement[]>;
19
19
  getDecoratorList(node: ts.Node): DecoratorMeta[];
20
20
  finalize(src: ts.SourceFile): ts.SourceFile;
@@ -22,12 +22,14 @@ export type State = {
22
22
 
23
23
  export type TransformPhase = 'before' | 'after';
24
24
 
25
- export type TransformerType = 'class' | 'method' | 'property' | 'getter' | 'setter' | 'parameter' | 'static-method' | 'call' | 'function';
25
+ export type TransformerType =
26
+ 'class' | 'method' | 'property' | 'getter' | 'setter' | 'parameter' |
27
+ 'static-method' | 'call' | 'function' | 'file';
26
28
 
27
- export const TransformerId = Symbol.for('@trv:transformer/id');
29
+ export const ModuleNameⲐ = Symbol.for('@travetto/transformer:id');
28
30
 
29
31
  export type Transformer = {
30
- [TransformerId]: string;
32
+ [ModuleNameⲐ]?: string;
31
33
  name: string;
32
34
  };
33
35
 
package/src/util/core.ts CHANGED
@@ -1,9 +1,10 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
3
  /**
4
4
  * Core utilities util
5
5
  */
6
6
  export class CoreUtil {
7
+
7
8
  /**
8
9
  * See if inbound node has an original property
9
10
  */
@@ -51,7 +52,6 @@ export class CoreUtil {
51
52
  */
52
53
  static createStaticField(factory: ts.NodeFactory, name: string, val: ts.Expression): ts.PropertyDeclaration {
53
54
  return factory.createPropertyDeclaration(
54
- undefined,
55
55
  [factory.createToken(ts.SyntaxKind.StaticKeyword)],
56
56
  name, undefined, undefined, val
57
57
  );
@@ -88,13 +88,15 @@ export class CoreUtil {
88
88
  factory: ts.NodeFactory,
89
89
  first: string | ts.Expression,
90
90
  second: string | ts.Identifier,
91
- ...items: (string | ts.Identifier)[]
92
- ): ts.PropertyAccessExpression {
91
+ ...items: (string | number | ts.Identifier)[]
92
+ ): ts.Expression {
93
93
  if (typeof first === 'string') {
94
94
  first = factory.createIdentifier(first);
95
95
  }
96
- return items.reduce(
97
- (acc, p) => factory.createPropertyAccessExpression(acc, p),
96
+ return items.reduce<ts.Expression>(
97
+ (acc, p) => typeof p === 'number' ?
98
+ factory.createElementAccessExpression(acc, p) :
99
+ factory.createPropertyAccessExpression(acc, p),
98
100
  factory.createPropertyAccessExpression(first, second)
99
101
  );
100
102
  }
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
  import { CoreUtil } from './core';
3
3
 
4
4
  /**
@@ -57,8 +57,8 @@ export class DeclarationUtil {
57
57
  * Resolve the `ts.ObjectFlags`
58
58
  */
59
59
  static getObjectFlags(type: ts.Type): ts.ObjectFlags {
60
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
61
- return (ts as unknown as { getObjectFlags(t: ts.Type): ts.ObjectFlags }).getObjectFlags(type);
60
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, no-bitwise
61
+ return (ts as unknown as { getObjectFlags(t: ts.Type): ts.ObjectFlags }).getObjectFlags(type) & ~(ts.NodeFlags.ThisNodeOrAnySubNodesHasError);
62
62
  }
63
63
 
64
64
  /**
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
  import { CoreUtil } from './core';
3
3
 
4
4
  /**
package/src/util/doc.ts CHANGED
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
3
  import { DeclDocumentation } from '../types/shared';
4
4
  import { CoreUtil } from './core';
@@ -1,7 +1,6 @@
1
- import * as ts from 'typescript';
2
- import { resolve as pathResolve } from 'path';
1
+ import ts from 'typescript';
3
2
 
4
- import { PathUtil } from '@travetto/boot';
3
+ import { PackageUtil, path } from '@travetto/manifest';
5
4
 
6
5
  import { Import } from '../types/shared';
7
6
 
@@ -13,9 +12,17 @@ export class ImportUtil {
13
12
  * useful for handling failed imports, but still transpiling
14
13
  */
15
14
  static optionalResolve(file: string, base?: string): string {
16
- file = base ? pathResolve(base, file) : file;
15
+ if (base?.endsWith('.ts')) {
16
+ base = path.dirname(base);
17
+ }
18
+ if (base && file.startsWith('.')) {
19
+ return path.resolve(base, file);
20
+ // TODO: Replace with manifest reverse lookup
21
+ } else if (file.startsWith('@')) {
22
+ return path.resolve('node_modules', file);
23
+ }
17
24
  try {
18
- return require.resolve(file);
25
+ return PackageUtil.resolveImport(file);
19
26
  } catch {
20
27
  return file;
21
28
  }
@@ -25,23 +32,23 @@ export class ImportUtil {
25
32
  * Collect all imports for a source file, as a hash map
26
33
  */
27
34
  static collectImports(src: ts.SourceFile): Map<string, Import> {
28
- const pth = require.resolve(src.fileName);
29
- const base = PathUtil.toUnix(pth);
35
+ // TODO: Replace with manifest reverse lookup
36
+ const base = path.toPosix(src.fileName);
30
37
 
31
38
  const imports = new Map<string, Import>();
32
39
 
33
40
  for (const stmt of src.statements) {
34
41
  if (ts.isImportDeclaration(stmt) && ts.isStringLiteral(stmt.moduleSpecifier)) {
35
- const path = this.optionalResolve(stmt.moduleSpecifier.text, base);
42
+ const resolved = this.optionalResolve(stmt.moduleSpecifier.text, base);
36
43
 
37
44
  if (stmt.importClause) {
38
45
  if (stmt.importClause.namedBindings) {
39
46
  const bindings = stmt.importClause.namedBindings;
40
47
  if (ts.isNamespaceImport(bindings)) {
41
- imports.set(bindings.name.text, { path, ident: bindings.name, stmt });
48
+ imports.set(bindings.name.text, { path: resolved, ident: bindings.name, stmt });
42
49
  } else if (ts.isNamedImports(bindings)) {
43
50
  for (const n of bindings.elements) {
44
- imports.set(n.name.text, { path, ident: n.name, stmt });
51
+ imports.set(n.name.text, { path: resolved, ident: n.name, stmt });
45
52
  }
46
53
  }
47
54
  }
@@ -1,4 +1,4 @@
1
- import * as ts from 'typescript';
1
+ import ts from 'typescript';
2
2
 
3
3
  /**
4
4
  * Utilities for dealing with literals
@@ -48,7 +48,8 @@ export class LiteralUtil {
48
48
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
49
49
  const ov = val as object;
50
50
  const pairs: ts.PropertyAssignment[] = [];
51
- for (const k of Object.keys(ov)) {
51
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
52
+ for (const k of Object.keys(ov) as (keyof typeof ov)[]) {
52
53
  if (ov[k] !== undefined) {
53
54
  pairs.push(
54
55
  factory.createPropertyAssignment(k, this.fromLiteral(factory, ov[k]))
package/src/util/log.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { Util } from '@travetto/base';
2
-
3
1
  const exclude = new Set([
4
2
  'parent', 'checker', 'end', 'pos', 'id', 'source', 'sourceFile', 'getSourceFile',
5
3
  'statements', 'stringIndexInfo', 'numberIndexInfo', 'instantiations', 'thisType',
@@ -22,7 +20,7 @@ export class LogUtil {
22
20
  * Clean up `ts.Node` contents for logging
23
21
  */
24
22
  static collapseNode(x: unknown, cache: Set<unknown> = new Set()): unknown {
25
- if (!x || Util.isPrimitive(x)) {
23
+ if (!x || !(typeof x === 'object' || typeof x === 'function')) {
26
24
  return x;
27
25
  }
28
26
 
@@ -38,8 +36,9 @@ export class LogUtil {
38
36
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
39
37
  const ox = x as object;
40
38
  const out: Record<string, unknown> = {};
41
- for (const key of Object.keys(ox)) {
42
- if (Util.isFunction(ox[key]) || exclude.has(key) || ox[key] === undefined) {
39
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
40
+ for (const key of Object.keys(ox) as (keyof typeof ox)[]) {
41
+ if (Object.getPrototypeOf(ox[key]) === Function.prototype || exclude.has(key) || ox[key] === undefined) {
43
42
  continue;
44
43
  }
45
44
  try {
@@ -0,0 +1,31 @@
1
+ import crypto from 'crypto';
2
+
3
+ export class SystemUtil {
4
+
5
+ /**
6
+ * Generate a random UUID
7
+ * @param len The length of the uuid to generate
8
+ */
9
+ static uuid(len: number = 32): string {
10
+ const bytes = crypto.randomBytes(Math.ceil(len / 2));
11
+ // eslint-disable-next-line no-bitwise
12
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
13
+ // eslint-disable-next-line no-bitwise
14
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
15
+ return bytes.toString('hex').substring(0, len);
16
+ }
17
+
18
+ /**
19
+ * Naive hashing
20
+ */
21
+ static naiveHash(text: string): number {
22
+ let hash = 5381;
23
+
24
+ for (let i = 0; i < text.length; i++) {
25
+ // eslint-disable-next-line no-bitwise
26
+ hash = (hash * 33) ^ text.charCodeAt(i);
27
+ }
28
+
29
+ return Math.abs(hash);
30
+ }
31
+ }
package/src/visitor.ts CHANGED
@@ -1,11 +1,6 @@
1
- import * as ts from 'typescript';
2
- import { createWriteStream } from 'fs';
3
-
4
- import { ConsoleManager } from '@travetto/base/src/console';
5
- import { AppCache } from '@travetto/boot';
1
+ import ts from 'typescript';
6
2
 
7
3
  import { DecoratorMeta, TransformerType, NodeTransformer, TransformerSet, State, TransformPhase } from './types/visitor';
8
- import { LogUtil } from './util/log';
9
4
  import { CoreUtil } from './util/core';
10
5
 
11
6
  /**
@@ -28,26 +23,24 @@ export class VisitorFactory<S extends State = State> {
28
23
  return 'class';
29
24
  } else if (ts.isParameter(node)) {
30
25
  return 'parameter';
31
- } else if (ts.isFunctionDeclaration(node) || (ts.isFunctionExpression(node) && !ts.isArrowFunction(node))) {
26
+ } else if ((ts.isFunctionDeclaration(node) && node.body) || (ts.isFunctionExpression(node) && !ts.isArrowFunction(node))) {
32
27
  return 'function';
33
28
  } else if (ts.isGetAccessor(node)) {
34
29
  return 'getter';
35
30
  } else if (ts.isSetAccessor(node)) {
36
31
  return 'setter';
32
+ } else if (ts.isSourceFile(node)) {
33
+ return 'file';
37
34
  }
38
35
  }
39
36
 
40
37
  #transformers = new Map<TransformerType, TransformerSet<S>>();
41
- #logTarget: string;
42
38
  #getState: (context: ts.TransformationContext, src: ts.SourceFile) => S;
43
- #logger: Console | undefined;
44
39
 
45
40
  constructor(
46
41
  getState: (context: ts.TransformationContext, src: ts.SourceFile) => S,
47
- transformers: NodeTransformer<S, TransformerType, ts.Node>[],
48
- logTarget = 'compiler.log'
42
+ transformers: NodeTransformer<S, TransformerType, ts.Node>[]
49
43
  ) {
50
- this.#logTarget = logTarget;
51
44
  this.#getState = getState;
52
45
  this.#init(transformers);
53
46
  }
@@ -79,26 +72,16 @@ export class VisitorFactory<S extends State = State> {
79
72
  }
80
73
  }
81
74
 
82
- get logger(): Console {
83
- this.#logger ??= new console.Console({
84
- stdout: createWriteStream(AppCache.toEntryName(this.#logTarget), { flags: 'a' }),
85
- inspectOptions: { depth: 4 },
86
- });
87
- return this.#logger;
88
- }
89
-
90
75
  /**
91
76
  * Produce a visitor for a given a file
92
77
  */
93
78
  visitor(): ts.TransformerFactory<ts.SourceFile> {
94
79
  return (context: ts.TransformationContext) => (file: ts.SourceFile): ts.SourceFile => {
95
- try {
96
- const c = this.logger;
97
- ConsoleManager.set({
98
- onLog: (level, ctx, args) => c[level](level, ctx, ...LogUtil.collapseNodes(args))
99
- });
80
+ if (!file.fileName.endsWith('.ts')) { // Skip all non-ts files
81
+ return file;
82
+ }
100
83
 
101
- console.debug('Processing', { file: file.fileName, pid: process.pid });
84
+ try {
102
85
  const state = this.#getState(context, file);
103
86
  let ret = this.visit(state, context, file);
104
87
 
@@ -106,12 +89,11 @@ export class VisitorFactory<S extends State = State> {
106
89
  const changed = state.added.size;
107
90
  let statements: ts.NodeArray<ts.Statement> | ts.Statement[] = ret.statements;
108
91
  while (state.added.size) {
109
- for (const [k, all] of [...state.added]) {
110
- const idx = k === -1 ? state.added.size : k;
92
+ for (const [idx, all] of [...state.added].sort(([idxA], [idxB]) => idxB - idxA)) {
111
93
  statements = [
112
- ...statements.slice(0, idx),
94
+ ...statements.slice(0, Math.max(idx, 0)),
113
95
  ...all.map(v => this.visit(state, context, v)),
114
- ...statements.slice(idx)
96
+ ...statements.slice(Math.max(idx, 0))
115
97
  ];
116
98
  state.added.delete(idx);
117
99
  }
@@ -125,12 +107,10 @@ export class VisitorFactory<S extends State = State> {
125
107
  if (!(err instanceof Error)) {
126
108
  throw err;
127
109
  }
128
- console.error('Failed transforming', { error: `${err.message}\n${err.stack}`, file: file.fileName });
110
+ console!.error('Failed transforming', { error: `${err.message}\n${err.stack}`, file: file.fileName });
129
111
  const out = new Error(`Failed transforming: ${file.fileName}: ${err.message}`);
130
112
  out.stack = err.stack;
131
113
  throw out;
132
- } finally {
133
- ConsoleManager.clear(); // Reset logging
134
114
  }
135
115
  };
136
116
  }
package/index.ts DELETED
@@ -1,7 +0,0 @@
1
- export * from './src/state';
2
- export * from './src/visitor';
3
- export * from './src/register';
4
- export * from './src/types/visitor';
5
- export * from './src/types/shared';
6
- export { AnyType } from './src/resolver/types';
7
- export * from './src/util';
package/src/util/index.ts DELETED
@@ -1,6 +0,0 @@
1
- export * from './core';
2
- export * from './declaration';
3
- export * from './decorator';
4
- export * from './doc';
5
- export * from './literal';
6
- export * from './log';