@travetto/transformer 5.0.0-rc.5 → 5.0.0-rc.7
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 +3 -3
- package/src/resolver/builder.ts +17 -12
- package/src/resolver/coerce.ts +12 -2
- package/src/resolver/service.ts +3 -4
- package/src/state.ts +13 -16
- package/src/types/shared.ts +5 -0
- package/src/types/visitor.ts +2 -2
- package/src/util/core.ts +14 -9
- package/src/util/declaration.ts +3 -2
- package/src/util/decorator.ts +4 -5
- package/src/util/doc.ts +2 -3
- package/src/util/literal.ts +23 -16
- package/src/util/log.ts +4 -4
- package/src/visitor.ts +2 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/transformer",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.7",
|
|
4
4
|
"description": "Functionality for AST transformations, with transformer registration, and general utils",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"directory": "module/transformer"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@travetto/manifest": "^5.0.0-rc.
|
|
27
|
+
"@travetto/manifest": "^5.0.0-rc.5",
|
|
28
28
|
"tslib": "^2.6.3",
|
|
29
|
-
"typescript": "^5.5.
|
|
29
|
+
"typescript": "^5.5.4"
|
|
30
30
|
},
|
|
31
31
|
"travetto": {
|
|
32
32
|
"displayName": "Transformation",
|
package/src/resolver/builder.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { DocUtil } from '../util/doc';
|
|
|
7
7
|
import { CoreUtil } from '../util/core';
|
|
8
8
|
import { DeclarationUtil } from '../util/declaration';
|
|
9
9
|
import { LiteralUtil } from '../util/literal';
|
|
10
|
-
import { TemplateLiteralPart } from '../types/shared';
|
|
10
|
+
import { transformCast, TemplateLiteralPart } from '../types/shared';
|
|
11
11
|
|
|
12
12
|
import { Type, AnyType, UnionType, TransformResolver, TemplateType } from './types';
|
|
13
13
|
import { CoerceUtil } from './coerce';
|
|
@@ -54,7 +54,7 @@ export function TypeCategorize(resolver: TransformResolver, type: ts.Type): { ca
|
|
|
54
54
|
return { category: 'undefined', type };
|
|
55
55
|
} else if (DocUtil.readDocTag(type, 'concrete').length) {
|
|
56
56
|
return { category: 'concrete', type };
|
|
57
|
-
} else if (flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { // Any or unknown
|
|
57
|
+
} else if (flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never)) { // Any or unknown
|
|
58
58
|
return { category: 'unknown', type };
|
|
59
59
|
} else if (objectFlags & ts.ObjectFlags.Reference && !CoreUtil.getSymbol(type)) { // Tuple type?
|
|
60
60
|
return { category: 'tuple', type };
|
|
@@ -91,9 +91,10 @@ export function TypeCategorize(resolver: TransformResolver, type: ts.Type): { ca
|
|
|
91
91
|
} else if (flags & (ts.TypeFlags.TemplateLiteral)) {
|
|
92
92
|
return { category: 'template', type };
|
|
93
93
|
} else if (flags & (
|
|
94
|
-
ts.TypeFlags.
|
|
95
|
-
ts.TypeFlags.
|
|
96
|
-
ts.TypeFlags.
|
|
94
|
+
ts.TypeFlags.BigIntLike |
|
|
95
|
+
ts.TypeFlags.BooleanLike |
|
|
96
|
+
ts.TypeFlags.NumberLike |
|
|
97
|
+
ts.TypeFlags.StringLike |
|
|
97
98
|
ts.TypeFlags.Void | ts.TypeFlags.Undefined
|
|
98
99
|
)) {
|
|
99
100
|
return { category: 'literal', type };
|
|
@@ -104,7 +105,7 @@ export function TypeCategorize(resolver: TransformResolver, type: ts.Type): { ca
|
|
|
104
105
|
} else if (type.isLiteral()) {
|
|
105
106
|
return { category: 'shape', type };
|
|
106
107
|
}
|
|
107
|
-
return { category: '
|
|
108
|
+
return { category: 'literal', type };
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
/**
|
|
@@ -117,7 +118,7 @@ export const TypeBuilder: {
|
|
|
117
118
|
}
|
|
118
119
|
} = {
|
|
119
120
|
unknown: {
|
|
120
|
-
build: (resolver, type) =>
|
|
121
|
+
build: (resolver, type) => ({ key: 'unknown' })
|
|
121
122
|
},
|
|
122
123
|
undefined: {
|
|
123
124
|
build: (resolver, type) => ({ key: 'literal', name: 'undefined', ctor: undefined })
|
|
@@ -165,8 +166,7 @@ export const TypeBuilder: {
|
|
|
165
166
|
|
|
166
167
|
if (name in GLOBAL_SIMPLE) {
|
|
167
168
|
const cons = GLOBAL_SIMPLE[name];
|
|
168
|
-
|
|
169
|
-
const ret = LiteralUtil.isLiteralType(type) ? CoerceUtil.coerce(type.value, cons as typeof String, false) :
|
|
169
|
+
const ret = LiteralUtil.isLiteralType(type) ? CoerceUtil.coerce(type.value, transformCast(cons), false) :
|
|
170
170
|
undefined;
|
|
171
171
|
|
|
172
172
|
return {
|
|
@@ -183,6 +183,12 @@ export const TypeBuilder: {
|
|
|
183
183
|
ctor: cons,
|
|
184
184
|
tsTypeArguments: resolver.getAllTypeArguments(type)
|
|
185
185
|
};
|
|
186
|
+
} else {
|
|
187
|
+
return {
|
|
188
|
+
key: 'literal',
|
|
189
|
+
name: 'Object',
|
|
190
|
+
ctor: Object
|
|
191
|
+
};
|
|
186
192
|
}
|
|
187
193
|
}
|
|
188
194
|
},
|
|
@@ -225,8 +231,7 @@ export const TypeBuilder: {
|
|
|
225
231
|
ctor: String,
|
|
226
232
|
nullable: type.nullable,
|
|
227
233
|
undefinable: type.undefinable,
|
|
228
|
-
|
|
229
|
-
template: { op: 'or', values: subTypes.map(x => (x as TemplateType).template!) }
|
|
234
|
+
template: { op: 'or', values: subTypes.map(x => transformCast<TemplateType>(x).template!) }
|
|
230
235
|
};
|
|
231
236
|
} else if (subTypes.length === 1) {
|
|
232
237
|
return { undefinable, nullable, ...first };
|
|
@@ -244,7 +249,7 @@ export const TypeBuilder: {
|
|
|
244
249
|
const tsTypeArguments = resolver.getAllTypeArguments(type);
|
|
245
250
|
const props = resolver.getPropertiesOfType(type);
|
|
246
251
|
if (props.length === 0) {
|
|
247
|
-
return { key: '
|
|
252
|
+
return { key: 'literal', name: 'Object', ctor: Object };
|
|
248
253
|
}
|
|
249
254
|
|
|
250
255
|
for (const member of props) {
|
package/src/resolver/coerce.ts
CHANGED
|
@@ -33,6 +33,7 @@ export class CoerceUtil {
|
|
|
33
33
|
* @param strict Should a failure to coerce throw an error?
|
|
34
34
|
*/
|
|
35
35
|
static coerce(input: unknown, type: typeof String, strict?: boolean): string;
|
|
36
|
+
static coerce(input: unknown, type: typeof BigInt, strict?: boolean): bigint;
|
|
36
37
|
static coerce(input: unknown, type: typeof Number, strict?: boolean): number;
|
|
37
38
|
static coerce(input: unknown, type: typeof Boolean, strict?: boolean): boolean;
|
|
38
39
|
static coerce(input: unknown, type: typeof Date, strict?: boolean): Date;
|
|
@@ -50,8 +51,7 @@ export class CoerceUtil {
|
|
|
50
51
|
switch (type) {
|
|
51
52
|
case Date: {
|
|
52
53
|
const res = typeof input === 'number' || /^[-]?\d+$/.test(`${input}`) ?
|
|
53
|
-
|
|
54
|
-
new Date(parseInt(input as string, 10)) : new Date(input as Date);
|
|
54
|
+
new Date(parseInt(`${input}`, 10)) : new Date(`${input}`);
|
|
55
55
|
if (strict && Number.isNaN(res.getTime())) {
|
|
56
56
|
throw new Error(`Invalid date value: ${input}`);
|
|
57
57
|
}
|
|
@@ -64,6 +64,16 @@ export class CoerceUtil {
|
|
|
64
64
|
}
|
|
65
65
|
return res;
|
|
66
66
|
}
|
|
67
|
+
case BigInt: {
|
|
68
|
+
try {
|
|
69
|
+
return BigInt(typeof input === 'string' || typeof input === 'number' ? input : `${input}`);
|
|
70
|
+
} catch {
|
|
71
|
+
if (strict) {
|
|
72
|
+
throw new Error(`Invalid numeric value: ${input}`);
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
67
77
|
case Boolean: {
|
|
68
78
|
const match = `${input}`.match(/^((?<TRUE>true|yes|1|on)|false|no|off|0)$/i);
|
|
69
79
|
if (strict && !match) {
|
package/src/resolver/service.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { TypeCategorize, TypeBuilder } from './builder';
|
|
|
7
7
|
import { VisitCache } from './cache';
|
|
8
8
|
import { DocUtil } from '../util/doc';
|
|
9
9
|
import { DeclarationUtil } from '../util/declaration';
|
|
10
|
+
import { transformCast } from '../types/shared';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Implementation of TransformResolver
|
|
@@ -80,8 +81,7 @@ export class SimpleResolver implements TransformResolver {
|
|
|
80
81
|
* Fetch all type arguments for a give type
|
|
81
82
|
*/
|
|
82
83
|
getAllTypeArguments(ref: ts.Type): ts.Type[] {
|
|
83
|
-
|
|
84
|
-
return this.#tsChecker.getTypeArguments(ref as ts.TypeReference) as ts.Type[];
|
|
84
|
+
return transformCast(this.#tsChecker.getTypeArguments(transformCast(ref)));
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
@@ -148,8 +148,7 @@ export class SimpleResolver implements TransformResolver {
|
|
|
148
148
|
delete result.tsSubTypes;
|
|
149
149
|
}
|
|
150
150
|
if (finalize) {
|
|
151
|
-
|
|
152
|
-
result = finalize(result as never);
|
|
151
|
+
result = finalize(transformCast(result));
|
|
153
152
|
}
|
|
154
153
|
}
|
|
155
154
|
|
package/src/state.ts
CHANGED
|
@@ -15,14 +15,12 @@ import { CoreUtil } from './util/core';
|
|
|
15
15
|
import { LiteralUtil } from './util/literal';
|
|
16
16
|
import { SystemUtil } from './util/system';
|
|
17
17
|
|
|
18
|
-
function hasOriginal(n:
|
|
19
|
-
|
|
20
|
-
return !!n && !(n as { parent?: unknown }).parent && !!(n as { original: unknown }).original;
|
|
18
|
+
function hasOriginal(n: ts.Node): n is ts.Node & { original: ts.Node } {
|
|
19
|
+
return !!n && !n.parent && 'original' in n && !!n.original;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
function hasEscapedName(n:
|
|
24
|
-
|
|
25
|
-
return !!n && !!(n as { name?: { escapedText?: string } }).name?.escapedText;
|
|
22
|
+
function hasEscapedName(n: ts.Node): n is ts.Node & { name: { escapedText: string } } {
|
|
23
|
+
return !!n && 'name' in n && typeof n.name === 'object' && !!n.name && 'escapedText' in n.name && !!n.name.escapedText;
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
/**
|
|
@@ -151,8 +149,7 @@ export class TransformerState implements State {
|
|
|
151
149
|
const targets = DocUtil.readAugments(this.#resolver.getType(ident));
|
|
152
150
|
const module = file ? mod : undefined;
|
|
153
151
|
const name = ident ?
|
|
154
|
-
|
|
155
|
-
ident.escapedText! as string :
|
|
152
|
+
ident.escapedText?.toString()! :
|
|
156
153
|
undefined;
|
|
157
154
|
|
|
158
155
|
if (ident && name) {
|
|
@@ -193,10 +190,11 @@ export class TransformerState implements State {
|
|
|
193
190
|
while (n && !ts.isSourceFile(n.parent) && n !== n.parent) {
|
|
194
191
|
n = n.parent;
|
|
195
192
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
193
|
+
if (!ts.isStatement(n)) {
|
|
194
|
+
throw new Error('Unable to find statement at top level');
|
|
195
|
+
}
|
|
196
|
+
if (n && ts.isSourceFile(n.parent) && stmts.indexOf(n) >= 0) {
|
|
197
|
+
idx = stmts.indexOf(n) - 1;
|
|
200
198
|
}
|
|
201
199
|
} else if (before !== undefined) {
|
|
202
200
|
idx = before;
|
|
@@ -225,8 +223,7 @@ export class TransformerState implements State {
|
|
|
225
223
|
fromLiteral(val: unknown[]): ts.ArrayLiteralExpression;
|
|
226
224
|
fromLiteral(val: string | boolean | number): ts.LiteralExpression;
|
|
227
225
|
fromLiteral(val: unknown): ts.Node {
|
|
228
|
-
|
|
229
|
-
return LiteralUtil.fromLiteral(this.factory, val as object);
|
|
226
|
+
return LiteralUtil.fromLiteral(this.factory, val!);
|
|
230
227
|
}
|
|
231
228
|
|
|
232
229
|
/**
|
|
@@ -308,9 +305,9 @@ export class TransformerState implements State {
|
|
|
308
305
|
const fileName = tgt.getSourceFile().fileName;
|
|
309
306
|
|
|
310
307
|
if (fileName === this.source.fileName) { // if in same file suffix with location
|
|
311
|
-
let child =
|
|
308
|
+
let child: ts.Node = tgt;
|
|
312
309
|
while (child && !ts.isSourceFile(child)) {
|
|
313
|
-
if (ts.isFunctionDeclaration(child) || ts.isMethodDeclaration(child) || ts.isClassDeclaration(child)) {
|
|
310
|
+
if (ts.isFunctionDeclaration(child) || ts.isMethodDeclaration(child) || ts.isClassDeclaration(child) || ts.isInterfaceDeclaration(child)) {
|
|
314
311
|
if (child.name) {
|
|
315
312
|
unique.push(child.name.getText());
|
|
316
313
|
}
|
package/src/types/shared.ts
CHANGED
|
@@ -30,3 +30,8 @@ export type Import = {
|
|
|
30
30
|
/** Template Literal Types */
|
|
31
31
|
export type TemplateLiteralPart = string | NumberConstructor | StringConstructor | BooleanConstructor;
|
|
32
32
|
export type TemplateLiteral = { op: 'and' | 'or', values: (TemplateLiteralPart | TemplateLiteral)[] };
|
|
33
|
+
|
|
34
|
+
export function transformCast<T>(input: unknown): T {
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
36
|
+
return input as T;
|
|
37
|
+
}
|
package/src/types/visitor.ts
CHANGED
|
@@ -42,6 +42,6 @@ export interface NodeTransformer<S extends State = State, T extends TransformerT
|
|
|
42
42
|
type: T;
|
|
43
43
|
key: string;
|
|
44
44
|
target?: string[];
|
|
45
|
-
before
|
|
46
|
-
after
|
|
45
|
+
before?<Z extends ts.Node = ts.Node>(state: S, node: N, dm?: DecoratorMeta): Z | undefined;
|
|
46
|
+
after?<Z extends ts.Node = ts.Node>(state: S, node: N, dm?: DecoratorMeta): Z | undefined;
|
|
47
47
|
}
|
package/src/util/core.ts
CHANGED
|
@@ -9,16 +9,14 @@ export class CoreUtil {
|
|
|
9
9
|
* See if inbound node has an original property
|
|
10
10
|
*/
|
|
11
11
|
static hasOriginal(o: ts.Node): o is (ts.Node & { original: ts.Node }) {
|
|
12
|
-
|
|
13
|
-
return 'original' in o && !!(o as { original?: ts.Node }).original;
|
|
12
|
+
return 'original' in o && !!o.original;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
16
|
* See if type has target
|
|
18
17
|
*/
|
|
19
18
|
static hasTarget(o: ts.Type): o is (ts.Type & { target: ts.Type }) {
|
|
20
|
-
|
|
21
|
-
return 'target' in o && !!(o as { target?: ts.Type }).target;
|
|
19
|
+
return 'target' in o && !!o.target;
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
/**
|
|
@@ -36,12 +34,19 @@ export class CoreUtil {
|
|
|
36
34
|
/**
|
|
37
35
|
* Find the primary argument of a call expression, or decorator.
|
|
38
36
|
*/
|
|
39
|
-
static
|
|
40
|
-
if (node && node
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
static findArgument<T extends ts.Expression = ts.Expression>(node: ts.CallExpression | undefined, pred: (x: ts.Expression) => x is T): T | undefined {
|
|
38
|
+
if (node && node.arguments && node.arguments.length) {
|
|
39
|
+
return node.arguments.find(pred);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Find the first argument of a call expression, or decorator.
|
|
45
|
+
*/
|
|
46
|
+
static firstArgument(node: ts.CallExpression | undefined): ts.Expression | undefined {
|
|
47
|
+
if (node && node!.arguments && node!.arguments.length) {
|
|
48
|
+
return node.arguments[0];
|
|
43
49
|
}
|
|
44
|
-
return;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
/**
|
package/src/util/declaration.ts
CHANGED
|
@@ -57,8 +57,9 @@ export class DeclarationUtil {
|
|
|
57
57
|
* Resolve the `ts.ObjectFlags`
|
|
58
58
|
*/
|
|
59
59
|
static getObjectFlags(type: ts.Type): ts.ObjectFlags {
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
const _ts: typeof ts & { getObjectFlags?(t: ts.Type): ts.ObjectFlags } = ts;
|
|
61
|
+
// eslint-disable-next-line no-bitwise
|
|
62
|
+
return _ts.getObjectFlags!(type) & ~(ts.NodeFlags.ThisNodeOrAnySubNodesHasError);
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
/**
|
package/src/util/decorator.ts
CHANGED
|
@@ -56,15 +56,14 @@ export class DecoratorUtil {
|
|
|
56
56
|
/**
|
|
57
57
|
* Find the primary argument of a call expression, or decorator.
|
|
58
58
|
*/
|
|
59
|
-
static getPrimaryArgument
|
|
60
|
-
return CoreUtil.
|
|
59
|
+
static getPrimaryArgument(node: ts.Decorator | undefined): ts.Expression | undefined {
|
|
60
|
+
return CoreUtil.firstArgument(node && ts.isCallExpression(node.expression) ? node.expression : undefined);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* Find the primary argument of a call expression, or decorator.
|
|
65
65
|
*/
|
|
66
|
-
static getArguments
|
|
67
|
-
|
|
68
|
-
return node && ts.isCallExpression(node.expression) ? [...node.expression.arguments] as T[] : undefined;
|
|
66
|
+
static getArguments(node: ts.Decorator | undefined): ts.Expression[] | undefined {
|
|
67
|
+
return node && ts.isCallExpression(node.expression) ? [...node.expression.arguments] : undefined;
|
|
69
68
|
}
|
|
70
69
|
}
|
package/src/util/doc.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
|
|
3
|
-
import { DeclDocumentation } from '../types/shared';
|
|
3
|
+
import { transformCast, DeclDocumentation } from '../types/shared';
|
|
4
4
|
import { CoreUtil } from './core';
|
|
5
5
|
import { DeclarationUtil } from './declaration';
|
|
6
6
|
|
|
@@ -38,8 +38,7 @@ export class DocUtil {
|
|
|
38
38
|
if (node) {
|
|
39
39
|
const tags = ts.getJSDocTags(node);
|
|
40
40
|
while (!this.hasJSDoc(node) && CoreUtil.hasOriginal(node)) {
|
|
41
|
-
|
|
42
|
-
node = node.original as ts.Declaration;
|
|
41
|
+
node = transformCast<ts.Declaration>(node.original);
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
const docs = this.hasJSDoc(node) ? node.jsDoc : undefined;
|
package/src/util/literal.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
|
|
3
|
-
import { TemplateLiteral } from '../types/shared';
|
|
3
|
+
import { transformCast, TemplateLiteral } from '../types/shared';
|
|
4
|
+
|
|
5
|
+
const TypedObject: {
|
|
6
|
+
keys<T = unknown, K extends keyof T = keyof T>(o: T): K[];
|
|
7
|
+
} & ObjectConstructor = Object;
|
|
8
|
+
|
|
9
|
+
function isNode(n: unknown): n is ts.Node {
|
|
10
|
+
return !!n && typeof n === 'object' && 'kind' in n;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const KNOWN_FNS = new Set<unknown>([String, Number, Boolean, Date, RegExp]);
|
|
14
|
+
|
|
15
|
+
function isKnownFn(n: unknown): n is Function {
|
|
16
|
+
return KNOWN_FNS.has(n);
|
|
17
|
+
}
|
|
4
18
|
|
|
5
19
|
/**
|
|
6
20
|
* Utilities for dealing with literals
|
|
@@ -27,10 +41,8 @@ export class LiteralUtil {
|
|
|
27
41
|
static fromLiteral(factory: ts.NodeFactory, val: unknown[]): ts.ArrayLiteralExpression;
|
|
28
42
|
static fromLiteral(factory: ts.NodeFactory, val: string | boolean | number): ts.LiteralExpression;
|
|
29
43
|
static fromLiteral(factory: ts.NodeFactory, val: unknown): ts.Node {
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
33
|
-
return val as ts.Node;
|
|
44
|
+
if (isNode(val)) { // If already a node
|
|
45
|
+
return val;
|
|
34
46
|
} else if (Array.isArray(val)) {
|
|
35
47
|
val = factory.createArrayLiteralExpression(val.map(v => this.fromLiteral(factory, v)));
|
|
36
48
|
} else if (val === undefined) {
|
|
@@ -45,15 +57,12 @@ export class LiteralUtil {
|
|
|
45
57
|
val = val ? factory.createTrue() : factory.createFalse();
|
|
46
58
|
} else if (val instanceof RegExp) {
|
|
47
59
|
val = factory.createRegularExpressionLiteral(`/${val.source}/${val.flags ?? ''}`);
|
|
48
|
-
} else if (val
|
|
49
|
-
|
|
50
|
-
val = factory.createIdentifier((val as Function).name);
|
|
60
|
+
} else if (isKnownFn(val)) {
|
|
61
|
+
val = factory.createIdentifier(val.name);
|
|
51
62
|
} else {
|
|
52
|
-
|
|
53
|
-
const ov = val as object;
|
|
63
|
+
const ov = val;
|
|
54
64
|
const pairs: ts.PropertyAssignment[] = [];
|
|
55
|
-
|
|
56
|
-
for (const k of Object.keys(ov) as (keyof typeof ov)[]) {
|
|
65
|
+
for (const k of TypedObject.keys(ov)) {
|
|
57
66
|
if (ov[k] !== undefined) {
|
|
58
67
|
pairs.push(
|
|
59
68
|
factory.createPropertyAssignment(k, this.fromLiteral(factory, ov[k]))
|
|
@@ -62,8 +71,7 @@ export class LiteralUtil {
|
|
|
62
71
|
}
|
|
63
72
|
return factory.createObjectLiteralExpression(pairs);
|
|
64
73
|
}
|
|
65
|
-
|
|
66
|
-
return val as ts.Expression;
|
|
74
|
+
return transformCast(val);
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
/**
|
|
@@ -164,8 +172,7 @@ export class LiteralUtil {
|
|
|
164
172
|
} else if (typeof el === 'string' || typeof el === 'number' || typeof el === 'boolean') {
|
|
165
173
|
out.push(`${el}`);
|
|
166
174
|
} else {
|
|
167
|
-
|
|
168
|
-
out.push(`(?:${this.templateLiteralToRegex(el as TemplateLiteral, false)})`);
|
|
175
|
+
out.push(`(?:${this.templateLiteralToRegex(transformCast(el), false)})`);
|
|
169
176
|
}
|
|
170
177
|
}
|
|
171
178
|
const body = out.join(template.op === 'and' ? '' : '|');
|
package/src/util/log.ts
CHANGED
|
@@ -5,6 +5,8 @@ const exclude = new Set([
|
|
|
5
5
|
'nextContainer', 'modifierFlagsCache', 'declaredProperties'
|
|
6
6
|
]);
|
|
7
7
|
|
|
8
|
+
const TypedObject: { keys<T = unknown, K extends keyof T = keyof T>(o: T): K[] } & ObjectConstructor = Object;
|
|
9
|
+
|
|
8
10
|
/**
|
|
9
11
|
* Utilities for logging typescript nodes
|
|
10
12
|
*/
|
|
@@ -33,11 +35,9 @@ export class LogUtil {
|
|
|
33
35
|
if (Array.isArray(x)) {
|
|
34
36
|
return x.map(v => this.collapseNode(v, cache));
|
|
35
37
|
} else {
|
|
36
|
-
|
|
37
|
-
const ox = x as object;
|
|
38
|
+
const ox = x;
|
|
38
39
|
const out: Record<string, unknown> = {};
|
|
39
|
-
|
|
40
|
-
for (const key of Object.keys(ox) as (keyof typeof ox)[]) {
|
|
40
|
+
for (const key of TypedObject.keys(ox)) {
|
|
41
41
|
if (Object.getPrototypeOf(ox[key]) === Function.prototype || exclude.has(key) || ox[key] === undefined) {
|
|
42
42
|
continue;
|
|
43
43
|
}
|
package/src/visitor.ts
CHANGED
|
@@ -126,8 +126,7 @@ export class VisitorFactory<S extends State = State> {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
for (const all of set[phase]!.get('ALL') ?? []) {
|
|
129
|
-
|
|
130
|
-
node = (all[phase]!(state, node) as T) ?? node;
|
|
129
|
+
node = all[phase]!<T>(state, node) ?? node;
|
|
131
130
|
}
|
|
132
131
|
return node;
|
|
133
132
|
}
|
|
@@ -160,8 +159,7 @@ export class VisitorFactory<S extends State = State> {
|
|
|
160
159
|
|
|
161
160
|
// For all matching handlers, execute
|
|
162
161
|
for (const item of values) {
|
|
163
|
-
|
|
164
|
-
node = (item[phase]!(state, node, dec) as T) ?? node;
|
|
162
|
+
node = item[phase]!<T>(state, node, dec) ?? node;
|
|
165
163
|
}
|
|
166
164
|
}
|
|
167
165
|
return node;
|