@travetto/transformer 7.0.0-rc.0 → 7.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/importer.ts +55 -55
- package/src/manager.ts +9 -4
- package/src/register.ts +62 -62
- package/src/resolver/builder.ts +57 -49
- package/src/resolver/coerce.ts +6 -6
- package/src/resolver/service.ts +10 -9
- package/src/state.ts +74 -74
- package/src/types/shared.ts +3 -3
- package/src/types/visitor.ts +3 -3
- package/src/util/core.ts +21 -19
- package/src/util/declaration.ts +24 -24
- package/src/util/decorator.ts +16 -16
- package/src/util/doc.ts +9 -9
- package/src/util/import.ts +11 -11
- package/src/util/literal.ts +84 -84
- package/src/util/log.ts +10 -10
- package/src/visitor.ts +18 -18
package/src/util/core.ts
CHANGED
|
@@ -8,25 +8,24 @@ export class CoreUtil {
|
|
|
8
8
|
/**
|
|
9
9
|
* See if inbound node has an original property
|
|
10
10
|
*/
|
|
11
|
-
static hasOriginal(
|
|
12
|
-
return 'original' in
|
|
11
|
+
static hasOriginal(value: ts.Node): value is (ts.Node & { original: ts.Node }) {
|
|
12
|
+
return 'original' in value && !!value.original;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* See if type has target
|
|
17
17
|
*/
|
|
18
|
-
static hasTarget(
|
|
19
|
-
return 'target' in
|
|
18
|
+
static hasTarget(value: ts.Type): value is (ts.Type & { target: ts.Type }) {
|
|
19
|
+
return 'target' in value && !!value.target;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Get code range of node
|
|
24
|
-
* @param m
|
|
25
24
|
*/
|
|
26
|
-
static getRangeOf<T extends ts.Node>(source: ts.SourceFile,
|
|
27
|
-
if (
|
|
28
|
-
const start = ts.getLineAndCharacterOfPosition(source,
|
|
29
|
-
const end = ts.getLineAndCharacterOfPosition(source,
|
|
25
|
+
static getRangeOf<T extends ts.Node>(source: ts.SourceFile, value: T | undefined): [start: number, end: number] | undefined {
|
|
26
|
+
if (value && value.pos >= 0) {
|
|
27
|
+
const start = ts.getLineAndCharacterOfPosition(source, value.getStart(source));
|
|
28
|
+
const end = ts.getLineAndCharacterOfPosition(source, value.getEnd());
|
|
30
29
|
return [start.line + 1, end.line + 1];
|
|
31
30
|
}
|
|
32
31
|
}
|
|
@@ -34,7 +33,10 @@ export class CoreUtil {
|
|
|
34
33
|
/**
|
|
35
34
|
* Find the primary argument of a call expression, or decorator.
|
|
36
35
|
*/
|
|
37
|
-
static findArgument<T extends ts.Expression = ts.Expression>(
|
|
36
|
+
static findArgument<T extends ts.Expression = ts.Expression>(
|
|
37
|
+
node: ts.CallExpression | undefined,
|
|
38
|
+
pred: (expr: ts.Expression) => expr is T
|
|
39
|
+
): T | undefined {
|
|
38
40
|
if (node && node.arguments && node.arguments.length) {
|
|
39
41
|
return node.arguments.find(pred);
|
|
40
42
|
}
|
|
@@ -52,10 +54,10 @@ export class CoreUtil {
|
|
|
52
54
|
/**
|
|
53
55
|
* Create a static field for a class
|
|
54
56
|
*/
|
|
55
|
-
static createStaticField(factory: ts.NodeFactory, name: string,
|
|
57
|
+
static createStaticField(factory: ts.NodeFactory, name: string, value: ts.Expression): ts.PropertyDeclaration {
|
|
56
58
|
return factory.createPropertyDeclaration(
|
|
57
59
|
[factory.createToken(ts.SyntaxKind.StaticKeyword)],
|
|
58
|
-
name, undefined, undefined,
|
|
60
|
+
name, undefined, undefined, value
|
|
59
61
|
);
|
|
60
62
|
}
|
|
61
63
|
|
|
@@ -74,12 +76,12 @@ export class CoreUtil {
|
|
|
74
76
|
|
|
75
77
|
/**
|
|
76
78
|
* Updates source
|
|
77
|
-
* @param
|
|
79
|
+
* @param source
|
|
78
80
|
* @param statements
|
|
79
81
|
*/
|
|
80
|
-
static updateSource(factory: ts.NodeFactory,
|
|
82
|
+
static updateSource(factory: ts.NodeFactory, source: ts.SourceFile, statements: ts.NodeArray<ts.Statement> | ts.Statement[]): ts.SourceFile {
|
|
81
83
|
return factory.updateSourceFile(
|
|
82
|
-
|
|
84
|
+
source, statements, source.isDeclarationFile, source.referencedFiles, source.typeReferenceDirectives, source.hasNoDefaultLib
|
|
83
85
|
);
|
|
84
86
|
}
|
|
85
87
|
|
|
@@ -96,9 +98,9 @@ export class CoreUtil {
|
|
|
96
98
|
first = factory.createIdentifier(first);
|
|
97
99
|
}
|
|
98
100
|
return items.reduce<ts.Expression>(
|
|
99
|
-
(
|
|
100
|
-
factory.createElementAccessExpression(
|
|
101
|
-
factory.createPropertyAccessExpression(
|
|
101
|
+
(expr, value) => typeof value === 'number' ?
|
|
102
|
+
factory.createElementAccessExpression(expr, value) :
|
|
103
|
+
factory.createPropertyAccessExpression(expr, value),
|
|
102
104
|
factory.createPropertyAccessExpression(first, second)
|
|
103
105
|
);
|
|
104
106
|
}
|
|
@@ -111,7 +113,7 @@ export class CoreUtil {
|
|
|
111
113
|
factory.createCallExpression(
|
|
112
114
|
name,
|
|
113
115
|
undefined,
|
|
114
|
-
contents.filter(
|
|
116
|
+
contents.filter(expr => !!expr)
|
|
115
117
|
)
|
|
116
118
|
);
|
|
117
119
|
}
|
package/src/util/declaration.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { CoreUtil } from './core.ts';
|
|
3
3
|
|
|
4
|
-
const isNamed = (
|
|
4
|
+
const isNamed = (value: ts.Declaration): value is ts.Declaration & { name: ts.Node } => 'name' in value && !!value.name;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Declaration utils
|
|
@@ -13,11 +13,11 @@ export class DeclarationUtil {
|
|
|
13
13
|
* and then checks the toString for `const `
|
|
14
14
|
*/
|
|
15
15
|
static isConstantDeclaration(node: ts.Node): boolean {
|
|
16
|
-
let
|
|
17
|
-
while (
|
|
18
|
-
|
|
16
|
+
let root: ts.Node = node;
|
|
17
|
+
while (root && !ts.isVariableDeclarationList(root)) {
|
|
18
|
+
root = root.parent;
|
|
19
19
|
}
|
|
20
|
-
return
|
|
20
|
+
return root?.getText().startsWith('const '); // Cheap out on check, ts is being weird
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -33,24 +33,24 @@ export class DeclarationUtil {
|
|
|
33
33
|
* Find declaration for a type, symbol or a declaration
|
|
34
34
|
*/
|
|
35
35
|
static getDeclarations(type: ts.Type | ts.Symbol | ts.Declaration[]): ts.Declaration[] {
|
|
36
|
-
let
|
|
36
|
+
let declarations: ts.Declaration[] = [];
|
|
37
37
|
if (Array.isArray(type)) {
|
|
38
|
-
|
|
38
|
+
declarations = type;
|
|
39
39
|
} else {
|
|
40
|
-
|
|
40
|
+
declarations = CoreUtil.getSymbol(type)?.getDeclarations?.() ?? [];
|
|
41
41
|
}
|
|
42
|
-
return
|
|
42
|
+
return declarations.filter(declaration => !!declaration);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Find primary declaration out of a list of declarations
|
|
47
47
|
*/
|
|
48
48
|
static getPrimaryDeclarationNode(node: ts.Type | ts.Symbol): ts.Declaration {
|
|
49
|
-
const
|
|
50
|
-
if (!
|
|
49
|
+
const declarations = this.getDeclarations(node);
|
|
50
|
+
if (!declarations.length) {
|
|
51
51
|
throw new Error('No declarations found for type');
|
|
52
52
|
}
|
|
53
|
-
return
|
|
53
|
+
return declarations[0];
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/**
|
|
@@ -64,7 +64,7 @@ export class DeclarationUtil {
|
|
|
64
64
|
* Resolve the `ts.ObjectFlags`
|
|
65
65
|
*/
|
|
66
66
|
static getObjectFlags(type: ts.Type): ts.ObjectFlags {
|
|
67
|
-
const _ts: typeof ts & { getObjectFlags?(
|
|
67
|
+
const _ts: typeof ts & { getObjectFlags?(node: ts.Type): ts.ObjectFlags } = ts;
|
|
68
68
|
// eslint-disable-next-line no-bitwise
|
|
69
69
|
return _ts.getObjectFlags!(type) & ~(ts.NodeFlags.ThisNodeOrAnySubNodesHasError);
|
|
70
70
|
}
|
|
@@ -78,27 +78,27 @@ export class DeclarationUtil {
|
|
|
78
78
|
static getAccessorPair(
|
|
79
79
|
node: ts.GetAccessorDeclaration | ts.SetAccessorDeclaration
|
|
80
80
|
): { getter?: ts.GetAccessorDeclaration, setter?: ts.SetAccessorDeclaration } {
|
|
81
|
-
const
|
|
81
|
+
const pair = { getter: ts.isGetAccessorDeclaration(node) ? node : undefined, setter: ts.isSetAccessorDeclaration(node) ? node : undefined };
|
|
82
82
|
if (ts.isClassDeclaration(node.parent)) {
|
|
83
|
-
for (const
|
|
84
|
-
if (
|
|
85
|
-
if (ts.isGetAccessor(
|
|
86
|
-
|
|
87
|
-
} else if (ts.isSetAccessor(
|
|
88
|
-
|
|
83
|
+
for (const member of node.parent.members) {
|
|
84
|
+
if (member.name && member.name.getText() === node.name.getText()) {
|
|
85
|
+
if (ts.isGetAccessor(member)) {
|
|
86
|
+
pair.getter = member;
|
|
87
|
+
} else if (ts.isSetAccessor(member)) {
|
|
88
|
+
pair.setter = member;
|
|
89
89
|
}
|
|
90
|
-
if (
|
|
91
|
-
return
|
|
90
|
+
if (pair.getter && pair.setter) {
|
|
91
|
+
return pair;
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
-
return
|
|
96
|
+
return pair;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
static isStatic(node: ts.Declaration): boolean {
|
|
100
100
|
if ('modifiers' in node && Array.isArray(node.modifiers)) {
|
|
101
|
-
return node.modifiers?.some(
|
|
101
|
+
return node.modifiers?.some(modifier => modifier.kind === ts.SyntaxKind.StaticKeyword) ?? false;
|
|
102
102
|
}
|
|
103
103
|
return false;
|
|
104
104
|
}
|
package/src/util/decorator.ts
CHANGED
|
@@ -6,17 +6,17 @@ import { CoreUtil } from './core.ts';
|
|
|
6
6
|
*/
|
|
7
7
|
export class DecoratorUtil {
|
|
8
8
|
|
|
9
|
-
static #getIdentFromExpression(
|
|
10
|
-
if (ts.isCallExpression(
|
|
11
|
-
return
|
|
12
|
-
} else if (ts.isIdentifier(
|
|
13
|
-
return
|
|
14
|
-
} else if (ts.isCallExpression(
|
|
15
|
-
return
|
|
16
|
-
} else if (ts.isPropertyAccessExpression(
|
|
17
|
-
return
|
|
18
|
-
} else if (ts.isParenthesizedExpression(
|
|
19
|
-
return this.#getIdentFromExpression(
|
|
9
|
+
static #getIdentFromExpression(expr: ts.Expression): ts.Identifier {
|
|
10
|
+
if (ts.isCallExpression(expr) && ts.isIdentifier(expr.expression)) {
|
|
11
|
+
return expr.expression;
|
|
12
|
+
} else if (ts.isIdentifier(expr)) {
|
|
13
|
+
return expr;
|
|
14
|
+
} else if (ts.isCallExpression(expr) && ts.isPropertyAccessExpression(expr.expression) && ts.isIdentifier(expr.expression.expression)) {
|
|
15
|
+
return expr.expression.expression;
|
|
16
|
+
} else if (ts.isPropertyAccessExpression(expr) && ts.isCallExpression(expr.expression) && ts.isIdentifier(expr.expression.expression)) {
|
|
17
|
+
return expr.expression.expression;
|
|
18
|
+
} else if (ts.isParenthesizedExpression(expr)) {
|
|
19
|
+
return this.#getIdentFromExpression(expr.expression);
|
|
20
20
|
} else {
|
|
21
21
|
throw new Error('No Identifier');
|
|
22
22
|
}
|
|
@@ -25,12 +25,12 @@ export class DecoratorUtil {
|
|
|
25
25
|
/**
|
|
26
26
|
* Get identifier for a decorator
|
|
27
27
|
*/
|
|
28
|
-
static
|
|
29
|
-
const
|
|
30
|
-
if (!
|
|
28
|
+
static getDecoratorIdentifier(decorator: ts.Decorator): ts.Identifier {
|
|
29
|
+
const identifier = this.#getIdentFromExpression(decorator.expression);
|
|
30
|
+
if (!identifier) {
|
|
31
31
|
throw new Error('No Identifier');
|
|
32
32
|
} else {
|
|
33
|
-
return
|
|
33
|
+
return identifier;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -44,7 +44,7 @@ export class DecoratorUtil {
|
|
|
44
44
|
if (idx < 0 && target) {
|
|
45
45
|
idx = node.modifiers?.indexOf(target) ?? -1;
|
|
46
46
|
}
|
|
47
|
-
const out = (node.modifiers ?? []).filter(
|
|
47
|
+
const out = (node.modifiers ?? []).filter(modifier => modifier !== target);
|
|
48
48
|
if (idx < 0) {
|
|
49
49
|
out.push(...replacements);
|
|
50
50
|
} else {
|
package/src/util/doc.ts
CHANGED
|
@@ -11,15 +11,15 @@ export class DocUtil {
|
|
|
11
11
|
/**
|
|
12
12
|
* See if node has js docs
|
|
13
13
|
*/
|
|
14
|
-
static hasJSDoc(
|
|
15
|
-
return 'jsDoc' in
|
|
14
|
+
static hasJSDoc(node: ts.Node): node is (ts.Node & { jsDoc: ts.JSDoc[] }) {
|
|
15
|
+
return 'jsDoc' in node && node.jsDoc !== null && node.jsDoc !== undefined && Array.isArray(node.jsDoc) && node.jsDoc.length > 0;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Read doc comment for node
|
|
20
20
|
*/
|
|
21
|
-
static getDocComment(
|
|
22
|
-
return (typeof
|
|
21
|
+
static getDocComment(node: ts.JSDoc | ts.JSDocTag, def?: string): string | undefined {
|
|
22
|
+
return (typeof node.comment === 'string' ? node.comment : undefined) ?? def;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -72,8 +72,8 @@ export class DocUtil {
|
|
|
72
72
|
static readDocTag(type: ts.Type | ts.Symbol, name: string): string[] {
|
|
73
73
|
const tags = CoreUtil.getSymbol(type)?.getJsDocTags() ?? [];
|
|
74
74
|
return tags
|
|
75
|
-
.filter(
|
|
76
|
-
.map(
|
|
75
|
+
.filter(tag => tag.name === name && !!tag.text)
|
|
76
|
+
.map(tag => tag.text!.map(part => part.text).join('')); // Join all text
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/**
|
|
@@ -81,7 +81,7 @@ export class DocUtil {
|
|
|
81
81
|
*/
|
|
82
82
|
static hasDocTag(type: ts.Type | ts.Symbol, name: string): boolean {
|
|
83
83
|
const tags = CoreUtil.getSymbol(type)?.getJsDocTags() ?? [];
|
|
84
|
-
return tags.some(
|
|
84
|
+
return tags.some(tag => tag.name === name);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
|
|
@@ -90,7 +90,7 @@ export class DocUtil {
|
|
|
90
90
|
* @param type
|
|
91
91
|
*/
|
|
92
92
|
static readAugments(type: ts.Type | ts.Symbol): string[] {
|
|
93
|
-
return this.readDocTag(type, 'augments').map(
|
|
93
|
+
return this.readDocTag(type, 'augments').map(line => line.replace(/^.*?([^` ]+).*?$/, (_, b) => b));
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/**
|
|
@@ -98,6 +98,6 @@ export class DocUtil {
|
|
|
98
98
|
* @param type
|
|
99
99
|
*/
|
|
100
100
|
static readExample(type: ts.Type | ts.Symbol): string[] {
|
|
101
|
-
return this.readDocTag(type, 'example').map(
|
|
101
|
+
return this.readDocTag(type, 'example').map(line => line.replace(/^.*?([^` ]+).*?$/, (_, b) => b));
|
|
102
102
|
}
|
|
103
103
|
}
|
package/src/util/import.ts
CHANGED
|
@@ -31,24 +31,24 @@ export class ImportUtil {
|
|
|
31
31
|
/**
|
|
32
32
|
* Collect all imports for a source file, as a hash map
|
|
33
33
|
*/
|
|
34
|
-
static collectImports(
|
|
34
|
+
static collectImports(source: ts.SourceFile): Map<string, Import> {
|
|
35
35
|
// TODO: Replace with manifest reverse lookup
|
|
36
|
-
const base = path.toPosix(
|
|
36
|
+
const base = path.toPosix(source.fileName);
|
|
37
37
|
|
|
38
38
|
const imports = new Map<string, Import>();
|
|
39
39
|
|
|
40
|
-
for (const
|
|
41
|
-
if (ts.isImportDeclaration(
|
|
42
|
-
const resolved = this.optionalResolve(
|
|
40
|
+
for (const statement of source.statements) {
|
|
41
|
+
if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
42
|
+
const resolved = this.optionalResolve(statement.moduleSpecifier.text, base);
|
|
43
43
|
|
|
44
|
-
if (
|
|
45
|
-
if (
|
|
46
|
-
const bindings =
|
|
44
|
+
if (statement.importClause) {
|
|
45
|
+
if (statement.importClause.namedBindings) {
|
|
46
|
+
const bindings = statement.importClause.namedBindings;
|
|
47
47
|
if (ts.isNamespaceImport(bindings)) {
|
|
48
|
-
imports.set(bindings.name.text, { path: resolved,
|
|
48
|
+
imports.set(bindings.name.text, { path: resolved, identifier: bindings.name, statement });
|
|
49
49
|
} else if (ts.isNamedImports(bindings)) {
|
|
50
|
-
for (const
|
|
51
|
-
imports.set(
|
|
50
|
+
for (const element of bindings.elements) {
|
|
51
|
+
imports.set(element.name.text, { path: resolved, identifier: element.name, statement });
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/util/literal.ts
CHANGED
|
@@ -3,17 +3,17 @@ import ts from 'typescript';
|
|
|
3
3
|
import { transformCast, TemplateLiteral } from '../types/shared.ts';
|
|
4
4
|
|
|
5
5
|
const TypedObject: {
|
|
6
|
-
keys<T = unknown, K extends keyof T = keyof T>(
|
|
6
|
+
keys<T = unknown, K extends keyof T = keyof T>(value: T): K[];
|
|
7
7
|
} & ObjectConstructor = Object;
|
|
8
8
|
|
|
9
|
-
function isNode(
|
|
10
|
-
return !!
|
|
9
|
+
function isNode(value: unknown): value is ts.Node {
|
|
10
|
+
return !!value && typeof value === 'object' && 'kind' in value;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
const KNOWN_FNS = new Set<unknown>([String, Number, Boolean, Date, RegExp]);
|
|
14
14
|
|
|
15
|
-
function isKnownFn(
|
|
16
|
-
return KNOWN_FNS.has(
|
|
15
|
+
function isKnownFn(value: unknown): value is Function {
|
|
16
|
+
return KNOWN_FNS.has(value);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -34,96 +34,96 @@ export class LiteralUtil {
|
|
|
34
34
|
/**
|
|
35
35
|
* Convert literal to a `ts.Node` type
|
|
36
36
|
*/
|
|
37
|
-
static fromLiteral<T extends ts.Expression>(factory: ts.NodeFactory,
|
|
38
|
-
static fromLiteral(factory: ts.NodeFactory,
|
|
39
|
-
static fromLiteral(factory: ts.NodeFactory,
|
|
40
|
-
static fromLiteral(factory: ts.NodeFactory,
|
|
41
|
-
static fromLiteral(factory: ts.NodeFactory,
|
|
42
|
-
static fromLiteral(factory: ts.NodeFactory,
|
|
43
|
-
static fromLiteral(factory: ts.NodeFactory,
|
|
44
|
-
static fromLiteral(factory: ts.NodeFactory,
|
|
45
|
-
static fromLiteral(factory: ts.NodeFactory,
|
|
46
|
-
if (isNode(
|
|
47
|
-
return
|
|
48
|
-
} else if (Array.isArray(
|
|
49
|
-
|
|
50
|
-
} else if (
|
|
51
|
-
|
|
52
|
-
} else if (
|
|
53
|
-
|
|
54
|
-
} else if (typeof
|
|
55
|
-
|
|
56
|
-
} else if (typeof
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
} else if (typeof
|
|
60
|
-
|
|
61
|
-
} else if (
|
|
62
|
-
|
|
63
|
-
} else if (isKnownFn(
|
|
64
|
-
|
|
37
|
+
static fromLiteral<T extends ts.Expression>(factory: ts.NodeFactory, value: T): T;
|
|
38
|
+
static fromLiteral(factory: ts.NodeFactory, value: undefined): ts.Identifier;
|
|
39
|
+
static fromLiteral(factory: ts.NodeFactory, value: null): ts.NullLiteral;
|
|
40
|
+
static fromLiteral(factory: ts.NodeFactory, value: object): ts.ObjectLiteralExpression;
|
|
41
|
+
static fromLiteral(factory: ts.NodeFactory, value: unknown[]): ts.ArrayLiteralExpression;
|
|
42
|
+
static fromLiteral(factory: ts.NodeFactory, value: string): ts.StringLiteral;
|
|
43
|
+
static fromLiteral(factory: ts.NodeFactory, value: number): ts.NumericLiteral;
|
|
44
|
+
static fromLiteral(factory: ts.NodeFactory, value: boolean): ts.BooleanLiteral;
|
|
45
|
+
static fromLiteral(factory: ts.NodeFactory, value: unknown): ts.Node {
|
|
46
|
+
if (isNode(value)) { // If already a node
|
|
47
|
+
return value;
|
|
48
|
+
} else if (Array.isArray(value)) {
|
|
49
|
+
value = factory.createArrayLiteralExpression(value.map(element => this.fromLiteral(factory, element)));
|
|
50
|
+
} else if (value === undefined) {
|
|
51
|
+
value = factory.createIdentifier('undefined');
|
|
52
|
+
} else if (value === null) {
|
|
53
|
+
value = factory.createNull();
|
|
54
|
+
} else if (typeof value === 'string') {
|
|
55
|
+
value = factory.createStringLiteral(value);
|
|
56
|
+
} else if (typeof value === 'number') {
|
|
57
|
+
const number = factory.createNumericLiteral(Math.abs(value));
|
|
58
|
+
value = value < 0 ? factory.createPrefixMinus(number) : number;
|
|
59
|
+
} else if (typeof value === 'boolean') {
|
|
60
|
+
value = value ? factory.createTrue() : factory.createFalse();
|
|
61
|
+
} else if (value instanceof RegExp) {
|
|
62
|
+
value = factory.createRegularExpressionLiteral(`/${value.source}/${value.flags ?? ''}`);
|
|
63
|
+
} else if (isKnownFn(value)) {
|
|
64
|
+
value = factory.createIdentifier(value.name);
|
|
65
65
|
} else {
|
|
66
|
-
const ov =
|
|
66
|
+
const ov = value;
|
|
67
67
|
const pairs: ts.PropertyAssignment[] = [];
|
|
68
|
-
for (const
|
|
69
|
-
if (ov[
|
|
68
|
+
for (const key of TypedObject.keys(ov)) {
|
|
69
|
+
if (ov[key] !== undefined) {
|
|
70
70
|
pairs.push(
|
|
71
|
-
factory.createPropertyAssignment(
|
|
71
|
+
factory.createPropertyAssignment(key, this.fromLiteral(factory, ov[key]))
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
return factory.createObjectLiteralExpression(pairs);
|
|
76
76
|
}
|
|
77
|
-
return transformCast(
|
|
77
|
+
return transformCast(value);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
81
|
* Convert a `ts.Node` to a JS literal
|
|
82
82
|
*/
|
|
83
|
-
static toLiteral(
|
|
84
|
-
static toLiteral(
|
|
85
|
-
static toLiteral(
|
|
86
|
-
static toLiteral(
|
|
87
|
-
static toLiteral(
|
|
88
|
-
static toLiteral(
|
|
89
|
-
static toLiteral(
|
|
90
|
-
static toLiteral(
|
|
91
|
-
static toLiteral(
|
|
92
|
-
if (!
|
|
93
|
-
throw new Error('
|
|
94
|
-
} else if (ts.isArrayLiteralExpression(
|
|
95
|
-
return
|
|
96
|
-
} else if (ts.isIdentifier(
|
|
97
|
-
if (
|
|
83
|
+
static toLiteral(value: ts.NullLiteral, strict?: boolean): null;
|
|
84
|
+
static toLiteral(value: ts.NumericLiteral, strict?: boolean): number;
|
|
85
|
+
static toLiteral(value: ts.StringLiteral, strict?: boolean): string;
|
|
86
|
+
static toLiteral(value: ts.BooleanLiteral, strict?: boolean): boolean;
|
|
87
|
+
static toLiteral(value: ts.ObjectLiteralExpression, strict?: boolean): object;
|
|
88
|
+
static toLiteral(value: ts.ArrayLiteralExpression, strict?: boolean): unknown[];
|
|
89
|
+
static toLiteral(value: undefined, strict?: boolean): undefined;
|
|
90
|
+
static toLiteral(value: ts.Node, strict?: boolean): unknown;
|
|
91
|
+
static toLiteral(value?: ts.Node, strict = true): unknown {
|
|
92
|
+
if (!value) {
|
|
93
|
+
throw new Error('Value is not defined');
|
|
94
|
+
} else if (ts.isArrayLiteralExpression(value)) {
|
|
95
|
+
return value.elements.map(item => this.toLiteral(item, strict));
|
|
96
|
+
} else if (ts.isIdentifier(value)) {
|
|
97
|
+
if (value.getText() === 'undefined') {
|
|
98
98
|
return undefined;
|
|
99
99
|
} else if (!strict) {
|
|
100
|
-
return
|
|
100
|
+
return value.getText();
|
|
101
101
|
}
|
|
102
|
-
} else if (
|
|
102
|
+
} else if (value.kind === ts.SyntaxKind.NullKeyword) {
|
|
103
103
|
return null;
|
|
104
|
-
} else if (ts.isStringLiteral(
|
|
105
|
-
return
|
|
106
|
-
} else if (ts.isNumericLiteral(
|
|
107
|
-
const txt =
|
|
104
|
+
} else if (ts.isStringLiteral(value)) {
|
|
105
|
+
return value.text;
|
|
106
|
+
} else if (ts.isNumericLiteral(value)) {
|
|
107
|
+
const txt = value.text;
|
|
108
108
|
if (txt.includes('.')) {
|
|
109
109
|
return parseFloat(txt);
|
|
110
110
|
} else {
|
|
111
111
|
return parseInt(txt, 10);
|
|
112
112
|
}
|
|
113
|
-
} else if (ts.isPrefixUnaryExpression(
|
|
114
|
-
const txt =
|
|
113
|
+
} else if (ts.isPrefixUnaryExpression(value) && value.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(value.operand)) {
|
|
114
|
+
const txt = value.operand.text;
|
|
115
115
|
if (txt.includes('.')) {
|
|
116
116
|
return -parseFloat(txt);
|
|
117
117
|
} else {
|
|
118
118
|
return -parseInt(txt, 10);
|
|
119
119
|
}
|
|
120
|
-
} else if (
|
|
120
|
+
} else if (value.kind === ts.SyntaxKind.FalseKeyword) {
|
|
121
121
|
return false;
|
|
122
|
-
} else if (
|
|
122
|
+
} else if (value.kind === ts.SyntaxKind.TrueKeyword) {
|
|
123
123
|
return true;
|
|
124
|
-
} else if (ts.isObjectLiteralExpression(
|
|
124
|
+
} else if (ts.isObjectLiteralExpression(value)) {
|
|
125
125
|
const out: Record<string, unknown> = {};
|
|
126
|
-
for (const pair of
|
|
126
|
+
for (const pair of value.properties) {
|
|
127
127
|
if (ts.isPropertyAssignment(pair)) {
|
|
128
128
|
out[pair.name.getText()] = this.toLiteral(pair.initializer, strict);
|
|
129
129
|
}
|
|
@@ -131,19 +131,19 @@ export class LiteralUtil {
|
|
|
131
131
|
return out;
|
|
132
132
|
}
|
|
133
133
|
if (strict) {
|
|
134
|
-
throw new Error(`Not a valid input, should be a valid ts.Node: ${
|
|
134
|
+
throw new Error(`Not a valid input, should be a valid ts.Node: ${value.kind}`);
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
/**
|
|
139
139
|
* Extend object literal, whether JSON or ts.ObjectLiteralExpression
|
|
140
140
|
*/
|
|
141
|
-
static extendObjectLiteral(factory: ts.NodeFactory,
|
|
142
|
-
let literal = this.fromLiteral(factory,
|
|
143
|
-
if (rest.find(
|
|
141
|
+
static extendObjectLiteral(factory: ts.NodeFactory, source: object | ts.Expression, ...rest: (object | ts.Expression)[]): ts.ObjectLiteralExpression {
|
|
142
|
+
let literal = this.fromLiteral(factory, source);
|
|
143
|
+
if (rest.find(item => !!item)) {
|
|
144
144
|
literal = factory.createObjectLiteralExpression([
|
|
145
145
|
factory.createSpreadAssignment(literal),
|
|
146
|
-
...(rest.filter(
|
|
146
|
+
...(rest.filter(item => !!item).map(expression => factory.createSpreadAssignment(this.fromLiteral(factory, expression))))
|
|
147
147
|
]);
|
|
148
148
|
}
|
|
149
149
|
return literal;
|
|
@@ -154,12 +154,12 @@ export class LiteralUtil {
|
|
|
154
154
|
*/
|
|
155
155
|
static getObjectValue(node: ts.Expression | undefined, key: string): ts.Expression | undefined {
|
|
156
156
|
if (node && ts.isObjectLiteralExpression(node) && node.properties) {
|
|
157
|
-
for (const
|
|
158
|
-
if (
|
|
159
|
-
if (ts.isPropertyAssignment(
|
|
160
|
-
return
|
|
161
|
-
} else if (ts.isShorthandPropertyAssignment(
|
|
162
|
-
return
|
|
157
|
+
for (const property of node.properties) {
|
|
158
|
+
if (property.name!.getText() === key) {
|
|
159
|
+
if (ts.isPropertyAssignment(property)) {
|
|
160
|
+
return property.initializer;
|
|
161
|
+
} else if (ts.isShorthandPropertyAssignment(property)) {
|
|
162
|
+
return property.name;
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
}
|
|
@@ -172,20 +172,20 @@ export class LiteralUtil {
|
|
|
172
172
|
*/
|
|
173
173
|
static templateLiteralToRegex(template: TemplateLiteral, exact = true): string {
|
|
174
174
|
const out: string[] = [];
|
|
175
|
-
for (const
|
|
176
|
-
if (
|
|
175
|
+
for (const value of template.values) {
|
|
176
|
+
if (value === Number) {
|
|
177
177
|
out.push('\\d+');
|
|
178
|
-
} else if (
|
|
178
|
+
} else if (value === Boolean) {
|
|
179
179
|
out.push('(?:true|false)');
|
|
180
|
-
} else if (
|
|
180
|
+
} else if (value === String) {
|
|
181
181
|
out.push('.+');
|
|
182
|
-
} else if (typeof
|
|
183
|
-
out.push(`${
|
|
182
|
+
} else if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
183
|
+
out.push(`${value}`);
|
|
184
184
|
} else {
|
|
185
|
-
out.push(`(?:${this.templateLiteralToRegex(transformCast(
|
|
185
|
+
out.push(`(?:${this.templateLiteralToRegex(transformCast(value), false)})`);
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
|
-
const body = out.join(template.
|
|
188
|
+
const body = out.join(template.operation === 'and' ? '' : '|');
|
|
189
189
|
if (exact) {
|
|
190
190
|
return `^(?:${body})$`;
|
|
191
191
|
} else {
|
package/src/util/log.ts
CHANGED
|
@@ -5,7 +5,7 @@ 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>(
|
|
8
|
+
const TypedObject: { keys<T = unknown, K extends keyof T = keyof T>(value: T): K[] } & ObjectConstructor = Object;
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Utilities for logging typescript nodes
|
|
@@ -15,27 +15,27 @@ export class LogUtil {
|
|
|
15
15
|
* Clean up `ts.Node` contents for logging
|
|
16
16
|
*/
|
|
17
17
|
static collapseNodes(all: unknown[]): unknown[] {
|
|
18
|
-
return all.map(
|
|
18
|
+
return all.map(value => this.collapseNode(value));
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Clean up `ts.Node` contents for logging
|
|
23
23
|
*/
|
|
24
|
-
static collapseNode(
|
|
25
|
-
if (!
|
|
26
|
-
return
|
|
24
|
+
static collapseNode(value: unknown, cache: Set<unknown> = new Set()): unknown {
|
|
25
|
+
if (!value || !(typeof value === 'object' || typeof value === 'function')) {
|
|
26
|
+
return value;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
if (cache.has(
|
|
29
|
+
if (cache.has(value)) {
|
|
30
30
|
return;
|
|
31
31
|
} else {
|
|
32
|
-
cache.add(
|
|
32
|
+
cache.add(value);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
if (Array.isArray(
|
|
36
|
-
return
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
return value.map(node => this.collapseNode(node, cache));
|
|
37
37
|
} else {
|
|
38
|
-
const ox =
|
|
38
|
+
const ox = value;
|
|
39
39
|
const out: Record<string, unknown> = {};
|
|
40
40
|
for (const key of TypedObject.keys(ox)) {
|
|
41
41
|
if (ox[key] === null || ox[key] === undefined || Object.getPrototypeOf(ox[key]) === Function.prototype || exclude.has(key)) {
|