@defold-typescript/types 0.39.0 → 0.41.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/api-availability.json +4024 -716
- package/api-migrations.json +27 -0
- package/api-signatures.json +18118 -10264
- package/api-targets.json +448 -11
- package/examples/translations.json +619 -148
- package/fixtures/messages_doc.json +96 -0
- package/generated/b2d.d.ts +680 -4
- package/generated/b2d_body.d.ts +29 -103
- package/generated/b2d_chain.d.ts +5 -6
- package/generated/b2d_fixture.d.ts +34 -38
- package/generated/b2d_joint.d.ts +503 -25
- package/generated/b2d_shape.d.ts +199 -14
- package/generated/b2d_world.d.ts +57 -63
- package/generated/buffer.d.ts +33 -29
- package/generated/builtin-messages.d.ts +7 -1
- package/generated/bullet3d.d.ts +91 -0
- package/generated/bullet3d_collision_object.d.ts +433 -0
- package/generated/bullet3d_constraint.d.ts +818 -0
- package/generated/bullet3d_rigid_body.d.ts +429 -0
- package/generated/bullet3d_shape.d.ts +123 -0
- package/generated/bullet3d_world.d.ts +492 -0
- package/generated/camera.d.ts +31 -34
- package/generated/collectionfactory.d.ts +26 -27
- package/generated/collectionproxy.d.ts +22 -6
- package/generated/compute.d.ts +12 -238
- package/generated/crash.d.ts +24 -10
- package/generated/editor-vm/http.d.ts +90 -7
- package/generated/editor-vm/image.d.ts +7 -7
- package/generated/editor-vm/json.d.ts +11 -0
- package/generated/editor-vm/localization.d.ts +7 -7
- package/generated/editor-vm/tilemap_tiles.d.ts +56 -10
- package/generated/editor-vm/zip.d.ts +28 -0
- package/generated/editor.d.ts +1496 -430
- package/generated/factory.d.ts +21 -25
- package/generated/font.d.ts +64 -22
- package/generated/go.d.ts +243 -186
- package/generated/graphics.d.ts +374 -84
- package/generated/gui.d.ts +282 -492
- package/generated/html5.d.ts +5 -3
- package/generated/http.d.ts +31 -36
- package/generated/image.d.ts +127 -85
- package/generated/json.d.ts +34 -16
- package/generated/kinds/gui-script.d.ts +8 -0
- package/generated/kinds/render-script.d.ts +8 -0
- package/generated/kinds/script.d.ts +8 -0
- package/generated/label.d.ts +77 -7
- package/generated/liveupdate.d.ts +13 -10
- package/generated/material.d.ts +312 -360
- package/generated/model.d.ts +72 -42
- package/generated/particlefx.d.ts +19 -28
- package/generated/physics.d.ts +378 -144
- package/generated/profiler.d.ts +14 -24
- package/generated/render.d.ts +294 -297
- package/generated/resource.d.ts +753 -641
- package/generated/socket.d.ts +131 -134
- package/generated/sound.d.ts +65 -34
- package/generated/sprite.d.ts +39 -17
- package/generated/sys.d.ts +237 -182
- package/generated/tilemap.d.ts +21 -16
- package/generated/timer.d.ts +34 -21
- package/generated/versions/defold-1.12.4/b2d_body.d.ts +0 -7
- package/generated/versions/defold-1.12.4/buffer.d.ts +18 -17
- package/generated/versions/defold-1.12.4/camera.d.ts +23 -23
- package/generated/versions/defold-1.12.4/collectionfactory.d.ts +21 -19
- package/generated/versions/defold-1.12.4/collectionproxy.d.ts +2 -2
- package/generated/versions/defold-1.12.4/crash.d.ts +2 -2
- package/generated/versions/defold-1.12.4/factory.d.ts +15 -16
- package/generated/versions/defold-1.12.4/go.d.ts +15 -17
- package/generated/versions/defold-1.12.4/gui.d.ts +111 -193
- package/generated/versions/defold-1.12.4/html5.d.ts +4 -2
- package/generated/versions/defold-1.12.4/http.d.ts +4 -15
- package/generated/versions/defold-1.12.4/image.d.ts +38 -46
- package/generated/versions/defold-1.12.4/index.d.ts +2 -0
- package/generated/versions/defold-1.12.4/json.d.ts +10 -6
- package/generated/versions/defold-1.12.4/label.d.ts +2 -3
- package/generated/versions/defold-1.12.4/liveupdate.d.ts +5 -3
- package/generated/versions/defold-1.12.4/model.d.ts +34 -13
- package/generated/versions/defold-1.12.4/particlefx.d.ts +2 -5
- package/generated/versions/defold-1.12.4/physics.d.ts +82 -78
- package/generated/versions/defold-1.12.4/profiler.d.ts +3 -6
- package/generated/versions/defold-1.12.4/render.d.ts +160 -132
- package/generated/versions/defold-1.12.4/resource.d.ts +212 -209
- package/generated/versions/defold-1.12.4/socket.d.ts +45 -61
- package/generated/versions/defold-1.12.4/sound.d.ts +11 -11
- package/generated/versions/defold-1.12.4/sprite.d.ts +24 -6
- package/generated/versions/defold-1.12.4/sys.d.ts +45 -68
- package/generated/versions/defold-1.12.4/tilemap.d.ts +18 -11
- package/generated/versions/defold-1.12.4/timer.d.ts +5 -3
- package/generated/versions/defold-1.12.4/vmath.d.ts +5 -26
- package/generated/versions/defold-1.12.4/window.d.ts +1 -16
- package/generated/versions/defold-1.13.0/b2d_body.d.ts +10 -55
- package/generated/versions/defold-1.13.0/b2d_fixture.d.ts +25 -25
- package/generated/versions/defold-1.13.0/b2d_shape.d.ts +188 -5
- package/generated/versions/defold-1.13.0/b2d_world.d.ts +16 -10
- package/generated/versions/defold-1.13.0/buffer.d.ts +18 -17
- package/generated/versions/defold-1.13.0/camera.d.ts +27 -27
- package/generated/versions/defold-1.13.0/collectionfactory.d.ts +21 -19
- package/generated/versions/defold-1.13.0/collectionproxy.d.ts +2 -2
- package/generated/versions/defold-1.13.0/compute.d.ts +1 -70
- package/generated/versions/defold-1.13.0/crash.d.ts +2 -2
- package/generated/versions/defold-1.13.0/editor-vm/tilemap_tiles.d.ts +3 -3
- package/generated/versions/defold-1.13.0/editor.d.ts +34 -24
- package/generated/versions/defold-1.13.0/factory.d.ts +15 -16
- package/generated/versions/defold-1.13.0/go.d.ts +15 -17
- package/generated/versions/defold-1.13.0/graphics.d.ts +121 -37
- package/generated/versions/defold-1.13.0/gui.d.ts +111 -193
- package/generated/versions/defold-1.13.0/html5.d.ts +4 -2
- package/generated/versions/defold-1.13.0/http.d.ts +4 -15
- package/generated/versions/defold-1.13.0/image.d.ts +38 -46
- package/generated/versions/defold-1.13.0/index.d.ts +2 -0
- package/generated/versions/defold-1.13.0/json.d.ts +10 -6
- package/generated/versions/defold-1.13.0/label.d.ts +2 -3
- package/generated/versions/defold-1.13.0/liveupdate.d.ts +7 -5
- package/generated/versions/defold-1.13.0/material.d.ts +69 -107
- package/generated/versions/defold-1.13.0/model.d.ts +34 -13
- package/generated/versions/defold-1.13.0/particlefx.d.ts +2 -5
- package/generated/versions/defold-1.13.0/physics.d.ts +82 -78
- package/generated/versions/defold-1.13.0/profiler.d.ts +3 -6
- package/generated/versions/defold-1.13.0/render.d.ts +160 -132
- package/generated/versions/defold-1.13.0/resource.d.ts +217 -210
- package/generated/versions/defold-1.13.0/socket.d.ts +45 -61
- package/generated/versions/defold-1.13.0/sound.d.ts +11 -11
- package/generated/versions/defold-1.13.0/sprite.d.ts +24 -6
- package/generated/versions/defold-1.13.0/sys.d.ts +45 -68
- package/generated/versions/defold-1.13.0/tilemap.d.ts +18 -11
- package/generated/versions/defold-1.13.0/timer.d.ts +5 -3
- package/generated/versions/defold-1.13.0/vmath.d.ts +5 -26
- package/generated/versions/defold-1.13.0/window.d.ts +1 -16
- package/generated/versions/defold-1.13.1/b2d.d.ts +33 -0
- package/generated/versions/defold-1.13.1/b2d_body.d.ts +636 -0
- package/generated/versions/defold-1.13.1/b2d_chain.d.ts +106 -0
- package/generated/versions/defold-1.13.1/b2d_fixture.d.ts +157 -0
- package/generated/versions/defold-1.13.1/b2d_joint.d.ts +823 -0
- package/generated/versions/defold-1.13.1/b2d_shape.d.ts +400 -0
- package/generated/versions/defold-1.13.1/b2d_world.d.ts +320 -0
- package/generated/versions/defold-1.13.1/buffer.d.ts +189 -0
- package/generated/versions/defold-1.13.1/camera.d.ts +303 -0
- package/generated/versions/defold-1.13.1/collectionfactory.d.ts +151 -0
- package/generated/versions/defold-1.13.1/collectionproxy.d.ts +93 -0
- package/generated/versions/defold-1.13.1/compute.d.ts +237 -0
- package/generated/versions/defold-1.13.1/crash.d.ts +143 -0
- package/generated/versions/defold-1.13.1/editor-vm/http.d.ts +56 -0
- package/generated/versions/defold-1.13.1/editor-vm/image.d.ts +48 -0
- package/generated/versions/defold-1.13.1/editor-vm/json.d.ts +10 -0
- package/generated/versions/defold-1.13.1/editor-vm/localization.d.ts +42 -0
- package/generated/versions/defold-1.13.1/editor-vm/tilemap_tiles.d.ts +80 -0
- package/generated/versions/defold-1.13.1/editor-vm/zip.d.ts +10 -0
- package/generated/versions/defold-1.13.1/editor-vm/zlib.d.ts +24 -0
- package/generated/versions/defold-1.13.1/editor.d.ts +1121 -0
- package/generated/versions/defold-1.13.1/factory.d.ts +124 -0
- package/generated/versions/defold-1.13.1/font.d.ts +81 -0
- package/generated/versions/defold-1.13.1/go.d.ts +1107 -0
- package/generated/versions/defold-1.13.1/graphics.d.ts +411 -0
- package/generated/versions/defold-1.13.1/gui.d.ts +2353 -0
- package/generated/versions/defold-1.13.1/html5.d.ts +55 -0
- package/generated/versions/defold-1.13.1/http.d.ts +77 -0
- package/generated/versions/defold-1.13.1/image.d.ts +131 -0
- package/generated/versions/defold-1.13.1/index.d.ts +57 -0
- package/generated/versions/defold-1.13.1/json.d.ts +80 -0
- package/generated/versions/defold-1.13.1/kinds/editor-script.d.ts +14 -0
- package/generated/versions/defold-1.13.1/label.d.ts +93 -0
- package/generated/versions/defold-1.13.1/liveupdate.d.ts +142 -0
- package/generated/versions/defold-1.13.1/material.d.ts +408 -0
- package/generated/versions/defold-1.13.1/model.d.ts +272 -0
- package/generated/versions/defold-1.13.1/msg.d.ts +10 -0
- package/generated/versions/defold-1.13.1/particlefx.d.ts +163 -0
- package/generated/versions/defold-1.13.1/physics.d.ts +559 -0
- package/generated/versions/defold-1.13.1/profiler.d.ts +235 -0
- package/generated/versions/defold-1.13.1/render.d.ts +1190 -0
- package/generated/versions/defold-1.13.1/resource.d.ts +1523 -0
- package/generated/versions/defold-1.13.1/socket.d.ts +784 -0
- package/generated/versions/defold-1.13.1/sound.d.ts +292 -0
- package/generated/versions/defold-1.13.1/sprite.d.ts +175 -0
- package/generated/versions/defold-1.13.1/sys.d.ts +678 -0
- package/generated/versions/defold-1.13.1/tilemap.d.ts +208 -0
- package/generated/versions/defold-1.13.1/timer.d.ts +125 -0
- package/generated/versions/defold-1.13.1/types.d.ts +61 -0
- package/generated/versions/defold-1.13.1/vmath.d.ts +774 -0
- package/generated/versions/defold-1.13.1/window.d.ts +183 -0
- package/generated/versions/defold-1.13.1/zlib.d.ts +41 -0
- package/generated/vmath.d.ts +6 -26
- package/generated/window.d.ts +71 -71
- package/identity-vocabulary.json +561 -0
- package/index.d.ts +8 -0
- package/package.json +13 -2
- package/scripts/example-store-io.ts +12 -1
- package/scripts/extension-goldens.ts +1 -0
- package/scripts/fidelity-baseline.json +146 -46
- package/scripts/generate-api-availability.ts +90 -12
- package/scripts/generate-api-signatures.ts +14 -3
- package/scripts/import-defold-release.ts +85 -24
- package/scripts/prose-constants.ts +157 -0
- package/scripts/regen.ts +396 -78
- package/scripts/shared-handle-methods.ts +53 -0
- package/scripts/signature-store-fs.ts +1 -0
- package/scripts/sync-api-docs.ts +16 -5
- package/src/api-availability.ts +0 -0
- package/src/api-doc.ts +201 -3
- package/src/api-identity.ts +252 -0
- package/src/component-properties.d.ts +33 -0
- package/src/core-types.ts +28 -3
- package/src/correction-pins.ts +49 -0
- package/src/custom-messages.d.ts +4 -3
- package/src/doc-comment.ts +139 -23
- package/src/doc-corrections.ts +108 -0
- package/src/editor-vm-globals.d.ts +5 -2
- package/src/emit-dts.ts +2474 -281
- package/src/emit-messages.ts +52 -0
- package/src/engine-globals.d.ts +2 -2
- package/src/example-store.ts +125 -14
- package/src/field-correction-coverage.ts +204 -0
- package/src/fnv1a.ts +16 -0
- package/src/go-overloads.d.ts +33 -13
- package/src/index-base-table.ts +145 -0
- package/src/index-slot-classifications.ts +588 -0
- package/src/index.ts +39 -2
- package/src/library-index-slot-classifications.ts +332 -0
- package/src/lifecycle.ts +61 -199
- package/src/luals-type-expr.ts +354 -0
- package/src/msg-overloads.d.ts +0 -1
- package/src/param-correction-provenance.ts +64 -0
- package/src/return-correction-provenance.ts +58 -16
- package/src/script-api.ts +3 -1
- package/src/sys-overloads.d.ts +48 -0
- package/src/vmath-overloads.d.ts +27 -1
- package/src/window-event-guard.d.ts +6 -9
- package/url-parameters.json +1 -2
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { ModuleManifestEntry } from "./regen";
|
|
2
|
+
|
|
3
|
+
// A method the engine shares across several handle classes where a release's
|
|
4
|
+
// ref-doc documents it on only some of them. The handles it omits are restored
|
|
5
|
+
// from the documented one, so a doc omission never drops a method the engine
|
|
6
|
+
// still binds. Applies only where the source handle documents it.
|
|
7
|
+
export interface SharedHandleMethod {
|
|
8
|
+
readonly namespace: string;
|
|
9
|
+
readonly method: string;
|
|
10
|
+
readonly source: string;
|
|
11
|
+
readonly handles: readonly string[];
|
|
12
|
+
readonly evidence: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const TCP_ANY =
|
|
16
|
+
'LuaSocket tcp.c binds it in the one method table every tcp class shares, and checks its argument with auxiliar_checkgroup(L, "tcp{any}", 1)';
|
|
17
|
+
|
|
18
|
+
export const SHARED_HANDLE_METHODS: readonly SharedHandleMethod[] = (
|
|
19
|
+
["getstats", "setstats"] as const
|
|
20
|
+
).map((method) => ({
|
|
21
|
+
namespace: "socket",
|
|
22
|
+
method,
|
|
23
|
+
source: "client",
|
|
24
|
+
handles: ["master", "server"],
|
|
25
|
+
evidence: TCP_ANY,
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
interface DocElement {
|
|
29
|
+
readonly name: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function restoreSharedHandleMethods(
|
|
33
|
+
modules: readonly ModuleManifestEntry[],
|
|
34
|
+
): ModuleManifestEntry[] {
|
|
35
|
+
return modules.map((entry) => {
|
|
36
|
+
const shared = SHARED_HANDLE_METHODS.filter((row) => row.namespace === entry.namespace);
|
|
37
|
+
if (shared.length === 0) return entry;
|
|
38
|
+
const doc = entry.doc as { elements: DocElement[] };
|
|
39
|
+
const declared = new Set(doc.elements.map((element) => element.name));
|
|
40
|
+
const restored: DocElement[] = [];
|
|
41
|
+
for (const { method, source, handles } of shared) {
|
|
42
|
+
const documented = doc.elements.find((element) => element.name === `${source}:${method}`);
|
|
43
|
+
if (documented === undefined) continue;
|
|
44
|
+
for (const handle of handles) {
|
|
45
|
+
const name = `${handle}:${method}`;
|
|
46
|
+
if (!declared.has(name)) restored.push({ ...documented, name });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return restored.length === 0
|
|
50
|
+
? entry
|
|
51
|
+
: { ...entry, doc: { ...doc, elements: [...doc.elements, ...restored] } };
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -25,6 +25,7 @@ export const VMATH_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures"
|
|
|
25
25
|
export const GO_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "go.json");
|
|
26
26
|
export const MSG_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "msg.json");
|
|
27
27
|
export const RENDER_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "render.json");
|
|
28
|
+
export const SYS_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "sys.json");
|
|
28
29
|
|
|
29
30
|
export function loadSignatureFile(path: string): SignatureStore {
|
|
30
31
|
let raw: string;
|
package/scripts/sync-api-docs.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { MODULE_MANIFEST } from "./regen";
|
|
|
11
11
|
// model because the per-package `rootDir` boundary forbids a types-package
|
|
12
12
|
// module importing outside its own tree; `scripts/release-model.test.ts`
|
|
13
13
|
// correspondence-guards these against the model so drift fails CI.
|
|
14
|
-
export const DEFOLD_VERSION = "1.13.
|
|
14
|
+
export const DEFOLD_VERSION = "1.13.2";
|
|
15
15
|
export const refDocUrl = (version = DEFOLD_VERSION): string =>
|
|
16
16
|
`https://github.com/defold/defold/releases/download/${version}/ref-doc.zip`;
|
|
17
17
|
|
|
@@ -52,13 +52,24 @@ export const SYNC_MANIFEST: readonly SyncManifestEntry[] = [
|
|
|
52
52
|
"doc/scripts-box2d-v3-script_box2d_world_v3.cpp_doc.json",
|
|
53
53
|
]),
|
|
54
54
|
entry("buffer", "doc/scripts-script_buffer.cpp_doc.json"),
|
|
55
|
+
entry("bullet3d", "doc/scripts-bullet3d-script_bullet3d.cpp_doc.json"),
|
|
56
|
+
entry(
|
|
57
|
+
"bullet3d.collision_object",
|
|
58
|
+
"doc/scripts-bullet3d-script_bullet3d_collision_object.cpp_doc.json",
|
|
59
|
+
),
|
|
60
|
+
entry("bullet3d.constraint", "doc/scripts-bullet3d-script_bullet3d_constraint.cpp_doc.json"),
|
|
61
|
+
entry("bullet3d.rigid_body", "doc/scripts-bullet3d-script_bullet3d_rigid_body.cpp_doc.json"),
|
|
62
|
+
entry("bullet3d.shape", "doc/scripts-bullet3d-script_bullet3d_shape.cpp_doc.json"),
|
|
63
|
+
entry("bullet3d.world", "doc/scripts-bullet3d-script_bullet3d_world.cpp_doc.json"),
|
|
55
64
|
// Camera and component namespaces merge their DDF messages/properties into
|
|
56
65
|
// the callable script API so release snapshots retain every declared symbol.
|
|
57
66
|
entry("camera", "doc/gamesys-camera_ddf.proto_doc.json", undefined, [
|
|
58
67
|
"doc/render-render_script_camera.cpp_doc.json",
|
|
59
68
|
]),
|
|
60
69
|
entry("collectionfactory", "doc/scripts-script_collection_factory.cpp_doc.json"),
|
|
61
|
-
entry("collectionproxy", "doc/scripts-script_collectionproxy.cpp_doc.json"
|
|
70
|
+
entry("collectionproxy", "doc/scripts-script_collectionproxy.cpp_doc.json", undefined, [
|
|
71
|
+
"doc/gamesys-collectionproxy_ddf.proto_doc.json",
|
|
72
|
+
]),
|
|
62
73
|
entry("compute", "doc/scripts-script_compute.cpp_doc.json"),
|
|
63
74
|
entry("crash", "doc/script_crash.cpp_doc.json"),
|
|
64
75
|
entry("factory", "doc/scripts-script_factory.cpp_doc.json"),
|
|
@@ -115,11 +126,11 @@ export const SYNC_MANIFEST: readonly SyncManifestEntry[] = [
|
|
|
115
126
|
export const UNMAPPED: ReadonlyMap<string, string> = new Map();
|
|
116
127
|
|
|
117
128
|
// A Lua script namespace is a lowercase, dot-separated identifier (`sys`,
|
|
118
|
-
// `b2d.body`). The native C/C++ SDK docs (`dmGraphics`, …), the C# bindings
|
|
129
|
+
// `b2d.body`, `bullet3d.rigid_body`). The native C/C++ SDK docs (`dmGraphics`, …), the C# bindings
|
|
119
130
|
// (`cs-*`), and the struct-only docs (empty `info.namespace`) fail this shape,
|
|
120
131
|
// so the upstream-coverage guard skips them structurally rather than listing
|
|
121
132
|
// each by hand — that keeps the guard self-maintaining as the SDK grows.
|
|
122
|
-
const LUA_NAMESPACE = /^[a-z][a-z0-
|
|
133
|
+
const LUA_NAMESPACE = /^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$/;
|
|
123
134
|
|
|
124
135
|
// Lowercase-identifier namespaces that pass LUA_NAMESPACE but are intentionally
|
|
125
136
|
// not wired through SYNC_MANIFEST, each with a sourced reason (mirrors the
|
|
@@ -205,7 +216,7 @@ function editorVm(namespace: string): SyncManifestEntry {
|
|
|
205
216
|
function entry(
|
|
206
217
|
namespace: string,
|
|
207
218
|
zipEntry: string,
|
|
208
|
-
fixture: string = `fixtures/defold-1.13.
|
|
219
|
+
fixture: string = `fixtures/defold-1.13.2/${namespace.replace(/\./g, "_")}_doc.json`,
|
|
209
220
|
mergeEntries?: readonly string[],
|
|
210
221
|
): SyncManifestEntry {
|
|
211
222
|
return { namespace, zipEntry, fixture, ...(mergeEntries ? { mergeEntries } : {}) };
|
package/src/api-availability.ts
CHANGED
|
Binary file
|
package/src/api-doc.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { correctedDoc, docCorrectionKey } from "./doc-corrections";
|
|
2
|
+
|
|
1
3
|
export interface ApiModule {
|
|
2
4
|
namespace: string;
|
|
3
5
|
brief: string;
|
|
@@ -7,6 +9,39 @@ export interface ApiModule {
|
|
|
7
9
|
constants: ApiConstant[];
|
|
8
10
|
properties: ApiProperty[];
|
|
9
11
|
typedefs: ApiTypedef[];
|
|
12
|
+
/**
|
|
13
|
+
* Each ref-doc `ENUM`, whose members are also lowered into `constants`. Absent
|
|
14
|
+
* on a hand-built module, which reads the same as an empty list.
|
|
15
|
+
*/
|
|
16
|
+
enums?: ApiEnum[];
|
|
17
|
+
/** Each ref-doc `STRUCT`. Absent on a hand-built module, read as an empty list. */
|
|
18
|
+
structs?: ApiStruct[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** A ref-doc `STRUCT`: a named table shape. */
|
|
22
|
+
export interface ApiStruct {
|
|
23
|
+
name: string;
|
|
24
|
+
brief: string;
|
|
25
|
+
description: string;
|
|
26
|
+
members: ApiStructMember[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** One `STRUCT` member; upstream marks an optional one with a `name?` suffix. */
|
|
30
|
+
export interface ApiStructMember {
|
|
31
|
+
name: string;
|
|
32
|
+
doc: string;
|
|
33
|
+
/** One LuaLS type expression. */
|
|
34
|
+
type: string;
|
|
35
|
+
isOptional: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A ref-doc `ENUM`: a named set of constants, each lowered into `constants`. */
|
|
39
|
+
export interface ApiEnum {
|
|
40
|
+
name: string;
|
|
41
|
+
brief: string;
|
|
42
|
+
description: string;
|
|
43
|
+
/** The member FQNs, in documentation order. */
|
|
44
|
+
members: string[];
|
|
10
45
|
}
|
|
11
46
|
|
|
12
47
|
export interface ApiProperty {
|
|
@@ -24,6 +59,11 @@ export interface ApiTypedef {
|
|
|
24
59
|
types?: string[];
|
|
25
60
|
/** The type text of each parent an interface-backed typedef extends. */
|
|
26
61
|
extends?: string[];
|
|
62
|
+
/**
|
|
63
|
+
* The type an engine ref-doc `TYPEDEF` aliases (`parameters[0].types`): a
|
|
64
|
+
* handle's `userdata`/`number`, or the arms of a union, literal or record alias.
|
|
65
|
+
*/
|
|
66
|
+
aliasOf?: string[];
|
|
27
67
|
/** See {@link ApiFunction.global}. */
|
|
28
68
|
global?: true;
|
|
29
69
|
}
|
|
@@ -32,6 +72,16 @@ export interface ApiConstant {
|
|
|
32
72
|
name: string;
|
|
33
73
|
brief: string;
|
|
34
74
|
description: string;
|
|
75
|
+
/**
|
|
76
|
+
* Present when the constant is a member of an `ENUM` whose value type is
|
|
77
|
+
* `string` (`parameters[0].types`); absence means a number, as every
|
|
78
|
+
* pre-`ENUM` constant is.
|
|
79
|
+
*/
|
|
80
|
+
valueType?: "string";
|
|
81
|
+
/** Present when an `ENUM` member is typed `<ENUM>|nil`: some platforms leave it unset. */
|
|
82
|
+
nilable?: true;
|
|
83
|
+
/** The documented constant a back-filled one shares its value, and so its type, with. */
|
|
84
|
+
aliasOf?: string;
|
|
35
85
|
/** See {@link ApiFunction.global}. */
|
|
36
86
|
global?: true;
|
|
37
87
|
}
|
|
@@ -122,6 +172,27 @@ function docSourceKey(element: Record<string, unknown>): { docSource?: "upstream
|
|
|
122
172
|
return element.docSource === "upstream" ? { docSource: "upstream" } : {};
|
|
123
173
|
}
|
|
124
174
|
|
|
175
|
+
// A function the ref-doc names differently from the name its engine binding
|
|
176
|
+
// registers, so the documented call raises "attempt to call a nil value". Keyed
|
|
177
|
+
// by the ref-doc FQN; `name` is the registered FQN and `evidence` the
|
|
178
|
+
// registration. The parse renames the element, so the declaration, the signature
|
|
179
|
+
// store, the example translations and every audit read the bound name. An entry
|
|
180
|
+
// is deleted once no retained target documents the old name.
|
|
181
|
+
export interface FunctionNameCorrection {
|
|
182
|
+
readonly name: string;
|
|
183
|
+
readonly evidence: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export const FUNCTION_NAME_CORRECTIONS: ReadonlyMap<string, FunctionNameCorrection> = new Map([
|
|
187
|
+
[
|
|
188
|
+
"sys.set_render_enable",
|
|
189
|
+
{
|
|
190
|
+
name: "sys.set_render_enabled",
|
|
191
|
+
evidence: 'script_engine.cpp registers {"set_render_enabled", EngineSys_SetRenderEnabled}',
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
]);
|
|
195
|
+
|
|
125
196
|
export function parseDefoldApiDoc(input: unknown): ApiModule {
|
|
126
197
|
if (!isRecord(input)) {
|
|
127
198
|
throw new Error(`parseDefoldApiDoc: expected object, got ${describeKind(input)}`);
|
|
@@ -145,24 +216,99 @@ export function parseDefoldApiDoc(input: unknown): ApiModule {
|
|
|
145
216
|
const constants: ApiConstant[] = [];
|
|
146
217
|
const properties: ApiProperty[] = [];
|
|
147
218
|
const typedefs: ApiTypedef[] = [];
|
|
219
|
+
const enums: ApiEnum[] = [];
|
|
220
|
+
const structs: ApiStruct[] = [];
|
|
148
221
|
|
|
149
222
|
for (const element of elements) {
|
|
150
223
|
if (!isRecord(element)) continue;
|
|
151
224
|
const type = element.type;
|
|
152
225
|
if (type === "FUNCTION") {
|
|
153
|
-
|
|
226
|
+
const fn = withDocCorrections(parseFunction(element));
|
|
227
|
+
const corrected = FUNCTION_NAME_CORRECTIONS.get(fn.name);
|
|
228
|
+
functions.push(corrected === undefined ? fn : { ...fn, name: corrected.name });
|
|
154
229
|
} else if (type === "VARIABLE") {
|
|
155
230
|
variables.push(parseVariable(element));
|
|
156
231
|
} else if (type === "CONSTANT") {
|
|
157
232
|
constants.push(parseConstant(element));
|
|
158
233
|
} else if (type === "PROPERTY") {
|
|
159
|
-
|
|
234
|
+
const property = parseProperty(element);
|
|
235
|
+
const doc = correctedDoc(
|
|
236
|
+
docCorrectionKey(namespace, "property", property.name),
|
|
237
|
+
property.description,
|
|
238
|
+
);
|
|
239
|
+
properties.push(doc === property.description ? property : { ...property, description: doc });
|
|
160
240
|
} else if (type === "TYPEDEF") {
|
|
161
241
|
typedefs.push(parseTypedef(element));
|
|
242
|
+
} else if (type === "ENUM") {
|
|
243
|
+
const members = parseEnumMembers(element);
|
|
244
|
+
constants.push(...members);
|
|
245
|
+
enums.push({
|
|
246
|
+
name: stringOr(element.name, ""),
|
|
247
|
+
brief: stringOr(element.brief, ""),
|
|
248
|
+
description: stringOr(element.description, ""),
|
|
249
|
+
members: members.map((m) => m.name),
|
|
250
|
+
});
|
|
251
|
+
} else if (type === "STRUCT") {
|
|
252
|
+
structs.push(parseStruct(element));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
namespace,
|
|
258
|
+
brief,
|
|
259
|
+
description,
|
|
260
|
+
functions,
|
|
261
|
+
variables,
|
|
262
|
+
constants,
|
|
263
|
+
properties,
|
|
264
|
+
typedefs,
|
|
265
|
+
enums,
|
|
266
|
+
structs,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Withholds one overload of a documented function — the one whose `param` has
|
|
271
|
+
// exactly the upstream type `type` — while its same-named siblings still emit.
|
|
272
|
+
// `name` is the local name, like a `skipFunctions` rule.
|
|
273
|
+
export interface SkipOverloadRule {
|
|
274
|
+
readonly name: string;
|
|
275
|
+
readonly param: string;
|
|
276
|
+
readonly type: string;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function withholdOverloads(
|
|
280
|
+
module: ApiModule,
|
|
281
|
+
rules: readonly SkipOverloadRule[],
|
|
282
|
+
): ApiModule {
|
|
283
|
+
let functions = module.functions;
|
|
284
|
+
for (const rule of rules) {
|
|
285
|
+
const fqn = `${module.namespace}.${rule.name}`;
|
|
286
|
+
const kept = functions.filter(
|
|
287
|
+
(fn) =>
|
|
288
|
+
fn.name !== fqn ||
|
|
289
|
+
!fn.parameters.some(
|
|
290
|
+
(p) => p.name === rule.param && p.types.length === 1 && p.types[0] === rule.type,
|
|
291
|
+
),
|
|
292
|
+
);
|
|
293
|
+
if (kept.length === functions.length) {
|
|
294
|
+
throw new Error(`skipOverloads: ${fqn} has no overload whose ${rule.param} is ${rule.type}`);
|
|
162
295
|
}
|
|
296
|
+
functions = kept;
|
|
163
297
|
}
|
|
298
|
+
return functions === module.functions ? module : { ...module, functions };
|
|
299
|
+
}
|
|
164
300
|
|
|
165
|
-
|
|
301
|
+
// Keyed by the ref-doc FQN, before any `FUNCTION_NAME_CORRECTIONS` rename.
|
|
302
|
+
function withDocCorrections(fn: ApiFunction): ApiFunction {
|
|
303
|
+
const correct = (slot: "param" | "return") => (p: ApiParameter) => {
|
|
304
|
+
const doc = correctedDoc(docCorrectionKey(fn.name, slot, p.name), p.doc);
|
|
305
|
+
return doc === p.doc ? p : { ...p, doc };
|
|
306
|
+
};
|
|
307
|
+
return {
|
|
308
|
+
...fn,
|
|
309
|
+
parameters: fn.parameters.map(correct("param")),
|
|
310
|
+
returnValues: fn.returnValues.map(correct("return")),
|
|
311
|
+
};
|
|
166
312
|
}
|
|
167
313
|
|
|
168
314
|
function parseTypedef(element: Record<string, unknown>): ApiTypedef {
|
|
@@ -170,16 +316,41 @@ function parseTypedef(element: Record<string, unknown>): ApiTypedef {
|
|
|
170
316
|
const properties = parseVariableList(element.properties);
|
|
171
317
|
const types = parseStringArray(element.types);
|
|
172
318
|
const parents = parseStringArray(element.extends);
|
|
319
|
+
const [aliased] = parseParameterList(element.parameters);
|
|
320
|
+
const aliasOf = aliased?.types ?? [];
|
|
173
321
|
return {
|
|
174
322
|
name: stringOr(element.name, ""),
|
|
175
323
|
...(functions.length > 0 ? { functions } : {}),
|
|
176
324
|
...(properties.length > 0 ? { properties } : {}),
|
|
177
325
|
...(types.length > 0 ? { types } : {}),
|
|
178
326
|
...(parents.length > 0 ? { extends: parents } : {}),
|
|
327
|
+
...(aliasOf.length > 0 ? { aliasOf } : {}),
|
|
179
328
|
...globalKey(element),
|
|
180
329
|
};
|
|
181
330
|
}
|
|
182
331
|
|
|
332
|
+
function parseStruct(element: Record<string, unknown>): ApiStruct {
|
|
333
|
+
const raw = Array.isArray(element.members) ? element.members : [];
|
|
334
|
+
const members: ApiStructMember[] = [];
|
|
335
|
+
for (const member of raw) {
|
|
336
|
+
if (!isRecord(member)) continue;
|
|
337
|
+
const name = stringOr(member.name, "");
|
|
338
|
+
const isOptional = name.endsWith("?");
|
|
339
|
+
members.push({
|
|
340
|
+
name: isOptional ? name.slice(0, -1) : name,
|
|
341
|
+
doc: stringOr(member.doc, ""),
|
|
342
|
+
type: stringOr(member.type, ""),
|
|
343
|
+
isOptional,
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
name: stringOr(element.name, ""),
|
|
348
|
+
brief: stringOr(element.brief, ""),
|
|
349
|
+
description: stringOr(element.description, ""),
|
|
350
|
+
members,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
183
354
|
function parseProperty(element: Record<string, unknown>): ApiProperty {
|
|
184
355
|
const brief = stringOr(element.brief, "");
|
|
185
356
|
const span = /<span class="type">([^<]+)<\/span>/.exec(brief);
|
|
@@ -207,6 +378,33 @@ function parseConstant(element: Record<string, unknown>): ApiConstant {
|
|
|
207
378
|
};
|
|
208
379
|
}
|
|
209
380
|
|
|
381
|
+
// A member carries one `doc` string where a constant carried `brief` and
|
|
382
|
+
// `description`; both take it.
|
|
383
|
+
function parseEnumMembers(element: Record<string, unknown>): ApiConstant[] {
|
|
384
|
+
// A member named bare (1.13.2's bullet3d enums) is registered on the enum's
|
|
385
|
+
// own namespace, so it takes that prefix.
|
|
386
|
+
const enumName = stringOr(element.name, "");
|
|
387
|
+
const owner = enumName.includes(".") ? enumName.slice(0, enumName.lastIndexOf(".")) : "";
|
|
388
|
+
const qualify = (name: string): string =>
|
|
389
|
+
name.includes(".") || owner === "" ? name : `${owner}.${name}`;
|
|
390
|
+
const [value] = parseParameterList(element.parameters);
|
|
391
|
+
const valueType = value?.types.length === 1 && value.types[0] === "string" ? "string" : null;
|
|
392
|
+
const raw = Array.isArray(element.members) ? element.members : [];
|
|
393
|
+
const out: ApiConstant[] = [];
|
|
394
|
+
for (const member of raw) {
|
|
395
|
+
if (!isRecord(member)) continue;
|
|
396
|
+
const doc = stringOr(member.doc, "");
|
|
397
|
+
out.push({
|
|
398
|
+
name: qualify(stringOr(member.name, "")),
|
|
399
|
+
brief: doc,
|
|
400
|
+
description: doc,
|
|
401
|
+
...(valueType === null ? {} : { valueType }),
|
|
402
|
+
...(stringOr(member.type, "").endsWith("|nil") ? { nilable: true } : {}),
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
return out;
|
|
406
|
+
}
|
|
407
|
+
|
|
210
408
|
function parseFunction(element: Record<string, unknown>): ApiFunction {
|
|
211
409
|
return {
|
|
212
410
|
name: stringOr(element.name, ""),
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import type { ApiFunction, ApiModule, ApiParameter } from "./api-doc";
|
|
2
|
+
import { DEFOLD_TYPE_MAP } from "./core-types";
|
|
3
|
+
import { pinMatches } from "./correction-pins";
|
|
4
|
+
import { splitTopLevel } from "./luals-type-expr";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A type correction as identity applies it: where the slot still declares one of
|
|
8
|
+
* `pins`, its values are the declared ones less `removes` plus `adds`, or
|
|
9
|
+
* `replaces` outright. Every list is written in ref-doc or TypeScript spelling;
|
|
10
|
+
* both canonicalize to the same values.
|
|
11
|
+
*/
|
|
12
|
+
export interface IdentityCorrection {
|
|
13
|
+
readonly pins: readonly (readonly string[])[];
|
|
14
|
+
readonly adds?: readonly string[];
|
|
15
|
+
readonly removes?: readonly string[];
|
|
16
|
+
readonly replaces?: readonly string[];
|
|
17
|
+
/** A return correction's slot name, when it rewrites one of several returns. */
|
|
18
|
+
readonly slot?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The corrections this repo records from verified engine behavior. Identity
|
|
23
|
+
* follows them rather than each release's markup, so a release whose ref-doc
|
|
24
|
+
* starts stating what a correction already did is not a change.
|
|
25
|
+
*/
|
|
26
|
+
export interface IdentityCorrections {
|
|
27
|
+
/** `<element>:param:<slot>` keys a correction makes optional. */
|
|
28
|
+
readonly optionalSlots: readonly string[];
|
|
29
|
+
/** `<element>:param:<slot>` keys a correction keeps required. */
|
|
30
|
+
readonly requiredSlots: readonly string[];
|
|
31
|
+
/** Keyed `<element>:param:<slot>`. */
|
|
32
|
+
readonly parameterCorrections: Readonly<Record<string, IdentityCorrection>>;
|
|
33
|
+
/** Keyed by element. */
|
|
34
|
+
readonly returnCorrections: Readonly<Record<string, IdentityCorrection>>;
|
|
35
|
+
/** Constant-family aliases a correction may name (`window.DimModeStateSettable`), with members. */
|
|
36
|
+
readonly constantFamilies: Readonly<Record<string, readonly string[]>>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The names a ref-doc type token may refer to, gathered across every committed
|
|
41
|
+
* target so each release's spelling resolves the same way, plus the corrections.
|
|
42
|
+
* A name keeps its kind across releases: a 1.13.2 `STRUCT` is a table wherever
|
|
43
|
+
* it appears.
|
|
44
|
+
*/
|
|
45
|
+
export interface IdentityVocabulary extends Omit<IdentityCorrections, "constantFamilies"> {
|
|
46
|
+
/** `STRUCT` names: a table at runtime. */
|
|
47
|
+
readonly tables: readonly string[];
|
|
48
|
+
/** `ENUM` names and constant families, with the runtime type of their members. */
|
|
49
|
+
readonly enums: Readonly<Record<string, "number" | "string">>;
|
|
50
|
+
/** Constants whose value is a string; every other constant is a number. */
|
|
51
|
+
readonly stringConstants: readonly string[];
|
|
52
|
+
/** Non-handle `TYPEDEF` names and the tokens they alias. */
|
|
53
|
+
readonly aliases: Readonly<Record<string, readonly string[]>>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const NO_IDENTITY_CORRECTIONS: IdentityCorrections = {
|
|
57
|
+
optionalSlots: [],
|
|
58
|
+
requiredSlots: [],
|
|
59
|
+
parameterCorrections: {},
|
|
60
|
+
returnCorrections: {},
|
|
61
|
+
constantFamilies: {},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const sortedRecord = <T>(entries: Iterable<[string, T]>): Record<string, T> =>
|
|
65
|
+
Object.fromEntries([...entries].sort(([a], [b]) => a.localeCompare(b)));
|
|
66
|
+
|
|
67
|
+
export function buildIdentityVocabulary(
|
|
68
|
+
modules: readonly ApiModule[],
|
|
69
|
+
corrections: IdentityCorrections = NO_IDENTITY_CORRECTIONS,
|
|
70
|
+
): IdentityVocabulary {
|
|
71
|
+
const tables = new Set<string>();
|
|
72
|
+
const stringConstants = new Set<string>();
|
|
73
|
+
const aliases = new Map<string, readonly string[]>();
|
|
74
|
+
const enumMembers = new Map<string, readonly string[]>(
|
|
75
|
+
Object.entries(corrections.constantFamilies),
|
|
76
|
+
);
|
|
77
|
+
for (const module of modules) {
|
|
78
|
+
for (const struct of module.structs ?? []) tables.add(struct.name);
|
|
79
|
+
for (const constant of module.constants) {
|
|
80
|
+
if (constant.valueType === "string") stringConstants.add(constant.name);
|
|
81
|
+
}
|
|
82
|
+
for (const enumeration of module.enums ?? []) {
|
|
83
|
+
enumMembers.set(enumeration.name, enumeration.members);
|
|
84
|
+
}
|
|
85
|
+
for (const typedef of module.typedefs) {
|
|
86
|
+
const aliasOf = typedef.aliasOf;
|
|
87
|
+
if (aliasOf === undefined || (aliasOf.length === 1 && aliasOf[0] === "userdata")) continue;
|
|
88
|
+
aliases.set(typedef.name, aliasOf);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const enums = [...enumMembers].map(([name, members]): [string, "number" | "string"] => [
|
|
92
|
+
name,
|
|
93
|
+
members.length > 0 && members.every((member) => stringConstants.has(member))
|
|
94
|
+
? "string"
|
|
95
|
+
: "number",
|
|
96
|
+
]);
|
|
97
|
+
return {
|
|
98
|
+
tables: [...tables].sort(),
|
|
99
|
+
enums: sortedRecord(enums),
|
|
100
|
+
stringConstants: [...stringConstants].sort(),
|
|
101
|
+
aliases: sortedRecord(aliases),
|
|
102
|
+
optionalSlots: [...corrections.optionalSlots].sort(),
|
|
103
|
+
requiredSlots: [...corrections.requiredSlots].sort(),
|
|
104
|
+
parameterCorrections: sortedRecord(Object.entries(corrections.parameterCorrections)),
|
|
105
|
+
returnCorrections: sortedRecord(Object.entries(corrections.returnCorrections)),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Tokens a later release renamed without changing what they denote.
|
|
110
|
+
const RENAMED_TOKENS: Readonly<Record<string, string>> = {
|
|
111
|
+
// 1.13.2 names the lifecycle callbacks' `self` after what it is.
|
|
112
|
+
script_instance: "userdata",
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const CONSTANT_FQN = /^[a-z_][\w.]*\.[A-Z][A-Z0-9_]*$/;
|
|
116
|
+
const NUMERIC_LITERAL = /^-?\d+(\.\d+)?$/;
|
|
117
|
+
const STRING_LITERAL = /^(".*"|'.*')$/;
|
|
118
|
+
// The TypeScript table types a correction writes.
|
|
119
|
+
const TS_TABLE = /^(Record|LuaMap|ReadonlyLuaMap|LuaTable)\b/;
|
|
120
|
+
|
|
121
|
+
function canonicalLeaves(
|
|
122
|
+
token: string,
|
|
123
|
+
vocabulary: IdentityVocabulary,
|
|
124
|
+
expanding: ReadonlySet<string>,
|
|
125
|
+
): string[] {
|
|
126
|
+
const trimmed = token.trim();
|
|
127
|
+
const arms = splitTopLevel(trimmed, "|");
|
|
128
|
+
if (arms.length > 1) return arms.flatMap((arm) => canonicalLeaves(arm, vocabulary, expanding));
|
|
129
|
+
if (trimmed.endsWith("?")) {
|
|
130
|
+
return [...canonicalLeaves(trimmed.slice(0, -1), vocabulary, expanding), "nil"];
|
|
131
|
+
}
|
|
132
|
+
if (/^(fun|function)\b/.test(trimmed) || trimmed.includes("=>")) return ["function"];
|
|
133
|
+
if (trimmed.startsWith("(") && trimmed.endsWith(")")) {
|
|
134
|
+
return canonicalLeaves(trimmed.slice(1, -1), vocabulary, expanding);
|
|
135
|
+
}
|
|
136
|
+
if (trimmed.startsWith("typeof ")) {
|
|
137
|
+
return canonicalLeaves(trimmed.slice("typeof ".length), vocabulary, expanding);
|
|
138
|
+
}
|
|
139
|
+
if (trimmed === "nil" || trimmed === "undefined") return ["nil"];
|
|
140
|
+
// Every table shape — a bare or typed `table`, a list, an inline record, a
|
|
141
|
+
// struct, a built-in message payload — is one Lua table at runtime; its
|
|
142
|
+
// documented fields are not part of what identifies the call.
|
|
143
|
+
if (
|
|
144
|
+
trimmed === "table" ||
|
|
145
|
+
trimmed.startsWith("table<") ||
|
|
146
|
+
trimmed.startsWith("{") ||
|
|
147
|
+
trimmed.endsWith("[]") ||
|
|
148
|
+
trimmed.startsWith("message.") ||
|
|
149
|
+
TS_TABLE.test(trimmed) ||
|
|
150
|
+
vocabulary.tables.includes(trimmed)
|
|
151
|
+
) {
|
|
152
|
+
return ["table"];
|
|
153
|
+
}
|
|
154
|
+
if (STRING_LITERAL.test(trimmed)) return ["string"];
|
|
155
|
+
if (NUMERIC_LITERAL.test(trimmed)) return ["number"];
|
|
156
|
+
if (trimmed === "true" || trimmed === "false") return ["boolean"];
|
|
157
|
+
// An enum, one of its constants, or the untyped `constant` older releases
|
|
158
|
+
// wrote are all the value the engine registered: a number unless declared a
|
|
159
|
+
// string.
|
|
160
|
+
const enumType = vocabulary.enums[trimmed];
|
|
161
|
+
if (enumType !== undefined) return [enumType];
|
|
162
|
+
if (vocabulary.stringConstants.includes(trimmed)) return ["string"];
|
|
163
|
+
if (trimmed === "constant" || CONSTANT_FQN.test(trimmed)) return ["number"];
|
|
164
|
+
const aliasOf = vocabulary.aliases[trimmed];
|
|
165
|
+
if (aliasOf !== undefined && !expanding.has(trimmed)) {
|
|
166
|
+
const next = new Set(expanding).add(trimmed);
|
|
167
|
+
return aliasOf.flatMap((aliased) => canonicalLeaves(aliased, vocabulary, next));
|
|
168
|
+
}
|
|
169
|
+
const renamed = RENAMED_TOKENS[trimmed] ?? trimmed;
|
|
170
|
+
// Primitive synonyms (`integer` and `number`, `buffer_data` and `buffer`) are
|
|
171
|
+
// the tokens the engine vocabulary maps to one TypeScript type.
|
|
172
|
+
return [
|
|
173
|
+
Object.hasOwn(DEFOLD_TYPE_MAP, renamed)
|
|
174
|
+
? ((DEFOLD_TYPE_MAP as Readonly<Record<string, string>>)[renamed] as string)
|
|
175
|
+
: renamed,
|
|
176
|
+
];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* A slot's ref-doc tokens in a vocabulary-neutral form: the runtime values the
|
|
181
|
+
* slot takes, sorted and without duplicates, so a release that only respells a
|
|
182
|
+
* slot keeps its identity while one that changes what it takes does not.
|
|
183
|
+
*/
|
|
184
|
+
export function canonicalIdentityTypes(
|
|
185
|
+
types: readonly string[],
|
|
186
|
+
vocabulary: IdentityVocabulary,
|
|
187
|
+
): string[] {
|
|
188
|
+
return [
|
|
189
|
+
...new Set(types.flatMap((token) => canonicalLeaves(token, vocabulary, new Set()))),
|
|
190
|
+
].sort();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function correctedTypes(
|
|
194
|
+
types: readonly string[],
|
|
195
|
+
correction: IdentityCorrection | undefined,
|
|
196
|
+
vocabulary: IdentityVocabulary,
|
|
197
|
+
): string[] {
|
|
198
|
+
if (correction === undefined || !pinMatches(types, correction.pins)) {
|
|
199
|
+
return canonicalIdentityTypes(types, vocabulary);
|
|
200
|
+
}
|
|
201
|
+
if (correction.replaces !== undefined) {
|
|
202
|
+
return canonicalIdentityTypes(correction.replaces, vocabulary);
|
|
203
|
+
}
|
|
204
|
+
const removed = new Set(canonicalIdentityTypes(correction.removes ?? [], vocabulary));
|
|
205
|
+
return [
|
|
206
|
+
...new Set([
|
|
207
|
+
...canonicalIdentityTypes(types, vocabulary).filter((value) => !removed.has(value)),
|
|
208
|
+
...canonicalIdentityTypes(correction.adds ?? [], vocabulary),
|
|
209
|
+
]),
|
|
210
|
+
].sort();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface IdentitySlot {
|
|
214
|
+
readonly types: readonly string[];
|
|
215
|
+
readonly isOptional: boolean;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** A parameter as identity reads it: its corrected values and effective optionality. */
|
|
219
|
+
export function identityParameter(
|
|
220
|
+
fn: ApiFunction,
|
|
221
|
+
parameter: ApiParameter,
|
|
222
|
+
vocabulary: IdentityVocabulary,
|
|
223
|
+
): IdentitySlot {
|
|
224
|
+
const key = `${fn.name}:param:${parameter.name}`;
|
|
225
|
+
const types = correctedTypes(parameter.types, vocabulary.parameterCorrections[key], vocabulary);
|
|
226
|
+
// A slot a correction keeps required may still take an explicit nil, which
|
|
227
|
+
// stays part of what it takes; anywhere else, taking nil is being omissible.
|
|
228
|
+
if (vocabulary.requiredSlots.includes(key)) return { types, isOptional: false };
|
|
229
|
+
return {
|
|
230
|
+
types: types.filter((value) => value !== "nil"),
|
|
231
|
+
isOptional:
|
|
232
|
+
parameter.isOptional || types.includes("nil") || vocabulary.optionalSlots.includes(key),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** A return value as identity reads it, with a return correction applied where it holds. */
|
|
237
|
+
export function identityReturn(
|
|
238
|
+
fn: ApiFunction,
|
|
239
|
+
returned: ApiParameter,
|
|
240
|
+
vocabulary: IdentityVocabulary,
|
|
241
|
+
): IdentitySlot {
|
|
242
|
+
const correction = vocabulary.returnCorrections[fn.name];
|
|
243
|
+
const applies =
|
|
244
|
+
correction !== undefined &&
|
|
245
|
+
(correction.slot === undefined
|
|
246
|
+
? fn.returnValues.length === 1
|
|
247
|
+
: correction.slot === returned.name);
|
|
248
|
+
return {
|
|
249
|
+
types: correctedTypes(returned.types, applies ? correction : undefined, vocabulary),
|
|
250
|
+
isOptional: returned.isOptional,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** @noSelfInFile */
|
|
2
|
+
|
|
3
|
+
import type { Hash } from "./core-types";
|
|
4
|
+
|
|
5
|
+
// Component property keys upstream examples read through `go.get` while no
|
|
6
|
+
// ref-doc catalog declares them. Only evidenced keys belong here.
|
|
7
|
+
declare global {
|
|
8
|
+
namespace sprite {
|
|
9
|
+
interface properties {
|
|
10
|
+
/**
|
|
11
|
+
* The texture bound to the sprite's first sampler. Not in the sprite
|
|
12
|
+
* ref-doc; `resource.set`'s example reads it with
|
|
13
|
+
* `go.get("#sprite", "texture0")`.
|
|
14
|
+
*/
|
|
15
|
+
texture0: Hash;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Mesh component properties. Upstream ships no mesh API module, so this
|
|
21
|
+
* catalog holds only the keys upstream examples read.
|
|
22
|
+
*/
|
|
23
|
+
namespace mesh {
|
|
24
|
+
interface properties {
|
|
25
|
+
/**
|
|
26
|
+
* The buffer resource holding the mesh's vertex data.
|
|
27
|
+
* `resource.get_buffer` and `resource.set_buffer` read it with
|
|
28
|
+
* `go.get("#mesh", "vertices")`.
|
|
29
|
+
*/
|
|
30
|
+
vertices: Hash;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|