xray16 1.6.2 → 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 CHANGED
@@ -62,6 +62,7 @@ Plugins can be included in [tstl tsconfig](https://typescripttolua.github.io/doc
62
62
  { "name": "xray16/plugins/inject_filename" },
63
63
  { "name": "xray16/plugins/from_cast_utils" },
64
64
  { "name": "xray16/plugins/optimize_return_ternary" },
65
+ { "name": "xray16/plugins/inline_constants/plugin" },
65
66
  { "name": "xray16/plugins/inject_tracy_zones" }
66
67
  ]
67
68
  }
@@ -112,6 +113,40 @@ All the calls are completely gets stripped and removed from runtime.
112
113
  Plugin rewrites returned ternary expressions into direct `if` / `else` branch returns when it is safe.\
113
114
  This avoids temporary result locals for patterns like `return condition ? first : second` while preserving general ternary semantics.
114
115
 
116
+ ### inline_constants
117
+
118
+ Plugin that inlines compile-time constants from declarations tagged with `@inline` or `@virtual`.\
119
+ Supported targets are enums, module-level `as const` object literals and module-level scalar constants.\
120
+ Values may be literals or expressions that can be folded at build time: arithmetic, string concatenation,
121
+ template literals and references to other constant declarations.\
122
+ Tagged declarations act as an explicit whitelist and produce build errors when they cannot be inlined.
123
+
124
+ - `@inline` replaces accesses with literal values but still emits the original declaration, so iteration,
125
+ reverse mapping and whole-object usages keep working. Import bindings that are no longer used at runtime
126
+ are stripped; if the target module is proven pure, its `require` is dropped too.
127
+ - `@virtual` includes `@inline` behavior and also removes the declaration from emitted output. Every value
128
+ reference must be computable at build time. Object spreads of virtual objects are expanded to table literals.
129
+
130
+ ```typescript
131
+ /**
132
+ * @inline
133
+ */
134
+ export const medkits = {
135
+ medkit: "medkit",
136
+ medkit_army: "medkit_army",
137
+ } as const;
138
+
139
+ /**
140
+ * @virtual
141
+ */
142
+ export const TIMEOUT: number = 60 * 1000;
143
+
144
+ // Build time: `medkits.medkit_army` access is emitted as plain "medkit_army" string literal.
145
+ // Build time: `TIMEOUT` reference is emitted as 60000 and the declaration is erased from output.
146
+ ```
147
+
148
+ See [src/plugins/inline_constants/README.md](src/plugins/inline_constants/README.md) for full documentation.
149
+
115
150
  ### inject_tracy_zones
116
151
 
117
152
  Plugin designed to work specifically with [tracy profiler](https://github.com/wolfpld/tracy).\
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xray16",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "author": "Neloreck",
5
5
  "repository": "https://github.com/xray-forge/xray-16-types",
6
6
  "homepage": "https://xray-forge.github.io/xray-16-types/index.html",
@@ -11,10 +11,11 @@
11
11
  "prepublish": "npm run build",
12
12
  "prepack": "npm run build",
13
13
  "build": "npm run build:plugins && npm run build:types",
14
- "build:plugins": "tsc -p ./src/tsconfig.json",
14
+ "build:plugins": "tsc -p ./src/tsconfig.build.json",
15
15
  "build:types": "rollup -c rollup.dts.config.mjs",
16
16
  "build:docs": "typedoc",
17
- "typecheck": "tsc --noEmit",
17
+ "test": "jest",
18
+ "typecheck": "tsc --noEmit && tsc --noEmit -p ./src/tsconfig.json",
18
19
  "typedoc": "typedoc",
19
20
  "format": "prettier --write \"**/*.(js|ts|tsx|md)\" && eslint . --fix",
20
21
  "lint": "eslint ."
@@ -24,6 +25,7 @@
24
25
  },
25
26
  "devDependencies": {
26
27
  "@eslint/js": "^9.39.4",
28
+ "@types/jest": "^29.5.14",
27
29
  "@types/node": "22.10.2",
28
30
  "@typescript-eslint/eslint-plugin": "^8.62.0",
29
31
  "@typescript-eslint/parser": "^8.62.0",
@@ -34,9 +36,11 @@
34
36
  "eslint-plugin-jest": "^29.15.2",
35
37
  "eslint-plugin-jsdoc": "^63.0.7",
36
38
  "globals": "^17.7.0",
39
+ "jest": "^29.7.0",
37
40
  "prettier": "^3.4.2",
38
41
  "rollup": "^4.62.2",
39
42
  "rollup-plugin-dts": "^6.4.1",
43
+ "ts-jest": "^29.4.11",
40
44
  "typedoc": "^0.27.5",
41
45
  "typescript": "5.7.2",
42
46
  "typescript-eslint": "^8.62.0",
@@ -0,0 +1,21 @@
1
+ import { type Plugin } from "typescript-to-lua";
2
+ /**
3
+ * Plugin that inlines compile-time constants from declarations tagged with `@inline` or `@virtual`.
4
+ *
5
+ * Supported targets are enums, module-level `as const` object literals and module-level scalar constants.
6
+ * Values may be literals or expressions that can be folded at build time: arithmetic, string concatenation,
7
+ * template literals and references to other constant declarations (enum members, const scalars,
8
+ * `as const` object properties, whitelisted constants like 'math.pi').
9
+ *
10
+ * `@inline` replaces member accesses with literal values while still emitting the original declaration,
11
+ * so iteration, reverse mapping and whole-object usages keep working. Import bindings with no remaining
12
+ * runtime usages are stripped; requires of provably pure modules are dropped with them.
13
+ *
14
+ * `@virtual` includes `@inline` behavior and also erases the declaration from emitted output. Every
15
+ * value reference must be computable at build time. Object spreads are expanded to table literals.
16
+ * Modules containing `@virtual` declarations are validated to be side-effect free.
17
+ *
18
+ * Tagged declarations act as an explicit whitelist and produce build errors when they cannot be inlined.
19
+ */
20
+ declare const plugin: Plugin;
21
+ export default plugin;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const ts = require("typescript");
4
+ const transformation_1 = require("./transformation");
5
+ /**
6
+ * Plugin that inlines compile-time constants from declarations tagged with `@inline` or `@virtual`.
7
+ *
8
+ * Supported targets are enums, module-level `as const` object literals and module-level scalar constants.
9
+ * Values may be literals or expressions that can be folded at build time: arithmetic, string concatenation,
10
+ * template literals and references to other constant declarations (enum members, const scalars,
11
+ * `as const` object properties, whitelisted constants like 'math.pi').
12
+ *
13
+ * `@inline` replaces member accesses with literal values while still emitting the original declaration,
14
+ * so iteration, reverse mapping and whole-object usages keep working. Import bindings with no remaining
15
+ * runtime usages are stripped; requires of provably pure modules are dropped with them.
16
+ *
17
+ * `@virtual` includes `@inline` behavior and also erases the declaration from emitted output. Every
18
+ * value reference must be computable at build time. Object spreads are expanded to table literals.
19
+ * Modules containing `@virtual` declarations are validated to be side-effect free.
20
+ *
21
+ * Tagged declarations act as an explicit whitelist and produce build errors when they cannot be inlined.
22
+ */
23
+ const plugin = {
24
+ beforeTransform(program) {
25
+ // Force binder to assign node parents before any 'getJSDocTags' call,
26
+ // otherwise empty results are computed for parent-less nodes and cached on them forever.
27
+ program.getTypeChecker();
28
+ const diagnostics = [...(0, transformation_1.validateTopLevelTags)(program), ...(0, transformation_1.collectVirtualDiagnostics)(program)];
29
+ if (diagnostics.length > 0) {
30
+ return diagnostics;
31
+ }
32
+ },
33
+ visitors: {
34
+ [ts.SyntaxKind.PropertyAccessExpression]: transformation_1.transformAccessExpression,
35
+ [ts.SyntaxKind.ElementAccessExpression]: transformation_1.transformAccessExpression,
36
+ [ts.SyntaxKind.Identifier]: transformation_1.transformIdentifierExpression,
37
+ [ts.SyntaxKind.ImportDeclaration]: transformation_1.transformImportDeclaration,
38
+ [ts.SyntaxKind.VariableStatement]: (statement, context) => {
39
+ if ((0, transformation_1.hasInlineTag)(statement)) {
40
+ (0, transformation_1.validateVariableStatement)(statement, context);
41
+ if ((0, transformation_1.hasVirtualTag)(statement)) {
42
+ return [];
43
+ }
44
+ }
45
+ return context.superTransformStatements(statement);
46
+ },
47
+ [ts.SyntaxKind.EnumDeclaration]: (declaration, context) => {
48
+ if ((0, transformation_1.hasInlineTag)(declaration)) {
49
+ (0, transformation_1.validateEnumDeclaration)(declaration, context);
50
+ if ((0, transformation_1.hasVirtualTag)(declaration)) {
51
+ return [];
52
+ }
53
+ }
54
+ return context.superTransformStatements(declaration);
55
+ },
56
+ },
57
+ };
58
+ exports.default = plugin;
@@ -0,0 +1,69 @@
1
+ import * as ts from "typescript";
2
+ /**
3
+ * Check whether a node is whitelisted for inlining.
4
+ * Both `@inline` and `@virtual` enable inlining; `@virtual` adds erasure rules elsewhere.
5
+ *
6
+ * @param node - Node to check tags for.
7
+ * @returns Whether the node is whitelisted for inlining.
8
+ */
9
+ export declare function hasInlineTag(node: ts.Node): boolean;
10
+ /**
11
+ * Check whether a node has the `@virtual` JSDoc tag.
12
+ *
13
+ * @param node - Node to check tags for.
14
+ * @returns Whether the node has `@virtual` JSDoc tag.
15
+ */
16
+ export declare function hasVirtualTag(node: ts.Node): boolean;
17
+ /**
18
+ * Find the variable statement that contains the provided declaration node.
19
+ *
20
+ * @param node - Declaration node to walk up from.
21
+ * @returns Containing variable statement or null.
22
+ */
23
+ export declare function getContainingVariableStatement(node: ts.Node): ts.VariableStatement | null;
24
+ /**
25
+ * Unwrap an initializer expression from `as`, `satisfies`, and parenthesized wrappers.
26
+ *
27
+ * @param expression - Initializer expression to unwrap.
28
+ * @returns Unwrapped expression or null.
29
+ */
30
+ export declare function unwrapInitializer(expression?: ts.Expression): ts.Expression | null;
31
+ /**
32
+ * Check whether variable statement is a module-level `const` declaration.
33
+ *
34
+ * @param statement - Variable statement to check.
35
+ * @returns Whether the statement is a module-level const.
36
+ */
37
+ export declare function isModuleLevelConst(statement: ts.VariableStatement): boolean;
38
+ /**
39
+ * Check whether an expression is wrapped in an `as const` assertion, possibly through parens/satisfies wrappers.
40
+ *
41
+ * @param expression - Expression to check.
42
+ * @returns Whether the expression has an `as const` assertion.
43
+ */
44
+ export declare function hasAsConstAssertion(expression?: ts.Expression): boolean;
45
+ /**
46
+ * Check whether a property is declared inside an `as const` object literal assigned to a module-level const.
47
+ * Such properties are readonly and cannot be legally reassigned, so their values are stable at runtime.
48
+ *
49
+ * @param declaration - Property declaration to check.
50
+ * @returns Whether property value is safe to fold.
51
+ */
52
+ export declare function isReadonlyModuleConstProperty(declaration: ts.PropertyAssignment | ts.ShorthandPropertyAssignment): boolean;
53
+ /**
54
+ * Check whether an identifier is used in a value position where it can be replaced with a literal.
55
+ *
56
+ * @param node - Identifier node to check.
57
+ * @returns Whether the identifier is a replaceable value usage.
58
+ */
59
+ export declare function isValueUsagePosition(node: ts.Identifier): boolean;
60
+ /**
61
+ * Get global access path for a runtime-constant engine member declaration.
62
+ * Qualifying declarations are `static readonly` class members declared inside ambient `declare module "xray16"` -
63
+ * such values are registered once by the engine and never change at runtime.
64
+ * The path uses the declared class name, so import aliases do not affect emitted references.
65
+ *
66
+ * @param declaration - Declaration to check.
67
+ * @returns Global access path like ['stalker_ids', 'action_dying'], or null when not a constant engine member.
68
+ */
69
+ export declare function getEngineConstantPath(declaration: ts.Declaration): Array<string> | null;
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasInlineTag = hasInlineTag;
4
+ exports.hasVirtualTag = hasVirtualTag;
5
+ exports.getContainingVariableStatement = getContainingVariableStatement;
6
+ exports.unwrapInitializer = unwrapInitializer;
7
+ exports.isModuleLevelConst = isModuleLevelConst;
8
+ exports.hasAsConstAssertion = hasAsConstAssertion;
9
+ exports.isReadonlyModuleConstProperty = isReadonlyModuleConstProperty;
10
+ exports.isValueUsagePosition = isValueUsagePosition;
11
+ exports.getEngineConstantPath = getEngineConstantPath;
12
+ const ts = require("typescript");
13
+ const constants_1 = require("./constants");
14
+ /**
15
+ * Check whether a node has the provided JSDoc tag.
16
+ *
17
+ * @param node - Node to check tags for.
18
+ * @param tag - Tag name to look for.
19
+ * @returns Whether the node has the JSDoc tag.
20
+ */
21
+ function hasJsDocTag(node, tag) {
22
+ return ts.getJSDocTags(node).some((it) => it.tagName.text === tag);
23
+ }
24
+ /**
25
+ * Check whether a node is whitelisted for inlining.
26
+ * Both `@inline` and `@virtual` enable inlining; `@virtual` adds erasure rules elsewhere.
27
+ *
28
+ * @param node - Node to check tags for.
29
+ * @returns Whether the node is whitelisted for inlining.
30
+ */
31
+ function hasInlineTag(node) {
32
+ return hasJsDocTag(node, constants_1.INLINE_TAG) || hasJsDocTag(node, constants_1.VIRTUAL_TAG);
33
+ }
34
+ /**
35
+ * Check whether a node has the `@virtual` JSDoc tag.
36
+ *
37
+ * @param node - Node to check tags for.
38
+ * @returns Whether the node has `@virtual` JSDoc tag.
39
+ */
40
+ function hasVirtualTag(node) {
41
+ return hasJsDocTag(node, constants_1.VIRTUAL_TAG);
42
+ }
43
+ /**
44
+ * Find the variable statement that contains the provided declaration node.
45
+ *
46
+ * @param node - Declaration node to walk up from.
47
+ * @returns Containing variable statement or null.
48
+ */
49
+ function getContainingVariableStatement(node) {
50
+ let current = node;
51
+ while (current !== undefined && !ts.isSourceFile(current)) {
52
+ if (ts.isVariableStatement(current)) {
53
+ return current;
54
+ }
55
+ current = current.parent;
56
+ }
57
+ return null;
58
+ }
59
+ /**
60
+ * Unwrap an initializer expression from `as`, `satisfies`, and parenthesized wrappers.
61
+ *
62
+ * @param expression - Initializer expression to unwrap.
63
+ * @returns Unwrapped expression or null.
64
+ */
65
+ function unwrapInitializer(expression) {
66
+ let current = expression ?? null;
67
+ while (current !== null &&
68
+ (ts.isAsExpression(current) ||
69
+ ts.isSatisfiesExpression(current) ||
70
+ ts.isParenthesizedExpression(current) ||
71
+ ts.isTypeAssertionExpression(current))) {
72
+ current = current.expression;
73
+ }
74
+ return current;
75
+ }
76
+ /**
77
+ * Check whether variable statement is a module-level `const` declaration.
78
+ *
79
+ * @param statement - Variable statement to check.
80
+ * @returns Whether the statement is a module-level const.
81
+ */
82
+ function isModuleLevelConst(statement) {
83
+ return ts.isSourceFile(statement.parent) && (statement.declarationList.flags & ts.NodeFlags.Const) !== 0;
84
+ }
85
+ /**
86
+ * Check whether an expression is wrapped in an `as const` assertion, possibly through parens/satisfies wrappers.
87
+ *
88
+ * @param expression - Expression to check.
89
+ * @returns Whether the expression has an `as const` assertion.
90
+ */
91
+ function hasAsConstAssertion(expression) {
92
+ let current = expression;
93
+ while (current !== undefined) {
94
+ if (ts.isAsExpression(current) &&
95
+ ts.isTypeReferenceNode(current.type) &&
96
+ current.type.typeName.getText() === "const") {
97
+ return true;
98
+ }
99
+ if (ts.isAsExpression(current) || ts.isParenthesizedExpression(current) || ts.isSatisfiesExpression(current)) {
100
+ current = current.expression;
101
+ }
102
+ else {
103
+ return false;
104
+ }
105
+ }
106
+ return false;
107
+ }
108
+ /**
109
+ * Check whether a property is declared inside an `as const` object literal assigned to a module-level const.
110
+ * Such properties are readonly and cannot be legally reassigned, so their values are stable at runtime.
111
+ *
112
+ * @param declaration - Property declaration to check.
113
+ * @returns Whether property value is safe to fold.
114
+ */
115
+ function isReadonlyModuleConstProperty(declaration) {
116
+ let sawAsConst = false;
117
+ let current = declaration.parent;
118
+ while (current !== undefined && !ts.isVariableDeclaration(current)) {
119
+ if (ts.isAsExpression(current) &&
120
+ ts.isTypeReferenceNode(current.type) &&
121
+ current.type.typeName.getText() === "const") {
122
+ sawAsConst = true;
123
+ }
124
+ if (!ts.isObjectLiteralExpression(current) &&
125
+ !ts.isPropertyAssignment(current) &&
126
+ !ts.isAsExpression(current) &&
127
+ !ts.isParenthesizedExpression(current) &&
128
+ !ts.isSatisfiesExpression(current)) {
129
+ return false;
130
+ }
131
+ current = current.parent;
132
+ }
133
+ if (current === undefined || !sawAsConst) {
134
+ return false;
135
+ }
136
+ const statement = getContainingVariableStatement(current);
137
+ return statement !== null && isModuleLevelConst(statement);
138
+ }
139
+ /**
140
+ * Check whether an identifier is used in a value position where it can be replaced with a literal.
141
+ *
142
+ * @param node - Identifier node to check.
143
+ * @returns Whether the identifier is a replaceable value usage.
144
+ */
145
+ function isValueUsagePosition(node) {
146
+ const parent = node.parent;
147
+ if (parent === undefined || ts.isPartOfTypeNode(node)) {
148
+ return false;
149
+ }
150
+ if (ts.isPropertyAccessExpression(parent)) {
151
+ return parent.expression === node;
152
+ }
153
+ if (ts.isPropertyAssignment(parent) ||
154
+ ts.isBindingElement(parent) ||
155
+ ts.isParameter(parent) ||
156
+ ts.isEnumMember(parent) ||
157
+ ts.isPropertyDeclaration(parent) ||
158
+ ts.isVariableDeclaration(parent)) {
159
+ return parent.initializer === node;
160
+ }
161
+ if (ts.isShorthandPropertyAssignment(parent) ||
162
+ ts.isImportSpecifier(parent) ||
163
+ ts.isImportClause(parent) ||
164
+ ts.isNamespaceImport(parent) ||
165
+ ts.isExportSpecifier(parent) ||
166
+ ts.isNamespaceExport(parent) ||
167
+ ts.isImportEqualsDeclaration(parent) ||
168
+ ts.isQualifiedName(parent) ||
169
+ ts.isLabeledStatement(parent) ||
170
+ ts.isBreakOrContinueStatement(parent)) {
171
+ return false;
172
+ }
173
+ if (ts.isFunctionDeclaration(parent) ||
174
+ ts.isFunctionExpression(parent) ||
175
+ ts.isClassDeclaration(parent) ||
176
+ ts.isClassExpression(parent) ||
177
+ ts.isMethodDeclaration(parent) ||
178
+ ts.isGetAccessorDeclaration(parent) ||
179
+ ts.isSetAccessorDeclaration(parent) ||
180
+ ts.isModuleDeclaration(parent) ||
181
+ ts.isEnumDeclaration(parent) ||
182
+ ts.isInterfaceDeclaration(parent) ||
183
+ ts.isTypeAliasDeclaration(parent)) {
184
+ return parent.name !== node;
185
+ }
186
+ return true;
187
+ }
188
+ /**
189
+ * Get global access path for a runtime-constant engine member declaration.
190
+ * Qualifying declarations are `static readonly` class members declared inside ambient `declare module "xray16"` -
191
+ * such values are registered once by the engine and never change at runtime.
192
+ * The path uses the declared class name, so import aliases do not affect emitted references.
193
+ *
194
+ * @param declaration - Declaration to check.
195
+ * @returns Global access path like ['stalker_ids', 'action_dying'], or null when not a constant engine member.
196
+ */
197
+ function getEngineConstantPath(declaration) {
198
+ if (!ts.isPropertyDeclaration(declaration) || !ts.isIdentifier(declaration.name)) {
199
+ return null;
200
+ }
201
+ const modifiers = ts.getModifiers(declaration) ?? [];
202
+ const isStaticReadonly = modifiers.some((it) => it.kind === ts.SyntaxKind.StaticKeyword) &&
203
+ modifiers.some((it) => it.kind === ts.SyntaxKind.ReadonlyKeyword);
204
+ if (!isStaticReadonly) {
205
+ return null;
206
+ }
207
+ const classDeclaration = declaration.parent;
208
+ if (!ts.isClassDeclaration(classDeclaration) || classDeclaration.name === undefined) {
209
+ return null;
210
+ }
211
+ let current = classDeclaration.parent;
212
+ while (current !== undefined && !ts.isSourceFile(current)) {
213
+ if (ts.isModuleDeclaration(current) && ts.isStringLiteral(current.name) && current.name.text === "xray16") {
214
+ return [classDeclaration.name.text, declaration.name.text];
215
+ }
216
+ current = current.parent;
217
+ }
218
+ return null;
219
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * JSDoc tag marking declarations as whitelisted for compile-time inlining.
3
+ */
4
+ export declare const INLINE_TAG: string;
5
+ /**
6
+ * JSDoc tag marking declarations for compile-time inlining and erasure from emitted output.
7
+ * Includes `@inline` behavior and requires every value reference to be erasable.
8
+ */
9
+ export declare const VIRTUAL_TAG: string;
10
+ /**
11
+ * Value types that can be inlined as Lua literals.
12
+ */
13
+ export type TInlineValue = string | number | boolean;
14
+ /**
15
+ * Reference to a runtime-constant engine value like 'stalker_ids.action_dying'.
16
+ * Emitted as a global access expression instead of a baked literal, so values stay correct
17
+ * even when engine builds diverge from the literal types declared in typings.
18
+ */
19
+ export interface IEngineReference {
20
+ kind: "engine-ref";
21
+ path: Array<string>;
22
+ isNumeric: boolean;
23
+ }
24
+ /**
25
+ * Binary numeric expression mixing engine references with other folded values.
26
+ */
27
+ export interface IFoldedBinary {
28
+ kind: "binary";
29
+ operator: TFoldedBinaryOperator;
30
+ left: TFoldedValue;
31
+ right: TFoldedValue;
32
+ }
33
+ /**
34
+ * Numeric negation of a folded expression.
35
+ */
36
+ export interface IFoldedNegation {
37
+ kind: "negate";
38
+ operand: TFoldedValue;
39
+ }
40
+ /**
41
+ * Operators allowed in folded expression trees - restricted to those where emitted Lua matches
42
+ * tstl lowering exactly. '%', bitwise operators and string concatenation are rejected for trees.
43
+ */
44
+ export type TFoldedBinaryOperator = "+" | "-" | "*" | "/" | "**";
45
+ /**
46
+ * Expression parts of folded values that cannot be computed to plain literals at build time.
47
+ */
48
+ export type TFoldedExpression = IEngineReference | IFoldedBinary | IFoldedNegation;
49
+ /**
50
+ * Result of build-time folding - either a plain literal or an expression tree with engine references.
51
+ */
52
+ export type TFoldedValue = TInlineValue | TFoldedExpression;
53
+ /**
54
+ * Check whether folded value is an expression tree rather than a plain literal.
55
+ *
56
+ * @param value - Folded value to check.
57
+ * @returns Whether value is an expression tree.
58
+ */
59
+ export declare function isFoldedExpression(value: TFoldedValue): value is TFoldedExpression;
60
+ /**
61
+ * Check whether folded value is numeric - a number literal or a numeric expression tree.
62
+ *
63
+ * @param value - Folded value to check.
64
+ * @returns Whether value is numeric.
65
+ */
66
+ export declare function isNumericFoldedValue(value: TFoldedValue): boolean;
67
+ /**
68
+ * Numeric namespace constants with identical IEEE 754 double values in the build environment and LuaJIT runtime.
69
+ * Covers both TS 'Math' and Lua 'math' namespaces. Function calls are intentionally not supported because
70
+ * libm implementations may differ between build machine and game runtime.
71
+ */
72
+ export declare const FOLDABLE_NAMESPACE_CONSTANTS: Record<string, Record<string, number>>;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FOLDABLE_NAMESPACE_CONSTANTS = exports.VIRTUAL_TAG = exports.INLINE_TAG = void 0;
4
+ exports.isFoldedExpression = isFoldedExpression;
5
+ exports.isNumericFoldedValue = isNumericFoldedValue;
6
+ /**
7
+ * JSDoc tag marking declarations as whitelisted for compile-time inlining.
8
+ */
9
+ exports.INLINE_TAG = "inline";
10
+ /**
11
+ * JSDoc tag marking declarations for compile-time inlining and erasure from emitted output.
12
+ * Includes `@inline` behavior and requires every value reference to be erasable.
13
+ */
14
+ exports.VIRTUAL_TAG = "virtual";
15
+ /**
16
+ * Check whether folded value is an expression tree rather than a plain literal.
17
+ *
18
+ * @param value - Folded value to check.
19
+ * @returns Whether value is an expression tree.
20
+ */
21
+ function isFoldedExpression(value) {
22
+ return typeof value === "object";
23
+ }
24
+ /**
25
+ * Check whether folded value is numeric - a number literal or a numeric expression tree.
26
+ *
27
+ * @param value - Folded value to check.
28
+ * @returns Whether value is numeric.
29
+ */
30
+ function isNumericFoldedValue(value) {
31
+ if (typeof value === "number") {
32
+ return true;
33
+ }
34
+ if (typeof value === "object") {
35
+ return value.kind === "engine-ref" ? value.isNumeric : true;
36
+ }
37
+ return false;
38
+ }
39
+ /**
40
+ * Numeric namespace constants with identical IEEE 754 double values in the build environment and LuaJIT runtime.
41
+ * Covers both TS 'Math' and Lua 'math' namespaces. Function calls are intentionally not supported because
42
+ * libm implementations may differ between build machine and game runtime.
43
+ */
44
+ exports.FOLDABLE_NAMESPACE_CONSTANTS = {
45
+ Math: {
46
+ E: Math.E,
47
+ LN10: Math.LN10,
48
+ LN2: Math.LN2,
49
+ LOG10E: Math.LOG10E,
50
+ LOG2E: Math.LOG2E,
51
+ PI: Math.PI,
52
+ SQRT1_2: Math.SQRT1_2,
53
+ SQRT2: Math.SQRT2,
54
+ },
55
+ math: {
56
+ pi: Math.PI,
57
+ },
58
+ };
@@ -0,0 +1,30 @@
1
+ export declare const createUnsupportedDeclarationError: ((node: import("typescript").Node, ...args: any[]) => import("typescript").Diagnostic) & {
2
+ code: number;
3
+ };
4
+ export declare const createVirtualValueReferenceError: ((node: import("typescript").Node, name: string) => import("typescript").Diagnostic) & {
5
+ code: number;
6
+ };
7
+ export declare const createImpureVirtualModuleError: ((node: import("typescript").Node, ...args: any[]) => import("typescript").Diagnostic) & {
8
+ code: number;
9
+ };
10
+ export declare const createNotModuleLevelError: ((node: import("typescript").Node, ...args: any[]) => import("typescript").Diagnostic) & {
11
+ code: number;
12
+ };
13
+ export declare const createNotConstError: ((node: import("typescript").Node, ...args: any[]) => import("typescript").Diagnostic) & {
14
+ code: number;
15
+ };
16
+ export declare const createNotAsConstObjectError: ((node: import("typescript").Node, name: string) => import("typescript").Diagnostic) & {
17
+ code: number;
18
+ };
19
+ export declare const createNotLiteralConstantError: ((node: import("typescript").Node, name: string) => import("typescript").Diagnostic) & {
20
+ code: number;
21
+ };
22
+ export declare const createNotLiteralPropertyError: ((node: import("typescript").Node, object: string, property: string) => import("typescript").Diagnostic) & {
23
+ code: number;
24
+ };
25
+ export declare const createForeignPropertyError: ((node: import("typescript").Node, object: string, property: string) => import("typescript").Diagnostic) & {
26
+ code: number;
27
+ };
28
+ export declare const createNotConstantEnumMemberError: ((node: import("typescript").Node, name: string) => import("typescript").Diagnostic) & {
29
+ code: number;
30
+ };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNotConstantEnumMemberError = exports.createForeignPropertyError = exports.createNotLiteralPropertyError = exports.createNotLiteralConstantError = exports.createNotAsConstObjectError = exports.createNotConstError = exports.createNotModuleLevelError = exports.createImpureVirtualModuleError = exports.createVirtualValueReferenceError = exports.createUnsupportedDeclarationError = void 0;
4
+ const diagnostics_1 = require("../../utils/diagnostics");
5
+ const constants_1 = require("./constants");
6
+ exports.createUnsupportedDeclarationError = (0, diagnostics_1.createErrorDiagnosticFactory)(`'@${constants_1.INLINE_TAG}' and '@${constants_1.VIRTUAL_TAG}' are supported only for enums and module-level 'const' declarations.`);
7
+ exports.createVirtualValueReferenceError = (0, diagnostics_1.createErrorDiagnosticFactory)((name) => `'@${constants_1.VIRTUAL_TAG}' declaration '${name}' is referenced as a value and cannot be erased, ` +
8
+ `demote it to '@${constants_1.INLINE_TAG}' or make the reference computable on build time.`);
9
+ exports.createImpureVirtualModuleError = (0, diagnostics_1.createErrorDiagnosticFactory)(`Modules with '@${constants_1.VIRTUAL_TAG}' declarations may contain only type-only imports, ` +
10
+ `'@${constants_1.INLINE_TAG}'/'@${constants_1.VIRTUAL_TAG}' constants, constant enums, type aliases and interfaces.`);
11
+ exports.createNotModuleLevelError = (0, diagnostics_1.createErrorDiagnosticFactory)(`'@${constants_1.INLINE_TAG}' declarations must be module-level statements.`);
12
+ exports.createNotConstError = (0, diagnostics_1.createErrorDiagnosticFactory)(`'@${constants_1.INLINE_TAG}' declarations must use 'const' keyword.`);
13
+ exports.createNotAsConstObjectError = (0, diagnostics_1.createErrorDiagnosticFactory)((name) => `'@${constants_1.INLINE_TAG}' object '${name}' must use 'as const' assertion.`);
14
+ exports.createNotLiteralConstantError = (0, diagnostics_1.createErrorDiagnosticFactory)((name) => `'@${constants_1.INLINE_TAG}' constant '${name}' must have a compile-time constant value, ` +
15
+ "use a literal or an expression computable on build time.");
16
+ exports.createNotLiteralPropertyError = (0, diagnostics_1.createErrorDiagnosticFactory)((object, property) => `'@${constants_1.INLINE_TAG}' object '${object}' property '${property}' must have a compile-time constant value, ` +
17
+ "use a literal or an expression computable on build time.");
18
+ exports.createForeignPropertyError = (0, diagnostics_1.createErrorDiagnosticFactory)((object, property) => `'@${constants_1.INLINE_TAG}' object '${object}' property '${property}' is declared outside of '@${constants_1.INLINE_TAG}' statements, ` +
19
+ `mark the source declaration with '@${constants_1.INLINE_TAG}' too.`);
20
+ exports.createNotConstantEnumMemberError = (0, diagnostics_1.createErrorDiagnosticFactory)((name) => `'@${constants_1.INLINE_TAG}' enum member '${name}' must have a compile-time constant value.`);