xray16 1.0.0

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.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -0
  3. package/package.json +38 -0
  4. package/plugins/built_at_info.ts +18 -0
  5. package/plugins/from_cast_utils.ts +34 -0
  6. package/plugins/global_declarations_transform.ts +24 -0
  7. package/plugins/inject_filename.ts +22 -0
  8. package/plugins/strip_lua_logger.ts +73 -0
  9. package/plugins/transform_luabind_class/plugin.ts +51 -0
  10. package/plugins/transform_luabind_class/transformation/class_declaration.ts +226 -0
  11. package/plugins/transform_luabind_class/transformation/constants.ts +4 -0
  12. package/plugins/transform_luabind_class/transformation/decorators.ts +16 -0
  13. package/plugins/transform_luabind_class/transformation/errors.ts +31 -0
  14. package/plugins/transform_luabind_class/transformation/index.ts +5 -0
  15. package/plugins/transform_luabind_class/transformation/members/accessors.ts +48 -0
  16. package/plugins/transform_luabind_class/transformation/members/constructor.ts +107 -0
  17. package/plugins/transform_luabind_class/transformation/members/fields.ts +53 -0
  18. package/plugins/transform_luabind_class/transformation/members/method.ts +70 -0
  19. package/plugins/transform_luabind_class/transformation/new.ts +14 -0
  20. package/plugins/transform_luabind_class/transformation/setup.ts +128 -0
  21. package/plugins/transform_luabind_class/transformation/super.ts +92 -0
  22. package/plugins/transform_luabind_class/transformation/utils.ts +90 -0
  23. package/plugins/utils/diagnostics.ts +24 -0
  24. package/src/index.d.ts +63 -0
  25. package/src/xr_constant.d.ts +976 -0
  26. package/src/xr_core.d.ts +347 -0
  27. package/src/xr_global.d.ts +613 -0
  28. package/src/xr_lib/xr_fs.d.ts +333 -0
  29. package/src/xr_lib/xr_math.d.ts +165 -0
  30. package/src/xr_lib/xr_utils.d.ts +407 -0
  31. package/src/xr_luabind.d.ts +34 -0
  32. package/src/xr_map/xr_map.d.ts +42 -0
  33. package/src/xr_object/xr_action.d.ts +482 -0
  34. package/src/xr_object/xr_alife.d.ts +206 -0
  35. package/src/xr_object/xr_anomaly.d.ts +50 -0
  36. package/src/xr_object/xr_artefact.d.ts +98 -0
  37. package/src/xr_object/xr_client_object.d.ts +1255 -0
  38. package/src/xr_object/xr_creature.d.ts +157 -0
  39. package/src/xr_object/xr_dialog.d.ts +34 -0
  40. package/src/xr_object/xr_item.d.ts +239 -0
  41. package/src/xr_object/xr_level.d.ts +166 -0
  42. package/src/xr_object/xr_physic.d.ts +119 -0
  43. package/src/xr_object/xr_quest.d.ts +47 -0
  44. package/src/xr_object/xr_server_object.d.ts +686 -0
  45. package/src/xr_online/xr_multiplayer.d.ts +299 -0
  46. package/src/xr_sound/xr_sound.d.ts +153 -0
  47. package/src/xr_type/xr_enums.d.ts +17 -0
  48. package/src/xr_type/xr_type.d.ts +70 -0
  49. package/src/xr_ui/README.md +277 -0
  50. package/src/xr_ui/demo/CServerList.png +0 -0
  51. package/src/xr_ui/demo/CUI3tButton.png +0 -0
  52. package/src/xr_ui/demo/CUICheckButton.png +0 -0
  53. package/src/xr_ui/demo/CUIComboBox.png +0 -0
  54. package/src/xr_ui/demo/CUICustomEdit.png +0 -0
  55. package/src/xr_ui/demo/CUIStatic.png +0 -0
  56. package/src/xr_ui/demo/CUITrackBar.png +0 -0
  57. package/src/xr_ui/xr_ui_core.d.ts +185 -0
  58. package/src/xr_ui/xr_ui_interface.d.ts +666 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 stalker-xrts
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # [📡 XRay-16 engine typescript definitions](https://github.com/xray-forge/xray-16-types)
2
+
3
+ [![Node.js CI](https://github.com/xray-forge/xray-16-types/actions/workflows/build_and_test.yml/badge.svg)](https://github.com/xray-forge/xray-16-types/actions/workflows/build_and_test.yml)
4
+
5
+ X-Ray16 engine bindings documentation and types. <br/>
6
+ For usage with [TypeScriptToLua](https://typescripttolua.github.io/docs/getting-started).
7
+
8
+ <p>
9
+ Module contains xray engine globals typedefs for typescript. <br/>
10
+ By default x-ray export many bindings that can be used from lua scripts, but without game API documentation.
11
+
12
+ To check more details / correct typing you always can reference X-Ray source code.
13
+
14
+ </p>
15
+
16
+ ## 🗻 Docs
17
+
18
+ Types documentation can be checked [here](https://xray-forge.github.io/xray-16-types/modules.html).
19
+
20
+ ## 🧱 Usage
21
+
22
+ Types are used with [xrf template](https://github.com/xray-forge/stalker-xrf-template) and can be referenced as an example.
23
+
24
+ ## 🎮 Updating types
25
+
26
+ For easier navigation over codebase and typing following rules are applied:
27
+
28
+ - Type declaration should have \@source docblock with matching c++ counterpart signature
29
+ - Variable and class namings follow c++ conventions for easier binding and matching engine codebase
30
+ - XRay types should be prefixed with IXR or TXR if they do not have runtime representation
31
+
32
+ ## 📦Extending C++ classes and overriding virtual methods
33
+
34
+ ### Lua
35
+
36
+ <p>
37
+ C++ classes can be extended in Lua code with 'class' keyword.
38
+ Class declaration registers table as userdata and adds constructor/destructor metamethods. <br/>
39
+ </p>
40
+
41
+ ### Typescript
42
+
43
+ <p>
44
+ In TS codebase '@LuabindClass' decorator can be used to modify transformation and enable virtual calls. <br/>
45
+ Separate transformer is needed to build luabind classes instead of table-based classes.
46
+ </p>
47
+
48
+ ## 🧱 Getting up-to-date LUA bindings
49
+
50
+ - Run game engine with `-dump_bindings` flag
51
+ - Check userdata folder _(where game saves are stored)_ `scriptbindings_*.txt` files
52
+
53
+ ## 🧲 References
54
+
55
+ - X-Ray C++ source code
56
+ - LuaBind sources and docs
57
+ - LuaJit sources and docs
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "xray16",
3
+ "version": "1.0.0",
4
+ "author": "Neloreck",
5
+ "repository": "https://github.com/stalker-xrts/xray-16-types",
6
+ "private": false,
7
+ "main": "src/index.d.ts",
8
+ "types": "src/index.d.ts",
9
+ "scripts": {
10
+ "typecheck": "tsc --noEmit",
11
+ "typedoc": "typedoc",
12
+ "format": "prettier --write \"**/*.(js|ts|tsx|md)\" && eslint . --ext .ts,.tsx,.js --fix",
13
+ "lint": "eslint . --ext .ts,.tsx,.js"
14
+ },
15
+ "peerDependencies": {
16
+ "typescript-to-lua": "^1.16.3"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "20.3.1",
20
+ "@typescript-eslint/eslint-plugin": "^5.54.0",
21
+ "@typescript-eslint/parser": "^5.54.0",
22
+ "@typescript-to-lua/language-extensions": "1.0.0",
23
+ "eslint": "^8.35.0",
24
+ "eslint-config-standard-with-typescript": "^34.0.0",
25
+ "eslint-plugin-import": "^2.27.5",
26
+ "eslint-plugin-jest": "^27.2.1",
27
+ "eslint-plugin-sort-keys-fix": "^1.1.2",
28
+ "prettier": "^3.0.1",
29
+ "typedoc": "^0.24.8",
30
+ "typescript": "^5.1.6"
31
+ },
32
+ "files": [
33
+ "plugins/**/*",
34
+ "src/**/*",
35
+ "README.md",
36
+ "LICENSE"
37
+ ]
38
+ }
@@ -0,0 +1,18 @@
1
+ import { Program } from "typescript";
2
+ import { Plugin, CompilerOptions, EmitFile, EmitHost } from "typescript-to-lua";
3
+
4
+ const comment: string = `-- Generated by xrf util at: ${new Date().toString()}\n\n`;
5
+
6
+ const plugin: Plugin = {
7
+ beforeEmit(program: Program, options: CompilerOptions, emitHost: EmitHost, result: Array<EmitFile>) {
8
+ void program;
9
+ void options;
10
+ void emitHost;
11
+
12
+ for (const file of result) {
13
+ file.code = comment + file.code;
14
+ }
15
+ },
16
+ };
17
+
18
+ export default plugin;
@@ -0,0 +1,34 @@
1
+ import { isIdentifier, SyntaxKind } from "typescript";
2
+ import { Plugin } from "typescript-to-lua";
3
+ import { createErrorDiagnosticFactory } from "./utils/diagnostics";
4
+
5
+ const FROM_CAST_METHODS: Array<string> = ["$fromObject", "$fromArray", "$fromLuaArray", "$fromLuaTable"];
6
+
7
+ /**
8
+ * Push generic error to notify about usage issue.
9
+ */
10
+ const createInvalidFunctionCallError = createErrorDiagnosticFactory((name?: string) => {
11
+ return `Invalid transformer call, expected function to have exactly 1 argument.`;
12
+ });
13
+
14
+ /**
15
+ * Plugin for transformation of casting methods.
16
+ * Simplifies TS/Lua testing and interoperation.
17
+ */
18
+ const plugin: Plugin = {
19
+ visitors: {
20
+ [SyntaxKind.CallExpression]: (node, context) => {
21
+ if (isIdentifier(node.expression) && FROM_CAST_METHODS.includes(node.expression.text)) {
22
+ if (node.arguments.length !== 1) {
23
+ context.diagnostics.push(createInvalidFunctionCallError(node));
24
+ }
25
+
26
+ return context.transformExpression(node.arguments[0]);
27
+ }
28
+
29
+ return context.superTransformExpression(node);
30
+ },
31
+ },
32
+ };
33
+
34
+ export default plugin;
@@ -0,0 +1,24 @@
1
+ import { SyntaxKind } from "typescript";
2
+ import { Plugin } from "typescript-to-lua";
3
+
4
+ const XRF_GLOBALS: Array<string> = ["xray16"];
5
+
6
+ /**
7
+ * Plugin that removes imports from 'global' libraries like engine typedefs.
8
+ */
9
+ const plugin: Plugin = {
10
+ visitors: {
11
+ [SyntaxKind.ImportDeclaration]: (node, context) => {
12
+ const module: string = node.moduleSpecifier.getText().slice(1, -1);
13
+ const shouldNotBeTransformed: boolean = XRF_GLOBALS.includes(module);
14
+
15
+ if (shouldNotBeTransformed) {
16
+ return undefined;
17
+ }
18
+
19
+ return context.superTransformStatements(node);
20
+ },
21
+ },
22
+ };
23
+
24
+ export default plugin;
@@ -0,0 +1,22 @@
1
+ import * as path from "path";
2
+ import { SyntaxKind } from "typescript";
3
+ import { createStringLiteral, Plugin } from "typescript-to-lua";
4
+
5
+ const FILENAME_IDENTIFIER: string = "$filename";
6
+
7
+ /**
8
+ * Plugin that injects FILE_NAME in compile-time.
9
+ */
10
+ const plugin: Plugin = {
11
+ visitors: {
12
+ [SyntaxKind.Identifier]: (node, context) => {
13
+ if (node.text === FILENAME_IDENTIFIER) {
14
+ return createStringLiteral(path.parse(context.sourceFile.fileName).name);
15
+ }
16
+
17
+ return context.superTransformExpression(node);
18
+ },
19
+ },
20
+ };
21
+
22
+ export default plugin;
@@ -0,0 +1,73 @@
1
+ import {
2
+ CallExpression,
3
+ factory,
4
+ Identifier,
5
+ PropertyAccessExpression,
6
+ SyntaxKind,
7
+ Type,
8
+ TypeChecker,
9
+ VariableDeclaration,
10
+ VariableDeclarationList,
11
+ } from "typescript";
12
+ import { Plugin } from "typescript-to-lua";
13
+
14
+ const LUA_LOGGER_STRIP_TARGET: string = "LuaLogger";
15
+ const IS_LUA_LOGGER_DISABLED: boolean = process.argv.includes("--no-lua-logs");
16
+
17
+ /**
18
+ * Plugin that removes all LuaLogger instance creations and calls when possible.
19
+ */
20
+ const plugin: Plugin = {
21
+ visitors: {
22
+ [SyntaxKind.VariableStatement]: (statement, context) => {
23
+ if (IS_LUA_LOGGER_DISABLED) {
24
+ let elementsCount: number = 0;
25
+ const list = statement.declarationList as VariableDeclarationList;
26
+ const nodes: Array<VariableDeclaration> = [];
27
+
28
+ list.forEachChild((it: VariableDeclaration) => {
29
+ const checker: TypeChecker = context.program.getTypeChecker();
30
+ const typeSymbol: Type = checker.getTypeAtLocation(it);
31
+
32
+ if (typeSymbol.symbol?.name === LUA_LOGGER_STRIP_TARGET) {
33
+ // nothing
34
+ } else {
35
+ nodes.push(it);
36
+ }
37
+
38
+ elementsCount += 1;
39
+ });
40
+
41
+ if (nodes.length === 0) {
42
+ return undefined;
43
+ } else if (nodes.length !== elementsCount) {
44
+ return context.superTransformStatements(
45
+ factory.createVariableStatement(statement.modifiers, factory.updateVariableDeclarationList(list, nodes))
46
+ );
47
+ }
48
+ }
49
+
50
+ return context.superTransformStatements(statement);
51
+ },
52
+ [SyntaxKind.ExpressionStatement]: (statement, context) => {
53
+ if (IS_LUA_LOGGER_DISABLED && statement.expression?.kind === SyntaxKind.CallExpression) {
54
+ const expression: CallExpression = statement.expression as CallExpression;
55
+ const propertyAccess: PropertyAccessExpression = expression.expression as PropertyAccessExpression;
56
+
57
+ if (propertyAccess.expression?.kind === SyntaxKind.Identifier) {
58
+ const checker: TypeChecker = context.program.getTypeChecker();
59
+ const identifier: Identifier = propertyAccess.expression as Identifier;
60
+ const typeSymbol: Type = checker.getTypeAtLocation(identifier);
61
+
62
+ if (typeSymbol.symbol?.name === LUA_LOGGER_STRIP_TARGET) {
63
+ return undefined;
64
+ }
65
+ }
66
+ }
67
+
68
+ return context.superTransformStatements(statement);
69
+ },
70
+ },
71
+ };
72
+
73
+ export default plugin;
@@ -0,0 +1,51 @@
1
+ import {
2
+ transformLuabindClassDeclaration,
3
+ transformNewCallExpression,
4
+ isLuabindClassSuperCall,
5
+ transformClassSuperMethodExpression,
6
+ transformLuabindConstructorSuperCall,
7
+ ITransformationContext,
8
+ isLuabindClassType,
9
+ isLuabindDecoratedClass,
10
+ isLuabindClassSuperMethodCall,
11
+ } from "./transformation";
12
+ import { CallExpression, NewExpression, SuperExpression, SyntaxKind } from "typescript";
13
+ import { Plugin } from "typescript-to-lua";
14
+
15
+ /**
16
+ * Plugin that transform TS classes marked with decorator to luabind class declaration.
17
+ */
18
+ const plugin: Plugin = {
19
+ visitors: {
20
+ [SyntaxKind.CallExpression]: (expression: CallExpression, context: ITransformationContext) => {
21
+ if (isLuabindClassSuperCall(expression, context)) {
22
+ return transformLuabindConstructorSuperCall(expression, context);
23
+ }
24
+
25
+ return context.superTransformExpression(expression);
26
+ },
27
+ [SyntaxKind.ClassDeclaration]: (declaration, context: ITransformationContext) => {
28
+ if (isLuabindDecoratedClass(declaration)) {
29
+ return transformLuabindClassDeclaration(declaration, context);
30
+ }
31
+
32
+ return context.superTransformStatements(declaration);
33
+ },
34
+ [SyntaxKind.NewExpression]: (expression: NewExpression, context: ITransformationContext) => {
35
+ if (isLuabindClassType(expression, context)) {
36
+ return transformNewCallExpression(expression, context);
37
+ }
38
+
39
+ return context.superTransformExpression(expression);
40
+ },
41
+ [SyntaxKind.SuperKeyword]: (expression: SuperExpression, context: ITransformationContext) => {
42
+ if (isLuabindClassSuperMethodCall(expression, context)) {
43
+ return transformClassSuperMethodExpression(expression, context);
44
+ }
45
+
46
+ return context.superTransformExpression(expression);
47
+ },
48
+ },
49
+ };
50
+
51
+ export default plugin;
@@ -0,0 +1,226 @@
1
+ import { LUABIND_CONSTRUCTOR_METHOD } from "./constants";
2
+ import { checkLuabindClassDecoratorExpression } from "./decorators";
3
+ import { unsupportedStaticMethod } from "./errors";
4
+ import { transformAccessorDeclarations } from "./members/accessors";
5
+ import { createConstructorName, transformConstructorDeclaration } from "./members/constructor";
6
+ import { verifyPropertyDecoratingExpression, transformClassInstanceFields } from "./members/fields";
7
+ import { verifyMethodDecoratingExpression, transformMethodDeclaration } from "./members/method";
8
+ import { createClassSetup } from "./setup";
9
+ import { getExtendedNode, getExtendedType, isStaticNode, markTypeAsLuabind } from "./utils";
10
+ import {
11
+ canHaveDecorators,
12
+ ClassLikeDeclaration,
13
+ ConstructorDeclaration,
14
+ ExpressionWithTypeArguments,
15
+ factory,
16
+ getDecorators,
17
+ isAccessor,
18
+ isConstructorDeclaration,
19
+ isMethodDeclaration,
20
+ isPropertyDeclaration,
21
+ } from "typescript";
22
+ import * as tstl from "typescript-to-lua";
23
+ import { LuaTarget, TransformationContext } from "typescript-to-lua";
24
+ import {
25
+ createDefaultExportExpression,
26
+ createExportedIdentifier,
27
+ hasDefaultExportModifier,
28
+ hasExportModifier,
29
+ } from "typescript-to-lua/dist/transformation/utils/export";
30
+ import { createSelfIdentifier } from "typescript-to-lua/dist/transformation/utils/lua-ast";
31
+ import { transformInPrecedingStatementScope } from "typescript-to-lua/dist/transformation/utils/preceding-statements";
32
+ import { createSafeName, isUnsafeName } from "typescript-to-lua/dist/transformation/utils/safe-names";
33
+ import { transformIdentifier } from "typescript-to-lua/dist/transformation/visitors/identifier";
34
+
35
+ export interface ITransformationContext extends TransformationContext {
36
+ classSuperInfos: Array<ClassSuperInfo>;
37
+ }
38
+
39
+ export const transformLuabindClassDeclaration = (declaration, context: TransformationContext) => {
40
+ // If declaration is a default export, transform to export variable assignment instead
41
+ if (hasDefaultExportModifier(declaration)) {
42
+ // Class declaration including assignment to ____exports.default are in preceding statements
43
+ const { precedingStatements } = transformInPrecedingStatementScope(context, () => {
44
+ transformClassAsExpression(declaration, context as ITransformationContext);
45
+ return [];
46
+ });
47
+ return precedingStatements;
48
+ }
49
+
50
+ const { statements } = transformClassLikeDeclaration(declaration, context as ITransformationContext);
51
+ return statements;
52
+ };
53
+
54
+ export function transformClassAsExpression(
55
+ expression: ClassLikeDeclaration,
56
+ context: ITransformationContext
57
+ ): tstl.Expression {
58
+ const { statements, name } = transformClassLikeDeclaration(expression, context);
59
+ context.addPrecedingStatements(statements);
60
+ return name;
61
+ }
62
+
63
+ /** @internal */
64
+ export interface ClassSuperInfo {
65
+ className: tstl.Identifier;
66
+ classDeclaration: ClassLikeDeclaration;
67
+ extendedTypeNode?: ExpressionWithTypeArguments;
68
+ }
69
+
70
+ export function transformClassLikeDeclaration(
71
+ classDeclaration: ClassLikeDeclaration,
72
+ context: ITransformationContext,
73
+ nameOverride?: tstl.Identifier
74
+ ): { statements: tstl.Statement[]; name: tstl.Identifier } {
75
+ let className: tstl.Identifier;
76
+
77
+ if (nameOverride !== undefined) {
78
+ className = nameOverride;
79
+ } else if (classDeclaration.name !== undefined) {
80
+ className = transformIdentifier(context, classDeclaration.name);
81
+ } else {
82
+ className = tstl.createIdentifier(context.createTempName("class"), classDeclaration);
83
+ }
84
+
85
+ markTypeAsLuabind(classDeclaration, context);
86
+
87
+ // Get type that is extended
88
+ const extendedTypeNode = getExtendedNode(classDeclaration);
89
+ const extendedType = getExtendedType(context, classDeclaration);
90
+
91
+ context.classSuperInfos.push({ className, classDeclaration: classDeclaration, extendedTypeNode });
92
+
93
+ // Get all properties with value
94
+ const properties = classDeclaration.members.filter(isPropertyDeclaration).filter((member) => member.initializer);
95
+
96
+ // Divide properties into static and non-static
97
+ const instanceFields = properties.filter((prop) => !isStaticNode(prop));
98
+
99
+ const result: tstl.Statement[] = [];
100
+
101
+ let localClassName: tstl.Identifier;
102
+ if (isUnsafeName(className.text, context.options)) {
103
+ localClassName = tstl.createIdentifier(
104
+ createSafeName(className.text),
105
+ undefined,
106
+ className.symbolId,
107
+ className.text
108
+ );
109
+ tstl.setNodePosition(localClassName, className);
110
+ } else {
111
+ localClassName = className;
112
+ }
113
+
114
+ result.push(...createClassSetup(context, classDeclaration, className, localClassName));
115
+
116
+ // Find first constructor with body
117
+ const constructor = classDeclaration.members.find(
118
+ (n): n is ConstructorDeclaration => isConstructorDeclaration(n) && n.body !== undefined
119
+ );
120
+
121
+ if (constructor) {
122
+ // Add constructor plus initialization of instance fields
123
+ const constructorResult = transformConstructorDeclaration(
124
+ context,
125
+ constructor,
126
+ localClassName,
127
+ instanceFields,
128
+ classDeclaration
129
+ );
130
+
131
+ if (constructorResult) result.push(constructorResult);
132
+ } else if (!extendedType) {
133
+ // Generate a constructor if none was defined in a base class
134
+ const constructorResult = transformConstructorDeclaration(
135
+ context,
136
+ factory.createConstructorDeclaration([], [], factory.createBlock([], true)),
137
+ localClassName,
138
+ instanceFields,
139
+ classDeclaration
140
+ );
141
+
142
+ if (constructorResult) result.push(constructorResult);
143
+ } else {
144
+ // Generate a constructor if none was defined in a class with instance fields that need initialization
145
+ // localClassName.__init = function(self, ...)
146
+ // baseClassName.__init(self, ...) // or unpack(arg) for Lua 5.0
147
+ // ...
148
+ // Also luabind always needs definition of call expression to use table as class.
149
+ const constructorBody = transformClassInstanceFields(context, instanceFields);
150
+ const argsExpression =
151
+ context.luaTarget === LuaTarget.Lua50
152
+ ? tstl.createCallExpression(tstl.createIdentifier("unpack"), [tstl.createArgLiteral()])
153
+ : tstl.createDotsLiteral();
154
+ const superCall = tstl.createExpressionStatement(
155
+ tstl.createCallExpression(
156
+ tstl.createTableIndexExpression(
157
+ context.transformExpression(factory.createSuper()),
158
+ tstl.createStringLiteral(LUABIND_CONSTRUCTOR_METHOD)
159
+ ),
160
+ [createSelfIdentifier(), argsExpression]
161
+ )
162
+ );
163
+ constructorBody.unshift(superCall);
164
+ const constructorFunction = tstl.createFunctionExpression(
165
+ tstl.createBlock(constructorBody),
166
+ [createSelfIdentifier()],
167
+ tstl.createDotsLiteral(),
168
+ tstl.NodeFlags.Declaration
169
+ );
170
+ result.push(
171
+ tstl.createAssignmentStatement(createConstructorName(localClassName), constructorFunction, classDeclaration)
172
+ );
173
+ }
174
+
175
+ // Transform accessors
176
+ for (const member of classDeclaration.members) {
177
+ if (!isAccessor(member)) continue;
178
+ const accessors = context.resolver.getAllAccessorDeclarations(member);
179
+ if (accessors.firstAccessor !== member) continue;
180
+
181
+ const accessorsResult = transformAccessorDeclarations(context, accessors, localClassName);
182
+ if (accessorsResult) {
183
+ result.push(accessorsResult);
184
+ }
185
+ }
186
+
187
+ const decorationStatements: tstl.Statement[] = [];
188
+
189
+ for (const member of classDeclaration.members) {
190
+ if (isAccessor(member)) {
191
+ verifyPropertyDecoratingExpression(context, member);
192
+ } else if (isMethodDeclaration(member)) {
193
+ const statement = transformMethodDeclaration(context, member, localClassName);
194
+ if (statement) result.push(statement);
195
+ if (member.body) {
196
+ verifyMethodDecoratingExpression(context, member);
197
+ }
198
+ } else if (isPropertyDeclaration(member)) {
199
+ if (isStaticNode(member)) {
200
+ context.diagnostics.push(unsupportedStaticMethod(member));
201
+ }
202
+
203
+ verifyPropertyDecoratingExpression(context, member);
204
+ }
205
+ }
206
+
207
+ result.push(...decorationStatements);
208
+
209
+ // Decorate the class
210
+ if (canHaveDecorators(classDeclaration) && getDecorators(classDeclaration)) {
211
+ getDecorators(classDeclaration)?.forEach((d) => checkLuabindClassDecoratorExpression(context, d));
212
+
213
+ if (hasExportModifier(classDeclaration)) {
214
+ const exportExpression = hasDefaultExportModifier(classDeclaration)
215
+ ? createDefaultExportExpression(classDeclaration)
216
+ : createExportedIdentifier(context, className);
217
+
218
+ const classAssignment = tstl.createAssignmentStatement(exportExpression, localClassName);
219
+ result.push(classAssignment);
220
+ }
221
+ }
222
+
223
+ context.classSuperInfos.pop();
224
+
225
+ return { statements: result, name: className };
226
+ }
@@ -0,0 +1,4 @@
1
+ export const LUABIND_NAME_FIELD: string = "__name";
2
+ export const LUABIND_DECORATOR: string = "LuabindClass";
3
+ export const LUABIND_CONSTRUCTOR_METHOD: string = "__init";
4
+ export const LUABIND_SYMBOL: symbol = Symbol("IS_LUABIND_CLASS");
@@ -0,0 +1,16 @@
1
+ import { unsupportedClassDecorator } from "./errors";
2
+ import { LUABIND_DECORATOR } from "./constants";
3
+ import { CallExpression, Decorator, Identifier } from "typescript";
4
+ import { TransformationContext } from "typescript-to-lua";
5
+
6
+ /**
7
+ * Transform decorator call expressions for luabind class.
8
+ */
9
+ export function checkLuabindClassDecoratorExpression(context: TransformationContext, decorator: Decorator) {
10
+ const expression = decorator.expression;
11
+
12
+ // Do not transform luabind decorator.
13
+ if (((expression as CallExpression).expression as Identifier).text !== LUABIND_DECORATOR) {
14
+ context.diagnostics.push(unsupportedClassDecorator(expression));
15
+ }
16
+ }
@@ -0,0 +1,31 @@
1
+ import { createErrorDiagnosticFactory } from "../../utils/diagnostics";
2
+
3
+ export const unsupportedStaticMethod = createErrorDiagnosticFactory((name?: string) => {
4
+ const nameReference = name ? ` '${name}'` : "";
5
+ return `Unable transform static properties for luabind classes${nameReference}.`;
6
+ });
7
+
8
+ export const unsupportedClassDecorator = createErrorDiagnosticFactory((name?: string) => {
9
+ const nameReference = name ? ` '${name}'` : "";
10
+ return `Unable transform class decorators for luabind classes${nameReference}.`;
11
+ });
12
+
13
+ export const unsupportedPropertyDecorator = createErrorDiagnosticFactory((name?: string) => {
14
+ const nameReference = name ? ` '${name}'` : "";
15
+ return `Unable transform property decorator for luabind classes${nameReference}.`;
16
+ });
17
+
18
+ export const unsupportedParameterDecorator = createErrorDiagnosticFactory((name?: string) => {
19
+ const nameReference = name ? ` '${name}'` : "";
20
+ return `Unable transform parameter decorator for luabind classes${nameReference}.`;
21
+ });
22
+
23
+ export const unsupportedMethodDecorator = createErrorDiagnosticFactory((name?: string) => {
24
+ const nameReference = name ? ` '${name}'` : "";
25
+ return `Unable transform method decorator for luabind classes${nameReference}.`;
26
+ });
27
+
28
+ export const unsupportedStaticAccessor = createErrorDiagnosticFactory((name?: string) => {
29
+ const nameReference = name ? ` '${name}'` : "";
30
+ return `Unable transform static accessors for luabind classes${nameReference}.`;
31
+ });
@@ -0,0 +1,5 @@
1
+ export * from "./constants";
2
+ export * from "./utils";
3
+ export * from "./class_declaration";
4
+ export * from "./super";
5
+ export * from "./new";