xray16 1.6.3 → 1.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -15
- package/package.json +1 -1
- package/plugins/inline_constants/plugin.d.ts +12 -5
- package/plugins/inline_constants/plugin.js +20 -6
- package/plugins/inline_constants/transformation/ast.d.ts +25 -16
- package/plugins/inline_constants/transformation/ast.js +58 -24
- package/plugins/inline_constants/transformation/constants.d.ts +62 -4
- package/plugins/inline_constants/transformation/constants.js +35 -4
- package/plugins/inline_constants/transformation/errors.d.ts +6 -0
- package/plugins/inline_constants/transformation/errors.js +6 -2
- package/plugins/inline_constants/transformation/evaluation.d.ts +58 -28
- package/plugins/inline_constants/transformation/evaluation.js +130 -33
- package/plugins/inline_constants/transformation/index.d.ts +1 -0
- package/plugins/inline_constants/transformation/index.js +1 -0
- package/plugins/inline_constants/transformation/transformers.d.ts +24 -10
- package/plugins/inline_constants/transformation/transformers.js +225 -17
- package/plugins/inline_constants/transformation/validation.d.ts +2 -1
- package/plugins/inline_constants/transformation/validation.js +3 -2
- package/plugins/inline_constants/transformation/virtual.d.ts +74 -0
- package/plugins/inline_constants/transformation/virtual.js +340 -0
- package/xray16.d.ts +877 -366
|
@@ -1,79 +1,109 @@
|
|
|
1
1
|
import * as ts from "typescript";
|
|
2
|
-
import { type TInlineValue } from "./constants";
|
|
2
|
+
import { type TFoldedValue, type TInlineValue } from "./constants";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the member symbol for a property or element access expression.
|
|
5
|
+
* When direct symbol resolution fails, element access is resolved through the object type. This supports
|
|
6
|
+
* literal keys and keys that fold to constants at build time, such as 'table[misc.device_pda]'.
|
|
7
|
+
*
|
|
8
|
+
* @param checker - Program type checker.
|
|
9
|
+
* @param node - Access expression to resolve symbol for.
|
|
10
|
+
* @returns Resolved member symbol or null.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveMemberSymbol(checker: ts.TypeChecker, node: ts.PropertyAccessExpression | ts.ElementAccessExpression): ts.Symbol | null;
|
|
3
13
|
/**
|
|
4
14
|
* Get literal value of symbol declared type, if it is a unit type.
|
|
5
15
|
* Uses declared type instead of flow-narrowed type so mutable narrowed values are never inlined.
|
|
6
16
|
*
|
|
7
17
|
* @param checker - Program type checker.
|
|
8
18
|
* @param symbol - Symbol to get declared literal value for.
|
|
9
|
-
* @returns Literal value or null.
|
|
19
|
+
* @returns Literal value, or null when the declared type is not a unit type.
|
|
10
20
|
*/
|
|
11
21
|
export declare function getDeclaredLiteralValue(checker: ts.TypeChecker, symbol: ts.Symbol): TInlineValue | null;
|
|
12
22
|
/**
|
|
13
|
-
* Convert folded value to string for concatenation contexts.
|
|
14
|
-
* Non-integer numbers are rejected
|
|
23
|
+
* Convert a folded value to a string for concatenation contexts.
|
|
24
|
+
* Non-integer numbers are rejected because JS 'String()' and LuaJIT 'tostring' format them differently
|
|
15
25
|
* (17 significant digits vs '%.14g'), so folding would change runtime-visible output.
|
|
26
|
+
* Expression trees are rejected because Lua '..' coercion differs from JS string conversion.
|
|
16
27
|
*
|
|
17
28
|
* @param value - Folded value to convert.
|
|
18
29
|
* @returns String representation or null.
|
|
19
30
|
*/
|
|
20
|
-
export declare function toFoldedString(value:
|
|
31
|
+
export declare function toFoldedString(value: TFoldedValue | null): string | null;
|
|
21
32
|
/**
|
|
22
|
-
* Guard folded numeric results against NaN
|
|
33
|
+
* Guard folded numeric results against NaN and Infinity, which cannot be emitted as Lua literals.
|
|
23
34
|
*
|
|
24
35
|
* @param value - Folded numeric value.
|
|
25
|
-
* @returns Finite number or null.
|
|
36
|
+
* @returns Finite number, or null when the value cannot be emitted as a Lua literal.
|
|
26
37
|
*/
|
|
27
38
|
export declare function toFiniteNumber(value: number): number | null;
|
|
28
39
|
/**
|
|
29
|
-
* Fold binary expression
|
|
30
|
-
*
|
|
40
|
+
* Fold a binary expression with constant operands using JavaScript semantics.
|
|
41
|
+
* JavaScript semantics are the correct target because TSTL preserves them at runtime,
|
|
42
|
+
* including '%' behavior for negative operands.
|
|
43
|
+
*
|
|
44
|
+
* When an operand is an expression tree with engine references, the result is a tree as well.
|
|
45
|
+
* Trees only allow numeric operands and operators where emitted Lua matches TSTL lowering exactly:
|
|
46
|
+
* '%', bitwise operators and string concatenation with trees are rejected.
|
|
31
47
|
*
|
|
32
48
|
* @param operator - Binary operator kind.
|
|
33
49
|
* @param left - Folded left operand.
|
|
34
50
|
* @param right - Folded right operand.
|
|
35
|
-
* @returns Folded value or null.
|
|
51
|
+
* @returns Folded value, or null when the operation is not safe to fold.
|
|
36
52
|
*/
|
|
37
|
-
export declare function foldBinaryExpression(operator: ts.SyntaxKind, left:
|
|
53
|
+
export declare function foldBinaryExpression(operator: ts.SyntaxKind, left: TFoldedValue, right: TFoldedValue): TFoldedValue | null;
|
|
38
54
|
/**
|
|
39
|
-
* Evaluate expression to a compile-time constant value when possible.
|
|
55
|
+
* Evaluate an expression to a compile-time constant value when possible.
|
|
40
56
|
* Supports literals, unary/binary arithmetic, string concatenation, template literals,
|
|
41
|
-
* references to enum members / module-level const scalars / `as const` object properties
|
|
42
|
-
*
|
|
57
|
+
* references to enum members / module-level const scalars / `as const` object properties,
|
|
58
|
+
* whitelisted namespace constants like 'math.pi' and runtime-constant engine references
|
|
59
|
+
* like 'stalker_ids.action_dying' (emitted as expressions instead of baked literals).
|
|
43
60
|
*
|
|
44
61
|
* @param checker - Program type checker.
|
|
45
62
|
* @param expression - Expression to evaluate.
|
|
46
63
|
* @param seen - Set of declarations on current resolution path, guards from circular references.
|
|
47
|
-
* @returns Folded constant value or null.
|
|
64
|
+
* @returns Folded constant value, or null when the expression is not safe to fold.
|
|
65
|
+
*/
|
|
66
|
+
export declare function evaluateConstantExpression(checker: ts.TypeChecker, expression: ts.Expression, seen: Set<ts.Declaration>): TFoldedValue | null;
|
|
67
|
+
/**
|
|
68
|
+
* Check whether an enum member is computable at build time - either constant for TypeScript
|
|
69
|
+
* or initialized with an expression that folds to a literal or an engine reference tree.
|
|
70
|
+
*
|
|
71
|
+
* @param checker - Program type checker.
|
|
72
|
+
* @param member - Enum member to check.
|
|
73
|
+
* @returns Whether the member is computable at build time.
|
|
48
74
|
*/
|
|
49
|
-
export declare function
|
|
75
|
+
export declare function isComputableEnumMember(checker: ts.TypeChecker, member: ts.EnumMember): boolean;
|
|
50
76
|
/**
|
|
51
|
-
* Resolve referenced symbol to a compile-time constant value when the reference is safe to fold.
|
|
52
|
-
* Safe references are enum members, module-level const scalars
|
|
53
|
-
*
|
|
77
|
+
* Resolve a referenced symbol to a compile-time constant value when the reference is safe to fold.
|
|
78
|
+
* Safe references are enum members, module-level const scalars, readonly `as const` object properties
|
|
79
|
+
* and `static readonly` engine members from ambient 'xray16' typings - values that cannot legally
|
|
80
|
+
* change at runtime. Tags are not required on referenced declarations.
|
|
54
81
|
*
|
|
55
82
|
* @param checker - Program type checker.
|
|
56
83
|
* @param symbol - Referenced symbol to resolve.
|
|
57
84
|
* @param seen - Set of declarations on current resolution path.
|
|
58
|
-
* @returns Folded constant value or null.
|
|
85
|
+
* @returns Folded constant value, or null when the symbol is not safe to fold.
|
|
59
86
|
*/
|
|
60
|
-
export declare function resolveConstantSymbol(checker: ts.TypeChecker, symbol: ts.Symbol, seen: Set<ts.Declaration>):
|
|
87
|
+
export declare function resolveConstantSymbol(checker: ts.TypeChecker, symbol: ts.Symbol, seen: Set<ts.Declaration>): TFoldedValue | null;
|
|
61
88
|
/**
|
|
62
|
-
* Get constant value of a declaration
|
|
89
|
+
* Get the constant value of a declaration.
|
|
90
|
+
* Initializers are folded first so engine references are substituted as expressions - the declared
|
|
91
|
+
* literal type fast path would silently bake possibly stale values claimed by typings.
|
|
92
|
+
* Declared unit types are only used for initializer-less declarations like ambient constants.
|
|
63
93
|
* Safety and tagging requirements are checked by callers.
|
|
64
94
|
*
|
|
65
95
|
* @param checker - Program type checker.
|
|
66
96
|
* @param symbol - Symbol to get value for.
|
|
67
97
|
* @param seen - Set of declarations on current resolution path.
|
|
68
|
-
* @returns Constant value or null.
|
|
98
|
+
* @returns Constant value, or null when the declaration cannot be folded.
|
|
69
99
|
*/
|
|
70
|
-
export declare function getComputedDeclarationValue(checker: ts.TypeChecker, symbol: ts.Symbol, seen: Set<ts.Declaration>):
|
|
100
|
+
export declare function getComputedDeclarationValue(checker: ts.TypeChecker, symbol: ts.Symbol, seen: Set<ts.Declaration>): TFoldedValue | null;
|
|
71
101
|
/**
|
|
72
|
-
* Get
|
|
73
|
-
* Only symbols declared inside
|
|
102
|
+
* Get the inlineable value for a symbol resolved from an access expression or identifier.
|
|
103
|
+
* Only symbols declared inside tagged enums or variable statements produce values.
|
|
74
104
|
*
|
|
75
105
|
* @param checker - Program type checker.
|
|
76
106
|
* @param symbol - Symbol to resolve inline value for.
|
|
77
|
-
* @returns
|
|
107
|
+
* @returns Folded value, or null when the symbol is not tagged for inlining.
|
|
78
108
|
*/
|
|
79
|
-
export declare function tryGetInlineValue(checker: ts.TypeChecker, symbol: ts.Symbol):
|
|
109
|
+
export declare function tryGetInlineValue(checker: ts.TypeChecker, symbol: ts.Symbol): TFoldedValue | null;
|
|
@@ -1,23 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveMemberSymbol = resolveMemberSymbol;
|
|
3
4
|
exports.getDeclaredLiteralValue = getDeclaredLiteralValue;
|
|
4
5
|
exports.toFoldedString = toFoldedString;
|
|
5
6
|
exports.toFiniteNumber = toFiniteNumber;
|
|
6
7
|
exports.foldBinaryExpression = foldBinaryExpression;
|
|
7
8
|
exports.evaluateConstantExpression = evaluateConstantExpression;
|
|
9
|
+
exports.isComputableEnumMember = isComputableEnumMember;
|
|
8
10
|
exports.resolveConstantSymbol = resolveConstantSymbol;
|
|
9
11
|
exports.getComputedDeclarationValue = getComputedDeclarationValue;
|
|
10
12
|
exports.tryGetInlineValue = tryGetInlineValue;
|
|
11
13
|
const ts = require("typescript");
|
|
12
14
|
const ast_1 = require("./ast");
|
|
13
15
|
const constants_1 = require("./constants");
|
|
16
|
+
const TREE_BINARY_OPERATORS = {
|
|
17
|
+
[ts.SyntaxKind.PlusToken]: "+",
|
|
18
|
+
[ts.SyntaxKind.MinusToken]: "-",
|
|
19
|
+
[ts.SyntaxKind.AsteriskToken]: "*",
|
|
20
|
+
[ts.SyntaxKind.SlashToken]: "/",
|
|
21
|
+
[ts.SyntaxKind.AsteriskAsteriskToken]: "**",
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the member symbol for a property or element access expression.
|
|
25
|
+
* When direct symbol resolution fails, element access is resolved through the object type. This supports
|
|
26
|
+
* literal keys and keys that fold to constants at build time, such as 'table[misc.device_pda]'.
|
|
27
|
+
*
|
|
28
|
+
* @param checker - Program type checker.
|
|
29
|
+
* @param node - Access expression to resolve symbol for.
|
|
30
|
+
* @returns Resolved member symbol or null.
|
|
31
|
+
*/
|
|
32
|
+
function resolveMemberSymbol(checker, node) {
|
|
33
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
34
|
+
if (symbol !== undefined) {
|
|
35
|
+
return symbol;
|
|
36
|
+
}
|
|
37
|
+
if (ts.isElementAccessExpression(node)) {
|
|
38
|
+
const key = evaluateConstantExpression(checker, node.argumentExpression, new Set());
|
|
39
|
+
if (typeof key === "string" || typeof key === "number") {
|
|
40
|
+
return checker.getTypeAtLocation(node.expression).getProperty(String(key)) ?? null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
14
45
|
/**
|
|
15
46
|
* Get literal value of symbol declared type, if it is a unit type.
|
|
16
47
|
* Uses declared type instead of flow-narrowed type so mutable narrowed values are never inlined.
|
|
17
48
|
*
|
|
18
49
|
* @param checker - Program type checker.
|
|
19
50
|
* @param symbol - Symbol to get declared literal value for.
|
|
20
|
-
* @returns Literal value or null.
|
|
51
|
+
* @returns Literal value, or null when the declared type is not a unit type.
|
|
21
52
|
*/
|
|
22
53
|
function getDeclaredLiteralValue(checker, symbol) {
|
|
23
54
|
const declaration = symbol.valueDeclaration;
|
|
@@ -37,9 +68,10 @@ function getDeclaredLiteralValue(checker, symbol) {
|
|
|
37
68
|
return null;
|
|
38
69
|
}
|
|
39
70
|
/**
|
|
40
|
-
* Convert folded value to string for concatenation contexts.
|
|
41
|
-
* Non-integer numbers are rejected
|
|
71
|
+
* Convert a folded value to a string for concatenation contexts.
|
|
72
|
+
* Non-integer numbers are rejected because JS 'String()' and LuaJIT 'tostring' format them differently
|
|
42
73
|
* (17 significant digits vs '%.14g'), so folding would change runtime-visible output.
|
|
74
|
+
* Expression trees are rejected because Lua '..' coercion differs from JS string conversion.
|
|
43
75
|
*
|
|
44
76
|
* @param value - Folded value to convert.
|
|
45
77
|
* @returns String representation or null.
|
|
@@ -54,24 +86,36 @@ function toFoldedString(value) {
|
|
|
54
86
|
return null;
|
|
55
87
|
}
|
|
56
88
|
/**
|
|
57
|
-
* Guard folded numeric results against NaN
|
|
89
|
+
* Guard folded numeric results against NaN and Infinity, which cannot be emitted as Lua literals.
|
|
58
90
|
*
|
|
59
91
|
* @param value - Folded numeric value.
|
|
60
|
-
* @returns Finite number or null.
|
|
92
|
+
* @returns Finite number, or null when the value cannot be emitted as a Lua literal.
|
|
61
93
|
*/
|
|
62
94
|
function toFiniteNumber(value) {
|
|
63
95
|
return Number.isFinite(value) ? value : null;
|
|
64
96
|
}
|
|
65
97
|
/**
|
|
66
|
-
* Fold binary expression
|
|
67
|
-
*
|
|
98
|
+
* Fold a binary expression with constant operands using JavaScript semantics.
|
|
99
|
+
* JavaScript semantics are the correct target because TSTL preserves them at runtime,
|
|
100
|
+
* including '%' behavior for negative operands.
|
|
101
|
+
*
|
|
102
|
+
* When an operand is an expression tree with engine references, the result is a tree as well.
|
|
103
|
+
* Trees only allow numeric operands and operators where emitted Lua matches TSTL lowering exactly:
|
|
104
|
+
* '%', bitwise operators and string concatenation with trees are rejected.
|
|
68
105
|
*
|
|
69
106
|
* @param operator - Binary operator kind.
|
|
70
107
|
* @param left - Folded left operand.
|
|
71
108
|
* @param right - Folded right operand.
|
|
72
|
-
* @returns Folded value or null.
|
|
109
|
+
* @returns Folded value, or null when the operation is not safe to fold.
|
|
73
110
|
*/
|
|
74
111
|
function foldBinaryExpression(operator, left, right) {
|
|
112
|
+
if (typeof left === "object" || typeof right === "object") {
|
|
113
|
+
const treeOperator = TREE_BINARY_OPERATORS[operator];
|
|
114
|
+
if (treeOperator === undefined || !(0, constants_1.isNumericFoldedValue)(left) || !(0, constants_1.isNumericFoldedValue)(right)) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
return { kind: "binary", operator: treeOperator, left, right };
|
|
118
|
+
}
|
|
75
119
|
if (operator === ts.SyntaxKind.PlusToken) {
|
|
76
120
|
if (typeof left === "number" && typeof right === "number") {
|
|
77
121
|
return toFiniteNumber(left + right);
|
|
@@ -111,15 +155,16 @@ function foldBinaryExpression(operator, left, right) {
|
|
|
111
155
|
}
|
|
112
156
|
}
|
|
113
157
|
/**
|
|
114
|
-
* Evaluate expression to a compile-time constant value when possible.
|
|
158
|
+
* Evaluate an expression to a compile-time constant value when possible.
|
|
115
159
|
* Supports literals, unary/binary arithmetic, string concatenation, template literals,
|
|
116
|
-
* references to enum members / module-level const scalars / `as const` object properties
|
|
117
|
-
*
|
|
160
|
+
* references to enum members / module-level const scalars / `as const` object properties,
|
|
161
|
+
* whitelisted namespace constants like 'math.pi' and runtime-constant engine references
|
|
162
|
+
* like 'stalker_ids.action_dying' (emitted as expressions instead of baked literals).
|
|
118
163
|
*
|
|
119
164
|
* @param checker - Program type checker.
|
|
120
165
|
* @param expression - Expression to evaluate.
|
|
121
166
|
* @param seen - Set of declarations on current resolution path, guards from circular references.
|
|
122
|
-
* @returns Folded constant value or null.
|
|
167
|
+
* @returns Folded constant value, or null when the expression is not safe to fold.
|
|
123
168
|
*/
|
|
124
169
|
function evaluateConstantExpression(checker, expression, seen) {
|
|
125
170
|
const node = (0, ast_1.unwrapInitializer)(expression);
|
|
@@ -145,9 +190,14 @@ function evaluateConstantExpression(checker, expression, seen) {
|
|
|
145
190
|
}
|
|
146
191
|
switch (node.operator) {
|
|
147
192
|
case ts.SyntaxKind.MinusToken:
|
|
148
|
-
|
|
193
|
+
if (typeof operand === "number") {
|
|
194
|
+
return toFiniteNumber(-operand);
|
|
195
|
+
}
|
|
196
|
+
return typeof operand === "object" && (0, constants_1.isNumericFoldedValue)(operand) ? { kind: "negate", operand } : null;
|
|
149
197
|
case ts.SyntaxKind.PlusToken:
|
|
150
|
-
return typeof operand === "number"
|
|
198
|
+
return typeof operand === "number" || (typeof operand === "object" && (0, constants_1.isNumericFoldedValue)(operand))
|
|
199
|
+
? operand
|
|
200
|
+
: null;
|
|
151
201
|
case ts.SyntaxKind.TildeToken:
|
|
152
202
|
return typeof operand === "number" ? ~operand : null;
|
|
153
203
|
case ts.SyntaxKind.ExclamationToken:
|
|
@@ -189,20 +239,58 @@ function evaluateConstantExpression(checker, expression, seen) {
|
|
|
189
239
|
return symbol === undefined ? null : resolveConstantSymbol(checker, symbol, seen);
|
|
190
240
|
}
|
|
191
241
|
if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {
|
|
192
|
-
const symbol =
|
|
242
|
+
const symbol = resolveMemberSymbol(checker, node);
|
|
193
243
|
return symbol === null ? null : resolveConstantSymbol(checker, symbol, seen);
|
|
194
244
|
}
|
|
195
245
|
return null;
|
|
196
246
|
}
|
|
197
247
|
/**
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
248
|
+
* Fold an enum member to a constant value.
|
|
249
|
+
* TypeScript computes literal values of constant members; members initialized with engine references
|
|
250
|
+
* fold to expression trees instead.
|
|
251
|
+
*
|
|
252
|
+
* @param checker - Program type checker.
|
|
253
|
+
* @param declaration - Enum member declaration to fold.
|
|
254
|
+
* @param seen - Set of declarations on current resolution path.
|
|
255
|
+
* @returns Folded constant value, or null when the member is not computable at build time.
|
|
256
|
+
*/
|
|
257
|
+
function getEnumMemberValue(checker, declaration, seen) {
|
|
258
|
+
const value = checker.getConstantValue(declaration);
|
|
259
|
+
if (typeof value === "string" || typeof value === "number") {
|
|
260
|
+
return value;
|
|
261
|
+
}
|
|
262
|
+
if (declaration.initializer === undefined || seen.has(declaration)) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
seen.add(declaration);
|
|
266
|
+
try {
|
|
267
|
+
return evaluateConstantExpression(checker, declaration.initializer, seen);
|
|
268
|
+
}
|
|
269
|
+
finally {
|
|
270
|
+
seen.delete(declaration);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Check whether an enum member is computable at build time - either constant for TypeScript
|
|
275
|
+
* or initialized with an expression that folds to a literal or an engine reference tree.
|
|
276
|
+
*
|
|
277
|
+
* @param checker - Program type checker.
|
|
278
|
+
* @param member - Enum member to check.
|
|
279
|
+
* @returns Whether the member is computable at build time.
|
|
280
|
+
*/
|
|
281
|
+
function isComputableEnumMember(checker, member) {
|
|
282
|
+
return getEnumMemberValue(checker, member, new Set()) !== null;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Resolve a referenced symbol to a compile-time constant value when the reference is safe to fold.
|
|
286
|
+
* Safe references are enum members, module-level const scalars, readonly `as const` object properties
|
|
287
|
+
* and `static readonly` engine members from ambient 'xray16' typings - values that cannot legally
|
|
288
|
+
* change at runtime. Tags are not required on referenced declarations.
|
|
201
289
|
*
|
|
202
290
|
* @param checker - Program type checker.
|
|
203
291
|
* @param symbol - Referenced symbol to resolve.
|
|
204
292
|
* @param seen - Set of declarations on current resolution path.
|
|
205
|
-
* @returns Folded constant value or null.
|
|
293
|
+
* @returns Folded constant value, or null when the symbol is not safe to fold.
|
|
206
294
|
*/
|
|
207
295
|
function resolveConstantSymbol(checker, symbol, seen) {
|
|
208
296
|
const resolved = (symbol.flags & ts.SymbolFlags.Alias) !== 0 ? checker.getAliasedSymbol(symbol) : symbol;
|
|
@@ -211,8 +299,19 @@ function resolveConstantSymbol(checker, symbol, seen) {
|
|
|
211
299
|
return null;
|
|
212
300
|
}
|
|
213
301
|
if (ts.isEnumMember(declaration)) {
|
|
214
|
-
|
|
215
|
-
|
|
302
|
+
return getEnumMemberValue(checker, declaration, seen);
|
|
303
|
+
}
|
|
304
|
+
if (ts.isPropertyDeclaration(declaration)) {
|
|
305
|
+
const path = (0, ast_1.getEngineConstantPath)(declaration);
|
|
306
|
+
if (path === null) {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
const type = checker.getTypeOfSymbolAtLocation(resolved, declaration);
|
|
310
|
+
return {
|
|
311
|
+
kind: "engine-ref",
|
|
312
|
+
path,
|
|
313
|
+
isNumeric: type.isNumberLiteral() || (type.flags & ts.TypeFlags.NumberLike) !== 0,
|
|
314
|
+
};
|
|
216
315
|
}
|
|
217
316
|
if (ts.isVariableDeclaration(declaration)) {
|
|
218
317
|
const statement = (0, ast_1.getContainingVariableStatement)(declaration);
|
|
@@ -227,23 +326,22 @@ function resolveConstantSymbol(checker, symbol, seen) {
|
|
|
227
326
|
return null;
|
|
228
327
|
}
|
|
229
328
|
/**
|
|
230
|
-
* Get constant value of a declaration
|
|
329
|
+
* Get the constant value of a declaration.
|
|
330
|
+
* Initializers are folded first so engine references are substituted as expressions - the declared
|
|
331
|
+
* literal type fast path would silently bake possibly stale values claimed by typings.
|
|
332
|
+
* Declared unit types are only used for initializer-less declarations like ambient constants.
|
|
231
333
|
* Safety and tagging requirements are checked by callers.
|
|
232
334
|
*
|
|
233
335
|
* @param checker - Program type checker.
|
|
234
336
|
* @param symbol - Symbol to get value for.
|
|
235
337
|
* @param seen - Set of declarations on current resolution path.
|
|
236
|
-
* @returns Constant value or null.
|
|
338
|
+
* @returns Constant value, or null when the declaration cannot be folded.
|
|
237
339
|
*/
|
|
238
340
|
function getComputedDeclarationValue(checker, symbol, seen) {
|
|
239
341
|
const declaration = symbol.valueDeclaration;
|
|
240
342
|
if (declaration === undefined) {
|
|
241
343
|
return null;
|
|
242
344
|
}
|
|
243
|
-
const declared = getDeclaredLiteralValue(checker, symbol);
|
|
244
|
-
if (declared !== null) {
|
|
245
|
-
return declared;
|
|
246
|
-
}
|
|
247
345
|
if (seen.has(declaration)) {
|
|
248
346
|
return null;
|
|
249
347
|
}
|
|
@@ -257,19 +355,19 @@ function getComputedDeclarationValue(checker, symbol, seen) {
|
|
|
257
355
|
const valueSymbol = checker.getShorthandAssignmentValueSymbol(declaration);
|
|
258
356
|
return valueSymbol === undefined ? null : resolveConstantSymbol(checker, valueSymbol, seen);
|
|
259
357
|
}
|
|
260
|
-
return
|
|
358
|
+
return getDeclaredLiteralValue(checker, symbol);
|
|
261
359
|
}
|
|
262
360
|
finally {
|
|
263
361
|
seen.delete(declaration);
|
|
264
362
|
}
|
|
265
363
|
}
|
|
266
364
|
/**
|
|
267
|
-
* Get
|
|
268
|
-
* Only symbols declared inside
|
|
365
|
+
* Get the inlineable value for a symbol resolved from an access expression or identifier.
|
|
366
|
+
* Only symbols declared inside tagged enums or variable statements produce values.
|
|
269
367
|
*
|
|
270
368
|
* @param checker - Program type checker.
|
|
271
369
|
* @param symbol - Symbol to resolve inline value for.
|
|
272
|
-
* @returns
|
|
370
|
+
* @returns Folded value, or null when the symbol is not tagged for inlining.
|
|
273
371
|
*/
|
|
274
372
|
function tryGetInlineValue(checker, symbol) {
|
|
275
373
|
const declaration = symbol.valueDeclaration;
|
|
@@ -280,8 +378,7 @@ function tryGetInlineValue(checker, symbol) {
|
|
|
280
378
|
if (!(0, ast_1.hasInlineTag)(declaration.parent)) {
|
|
281
379
|
return null;
|
|
282
380
|
}
|
|
283
|
-
|
|
284
|
-
return typeof value === "string" || typeof value === "number" ? value : null;
|
|
381
|
+
return getEnumMemberValue(checker, declaration, new Set());
|
|
285
382
|
}
|
|
286
383
|
if (ts.isPropertyAssignment(declaration) ||
|
|
287
384
|
ts.isShorthandPropertyAssignment(declaration) ||
|
|
@@ -1,27 +1,41 @@
|
|
|
1
1
|
import * as ts from "typescript";
|
|
2
2
|
import * as lua from "typescript-to-lua";
|
|
3
|
-
import { type
|
|
3
|
+
import { type TFoldedValue } from "./constants";
|
|
4
4
|
/**
|
|
5
|
-
* Create
|
|
5
|
+
* Create a Lua expression for the provided folded value.
|
|
6
|
+
* Literals become Lua literals; expression trees with engine references become global access
|
|
7
|
+
* expressions and arithmetic over them.
|
|
6
8
|
*
|
|
7
|
-
* @param value -
|
|
8
|
-
* @param node - Original
|
|
9
|
-
* @returns Lua
|
|
9
|
+
* @param value - Folded value to create expression for.
|
|
10
|
+
* @param node - Original TypeScript node.
|
|
11
|
+
* @returns Lua expression.
|
|
10
12
|
*/
|
|
11
|
-
export declare function
|
|
13
|
+
export declare function createFoldedExpression(value: TFoldedValue, node: ts.Node): lua.Expression;
|
|
12
14
|
/**
|
|
13
|
-
* Transform property
|
|
15
|
+
* Transform property and element access expressions by inlining literal values from tagged declarations.
|
|
16
|
+
* Object spreads of `@virtual` objects accessed through namespaces are expanded to table literals.
|
|
14
17
|
*
|
|
15
18
|
* @param node - Access expression node to transform.
|
|
16
19
|
* @param context - Transformation context.
|
|
17
|
-
* @returns Lua literal when access resolves to a tagged constant, default transformation otherwise.
|
|
20
|
+
* @returns Lua literal when the access resolves to a tagged constant, default transformation otherwise.
|
|
18
21
|
*/
|
|
19
22
|
export declare function transformAccessExpression(node: ts.PropertyAccessExpression | ts.ElementAccessExpression, context: lua.TransformationContext): lua.Expression;
|
|
20
23
|
/**
|
|
21
|
-
* Transform identifier expressions
|
|
24
|
+
* Transform identifier expressions by inlining literal values from tagged scalar constants
|
|
25
|
+
* and expand object spreads of `@virtual` objects into table literals.
|
|
22
26
|
*
|
|
23
27
|
* @param node - Identifier node to transform.
|
|
24
28
|
* @param context - Transformation context.
|
|
25
|
-
* @returns Lua literal when identifier resolves to a tagged constant, default transformation otherwise.
|
|
29
|
+
* @returns Lua literal when the identifier resolves to a tagged constant, default transformation otherwise.
|
|
26
30
|
*/
|
|
27
31
|
export declare function transformIdentifierExpression(node: ts.Identifier, context: lua.TransformationContext): lua.Expression;
|
|
32
|
+
/**
|
|
33
|
+
* Transform import declarations by stripping bindings for tagged declarations with no remaining runtime usages.
|
|
34
|
+
* When no runtime bindings remain, the require is dropped for provably pure modules
|
|
35
|
+
* or kept as a side-effect import otherwise.
|
|
36
|
+
*
|
|
37
|
+
* @param statement - Import declaration to transform.
|
|
38
|
+
* @param context - Transformation context.
|
|
39
|
+
* @returns Transformed statements.
|
|
40
|
+
*/
|
|
41
|
+
export declare function transformImportDeclaration(statement: ts.ImportDeclaration, context: lua.TransformationContext): Array<lua.Statement>;
|