@gwigz/slua-tstl-plugin 1.1.0 → 1.3.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.
@@ -0,0 +1,422 @@
1
+ import * as lua from "typescript-to-lua";
2
+ function walkExpression(expr, blockVisitor) {
3
+ switch (expr.kind) {
4
+ case lua.SyntaxKind.StringLiteral:
5
+ case lua.SyntaxKind.NumericLiteral:
6
+ case lua.SyntaxKind.NilKeyword:
7
+ case lua.SyntaxKind.DotsKeyword:
8
+ case lua.SyntaxKind.ArgKeyword:
9
+ case lua.SyntaxKind.TrueKeyword:
10
+ case lua.SyntaxKind.FalseKeyword:
11
+ case lua.SyntaxKind.Identifier:
12
+ break;
13
+ case lua.SyntaxKind.BinaryExpression: {
14
+ const bin = expr;
15
+ walkExpression(bin.left, blockVisitor);
16
+ walkExpression(bin.right, blockVisitor);
17
+ break;
18
+ }
19
+ case lua.SyntaxKind.UnaryExpression:
20
+ walkExpression(expr.operand, blockVisitor);
21
+ break;
22
+ case lua.SyntaxKind.ParenthesizedExpression:
23
+ walkExpression(expr.expression, blockVisitor);
24
+ break;
25
+ case lua.SyntaxKind.ConditionalExpression: {
26
+ const cond = expr;
27
+ walkExpression(cond.condition, blockVisitor);
28
+ walkExpression(cond.whenTrue, blockVisitor);
29
+ walkExpression(cond.whenFalse, blockVisitor);
30
+ break;
31
+ }
32
+ case lua.SyntaxKind.CallExpression: {
33
+ const call = expr;
34
+ walkExpression(call.expression, blockVisitor);
35
+ for (const p of call.params)
36
+ walkExpression(p, blockVisitor);
37
+ break;
38
+ }
39
+ case lua.SyntaxKind.MethodCallExpression: {
40
+ const mc = expr;
41
+ walkExpression(mc.prefixExpression, blockVisitor);
42
+ for (const p of mc.params)
43
+ walkExpression(p, blockVisitor);
44
+ break;
45
+ }
46
+ case lua.SyntaxKind.TableIndexExpression: {
47
+ const ti = expr;
48
+ walkExpression(ti.table, blockVisitor);
49
+ walkExpression(ti.index, blockVisitor);
50
+ break;
51
+ }
52
+ case lua.SyntaxKind.TableExpression:
53
+ for (const f of expr.fields) {
54
+ walkExpression(f.value, blockVisitor);
55
+ if (f.key)
56
+ walkExpression(f.key, blockVisitor);
57
+ }
58
+ break;
59
+ case lua.SyntaxKind.FunctionExpression: {
60
+ const fn = expr;
61
+ walkBlock(fn.body, blockVisitor);
62
+ break;
63
+ }
64
+ case lua.SyntaxKind.TableFieldExpression: {
65
+ const tf = expr;
66
+ walkExpression(tf.value, blockVisitor);
67
+ if (tf.key)
68
+ walkExpression(tf.key, blockVisitor);
69
+ break;
70
+ }
71
+ }
72
+ }
73
+ function walkStatement(stmt, blockVisitor) {
74
+ switch (stmt.kind) {
75
+ case lua.SyntaxKind.DoStatement:
76
+ walkBlock(stmt, blockVisitor);
77
+ break;
78
+ case lua.SyntaxKind.VariableDeclarationStatement: {
79
+ const vds = stmt;
80
+ if (vds.right) {
81
+ for (const r of vds.right)
82
+ walkExpression(r, blockVisitor);
83
+ }
84
+ break;
85
+ }
86
+ case lua.SyntaxKind.AssignmentStatement: {
87
+ const as_ = stmt;
88
+ for (const l of as_.left)
89
+ walkExpression(l, blockVisitor);
90
+ for (const r of as_.right)
91
+ walkExpression(r, blockVisitor);
92
+ break;
93
+ }
94
+ case lua.SyntaxKind.IfStatement: {
95
+ const is_ = stmt;
96
+ walkExpression(is_.condition, blockVisitor);
97
+ walkBlock(is_.ifBlock, blockVisitor);
98
+ if (is_.elseBlock) {
99
+ if (lua.isIfStatement(is_.elseBlock)) {
100
+ walkStatement(is_.elseBlock, blockVisitor);
101
+ }
102
+ else {
103
+ walkBlock(is_.elseBlock, blockVisitor);
104
+ }
105
+ }
106
+ break;
107
+ }
108
+ case lua.SyntaxKind.WhileStatement: {
109
+ const ws = stmt;
110
+ walkExpression(ws.condition, blockVisitor);
111
+ walkBlock(ws.body, blockVisitor);
112
+ break;
113
+ }
114
+ case lua.SyntaxKind.RepeatStatement: {
115
+ const rs = stmt;
116
+ walkExpression(rs.condition, blockVisitor);
117
+ walkBlock(rs.body, blockVisitor);
118
+ break;
119
+ }
120
+ case lua.SyntaxKind.ForStatement: {
121
+ const fs = stmt;
122
+ walkExpression(fs.controlVariableInitializer, blockVisitor);
123
+ walkExpression(fs.limitExpression, blockVisitor);
124
+ if (fs.stepExpression)
125
+ walkExpression(fs.stepExpression, blockVisitor);
126
+ walkBlock(fs.body, blockVisitor);
127
+ break;
128
+ }
129
+ case lua.SyntaxKind.ForInStatement: {
130
+ const fis = stmt;
131
+ for (const e of fis.expressions)
132
+ walkExpression(e, blockVisitor);
133
+ walkBlock(fis.body, blockVisitor);
134
+ break;
135
+ }
136
+ case lua.SyntaxKind.ReturnStatement:
137
+ for (const e of stmt.expressions)
138
+ walkExpression(e, blockVisitor);
139
+ break;
140
+ case lua.SyntaxKind.ExpressionStatement:
141
+ walkExpression(stmt.expression, blockVisitor);
142
+ break;
143
+ case lua.SyntaxKind.GotoStatement:
144
+ case lua.SyntaxKind.LabelStatement:
145
+ case lua.SyntaxKind.BreakStatement:
146
+ case lua.SyntaxKind.ContinueStatement:
147
+ break;
148
+ }
149
+ }
150
+ function walkBlock(block, blockVisitor) {
151
+ blockVisitor(block.statements);
152
+ for (const stmt of block.statements) {
153
+ walkStatement(stmt, blockVisitor);
154
+ }
155
+ }
156
+ /** Walk all statement arrays in a File. Depth-first. */
157
+ export function walkBlocks(file, visitor) {
158
+ walkBlock(file, visitor);
159
+ }
160
+ function walkExpressionIds(expr, cb) {
161
+ switch (expr.kind) {
162
+ case lua.SyntaxKind.Identifier:
163
+ cb(expr);
164
+ break;
165
+ case lua.SyntaxKind.StringLiteral:
166
+ case lua.SyntaxKind.NumericLiteral:
167
+ case lua.SyntaxKind.NilKeyword:
168
+ case lua.SyntaxKind.DotsKeyword:
169
+ case lua.SyntaxKind.ArgKeyword:
170
+ case lua.SyntaxKind.TrueKeyword:
171
+ case lua.SyntaxKind.FalseKeyword:
172
+ break;
173
+ case lua.SyntaxKind.BinaryExpression: {
174
+ const bin = expr;
175
+ walkExpressionIds(bin.left, cb);
176
+ walkExpressionIds(bin.right, cb);
177
+ break;
178
+ }
179
+ case lua.SyntaxKind.UnaryExpression:
180
+ walkExpressionIds(expr.operand, cb);
181
+ break;
182
+ case lua.SyntaxKind.ParenthesizedExpression:
183
+ walkExpressionIds(expr.expression, cb);
184
+ break;
185
+ case lua.SyntaxKind.ConditionalExpression: {
186
+ const cond = expr;
187
+ walkExpressionIds(cond.condition, cb);
188
+ walkExpressionIds(cond.whenTrue, cb);
189
+ walkExpressionIds(cond.whenFalse, cb);
190
+ break;
191
+ }
192
+ case lua.SyntaxKind.CallExpression: {
193
+ const call = expr;
194
+ walkExpressionIds(call.expression, cb);
195
+ for (const p of call.params)
196
+ walkExpressionIds(p, cb);
197
+ break;
198
+ }
199
+ case lua.SyntaxKind.MethodCallExpression: {
200
+ const mc = expr;
201
+ walkExpressionIds(mc.prefixExpression, cb);
202
+ walkExpressionIds(mc.name, cb);
203
+ for (const p of mc.params)
204
+ walkExpressionIds(p, cb);
205
+ break;
206
+ }
207
+ case lua.SyntaxKind.TableIndexExpression: {
208
+ const ti = expr;
209
+ walkExpressionIds(ti.table, cb);
210
+ walkExpressionIds(ti.index, cb);
211
+ break;
212
+ }
213
+ case lua.SyntaxKind.TableExpression:
214
+ for (const f of expr.fields) {
215
+ walkExpressionIds(f.value, cb);
216
+ if (f.key)
217
+ walkExpressionIds(f.key, cb);
218
+ }
219
+ break;
220
+ case lua.SyntaxKind.FunctionExpression: {
221
+ const fn = expr;
222
+ if (fn.params) {
223
+ for (const p of fn.params)
224
+ cb(p);
225
+ }
226
+ walkBlockIds(fn.body, cb);
227
+ break;
228
+ }
229
+ case lua.SyntaxKind.TableFieldExpression: {
230
+ const tf = expr;
231
+ walkExpressionIds(tf.value, cb);
232
+ if (tf.key)
233
+ walkExpressionIds(tf.key, cb);
234
+ break;
235
+ }
236
+ }
237
+ }
238
+ function walkStatementIds(stmt, cb) {
239
+ switch (stmt.kind) {
240
+ case lua.SyntaxKind.DoStatement:
241
+ walkBlockIds(stmt, cb);
242
+ break;
243
+ case lua.SyntaxKind.VariableDeclarationStatement: {
244
+ const vds = stmt;
245
+ for (const l of vds.left)
246
+ cb(l);
247
+ if (vds.right) {
248
+ for (const r of vds.right)
249
+ walkExpressionIds(r, cb);
250
+ }
251
+ break;
252
+ }
253
+ case lua.SyntaxKind.AssignmentStatement: {
254
+ const as_ = stmt;
255
+ for (const l of as_.left)
256
+ walkExpressionIds(l, cb);
257
+ for (const r of as_.right)
258
+ walkExpressionIds(r, cb);
259
+ break;
260
+ }
261
+ case lua.SyntaxKind.IfStatement: {
262
+ const is_ = stmt;
263
+ walkExpressionIds(is_.condition, cb);
264
+ walkBlockIds(is_.ifBlock, cb);
265
+ if (is_.elseBlock) {
266
+ if (lua.isIfStatement(is_.elseBlock)) {
267
+ walkStatementIds(is_.elseBlock, cb);
268
+ }
269
+ else {
270
+ walkBlockIds(is_.elseBlock, cb);
271
+ }
272
+ }
273
+ break;
274
+ }
275
+ case lua.SyntaxKind.WhileStatement: {
276
+ const ws = stmt;
277
+ walkExpressionIds(ws.condition, cb);
278
+ walkBlockIds(ws.body, cb);
279
+ break;
280
+ }
281
+ case lua.SyntaxKind.RepeatStatement: {
282
+ const rs = stmt;
283
+ walkExpressionIds(rs.condition, cb);
284
+ walkBlockIds(rs.body, cb);
285
+ break;
286
+ }
287
+ case lua.SyntaxKind.ForStatement: {
288
+ const fs = stmt;
289
+ cb(fs.controlVariable);
290
+ walkExpressionIds(fs.controlVariableInitializer, cb);
291
+ walkExpressionIds(fs.limitExpression, cb);
292
+ if (fs.stepExpression)
293
+ walkExpressionIds(fs.stepExpression, cb);
294
+ walkBlockIds(fs.body, cb);
295
+ break;
296
+ }
297
+ case lua.SyntaxKind.ForInStatement: {
298
+ const fis = stmt;
299
+ for (const n of fis.names)
300
+ cb(n);
301
+ for (const e of fis.expressions)
302
+ walkExpressionIds(e, cb);
303
+ walkBlockIds(fis.body, cb);
304
+ break;
305
+ }
306
+ case lua.SyntaxKind.ReturnStatement:
307
+ for (const e of stmt.expressions)
308
+ walkExpressionIds(e, cb);
309
+ break;
310
+ case lua.SyntaxKind.ExpressionStatement:
311
+ walkExpressionIds(stmt.expression, cb);
312
+ break;
313
+ case lua.SyntaxKind.GotoStatement:
314
+ case lua.SyntaxKind.LabelStatement:
315
+ case lua.SyntaxKind.BreakStatement:
316
+ case lua.SyntaxKind.ContinueStatement:
317
+ break;
318
+ }
319
+ }
320
+ function walkBlockIds(block, cb) {
321
+ for (const stmt of block.statements) {
322
+ walkStatementIds(stmt, cb);
323
+ }
324
+ }
325
+ /** Walk all Identifier nodes in a File. Callback may mutate id.text. */
326
+ export function walkIdentifiers(file, cb) {
327
+ walkBlockIds(file, cb);
328
+ }
329
+ /** Check if an expression tree contains an Identifier with the given name. */
330
+ export function containsIdentifier(node, name) {
331
+ if (lua.isIdentifier(node)) {
332
+ return node.text === name;
333
+ }
334
+ // Walk expressions
335
+ if (lua.isBinaryExpression(node)) {
336
+ return containsIdentifier(node.left, name) || containsIdentifier(node.right, name);
337
+ }
338
+ if (lua.isUnaryExpression(node)) {
339
+ return containsIdentifier(node.operand, name);
340
+ }
341
+ if (lua.isParenthesizedExpression(node)) {
342
+ return containsIdentifier(node.expression, name);
343
+ }
344
+ if (lua.isConditionalExpression(node)) {
345
+ return (containsIdentifier(node.condition, name) ||
346
+ containsIdentifier(node.whenTrue, name) ||
347
+ containsIdentifier(node.whenFalse, name));
348
+ }
349
+ if (lua.isCallExpression(node)) {
350
+ return (containsIdentifier(node.expression, name) ||
351
+ node.params.some((p) => containsIdentifier(p, name)));
352
+ }
353
+ if (lua.isMethodCallExpression(node)) {
354
+ return (containsIdentifier(node.prefixExpression, name) ||
355
+ containsIdentifier(node.name, name) ||
356
+ node.params.some((p) => containsIdentifier(p, name)));
357
+ }
358
+ if (lua.isTableIndexExpression(node)) {
359
+ return containsIdentifier(node.table, name) || containsIdentifier(node.index, name);
360
+ }
361
+ if (lua.isTableExpression(node)) {
362
+ return node.fields.some((f) => containsIdentifier(f.value, name) || (f.key ? containsIdentifier(f.key, name) : false));
363
+ }
364
+ if (lua.isTableFieldExpression(node)) {
365
+ return (containsIdentifier(node.value, name) ||
366
+ (node.key ? containsIdentifier(node.key, name) : false));
367
+ }
368
+ if (lua.isFunctionExpression(node)) {
369
+ return node.body.statements.some((s) => containsIdentifierInStatement(s, name));
370
+ }
371
+ // Walk statements
372
+ if (lua.isDoStatement(node)) {
373
+ return node.statements.some((s) => containsIdentifierInStatement(s, name));
374
+ }
375
+ if (lua.isVariableDeclarationStatement(node)) {
376
+ return (node.left.some((l) => l.text === name) ||
377
+ (node.right?.some((r) => containsIdentifier(r, name)) ?? false));
378
+ }
379
+ if (lua.isAssignmentStatement(node)) {
380
+ return (node.left.some((l) => containsIdentifier(l, name)) ||
381
+ node.right.some((r) => containsIdentifier(r, name)));
382
+ }
383
+ if (lua.isIfStatement(node)) {
384
+ if (containsIdentifier(node.condition, name))
385
+ return true;
386
+ if (node.ifBlock.statements.some((s) => containsIdentifierInStatement(s, name)))
387
+ return true;
388
+ if (node.elseBlock) {
389
+ if (lua.isIfStatement(node.elseBlock))
390
+ return containsIdentifier(node.elseBlock, name);
391
+ return node.elseBlock.statements.some((s) => containsIdentifierInStatement(s, name));
392
+ }
393
+ return false;
394
+ }
395
+ if (lua.isReturnStatement(node)) {
396
+ return node.expressions.some((e) => containsIdentifier(e, name));
397
+ }
398
+ if (lua.isExpressionStatement(node)) {
399
+ return containsIdentifier(node.expression, name);
400
+ }
401
+ if (lua.isIterationStatement(node)) {
402
+ if (lua.isForStatement(node)) {
403
+ return (node.controlVariable.text === name ||
404
+ containsIdentifier(node.controlVariableInitializer, name) ||
405
+ containsIdentifier(node.limitExpression, name) ||
406
+ (node.stepExpression ? containsIdentifier(node.stepExpression, name) : false) ||
407
+ node.body.statements.some((s) => containsIdentifierInStatement(s, name)));
408
+ }
409
+ if (lua.isForInStatement(node)) {
410
+ return (node.names.some((n) => n.text === name) ||
411
+ node.expressions.some((e) => containsIdentifier(e, name)) ||
412
+ node.body.statements.some((s) => containsIdentifierInStatement(s, name)));
413
+ }
414
+ // While / Repeat
415
+ return (containsIdentifier(node.condition, name) ||
416
+ node.body.statements.some((s) => containsIdentifierInStatement(s, name)));
417
+ }
418
+ return false;
419
+ }
420
+ function containsIdentifierInStatement(stmt, name) {
421
+ return containsIdentifier(stmt, name);
422
+ }
@@ -0,0 +1,41 @@
1
+ import * as ts from "typescript";
2
+ import * as lua from "typescript-to-lua";
3
+ /**
4
+ * Strip internal JSDoc tags from Lua comments (@indexArg, @indexReturn, @define).
5
+ * These are only consumed by the plugin at transpile time.
6
+ *
7
+ * TSTL generates JSDoc as flat string arrays in leadingComments:
8
+ * ["-", " @define FLAG", " continuation line", " @indexArg 0"]
9
+ * Each string becomes a `-- <text>` line. When we find a tag line, we also
10
+ * remove its continuation lines (those starting with ` ` but not ` @`).
11
+ */
12
+ export declare function stripInternalJSDocTags(file: lua.File): boolean;
13
+ /**
14
+ * Strip empty module boilerplate from files without explicit exports.
15
+ * `moduleDetection: "force"` causes TSTL to wrap every file as a module;
16
+ * standalone SLua scripts don't need the ____exports wrapper.
17
+ */
18
+ export declare function stripEmptyModuleBoilerplate(file: lua.File, sourceFiles: readonly ts.SourceFile[] | undefined): boolean;
19
+ /**
20
+ * Collapse default-parameter nil-checks into `x = x or <literal>`.
21
+ * Matches: if x == nil then x = <literal> end
22
+ * Safe for strings and numbers (both truthy in Lua); the TS source only
23
+ * generates these for string/number defaults.
24
+ */
25
+ export declare function collapseDefaultParamNilChecks(file: lua.File): boolean;
26
+ /**
27
+ * Shorten TSTL destructuring temp names: ____*_result_* -> _rN.
28
+ * Two-pass: collect unique names in order, then rename all identifiers.
29
+ */
30
+ export declare function shortenTempNames(file: lua.File): boolean;
31
+ /**
32
+ * Collapse consecutive field accesses from the same shortened temp into
33
+ * multi-assignment: `local a = _r0.x; local b = _r0.y` -> `local a, b = _r0.x, _r0.y`.
34
+ * Only collapses when the base matches `_r\d+` (shortened temps).
35
+ */
36
+ export declare function collapseFieldAccesses(file: lua.File): boolean;
37
+ /**
38
+ * Merge forward-declared `local x` with its first `x = value` assignment.
39
+ * Only inlines when there are no references to x between declaration and assignment.
40
+ */
41
+ export declare function inlineForwardDeclarations(file: lua.File): boolean;