xray16 1.0.0 → 1.0.3
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 +30 -1
- package/package.json +7 -4
- package/plugins/built_at_info.js +14 -0
- package/plugins/from_cast_utils.js +29 -0
- package/plugins/global_declarations_transform.js +20 -0
- package/plugins/inject_filename.js +20 -0
- package/plugins/plugins/built_at_info.js +12 -0
- package/plugins/plugins/from_cast_utils.js +27 -0
- package/plugins/plugins/global_declarations_transform.js +18 -0
- package/plugins/plugins/inject_filename.js +18 -0
- package/plugins/plugins/strip_lua_logger.js +51 -0
- package/plugins/plugins/transform_luabind_class/plugin.js +34 -0
- package/plugins/plugins/transform_luabind_class/transformation/class_declaration.js +141 -0
- package/plugins/plugins/transform_luabind_class/transformation/constants.js +4 -0
- package/plugins/plugins/transform_luabind_class/transformation/decorators.js +12 -0
- package/plugins/plugins/transform_luabind_class/transformation/errors.js +25 -0
- package/plugins/{transform_luabind_class/transformation/index.ts → plugins/transform_luabind_class/transformation/index.js} +5 -5
- package/plugins/plugins/transform_luabind_class/transformation/members/accessors.js +35 -0
- package/plugins/plugins/transform_luabind_class/transformation/members/constructor.js +56 -0
- package/plugins/plugins/transform_luabind_class/transformation/members/fields.js +36 -0
- package/plugins/plugins/transform_luabind_class/transformation/members/method.js +49 -0
- package/plugins/plugins/transform_luabind_class/transformation/new.js +8 -0
- package/plugins/plugins/transform_luabind_class/transformation/setup.js +76 -0
- package/plugins/plugins/transform_luabind_class/transformation/super.js +65 -0
- package/plugins/plugins/transform_luabind_class/transformation/utils.js +67 -0
- package/plugins/plugins/utils/diagnostics.js +17 -0
- package/plugins/strip_lua_logger.js +53 -0
- package/plugins/transform_luabind_class/plugin.js +36 -0
- package/plugins/transform_luabind_class/transformation/class_declaration.js +147 -0
- package/plugins/transform_luabind_class/transformation/constants.js +7 -0
- package/plugins/transform_luabind_class/transformation/decorators.js +16 -0
- package/plugins/transform_luabind_class/transformation/errors.js +28 -0
- package/plugins/transform_luabind_class/transformation/index.js +21 -0
- package/plugins/transform_luabind_class/transformation/members/accessors.js +39 -0
- package/plugins/transform_luabind_class/transformation/members/constructor.js +61 -0
- package/plugins/transform_luabind_class/transformation/members/fields.js +41 -0
- package/plugins/transform_luabind_class/transformation/members/method.js +56 -0
- package/plugins/transform_luabind_class/transformation/new.js +12 -0
- package/plugins/transform_luabind_class/transformation/setup.js +81 -0
- package/plugins/transform_luabind_class/transformation/super.js +72 -0
- package/plugins/transform_luabind_class/transformation/utils.js +77 -0
- package/plugins/utils/diagnostics.js +22 -0
- package/types/index.d.ts +28 -0
- package/{src → types}/xr_global.d.ts +35 -0
- package/{src → types}/xr_lib/xr_fs.d.ts +8 -1
- package/{src → types}/xr_object/xr_client_object.d.ts +31 -17
- package/{src → types}/xr_object/xr_server_object.d.ts +2 -0
- package/plugins/built_at_info.ts +0 -18
- package/plugins/from_cast_utils.ts +0 -34
- package/plugins/global_declarations_transform.ts +0 -24
- package/plugins/inject_filename.ts +0 -22
- package/plugins/strip_lua_logger.ts +0 -73
- package/plugins/transform_luabind_class/plugin.ts +0 -51
- package/plugins/transform_luabind_class/transformation/class_declaration.ts +0 -226
- package/plugins/transform_luabind_class/transformation/constants.ts +0 -4
- package/plugins/transform_luabind_class/transformation/decorators.ts +0 -16
- package/plugins/transform_luabind_class/transformation/errors.ts +0 -31
- package/plugins/transform_luabind_class/transformation/members/accessors.ts +0 -48
- package/plugins/transform_luabind_class/transformation/members/constructor.ts +0 -107
- package/plugins/transform_luabind_class/transformation/members/fields.ts +0 -53
- package/plugins/transform_luabind_class/transformation/members/method.ts +0 -70
- package/plugins/transform_luabind_class/transformation/new.ts +0 -14
- package/plugins/transform_luabind_class/transformation/setup.ts +0 -128
- package/plugins/transform_luabind_class/transformation/super.ts +0 -92
- package/plugins/transform_luabind_class/transformation/utils.ts +0 -90
- package/plugins/utils/diagnostics.ts +0 -24
- package/src/index.d.ts +0 -63
- /package/{src → types}/xr_constant.d.ts +0 -0
- /package/{src → types}/xr_core.d.ts +0 -0
- /package/{src → types}/xr_lib/xr_math.d.ts +0 -0
- /package/{src → types}/xr_lib/xr_utils.d.ts +0 -0
- /package/{src → types}/xr_luabind.d.ts +0 -0
- /package/{src → types}/xr_map/xr_map.d.ts +0 -0
- /package/{src → types}/xr_object/xr_action.d.ts +0 -0
- /package/{src → types}/xr_object/xr_alife.d.ts +0 -0
- /package/{src → types}/xr_object/xr_anomaly.d.ts +0 -0
- /package/{src → types}/xr_object/xr_artefact.d.ts +0 -0
- /package/{src → types}/xr_object/xr_creature.d.ts +0 -0
- /package/{src → types}/xr_object/xr_dialog.d.ts +0 -0
- /package/{src → types}/xr_object/xr_item.d.ts +0 -0
- /package/{src → types}/xr_object/xr_level.d.ts +0 -0
- /package/{src → types}/xr_object/xr_physic.d.ts +0 -0
- /package/{src → types}/xr_object/xr_quest.d.ts +0 -0
- /package/{src → types}/xr_online/xr_multiplayer.d.ts +0 -0
- /package/{src → types}/xr_sound/xr_sound.d.ts +0 -0
- /package/{src → types}/xr_type/xr_enums.d.ts +0 -0
- /package/{src → types}/xr_type/xr_type.d.ts +0 -0
- /package/{src → types}/xr_ui/README.md +0 -0
- /package/{src → types}/xr_ui/demo/CServerList.png +0 -0
- /package/{src → types}/xr_ui/demo/CUI3tButton.png +0 -0
- /package/{src → types}/xr_ui/demo/CUICheckButton.png +0 -0
- /package/{src → types}/xr_ui/demo/CUIComboBox.png +0 -0
- /package/{src → types}/xr_ui/demo/CUICustomEdit.png +0 -0
- /package/{src → types}/xr_ui/demo/CUIStatic.png +0 -0
- /package/{src → types}/xr_ui/demo/CUITrackBar.png +0 -0
- /package/{src → types}/xr_ui/xr_ui_core.d.ts +0 -0
- /package/{src → types}/xr_ui/xr_ui_interface.d.ts +0 -0
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ Class declaration registers table as userdata and adds constructor/destructor me
|
|
|
41
41
|
### Typescript
|
|
42
42
|
|
|
43
43
|
<p>
|
|
44
|
-
In TS codebase '
|
|
44
|
+
In TS codebase 'LuabindClass' decorator can be used to modify transformation and enable virtual calls. <br/>
|
|
45
45
|
Separate transformer is needed to build luabind classes instead of table-based classes.
|
|
46
46
|
</p>
|
|
47
47
|
|
|
@@ -55,3 +55,32 @@ Separate transformer is needed to build luabind classes instead of table-based c
|
|
|
55
55
|
- X-Ray C++ source code
|
|
56
56
|
- LuaBind sources and docs
|
|
57
57
|
- LuaJit sources and docs
|
|
58
|
+
|
|
59
|
+
## 🧱 Plugins
|
|
60
|
+
|
|
61
|
+
Package includes plugins for typescript-to-lua for easier work with xray16 typings. <br/>
|
|
62
|
+
Following ones are available:
|
|
63
|
+
|
|
64
|
+
- transform_luabind_class - transforms LuaBind decorated classes in a specific way
|
|
65
|
+
- built_at_info - adds build information in resulting files
|
|
66
|
+
- from_cast_utils - additional utils that should be removed in runtime
|
|
67
|
+
- global_declarations_transform - transforms xray16 imports and removes them from runtime
|
|
68
|
+
- inject_filename - adds $filename global variable to access current file name
|
|
69
|
+
- strip_lua_logger - removes lua logger from runtime
|
|
70
|
+
|
|
71
|
+
Plugins can be included in tsconfig file as following:
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"tstl": {
|
|
76
|
+
"luaPlugins": [
|
|
77
|
+
{ "name": "xray16/plugins/transform_luabind_class/plugin" },
|
|
78
|
+
{ "name": "xray16/plugins/global_declarations_transform" },
|
|
79
|
+
{ "name": "xray16/plugins/built_at_info" },
|
|
80
|
+
{ "name": "xray16/plugins/strip_lua_logger" },
|
|
81
|
+
{ "name": "xray16/plugins/inject_filename" },
|
|
82
|
+
{ "name": "xray16/plugins/from_cast_utils" }
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xray16",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"author": "Neloreck",
|
|
5
5
|
"repository": "https://github.com/stalker-xrts/xray-16-types",
|
|
6
6
|
"private": false,
|
|
7
|
-
"main": "
|
|
8
|
-
"types": "
|
|
7
|
+
"main": "types/index.d.ts",
|
|
8
|
+
"types": "types/index.d.ts",
|
|
9
9
|
"scripts": {
|
|
10
|
+
"prepublish": "npm run build:plugins",
|
|
11
|
+
"build:plugins": "tsc -p ./src/tsconfig.json",
|
|
12
|
+
"build:types": "typedoc",
|
|
10
13
|
"typecheck": "tsc --noEmit",
|
|
11
14
|
"typedoc": "typedoc",
|
|
12
15
|
"format": "prettier --write \"**/*.(js|ts|tsx|md)\" && eslint . --ext .ts,.tsx,.js --fix",
|
|
@@ -31,7 +34,7 @@
|
|
|
31
34
|
},
|
|
32
35
|
"files": [
|
|
33
36
|
"plugins/**/*",
|
|
34
|
-
"
|
|
37
|
+
"types/**/*",
|
|
35
38
|
"README.md",
|
|
36
39
|
"LICENSE"
|
|
37
40
|
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const comment = `-- Generated by xrf util at: ${new Date().toString()}\n\n`;
|
|
4
|
+
const plugin = {
|
|
5
|
+
beforeEmit(program, options, emitHost, result) {
|
|
6
|
+
void program;
|
|
7
|
+
void options;
|
|
8
|
+
void emitHost;
|
|
9
|
+
for (const file of result) {
|
|
10
|
+
file.code = comment + file.code;
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
exports.default = plugin;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const typescript_1 = require("typescript");
|
|
4
|
+
const diagnostics_1 = require("./utils/diagnostics");
|
|
5
|
+
const FROM_CAST_METHODS = ["$fromObject", "$fromArray", "$fromLuaArray", "$fromLuaTable"];
|
|
6
|
+
/**
|
|
7
|
+
* Push generic error to notify about usage issue.
|
|
8
|
+
*/
|
|
9
|
+
const createInvalidFunctionCallError = (0, diagnostics_1.createErrorDiagnosticFactory)((name) => {
|
|
10
|
+
return `Invalid transformer call, expected function to have exactly 1 argument.`;
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* Plugin for transformation of casting methods.
|
|
14
|
+
* Simplifies TS/Lua testing and interoperation.
|
|
15
|
+
*/
|
|
16
|
+
const plugin = {
|
|
17
|
+
visitors: {
|
|
18
|
+
[typescript_1.SyntaxKind.CallExpression]: (node, context) => {
|
|
19
|
+
if ((0, typescript_1.isIdentifier)(node.expression) && FROM_CAST_METHODS.includes(node.expression.text)) {
|
|
20
|
+
if (node.arguments.length !== 1) {
|
|
21
|
+
context.diagnostics.push(createInvalidFunctionCallError(node));
|
|
22
|
+
}
|
|
23
|
+
return context.transformExpression(node.arguments[0]);
|
|
24
|
+
}
|
|
25
|
+
return context.superTransformExpression(node);
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
exports.default = plugin;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const typescript_1 = require("typescript");
|
|
4
|
+
const XRF_GLOBALS = ["xray16"];
|
|
5
|
+
/**
|
|
6
|
+
* Plugin that removes imports from 'global' libraries like engine typedefs.
|
|
7
|
+
*/
|
|
8
|
+
const plugin = {
|
|
9
|
+
visitors: {
|
|
10
|
+
[typescript_1.SyntaxKind.ImportDeclaration]: (node, context) => {
|
|
11
|
+
const module = node.moduleSpecifier.getText().slice(1, -1);
|
|
12
|
+
const shouldNotBeTransformed = XRF_GLOBALS.includes(module);
|
|
13
|
+
if (shouldNotBeTransformed) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
return context.superTransformStatements(node);
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
exports.default = plugin;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const typescript_1 = require("typescript");
|
|
5
|
+
const typescript_to_lua_1 = require("typescript-to-lua");
|
|
6
|
+
const FILENAME_IDENTIFIER = "$filename";
|
|
7
|
+
/**
|
|
8
|
+
* Plugin that injects FILE_NAME in compile-time.
|
|
9
|
+
*/
|
|
10
|
+
const plugin = {
|
|
11
|
+
visitors: {
|
|
12
|
+
[typescript_1.SyntaxKind.Identifier]: (node, context) => {
|
|
13
|
+
if (node.text === FILENAME_IDENTIFIER) {
|
|
14
|
+
return (0, typescript_to_lua_1.createStringLiteral)(path.parse(context.sourceFile.fileName).name);
|
|
15
|
+
}
|
|
16
|
+
return context.superTransformExpression(node);
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
exports.default = plugin;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const comment = `-- Generated by xrf util at: ${new Date().toString()}\n\n`;
|
|
2
|
+
const plugin = {
|
|
3
|
+
beforeEmit(program, options, emitHost, result) {
|
|
4
|
+
void program;
|
|
5
|
+
void options;
|
|
6
|
+
void emitHost;
|
|
7
|
+
for (const file of result) {
|
|
8
|
+
file.code = comment + file.code;
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
export default plugin;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { isIdentifier, SyntaxKind } from "typescript";
|
|
2
|
+
import { createErrorDiagnosticFactory } from "./utils/diagnostics";
|
|
3
|
+
const FROM_CAST_METHODS = ["$fromObject", "$fromArray", "$fromLuaArray", "$fromLuaTable"];
|
|
4
|
+
/**
|
|
5
|
+
* Push generic error to notify about usage issue.
|
|
6
|
+
*/
|
|
7
|
+
const createInvalidFunctionCallError = createErrorDiagnosticFactory((name) => {
|
|
8
|
+
return `Invalid transformer call, expected function to have exactly 1 argument.`;
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* Plugin for transformation of casting methods.
|
|
12
|
+
* Simplifies TS/Lua testing and interoperation.
|
|
13
|
+
*/
|
|
14
|
+
const plugin = {
|
|
15
|
+
visitors: {
|
|
16
|
+
[SyntaxKind.CallExpression]: (node, context) => {
|
|
17
|
+
if (isIdentifier(node.expression) && FROM_CAST_METHODS.includes(node.expression.text)) {
|
|
18
|
+
if (node.arguments.length !== 1) {
|
|
19
|
+
context.diagnostics.push(createInvalidFunctionCallError(node));
|
|
20
|
+
}
|
|
21
|
+
return context.transformExpression(node.arguments[0]);
|
|
22
|
+
}
|
|
23
|
+
return context.superTransformExpression(node);
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export default plugin;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SyntaxKind } from "typescript";
|
|
2
|
+
const XRF_GLOBALS = ["xray16"];
|
|
3
|
+
/**
|
|
4
|
+
* Plugin that removes imports from 'global' libraries like engine typedefs.
|
|
5
|
+
*/
|
|
6
|
+
const plugin = {
|
|
7
|
+
visitors: {
|
|
8
|
+
[SyntaxKind.ImportDeclaration]: (node, context) => {
|
|
9
|
+
const module = node.moduleSpecifier.getText().slice(1, -1);
|
|
10
|
+
const shouldNotBeTransformed = XRF_GLOBALS.includes(module);
|
|
11
|
+
if (shouldNotBeTransformed) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
return context.superTransformStatements(node);
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
export default plugin;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { SyntaxKind } from "typescript";
|
|
3
|
+
import { createStringLiteral } from "typescript-to-lua";
|
|
4
|
+
const FILENAME_IDENTIFIER = "$filename";
|
|
5
|
+
/**
|
|
6
|
+
* Plugin that injects FILE_NAME in compile-time.
|
|
7
|
+
*/
|
|
8
|
+
const plugin = {
|
|
9
|
+
visitors: {
|
|
10
|
+
[SyntaxKind.Identifier]: (node, context) => {
|
|
11
|
+
if (node.text === FILENAME_IDENTIFIER) {
|
|
12
|
+
return createStringLiteral(path.parse(context.sourceFile.fileName).name);
|
|
13
|
+
}
|
|
14
|
+
return context.superTransformExpression(node);
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
export default plugin;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { factory, SyntaxKind, } from "typescript";
|
|
2
|
+
const LUA_LOGGER_STRIP_TARGET = "LuaLogger";
|
|
3
|
+
const IS_LUA_LOGGER_DISABLED = process.argv.includes("--no-lua-logs");
|
|
4
|
+
/**
|
|
5
|
+
* Plugin that removes all LuaLogger instance creations and calls when possible.
|
|
6
|
+
*/
|
|
7
|
+
const plugin = {
|
|
8
|
+
visitors: {
|
|
9
|
+
[SyntaxKind.VariableStatement]: (statement, context) => {
|
|
10
|
+
if (IS_LUA_LOGGER_DISABLED) {
|
|
11
|
+
let elementsCount = 0;
|
|
12
|
+
const list = statement.declarationList;
|
|
13
|
+
const nodes = [];
|
|
14
|
+
list.forEachChild((it) => {
|
|
15
|
+
const checker = context.program.getTypeChecker();
|
|
16
|
+
const typeSymbol = checker.getTypeAtLocation(it);
|
|
17
|
+
if (typeSymbol.symbol?.name === LUA_LOGGER_STRIP_TARGET) {
|
|
18
|
+
// nothing
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
nodes.push(it);
|
|
22
|
+
}
|
|
23
|
+
elementsCount += 1;
|
|
24
|
+
});
|
|
25
|
+
if (nodes.length === 0) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
else if (nodes.length !== elementsCount) {
|
|
29
|
+
return context.superTransformStatements(factory.createVariableStatement(statement.modifiers, factory.updateVariableDeclarationList(list, nodes)));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return context.superTransformStatements(statement);
|
|
33
|
+
},
|
|
34
|
+
[SyntaxKind.ExpressionStatement]: (statement, context) => {
|
|
35
|
+
if (IS_LUA_LOGGER_DISABLED && statement.expression?.kind === SyntaxKind.CallExpression) {
|
|
36
|
+
const expression = statement.expression;
|
|
37
|
+
const propertyAccess = expression.expression;
|
|
38
|
+
if (propertyAccess.expression?.kind === SyntaxKind.Identifier) {
|
|
39
|
+
const checker = context.program.getTypeChecker();
|
|
40
|
+
const identifier = propertyAccess.expression;
|
|
41
|
+
const typeSymbol = checker.getTypeAtLocation(identifier);
|
|
42
|
+
if (typeSymbol.symbol?.name === LUA_LOGGER_STRIP_TARGET) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return context.superTransformStatements(statement);
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
export default plugin;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { SyntaxKind } from "typescript";
|
|
2
|
+
import { isLuabindClassSuperCall, isLuabindClassSuperMethodCall, isLuabindClassType, isLuabindDecoratedClass, transformClassSuperMethodExpression, transformLuabindClassDeclaration, transformLuabindConstructorSuperCall, transformNewCallExpression, } from "./transformation";
|
|
3
|
+
/**
|
|
4
|
+
* Plugin that transform TS classes marked with decorator to luabind class declaration.
|
|
5
|
+
*/
|
|
6
|
+
const plugin = {
|
|
7
|
+
visitors: {
|
|
8
|
+
[SyntaxKind.CallExpression]: (expression, context) => {
|
|
9
|
+
if (isLuabindClassSuperCall(expression, context)) {
|
|
10
|
+
return transformLuabindConstructorSuperCall(expression, context);
|
|
11
|
+
}
|
|
12
|
+
return context.superTransformExpression(expression);
|
|
13
|
+
},
|
|
14
|
+
[SyntaxKind.ClassDeclaration]: (declaration, context) => {
|
|
15
|
+
if (isLuabindDecoratedClass(declaration)) {
|
|
16
|
+
return transformLuabindClassDeclaration(declaration, context);
|
|
17
|
+
}
|
|
18
|
+
return context.superTransformStatements(declaration);
|
|
19
|
+
},
|
|
20
|
+
[SyntaxKind.NewExpression]: (expression, context) => {
|
|
21
|
+
if (isLuabindClassType(expression, context)) {
|
|
22
|
+
return transformNewCallExpression(expression, context);
|
|
23
|
+
}
|
|
24
|
+
return context.superTransformExpression(expression);
|
|
25
|
+
},
|
|
26
|
+
[SyntaxKind.SuperKeyword]: (expression, context) => {
|
|
27
|
+
if (isLuabindClassSuperMethodCall(expression, context)) {
|
|
28
|
+
return transformClassSuperMethodExpression(expression, context);
|
|
29
|
+
}
|
|
30
|
+
return context.superTransformExpression(expression);
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
export default plugin;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { canHaveDecorators, factory, getDecorators, isAccessor, isConstructorDeclaration, isMethodDeclaration, isPropertyDeclaration, } from "typescript";
|
|
2
|
+
import * as tstl from "typescript-to-lua";
|
|
3
|
+
import { LuaTarget } from "typescript-to-lua";
|
|
4
|
+
import { createDefaultExportExpression, createExportedIdentifier, hasDefaultExportModifier, hasExportModifier, } from "typescript-to-lua/dist/transformation/utils/export";
|
|
5
|
+
import { createSelfIdentifier } from "typescript-to-lua/dist/transformation/utils/lua-ast";
|
|
6
|
+
import { transformInPrecedingStatementScope } from "typescript-to-lua/dist/transformation/utils/preceding-statements";
|
|
7
|
+
import { createSafeName, isUnsafeName } from "typescript-to-lua/dist/transformation/utils/safe-names";
|
|
8
|
+
import { transformIdentifier } from "typescript-to-lua/dist/transformation/visitors/identifier";
|
|
9
|
+
import { LUABIND_CONSTRUCTOR_METHOD } from "./constants";
|
|
10
|
+
import { checkLuabindClassDecoratorExpression } from "./decorators";
|
|
11
|
+
import { unsupportedStaticMethod } from "./errors";
|
|
12
|
+
import { transformAccessorDeclarations } from "./members/accessors";
|
|
13
|
+
import { createConstructorName, transformConstructorDeclaration } from "./members/constructor";
|
|
14
|
+
import { transformClassInstanceFields, verifyPropertyDecoratingExpression } from "./members/fields";
|
|
15
|
+
import { transformMethodDeclaration, verifyMethodDecoratingExpression } from "./members/method";
|
|
16
|
+
import { createClassSetup } from "./setup";
|
|
17
|
+
import { getExtendedNode, getExtendedType, isStaticNode, markTypeAsLuabind } from "./utils";
|
|
18
|
+
export const transformLuabindClassDeclaration = (declaration, context) => {
|
|
19
|
+
// If declaration is a default export, transform to export variable assignment instead
|
|
20
|
+
if (hasDefaultExportModifier(declaration)) {
|
|
21
|
+
// Class declaration including assignment to ____exports.default are in preceding statements
|
|
22
|
+
const { precedingStatements } = transformInPrecedingStatementScope(context, () => {
|
|
23
|
+
transformClassAsExpression(declaration, context);
|
|
24
|
+
return [];
|
|
25
|
+
});
|
|
26
|
+
return precedingStatements;
|
|
27
|
+
}
|
|
28
|
+
const { statements } = transformClassLikeDeclaration(declaration, context);
|
|
29
|
+
return statements;
|
|
30
|
+
};
|
|
31
|
+
export function transformClassAsExpression(expression, context) {
|
|
32
|
+
const { statements, name } = transformClassLikeDeclaration(expression, context);
|
|
33
|
+
context.addPrecedingStatements(statements);
|
|
34
|
+
return name;
|
|
35
|
+
}
|
|
36
|
+
export function transformClassLikeDeclaration(classDeclaration, context, nameOverride) {
|
|
37
|
+
let className;
|
|
38
|
+
if (nameOverride !== undefined) {
|
|
39
|
+
className = nameOverride;
|
|
40
|
+
}
|
|
41
|
+
else if (classDeclaration.name !== undefined) {
|
|
42
|
+
className = transformIdentifier(context, classDeclaration.name);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
className = tstl.createIdentifier(context.createTempName("class"), classDeclaration);
|
|
46
|
+
}
|
|
47
|
+
markTypeAsLuabind(classDeclaration, context);
|
|
48
|
+
// Get type that is extended
|
|
49
|
+
const extendedTypeNode = getExtendedNode(classDeclaration);
|
|
50
|
+
const extendedType = getExtendedType(context, classDeclaration);
|
|
51
|
+
context.classSuperInfos.push({ className, classDeclaration: classDeclaration, extendedTypeNode });
|
|
52
|
+
// Get all properties with value
|
|
53
|
+
const properties = classDeclaration.members.filter(isPropertyDeclaration).filter((member) => member.initializer);
|
|
54
|
+
// Divide properties into static and non-static
|
|
55
|
+
const instanceFields = properties.filter((prop) => !isStaticNode(prop));
|
|
56
|
+
const result = [];
|
|
57
|
+
let localClassName;
|
|
58
|
+
if (isUnsafeName(className.text, context.options)) {
|
|
59
|
+
localClassName = tstl.createIdentifier(createSafeName(className.text), undefined, className.symbolId, className.text);
|
|
60
|
+
tstl.setNodePosition(localClassName, className);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
localClassName = className;
|
|
64
|
+
}
|
|
65
|
+
result.push(...createClassSetup(context, classDeclaration, className, localClassName));
|
|
66
|
+
// Find first constructor with body
|
|
67
|
+
const constructor = classDeclaration.members.find((n) => isConstructorDeclaration(n) && n.body !== undefined);
|
|
68
|
+
if (constructor) {
|
|
69
|
+
// Add constructor plus initialization of instance fields
|
|
70
|
+
const constructorResult = transformConstructorDeclaration(context, constructor, localClassName, instanceFields, classDeclaration);
|
|
71
|
+
if (constructorResult)
|
|
72
|
+
result.push(constructorResult);
|
|
73
|
+
}
|
|
74
|
+
else if (!extendedType) {
|
|
75
|
+
// Generate a constructor if none was defined in a base class
|
|
76
|
+
const constructorResult = transformConstructorDeclaration(context, factory.createConstructorDeclaration([], [], factory.createBlock([], true)), localClassName, instanceFields, classDeclaration);
|
|
77
|
+
if (constructorResult)
|
|
78
|
+
result.push(constructorResult);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Generate a constructor if none was defined in a class with instance fields that need initialization
|
|
82
|
+
// localClassName.__init = function(self, ...)
|
|
83
|
+
// baseClassName.__init(self, ...) // or unpack(arg) for Lua 5.0
|
|
84
|
+
// ...
|
|
85
|
+
// Also luabind always needs definition of call expression to use table as class.
|
|
86
|
+
const constructorBody = transformClassInstanceFields(context, instanceFields);
|
|
87
|
+
const argsExpression = context.luaTarget === LuaTarget.Lua50
|
|
88
|
+
? tstl.createCallExpression(tstl.createIdentifier("unpack"), [tstl.createArgLiteral()])
|
|
89
|
+
: tstl.createDotsLiteral();
|
|
90
|
+
const superCall = tstl.createExpressionStatement(tstl.createCallExpression(tstl.createTableIndexExpression(context.transformExpression(factory.createSuper()), tstl.createStringLiteral(LUABIND_CONSTRUCTOR_METHOD)), [createSelfIdentifier(), argsExpression]));
|
|
91
|
+
constructorBody.unshift(superCall);
|
|
92
|
+
const constructorFunction = tstl.createFunctionExpression(tstl.createBlock(constructorBody), [createSelfIdentifier()], tstl.createDotsLiteral(), tstl.NodeFlags.Declaration);
|
|
93
|
+
result.push(tstl.createAssignmentStatement(createConstructorName(localClassName), constructorFunction, classDeclaration));
|
|
94
|
+
}
|
|
95
|
+
// Transform accessors
|
|
96
|
+
for (const member of classDeclaration.members) {
|
|
97
|
+
if (!isAccessor(member))
|
|
98
|
+
continue;
|
|
99
|
+
const accessors = context.resolver.getAllAccessorDeclarations(member);
|
|
100
|
+
if (accessors.firstAccessor !== member)
|
|
101
|
+
continue;
|
|
102
|
+
const accessorsResult = transformAccessorDeclarations(context, accessors, localClassName);
|
|
103
|
+
if (accessorsResult) {
|
|
104
|
+
result.push(accessorsResult);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const decorationStatements = [];
|
|
108
|
+
for (const member of classDeclaration.members) {
|
|
109
|
+
if (isAccessor(member)) {
|
|
110
|
+
verifyPropertyDecoratingExpression(context, member);
|
|
111
|
+
}
|
|
112
|
+
else if (isMethodDeclaration(member)) {
|
|
113
|
+
const statement = transformMethodDeclaration(context, member, localClassName);
|
|
114
|
+
if (statement)
|
|
115
|
+
result.push(statement);
|
|
116
|
+
if (member.body) {
|
|
117
|
+
verifyMethodDecoratingExpression(context, member);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else if (isPropertyDeclaration(member)) {
|
|
121
|
+
if (isStaticNode(member)) {
|
|
122
|
+
context.diagnostics.push(unsupportedStaticMethod(member));
|
|
123
|
+
}
|
|
124
|
+
verifyPropertyDecoratingExpression(context, member);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
result.push(...decorationStatements);
|
|
128
|
+
// Decorate the class
|
|
129
|
+
if (canHaveDecorators(classDeclaration) && getDecorators(classDeclaration)) {
|
|
130
|
+
getDecorators(classDeclaration)?.forEach((d) => checkLuabindClassDecoratorExpression(context, d));
|
|
131
|
+
if (hasExportModifier(classDeclaration)) {
|
|
132
|
+
const exportExpression = hasDefaultExportModifier(classDeclaration)
|
|
133
|
+
? createDefaultExportExpression(classDeclaration)
|
|
134
|
+
: createExportedIdentifier(context, className);
|
|
135
|
+
const classAssignment = tstl.createAssignmentStatement(exportExpression, localClassName);
|
|
136
|
+
result.push(classAssignment);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
context.classSuperInfos.pop();
|
|
140
|
+
return { statements: result, name: className };
|
|
141
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LUABIND_DECORATOR } from "./constants";
|
|
2
|
+
import { unsupportedClassDecorator } from "./errors";
|
|
3
|
+
/**
|
|
4
|
+
* Transform decorator call expressions for luabind class.
|
|
5
|
+
*/
|
|
6
|
+
export function checkLuabindClassDecoratorExpression(context, decorator) {
|
|
7
|
+
const expression = decorator.expression;
|
|
8
|
+
// Do not transform luabind decorator.
|
|
9
|
+
if (expression.expression.text !== LUABIND_DECORATOR) {
|
|
10
|
+
context.diagnostics.push(unsupportedClassDecorator(expression));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createErrorDiagnosticFactory } from "../../utils/diagnostics";
|
|
2
|
+
export const unsupportedStaticMethod = createErrorDiagnosticFactory((name) => {
|
|
3
|
+
const nameReference = name ? ` '${name}'` : "";
|
|
4
|
+
return `Unable transform static properties for luabind classes${nameReference}.`;
|
|
5
|
+
});
|
|
6
|
+
export const unsupportedClassDecorator = createErrorDiagnosticFactory((name) => {
|
|
7
|
+
const nameReference = name ? ` '${name}'` : "";
|
|
8
|
+
return `Unable transform class decorators for luabind classes${nameReference}.`;
|
|
9
|
+
});
|
|
10
|
+
export const unsupportedPropertyDecorator = createErrorDiagnosticFactory((name) => {
|
|
11
|
+
const nameReference = name ? ` '${name}'` : "";
|
|
12
|
+
return `Unable transform property decorator for luabind classes${nameReference}.`;
|
|
13
|
+
});
|
|
14
|
+
export const unsupportedParameterDecorator = createErrorDiagnosticFactory((name) => {
|
|
15
|
+
const nameReference = name ? ` '${name}'` : "";
|
|
16
|
+
return `Unable transform parameter decorator for luabind classes${nameReference}.`;
|
|
17
|
+
});
|
|
18
|
+
export const unsupportedMethodDecorator = createErrorDiagnosticFactory((name) => {
|
|
19
|
+
const nameReference = name ? ` '${name}'` : "";
|
|
20
|
+
return `Unable transform method decorator for luabind classes${nameReference}.`;
|
|
21
|
+
});
|
|
22
|
+
export const unsupportedStaticAccessor = createErrorDiagnosticFactory((name) => {
|
|
23
|
+
const nameReference = name ? ` '${name}'` : "";
|
|
24
|
+
return `Unable transform static accessors for luabind classes${nameReference}.`;
|
|
25
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from "./constants";
|
|
2
|
-
export * from "./utils";
|
|
3
|
-
export * from "./class_declaration";
|
|
4
|
-
export * from "./super";
|
|
5
|
-
export * from "./new";
|
|
1
|
+
export * from "./constants";
|
|
2
|
+
export * from "./utils";
|
|
3
|
+
export * from "./class_declaration";
|
|
4
|
+
export * from "./super";
|
|
5
|
+
export * from "./new";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { LuaLibFeature } from "typescript-to-lua";
|
|
2
|
+
import * as lua from "typescript-to-lua";
|
|
3
|
+
import { createSelfIdentifier } from "typescript-to-lua/dist/transformation/utils/lua-ast";
|
|
4
|
+
import { transformLuaLibFunction } from "typescript-to-lua/dist/transformation/utils/lualib";
|
|
5
|
+
import { transformFunctionBody, transformParameters } from "typescript-to-lua/dist/transformation/visitors/function";
|
|
6
|
+
import { transformPropertyName } from "typescript-to-lua/dist/transformation/visitors/literal";
|
|
7
|
+
import { unsupportedStaticAccessor } from "../errors";
|
|
8
|
+
import { isStaticNode } from "../utils";
|
|
9
|
+
function transformAccessor(context, node) {
|
|
10
|
+
const [params, dot, restParam] = transformParameters(context, node.parameters, createSelfIdentifier());
|
|
11
|
+
const body = node.body ? transformFunctionBody(context, node.parameters, node.body, restParam)[0] : [];
|
|
12
|
+
return lua.createFunctionExpression(lua.createBlock(body), params, dot, lua.NodeFlags.Declaration);
|
|
13
|
+
}
|
|
14
|
+
export function transformAccessorDeclarations(context, { firstAccessor, getAccessor, setAccessor }, className) {
|
|
15
|
+
const propertyName = transformPropertyName(context, firstAccessor.name);
|
|
16
|
+
const descriptor = lua.createTableExpression([]);
|
|
17
|
+
if (getAccessor) {
|
|
18
|
+
const getterFunction = transformAccessor(context, getAccessor);
|
|
19
|
+
descriptor.fields.push(lua.createTableFieldExpression(getterFunction, lua.createStringLiteral("get")));
|
|
20
|
+
}
|
|
21
|
+
if (setAccessor) {
|
|
22
|
+
const setterFunction = transformAccessor(context, setAccessor);
|
|
23
|
+
descriptor.fields.push(lua.createTableFieldExpression(setterFunction, lua.createStringLiteral("set")));
|
|
24
|
+
}
|
|
25
|
+
const isStatic = isStaticNode(firstAccessor);
|
|
26
|
+
if (isStatic) {
|
|
27
|
+
context.diagnostics.push(unsupportedStaticAccessor(firstAccessor));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const target = lua.cloneIdentifier(className);
|
|
31
|
+
const feature = LuaLibFeature.ObjectDefineProperty;
|
|
32
|
+
const parameters = [target, propertyName, descriptor];
|
|
33
|
+
const call = transformLuaLibFunction(context, feature, undefined, ...parameters);
|
|
34
|
+
return lua.createExpressionStatement(call);
|
|
35
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { isCallExpression, isExpressionStatement, isIdentifier, SyntaxKind, } from "typescript";
|
|
2
|
+
import * as lua from "typescript-to-lua";
|
|
3
|
+
import { createSelfIdentifier } from "typescript-to-lua/dist/transformation/utils/lua-ast";
|
|
4
|
+
import { ScopeType } from "typescript-to-lua/dist/transformation/utils/scope";
|
|
5
|
+
import { transformFunctionBodyContent, transformFunctionBodyHeader, transformParameters, } from "typescript-to-lua/dist/transformation/visitors/function";
|
|
6
|
+
import { transformIdentifier } from "typescript-to-lua/dist/transformation/visitors/identifier";
|
|
7
|
+
import { LUABIND_CONSTRUCTOR_METHOD } from "../constants";
|
|
8
|
+
import { transformClassInstanceFields } from "./fields";
|
|
9
|
+
export function createConstructorName(className) {
|
|
10
|
+
return lua.createTableIndexExpression(lua.cloneIdentifier(className), lua.createStringLiteral(LUABIND_CONSTRUCTOR_METHOD));
|
|
11
|
+
}
|
|
12
|
+
export function transformConstructorDeclaration(context, statement, className, instanceFields, classDeclaration) {
|
|
13
|
+
// Don't transform methods without body (overload declarations)
|
|
14
|
+
if (!statement.body) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
// Transform body
|
|
18
|
+
const scope = context.pushScope(ScopeType.Function);
|
|
19
|
+
const body = transformFunctionBodyContent(context, statement.body);
|
|
20
|
+
const [params, dotsLiteral, restParamName] = transformParameters(context, statement.parameters, createSelfIdentifier());
|
|
21
|
+
// Make sure default parameters are assigned before fields are initialized
|
|
22
|
+
const bodyWithFieldInitializers = transformFunctionBodyHeader(context, scope, statement.parameters, restParamName);
|
|
23
|
+
// Check for field declarations in constructor
|
|
24
|
+
const constructorFieldsDeclarations = statement.parameters.filter((p) => p.modifiers !== undefined);
|
|
25
|
+
const classInstanceFields = transformClassInstanceFields(context, instanceFields);
|
|
26
|
+
// If there are field initializers and the first statement is a super call,
|
|
27
|
+
// move super call between default assignments and initializers
|
|
28
|
+
if ((constructorFieldsDeclarations.length > 0 || classInstanceFields.length > 0) &&
|
|
29
|
+
statement.body &&
|
|
30
|
+
statement.body.statements.length > 0) {
|
|
31
|
+
const firstStatement = statement.body.statements[0];
|
|
32
|
+
if (isExpressionStatement(firstStatement) &&
|
|
33
|
+
isCallExpression(firstStatement.expression) &&
|
|
34
|
+
firstStatement.expression.expression.kind === SyntaxKind.SuperKeyword) {
|
|
35
|
+
const superCall = body.shift();
|
|
36
|
+
if (superCall) {
|
|
37
|
+
bodyWithFieldInitializers.push(superCall);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Add in instance field declarations
|
|
42
|
+
for (const declaration of constructorFieldsDeclarations) {
|
|
43
|
+
if (isIdentifier(declaration.name)) {
|
|
44
|
+
// self.declarationName = declarationName
|
|
45
|
+
const assignment = lua.createAssignmentStatement(lua.createTableIndexExpression(createSelfIdentifier(), lua.createStringLiteral(declaration.name.text)), transformIdentifier(context, declaration.name));
|
|
46
|
+
bodyWithFieldInitializers.push(assignment);
|
|
47
|
+
}
|
|
48
|
+
// else { TypeScript error: A parameter property may not be declared using a binding pattern }
|
|
49
|
+
}
|
|
50
|
+
bodyWithFieldInitializers.push(...classInstanceFields);
|
|
51
|
+
bodyWithFieldInitializers.push(...body);
|
|
52
|
+
const block = lua.createBlock(bodyWithFieldInitializers);
|
|
53
|
+
const constructorWasGenerated = statement.pos === -1;
|
|
54
|
+
context.popScope();
|
|
55
|
+
return lua.createAssignmentStatement(createConstructorName(className), lua.createFunctionExpression(block, params, dotsLiteral, lua.NodeFlags.Declaration), constructorWasGenerated ? classDeclaration : statement);
|
|
56
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { canHaveDecorators, getDecorators } from "typescript";
|
|
2
|
+
import * as tstl from "typescript-to-lua";
|
|
3
|
+
import { createSelfIdentifier } from "typescript-to-lua/dist/transformation/utils/lua-ast";
|
|
4
|
+
import { transformInPrecedingStatementScope } from "typescript-to-lua/dist/transformation/utils/preceding-statements";
|
|
5
|
+
import { transformPropertyName } from "typescript-to-lua/dist/transformation/visitors/literal";
|
|
6
|
+
import { unsupportedPropertyDecorator } from "../errors";
|
|
7
|
+
/**
|
|
8
|
+
* Verify whether decorators provided for luabind class.
|
|
9
|
+
*/
|
|
10
|
+
export function verifyPropertyDecoratingExpression(context, node) {
|
|
11
|
+
if (!canHaveDecorators(node))
|
|
12
|
+
return;
|
|
13
|
+
const decorators = getDecorators(node);
|
|
14
|
+
if (!decorators)
|
|
15
|
+
return;
|
|
16
|
+
decorators.forEach((decorator) => {
|
|
17
|
+
context.diagnostics.push(unsupportedPropertyDecorator(decorator));
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export function transformClassInstanceFields(context, instanceFields) {
|
|
21
|
+
const statements = [];
|
|
22
|
+
for (const f of instanceFields) {
|
|
23
|
+
const { precedingStatements, result: statement } = transformInPrecedingStatementScope(context, () => {
|
|
24
|
+
// Get identifier
|
|
25
|
+
const fieldName = transformPropertyName(context, f.name);
|
|
26
|
+
const value = f.initializer ? context.transformExpression(f.initializer) : undefined;
|
|
27
|
+
// self[fieldName]
|
|
28
|
+
const selfIndex = tstl.createTableIndexExpression(createSelfIdentifier(), fieldName);
|
|
29
|
+
// self[fieldName] = value
|
|
30
|
+
const assignClassField = tstl.createAssignmentStatement(selfIndex, value, f);
|
|
31
|
+
return assignClassField;
|
|
32
|
+
});
|
|
33
|
+
statements.push(...precedingStatements, statement);
|
|
34
|
+
}
|
|
35
|
+
return statements;
|
|
36
|
+
}
|