@defold-typescript/transpiler 0.5.5 → 0.6.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.
- package/dist/go-property-direct-call.d.ts +3 -0
- package/dist/index.js +81 -14
- package/dist/lifecycle-erasure.d.ts +2 -0
- package/dist/transpile.d.ts +1 -0
- package/package.json +2 -2
- package/src/go-property-direct-call.ts +26 -0
- package/src/lifecycle-erasure.ts +53 -3
- package/src/transpile.ts +44 -6
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
export declare const GO_PROPERTY_DIRECT_CALL_MESSAGE = "`go.property` called directly is deprecated; declare the property in `defineScript({ properties })` so it types onto `self` (the transpiler emits the registration for you).";
|
|
3
|
+
export declare function findDirectGoPropertyCalls(sourceFile: ts.SourceFile): ts.CallExpression[];
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { readFileSync as readFileSync2 } from "node:fs";
|
|
3
3
|
import { createRequire as createRequire2 } from "node:module";
|
|
4
4
|
import * as path2 from "node:path";
|
|
5
|
-
import * as
|
|
5
|
+
import * as ts5 from "typescript";
|
|
6
6
|
import * as tstl2 from "typescript-to-lua";
|
|
7
7
|
|
|
8
8
|
// src/lifecycle-erasure.ts
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
createIfStatement as createIfStatement2,
|
|
20
20
|
createNilLiteral,
|
|
21
21
|
createReturnStatement,
|
|
22
|
+
createStringLiteral as createStringLiteral2,
|
|
22
23
|
createTableIndexExpression,
|
|
23
24
|
createVariableDeclarationStatement as createVariableDeclarationStatement2,
|
|
24
25
|
NodeFlags as NodeFlags2,
|
|
@@ -141,6 +142,12 @@ var messageDispatchLoweringPlugin = {
|
|
|
141
142
|
// src/lifecycle-erasure.ts
|
|
142
143
|
var FACTORY_MODULE = "@defold-typescript/types";
|
|
143
144
|
var FACTORY_NAMES = new Set(["defineScript", "defineGuiScript", "defineRenderScript"]);
|
|
145
|
+
var FACTORY_SPECIFIERS = new Set([
|
|
146
|
+
FACTORY_MODULE,
|
|
147
|
+
`${FACTORY_MODULE}/script`,
|
|
148
|
+
`${FACTORY_MODULE}/gui-script`,
|
|
149
|
+
`${FACTORY_MODULE}/render-script`
|
|
150
|
+
]);
|
|
144
151
|
function resolvesToFactoryExport(callee, checker) {
|
|
145
152
|
let symbol = checker.getSymbolAtLocation(callee);
|
|
146
153
|
if (symbol === undefined) {
|
|
@@ -236,6 +243,23 @@ function emitInitMerge(fn, context, property) {
|
|
|
236
243
|
const initFn = createFunctionExpression2(createBlock2([stateDecl, guard]), [createIdentifier2("self")], undefined, NodeFlags2.Declaration, fn);
|
|
237
244
|
return [builderDecl, createAssignmentStatement(createIdentifier2("init"), initFn, property)];
|
|
238
245
|
}
|
|
246
|
+
function emitPropertyRegistrations(property, context) {
|
|
247
|
+
if (!ts2.isPropertyAssignment(property) || !ts2.isObjectLiteralExpression(property.initializer)) {
|
|
248
|
+
return [];
|
|
249
|
+
}
|
|
250
|
+
const registrations = [];
|
|
251
|
+
for (const member of property.initializer.properties) {
|
|
252
|
+
if (!ts2.isPropertyAssignment(member)) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
const key = member.name;
|
|
256
|
+
if (!ts2.isIdentifier(key) && !ts2.isStringLiteral(key)) {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
registrations.push(createExpressionStatement(createCallExpression2(createTableIndexExpression(createIdentifier2("go"), createStringLiteral2("property")), [createStringLiteral2(key.text), context.transformExpression(member.initializer)])));
|
|
260
|
+
}
|
|
261
|
+
return registrations;
|
|
262
|
+
}
|
|
239
263
|
function eraseFactoryCall(expression, context) {
|
|
240
264
|
if (!ts2.isCallExpression(expression)) {
|
|
241
265
|
return;
|
|
@@ -247,12 +271,17 @@ function eraseFactoryCall(expression, context) {
|
|
|
247
271
|
if (hooks === undefined || !ts2.isObjectLiteralExpression(hooks)) {
|
|
248
272
|
return;
|
|
249
273
|
}
|
|
274
|
+
const registrations = [];
|
|
250
275
|
const statements = [];
|
|
251
276
|
for (const property of hooks.properties) {
|
|
252
277
|
const name = hookName(property);
|
|
253
278
|
if (name === undefined) {
|
|
254
279
|
continue;
|
|
255
280
|
}
|
|
281
|
+
if (name === "properties") {
|
|
282
|
+
registrations.push(...emitPropertyRegistrations(property, context));
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
256
285
|
const fn = hookFunction(property);
|
|
257
286
|
if (fn === undefined) {
|
|
258
287
|
const dispatch = dispatcherInitializer(property, context.checker);
|
|
@@ -269,10 +298,10 @@ function eraseFactoryCall(expression, context) {
|
|
|
269
298
|
const fnExpression = createFunctionExpression2(createBlock2(transformHookBody(fn, context)), params, undefined, NodeFlags2.Declaration, fn);
|
|
270
299
|
statements.push(createAssignmentStatement(createIdentifier2(name), fnExpression, property));
|
|
271
300
|
}
|
|
272
|
-
return statements;
|
|
301
|
+
return [...registrations, ...statements];
|
|
273
302
|
}
|
|
274
303
|
function isFactoryOnlyImport(node) {
|
|
275
|
-
if (!ts2.isStringLiteral(node.moduleSpecifier) || node.moduleSpecifier.text
|
|
304
|
+
if (!ts2.isStringLiteral(node.moduleSpecifier) || !FACTORY_SPECIFIERS.has(node.moduleSpecifier.text)) {
|
|
276
305
|
return false;
|
|
277
306
|
}
|
|
278
307
|
const clause = node.importClause;
|
|
@@ -347,6 +376,23 @@ import { readdirSync, readFileSync } from "node:fs";
|
|
|
347
376
|
import { createRequire } from "node:module";
|
|
348
377
|
import * as path from "node:path";
|
|
349
378
|
import * as tstl from "typescript-to-lua";
|
|
379
|
+
|
|
380
|
+
// src/go-property-direct-call.ts
|
|
381
|
+
import * as ts4 from "typescript";
|
|
382
|
+
var GO_PROPERTY_DIRECT_CALL_MESSAGE = "`go.property` called directly is deprecated; declare the property in `defineScript({ properties })` so it types onto `self` (the transpiler emits the registration for you).";
|
|
383
|
+
function findDirectGoPropertyCalls(sourceFile) {
|
|
384
|
+
const calls = [];
|
|
385
|
+
const visit = (node) => {
|
|
386
|
+
if (ts4.isCallExpression(node) && ts4.isPropertyAccessExpression(node.expression) && node.expression.name.text === "property" && ts4.isIdentifier(node.expression.expression) && node.expression.expression.text === "go") {
|
|
387
|
+
calls.push(node);
|
|
388
|
+
}
|
|
389
|
+
ts4.forEachChild(node, visit);
|
|
390
|
+
};
|
|
391
|
+
ts4.forEachChild(sourceFile, visit);
|
|
392
|
+
return calls;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/transpile.ts
|
|
350
396
|
function flattenDiagnosticMessage(text) {
|
|
351
397
|
if (typeof text === "string") {
|
|
352
398
|
return text;
|
|
@@ -363,22 +409,27 @@ function buildAmbientFiles() {
|
|
|
363
409
|
const files = {
|
|
364
410
|
"node_modules/@typescript-to-lua/language-extensions/index.d.ts": readFileSync(path.join(TSTL_LANG_EXT_ROOT, "index.d.ts"), "utf8"),
|
|
365
411
|
"node_modules/@defold-typescript/types/src/core-types.ts": readAmbient("src/core-types.ts"),
|
|
412
|
+
"node_modules/@defold-typescript/types/src/engine-globals.d.ts": readAmbient("src/engine-globals.d.ts"),
|
|
413
|
+
"node_modules/@defold-typescript/types/src/go-overloads.d.ts": readAmbient("src/go-overloads.d.ts"),
|
|
366
414
|
"node_modules/@defold-typescript/types/src/msg-overloads.d.ts": readAmbient("src/msg-overloads.d.ts"),
|
|
367
415
|
"node_modules/@defold-typescript/types/src/message-guard.d.ts": readAmbient("src/message-guard.d.ts"),
|
|
368
416
|
"node_modules/@defold-typescript/types/src/message-dispatch.d.ts": readAmbient("src/message-dispatch.d.ts"),
|
|
369
417
|
"node_modules/@defold-typescript/types/src/lifecycle.ts": readAmbient("src/lifecycle.ts"),
|
|
370
418
|
"node_modules/@defold-typescript/types/index.ts": [
|
|
371
419
|
'export { defineGuiScript, defineRenderScript, defineScript } from "./src/lifecycle";',
|
|
372
|
-
'export type { GuiScriptHooks, InputAction, InputTouch, RenderScriptHooks, ScriptHooks } from "./src/lifecycle";',
|
|
420
|
+
'export type { GuiScriptHooks, InputAction, InputTouch, RenderScriptHooks, ScriptHooks, ScriptProperties, ScriptProperty } from "./src/lifecycle";',
|
|
373
421
|
'export type { Hash, Matrix4, Quaternion, Url, Vector, Vector3, Vector4 } from "./src/core-types";',
|
|
374
422
|
""
|
|
375
423
|
].join(`
|
|
376
424
|
`),
|
|
377
|
-
"node_modules/@defold-typescript/types/script.d.ts": `export {};
|
|
425
|
+
"node_modules/@defold-typescript/types/script.d.ts": `export { defineScript } from "./src/lifecycle.js";
|
|
426
|
+
export type { ScriptProperties, ScriptProperty } from "./src/lifecycle.js";
|
|
378
427
|
`,
|
|
379
|
-
"node_modules/@defold-typescript/types/gui-script.d.ts": `export {};
|
|
428
|
+
"node_modules/@defold-typescript/types/gui-script.d.ts": `export { defineGuiScript } from "./src/lifecycle.js";
|
|
429
|
+
export type { ScriptProperties, ScriptProperty } from "./src/lifecycle.js";
|
|
380
430
|
`,
|
|
381
|
-
"node_modules/@defold-typescript/types/render-script.d.ts": `export {};
|
|
431
|
+
"node_modules/@defold-typescript/types/render-script.d.ts": `export { defineRenderScript } from "./src/lifecycle.js";
|
|
432
|
+
export type { ScriptProperties, ScriptProperty } from "./src/lifecycle.js";
|
|
382
433
|
`
|
|
383
434
|
};
|
|
384
435
|
for (const entry of readdirSync(path.join(TYPES_PKG_ROOT, "generated"))) {
|
|
@@ -407,6 +458,22 @@ function collectOutputs(transpiledFiles, diagnostics, userKeys) {
|
|
|
407
458
|
const message = flattenDiagnosticMessage(d.messageText);
|
|
408
459
|
return fileName !== undefined && userKeys.has(fileName) ? { file: fileName, message } : { message };
|
|
409
460
|
});
|
|
461
|
+
const scanned = new Set;
|
|
462
|
+
for (const file of transpiledFiles) {
|
|
463
|
+
for (const sourceFile of file.sourceFiles) {
|
|
464
|
+
if (!userKeys.has(sourceFile.fileName) || scanned.has(sourceFile.fileName)) {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
scanned.add(sourceFile.fileName);
|
|
468
|
+
if (findDirectGoPropertyCalls(sourceFile).length > 0) {
|
|
469
|
+
collectedDiagnostics.push({
|
|
470
|
+
file: sourceFile.fileName,
|
|
471
|
+
message: GO_PROPERTY_DIRECT_CALL_MESSAGE,
|
|
472
|
+
category: "warning"
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
410
477
|
return { lua, sourceMaps, diagnostics: collectedDiagnostics };
|
|
411
478
|
}
|
|
412
479
|
function transpileProject(input) {
|
|
@@ -485,7 +552,7 @@ function createTranspileSession() {
|
|
|
485
552
|
if (cached) {
|
|
486
553
|
return cached;
|
|
487
554
|
}
|
|
488
|
-
const created =
|
|
555
|
+
const created = ts5.createSourceFile(fileName, content, ts5.ScriptTarget.Latest, false);
|
|
489
556
|
sourceFileCache.set(normalized, created);
|
|
490
557
|
return created;
|
|
491
558
|
}
|
|
@@ -504,7 +571,7 @@ function createTranspileSession() {
|
|
|
504
571
|
return cached;
|
|
505
572
|
}
|
|
506
573
|
const fileContent = readFileSync2(filePath, "utf8");
|
|
507
|
-
const created =
|
|
574
|
+
const created = ts5.createSourceFile(filePath, fileContent, ts5.ScriptTarget.Latest, false);
|
|
508
575
|
libCache.set(fileName, created);
|
|
509
576
|
return created;
|
|
510
577
|
}
|
|
@@ -517,10 +584,10 @@ function createTranspileSession() {
|
|
|
517
584
|
return AMBIENT_FILES[normalized];
|
|
518
585
|
}
|
|
519
586
|
const host = {
|
|
520
|
-
fileExists: (fileName) => mergedContent(normalizeSlashes(fileName)) !== undefined ||
|
|
587
|
+
fileExists: (fileName) => mergedContent(normalizeSlashes(fileName)) !== undefined || ts5.sys.fileExists(fileName),
|
|
521
588
|
getCanonicalFileName: (fileName) => fileName,
|
|
522
589
|
getCurrentDirectory: () => "",
|
|
523
|
-
getDefaultLibFileName:
|
|
590
|
+
getDefaultLibFileName: ts5.getDefaultLibFileName,
|
|
524
591
|
readFile: () => "",
|
|
525
592
|
getNewLine: () => `
|
|
526
593
|
`,
|
|
@@ -541,15 +608,15 @@ function createTranspileSession() {
|
|
|
541
608
|
}
|
|
542
609
|
const userKeys = new Set(userFiles.keys());
|
|
543
610
|
const rootNames = [...Object.keys(AMBIENT_FILES).map(normalizeSlashes), ...userKeys];
|
|
544
|
-
program =
|
|
545
|
-
const preEmitDiagnostics =
|
|
611
|
+
program = ts5.createProgram(rootNames, COMPILER_OPTIONS, host, program);
|
|
612
|
+
const preEmitDiagnostics = ts5.getPreEmitDiagnostics(program);
|
|
546
613
|
const collector = createOutputCollector();
|
|
547
614
|
const { diagnostics: transpileDiagnostics } = new tstl2.Transpiler().emit({
|
|
548
615
|
program,
|
|
549
616
|
writeFile: collector.writeFile
|
|
550
617
|
});
|
|
551
618
|
const diagnostics = [
|
|
552
|
-
...
|
|
619
|
+
...ts5.sortAndDeduplicateDiagnostics([...preEmitDiagnostics, ...transpileDiagnostics])
|
|
553
620
|
];
|
|
554
621
|
return collectOutputs(collector.files, diagnostics, userKeys);
|
|
555
622
|
}
|
package/dist/transpile.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defold-typescript/transpiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "TypeScript-to-Lua build pipeline tuned for Defold's runtime.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"test": "bun test"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@defold-typescript/types": "0.
|
|
31
|
+
"@defold-typescript/types": "0.6.0",
|
|
32
32
|
"@typescript-to-lua/language-extensions": "1.19.0",
|
|
33
33
|
"typescript-to-lua": "^1.36.0"
|
|
34
34
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
|
|
3
|
+
export const GO_PROPERTY_DIRECT_CALL_MESSAGE =
|
|
4
|
+
"`go.property` called directly is deprecated; declare the property in `defineScript({ properties })` so it types onto `self` (the transpiler emits the registration for you).";
|
|
5
|
+
|
|
6
|
+
// Match a user-source `go.property(...)` call — a `property` access on the `go`
|
|
7
|
+
// identifier. The blessed `properties`-field form never produces such a call;
|
|
8
|
+
// the synthesized registrations live only in emitted Lua, which this scan never
|
|
9
|
+
// sees (it walks the user TypeScript AST).
|
|
10
|
+
export function findDirectGoPropertyCalls(sourceFile: ts.SourceFile): ts.CallExpression[] {
|
|
11
|
+
const calls: ts.CallExpression[] = [];
|
|
12
|
+
const visit = (node: ts.Node): void => {
|
|
13
|
+
if (
|
|
14
|
+
ts.isCallExpression(node) &&
|
|
15
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
16
|
+
node.expression.name.text === "property" &&
|
|
17
|
+
ts.isIdentifier(node.expression.expression) &&
|
|
18
|
+
node.expression.expression.text === "go"
|
|
19
|
+
) {
|
|
20
|
+
calls.push(node);
|
|
21
|
+
}
|
|
22
|
+
ts.forEachChild(node, visit);
|
|
23
|
+
};
|
|
24
|
+
ts.forEachChild(sourceFile, visit);
|
|
25
|
+
return calls;
|
|
26
|
+
}
|
package/src/lifecycle-erasure.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
createIfStatement,
|
|
12
12
|
createNilLiteral,
|
|
13
13
|
createReturnStatement,
|
|
14
|
+
createStringLiteral,
|
|
14
15
|
createTableIndexExpression,
|
|
15
16
|
createVariableDeclarationStatement,
|
|
16
17
|
type Identifier,
|
|
@@ -24,6 +25,15 @@ import { resolvesToDispatchExport } from "./message-dispatch-lowering";
|
|
|
24
25
|
|
|
25
26
|
const FACTORY_MODULE = "@defold-typescript/types";
|
|
26
27
|
const FACTORY_NAMES = new Set(["defineScript", "defineGuiScript", "defineRenderScript"]);
|
|
28
|
+
// A walled source imports its factory from the matching kind subpath
|
|
29
|
+
// (`@defold-typescript/types/gui-script`) to avoid pulling the cross-kind
|
|
30
|
+
// `declare global` namespaces; those imports erase exactly like the bare one.
|
|
31
|
+
const FACTORY_SPECIFIERS = new Set([
|
|
32
|
+
FACTORY_MODULE,
|
|
33
|
+
`${FACTORY_MODULE}/script`,
|
|
34
|
+
`${FACTORY_MODULE}/gui-script`,
|
|
35
|
+
`${FACTORY_MODULE}/render-script`,
|
|
36
|
+
]);
|
|
27
37
|
|
|
28
38
|
function resolvesToFactoryExport(callee: ts.Expression, checker: ts.TypeChecker): boolean {
|
|
29
39
|
let symbol = checker.getSymbolAtLocation(callee);
|
|
@@ -185,6 +195,38 @@ function emitInitMerge(
|
|
|
185
195
|
return [builderDecl, createAssignmentStatement(createIdentifier("init"), initFn, property)];
|
|
186
196
|
}
|
|
187
197
|
|
|
198
|
+
// The value-keyed `properties` field maps each `key: default` to a chunk-scope
|
|
199
|
+
// `go.property("key", default)` the editor reads. Emitted before the hook
|
|
200
|
+
// assignments and after the source's `local` consts, so a default referencing a
|
|
201
|
+
// module const resolves.
|
|
202
|
+
function emitPropertyRegistrations(
|
|
203
|
+
property: ts.ObjectLiteralElementLike,
|
|
204
|
+
context: TransformationContext,
|
|
205
|
+
): Statement[] {
|
|
206
|
+
if (!ts.isPropertyAssignment(property) || !ts.isObjectLiteralExpression(property.initializer)) {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
const registrations: Statement[] = [];
|
|
210
|
+
for (const member of property.initializer.properties) {
|
|
211
|
+
if (!ts.isPropertyAssignment(member)) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const key = member.name;
|
|
215
|
+
if (!ts.isIdentifier(key) && !ts.isStringLiteral(key)) {
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
registrations.push(
|
|
219
|
+
createExpressionStatement(
|
|
220
|
+
createCallExpression(
|
|
221
|
+
createTableIndexExpression(createIdentifier("go"), createStringLiteral("property")),
|
|
222
|
+
[createStringLiteral(key.text), context.transformExpression(member.initializer)],
|
|
223
|
+
),
|
|
224
|
+
),
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
return registrations;
|
|
228
|
+
}
|
|
229
|
+
|
|
188
230
|
function eraseFactoryCall(
|
|
189
231
|
expression: ts.Expression,
|
|
190
232
|
context: TransformationContext,
|
|
@@ -199,12 +241,17 @@ function eraseFactoryCall(
|
|
|
199
241
|
if (hooks === undefined || !ts.isObjectLiteralExpression(hooks)) {
|
|
200
242
|
return undefined;
|
|
201
243
|
}
|
|
244
|
+
const registrations: Statement[] = [];
|
|
202
245
|
const statements: Statement[] = [];
|
|
203
246
|
for (const property of hooks.properties) {
|
|
204
247
|
const name = hookName(property);
|
|
205
248
|
if (name === undefined) {
|
|
206
249
|
continue;
|
|
207
250
|
}
|
|
251
|
+
if (name === "properties") {
|
|
252
|
+
registrations.push(...emitPropertyRegistrations(property, context));
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
208
255
|
const fn = hookFunction(property);
|
|
209
256
|
if (fn === undefined) {
|
|
210
257
|
// A hook whose initializer is a recognized `onMessage({...})` call: let it
|
|
@@ -238,11 +285,14 @@ function eraseFactoryCall(
|
|
|
238
285
|
);
|
|
239
286
|
statements.push(createAssignmentStatement(createIdentifier(name), fnExpression, property));
|
|
240
287
|
}
|
|
241
|
-
return statements;
|
|
288
|
+
return [...registrations, ...statements];
|
|
242
289
|
}
|
|
243
290
|
|
|
244
|
-
function isFactoryOnlyImport(node: ts.ImportDeclaration): boolean {
|
|
245
|
-
if (
|
|
291
|
+
export function isFactoryOnlyImport(node: ts.ImportDeclaration): boolean {
|
|
292
|
+
if (
|
|
293
|
+
!ts.isStringLiteral(node.moduleSpecifier) ||
|
|
294
|
+
!FACTORY_SPECIFIERS.has(node.moduleSpecifier.text)
|
|
295
|
+
) {
|
|
246
296
|
return false;
|
|
247
297
|
}
|
|
248
298
|
const clause = node.importClause;
|
package/src/transpile.ts
CHANGED
|
@@ -3,6 +3,10 @@ import { createRequire } from "node:module";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import type * as ts from "typescript";
|
|
5
5
|
import * as tstl from "typescript-to-lua";
|
|
6
|
+
import {
|
|
7
|
+
findDirectGoPropertyCalls,
|
|
8
|
+
GO_PROPERTY_DIRECT_CALL_MESSAGE,
|
|
9
|
+
} from "./go-property-direct-call";
|
|
6
10
|
import { lifecycleErasurePlugin } from "./lifecycle-erasure";
|
|
7
11
|
import { messageDispatchLoweringPlugin } from "./message-dispatch-lowering";
|
|
8
12
|
import { messageGuardLoweringPlugin } from "./message-guard-lowering";
|
|
@@ -16,6 +20,10 @@ export interface TranspileResult {
|
|
|
16
20
|
export interface TranspileDiagnostic {
|
|
17
21
|
readonly file?: string;
|
|
18
22
|
readonly message: string;
|
|
23
|
+
// Present only on advisory diagnostics (e.g. the deprecated direct
|
|
24
|
+
// `go.property` call). Absent means a hard failure, so `collectFailures`
|
|
25
|
+
// keeps treating uncategorized diagnostics as fatal.
|
|
26
|
+
readonly category?: "warning";
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
export interface TranspileProjectInput {
|
|
@@ -56,6 +64,10 @@ function buildAmbientFiles(): Record<string, string> {
|
|
|
56
64
|
"utf8",
|
|
57
65
|
),
|
|
58
66
|
"node_modules/@defold-typescript/types/src/core-types.ts": readAmbient("src/core-types.ts"),
|
|
67
|
+
"node_modules/@defold-typescript/types/src/engine-globals.d.ts":
|
|
68
|
+
readAmbient("src/engine-globals.d.ts"),
|
|
69
|
+
"node_modules/@defold-typescript/types/src/go-overloads.d.ts":
|
|
70
|
+
readAmbient("src/go-overloads.d.ts"),
|
|
59
71
|
"node_modules/@defold-typescript/types/src/msg-overloads.d.ts":
|
|
60
72
|
readAmbient("src/msg-overloads.d.ts"),
|
|
61
73
|
"node_modules/@defold-typescript/types/src/message-guard.d.ts":
|
|
@@ -68,16 +80,22 @@ function buildAmbientFiles(): Record<string, string> {
|
|
|
68
80
|
// file can `import { defineScript }` and `import type { Hash, Vector3 }`.
|
|
69
81
|
"node_modules/@defold-typescript/types/index.ts": [
|
|
70
82
|
'export { defineGuiScript, defineRenderScript, defineScript } from "./src/lifecycle";',
|
|
71
|
-
'export type { GuiScriptHooks, InputAction, InputTouch, RenderScriptHooks, ScriptHooks } from "./src/lifecycle";',
|
|
83
|
+
'export type { GuiScriptHooks, InputAction, InputTouch, RenderScriptHooks, ScriptHooks, ScriptProperties, ScriptProperty } from "./src/lifecycle";',
|
|
72
84
|
'export type { Hash, Matrix4, Quaternion, Url, Vector, Vector3, Vector4 } from "./src/core-types";',
|
|
73
85
|
"",
|
|
74
86
|
].join("\n"),
|
|
75
87
|
// Per-kind subpath entrypoints exist as package exports for the editor.
|
|
76
|
-
// Their namespaces are already seeded ambiently below
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"
|
|
88
|
+
// Their namespaces are already seeded ambiently below; mirror slice A's
|
|
89
|
+
// generated `generateKindIndex` output by re-exporting only the matching
|
|
90
|
+
// factory, so a walled source's subpath import resolves to it and the
|
|
91
|
+
// call-site erasure fires (otherwise the import lowers to a broken
|
|
92
|
+
// `require("@defold-typescript/types/gui-script")`).
|
|
93
|
+
"node_modules/@defold-typescript/types/script.d.ts":
|
|
94
|
+
'export { defineScript } from "./src/lifecycle.js";\nexport type { ScriptProperties, ScriptProperty } from "./src/lifecycle.js";\n',
|
|
95
|
+
"node_modules/@defold-typescript/types/gui-script.d.ts":
|
|
96
|
+
'export { defineGuiScript } from "./src/lifecycle.js";\nexport type { ScriptProperties, ScriptProperty } from "./src/lifecycle.js";\n',
|
|
97
|
+
"node_modules/@defold-typescript/types/render-script.d.ts":
|
|
98
|
+
'export { defineRenderScript } from "./src/lifecycle.js";\nexport type { ScriptProperties, ScriptProperty } from "./src/lifecycle.js";\n',
|
|
81
99
|
};
|
|
82
100
|
// Seed every generated namespace so real multi-namespace user code (sprite,
|
|
83
101
|
// physics, label, ...) resolves — not just the historical vmath/msg/go subset.
|
|
@@ -125,6 +143,26 @@ export function collectOutputs(
|
|
|
125
143
|
: { message };
|
|
126
144
|
});
|
|
127
145
|
|
|
146
|
+
// Advisory scan of the user TypeScript AST for the deprecated direct
|
|
147
|
+
// `go.property` call. Run here (shared by transpileProject and the watch
|
|
148
|
+
// session) so both paths report it identically.
|
|
149
|
+
const scanned = new Set<string>();
|
|
150
|
+
for (const file of transpiledFiles) {
|
|
151
|
+
for (const sourceFile of file.sourceFiles) {
|
|
152
|
+
if (!userKeys.has(sourceFile.fileName) || scanned.has(sourceFile.fileName)) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
scanned.add(sourceFile.fileName);
|
|
156
|
+
if (findDirectGoPropertyCalls(sourceFile).length > 0) {
|
|
157
|
+
collectedDiagnostics.push({
|
|
158
|
+
file: sourceFile.fileName,
|
|
159
|
+
message: GO_PROPERTY_DIRECT_CALL_MESSAGE,
|
|
160
|
+
category: "warning",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
128
166
|
return { lua, sourceMaps, diagnostics: collectedDiagnostics };
|
|
129
167
|
}
|
|
130
168
|
|