@defold-typescript/types 0.40.0 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/api-availability.json +3963 -772
  2. package/api-migrations.json +27 -0
  3. package/api-signatures.json +18069 -10240
  4. package/api-targets.json +448 -11
  5. package/examples/translations.json +560 -89
  6. package/fixtures/messages_doc.json +96 -0
  7. package/generated/b2d.d.ts +680 -4
  8. package/generated/b2d_body.d.ts +29 -103
  9. package/generated/b2d_chain.d.ts +5 -6
  10. package/generated/b2d_fixture.d.ts +34 -38
  11. package/generated/b2d_joint.d.ts +503 -25
  12. package/generated/b2d_shape.d.ts +183 -20
  13. package/generated/b2d_world.d.ts +57 -63
  14. package/generated/buffer.d.ts +16 -15
  15. package/generated/builtin-messages.d.ts +7 -1
  16. package/generated/bullet3d.d.ts +91 -0
  17. package/generated/bullet3d_collision_object.d.ts +433 -0
  18. package/generated/bullet3d_constraint.d.ts +818 -0
  19. package/generated/bullet3d_rigid_body.d.ts +429 -0
  20. package/generated/bullet3d_shape.d.ts +123 -0
  21. package/generated/bullet3d_world.d.ts +492 -0
  22. package/generated/camera.d.ts +29 -32
  23. package/generated/collectionfactory.d.ts +15 -18
  24. package/generated/collectionproxy.d.ts +22 -6
  25. package/generated/compute.d.ts +12 -238
  26. package/generated/crash.d.ts +24 -10
  27. package/generated/editor-vm/http.d.ts +90 -7
  28. package/generated/editor-vm/image.d.ts +7 -7
  29. package/generated/editor-vm/json.d.ts +11 -0
  30. package/generated/editor-vm/localization.d.ts +7 -7
  31. package/generated/editor-vm/tilemap_tiles.d.ts +56 -10
  32. package/generated/editor-vm/zip.d.ts +28 -0
  33. package/generated/editor.d.ts +1496 -430
  34. package/generated/factory.d.ts +21 -25
  35. package/generated/font.d.ts +64 -22
  36. package/generated/go.d.ts +235 -182
  37. package/generated/graphics.d.ts +335 -97
  38. package/generated/gui.d.ts +240 -471
  39. package/generated/html5.d.ts +2 -2
  40. package/generated/http.d.ts +28 -35
  41. package/generated/image.d.ts +105 -72
  42. package/generated/json.d.ts +34 -16
  43. package/generated/kinds/gui-script.d.ts +7 -0
  44. package/generated/kinds/render-script.d.ts +7 -0
  45. package/generated/kinds/script.d.ts +7 -0
  46. package/generated/label.d.ts +77 -7
  47. package/generated/liveupdate.d.ts +13 -10
  48. package/generated/material.d.ts +312 -360
  49. package/generated/model.d.ts +40 -39
  50. package/generated/particlefx.d.ts +19 -28
  51. package/generated/physics.d.ts +365 -133
  52. package/generated/profiler.d.ts +13 -23
  53. package/generated/render.d.ts +237 -297
  54. package/generated/resource.d.ts +664 -583
  55. package/generated/socket.d.ts +120 -133
  56. package/generated/sound.d.ts +62 -31
  57. package/generated/sprite.d.ts +31 -17
  58. package/generated/sys.d.ts +234 -190
  59. package/generated/tilemap.d.ts +21 -16
  60. package/generated/timer.d.ts +34 -21
  61. package/generated/versions/defold-1.12.4/b2d_body.d.ts +0 -7
  62. package/generated/versions/defold-1.12.4/buffer.d.ts +1 -3
  63. package/generated/versions/defold-1.12.4/camera.d.ts +21 -21
  64. package/generated/versions/defold-1.12.4/collectionfactory.d.ts +9 -9
  65. package/generated/versions/defold-1.12.4/collectionproxy.d.ts +2 -2
  66. package/generated/versions/defold-1.12.4/crash.d.ts +2 -2
  67. package/generated/versions/defold-1.12.4/factory.d.ts +15 -16
  68. package/generated/versions/defold-1.12.4/go.d.ts +6 -12
  69. package/generated/versions/defold-1.12.4/gui.d.ts +77 -175
  70. package/generated/versions/defold-1.12.4/html5.d.ts +1 -1
  71. package/generated/versions/defold-1.12.4/http.d.ts +0 -13
  72. package/generated/versions/defold-1.12.4/image.d.ts +16 -33
  73. package/generated/versions/defold-1.12.4/index.d.ts +1 -0
  74. package/generated/versions/defold-1.12.4/json.d.ts +10 -6
  75. package/generated/versions/defold-1.12.4/label.d.ts +2 -3
  76. package/generated/versions/defold-1.12.4/liveupdate.d.ts +5 -3
  77. package/generated/versions/defold-1.12.4/model.d.ts +2 -10
  78. package/generated/versions/defold-1.12.4/particlefx.d.ts +2 -5
  79. package/generated/versions/defold-1.12.4/physics.d.ts +69 -67
  80. package/generated/versions/defold-1.12.4/profiler.d.ts +2 -5
  81. package/generated/versions/defold-1.12.4/render.d.ts +99 -128
  82. package/generated/versions/defold-1.12.4/resource.d.ts +120 -148
  83. package/generated/versions/defold-1.12.4/socket.d.ts +34 -60
  84. package/generated/versions/defold-1.12.4/sound.d.ts +8 -8
  85. package/generated/versions/defold-1.12.4/sprite.d.ts +15 -5
  86. package/generated/versions/defold-1.12.4/sys.d.ts +37 -71
  87. package/generated/versions/defold-1.12.4/tilemap.d.ts +18 -11
  88. package/generated/versions/defold-1.12.4/timer.d.ts +5 -3
  89. package/generated/versions/defold-1.12.4/vmath.d.ts +0 -21
  90. package/generated/versions/defold-1.12.4/window.d.ts +1 -16
  91. package/generated/versions/defold-1.13.0/b2d_body.d.ts +10 -55
  92. package/generated/versions/defold-1.13.0/b2d_fixture.d.ts +25 -25
  93. package/generated/versions/defold-1.13.0/b2d_shape.d.ts +169 -8
  94. package/generated/versions/defold-1.13.0/b2d_world.d.ts +16 -10
  95. package/generated/versions/defold-1.13.0/buffer.d.ts +1 -3
  96. package/generated/versions/defold-1.13.0/camera.d.ts +25 -25
  97. package/generated/versions/defold-1.13.0/collectionfactory.d.ts +9 -9
  98. package/generated/versions/defold-1.13.0/collectionproxy.d.ts +2 -2
  99. package/generated/versions/defold-1.13.0/compute.d.ts +0 -69
  100. package/generated/versions/defold-1.13.0/crash.d.ts +2 -2
  101. package/generated/versions/defold-1.13.0/editor-vm/tilemap_tiles.d.ts +3 -3
  102. package/generated/versions/defold-1.13.0/editor.d.ts +34 -24
  103. package/generated/versions/defold-1.13.0/factory.d.ts +15 -16
  104. package/generated/versions/defold-1.13.0/go.d.ts +6 -12
  105. package/generated/versions/defold-1.13.0/graphics.d.ts +73 -37
  106. package/generated/versions/defold-1.13.0/gui.d.ts +77 -175
  107. package/generated/versions/defold-1.13.0/html5.d.ts +1 -1
  108. package/generated/versions/defold-1.13.0/http.d.ts +0 -13
  109. package/generated/versions/defold-1.13.0/image.d.ts +16 -33
  110. package/generated/versions/defold-1.13.0/index.d.ts +1 -0
  111. package/generated/versions/defold-1.13.0/json.d.ts +10 -6
  112. package/generated/versions/defold-1.13.0/label.d.ts +2 -3
  113. package/generated/versions/defold-1.13.0/liveupdate.d.ts +7 -5
  114. package/generated/versions/defold-1.13.0/material.d.ts +68 -106
  115. package/generated/versions/defold-1.13.0/model.d.ts +2 -10
  116. package/generated/versions/defold-1.13.0/particlefx.d.ts +2 -5
  117. package/generated/versions/defold-1.13.0/physics.d.ts +69 -67
  118. package/generated/versions/defold-1.13.0/profiler.d.ts +2 -5
  119. package/generated/versions/defold-1.13.0/render.d.ts +99 -128
  120. package/generated/versions/defold-1.13.0/resource.d.ts +126 -150
  121. package/generated/versions/defold-1.13.0/socket.d.ts +34 -60
  122. package/generated/versions/defold-1.13.0/sound.d.ts +8 -8
  123. package/generated/versions/defold-1.13.0/sprite.d.ts +15 -5
  124. package/generated/versions/defold-1.13.0/sys.d.ts +37 -71
  125. package/generated/versions/defold-1.13.0/tilemap.d.ts +18 -11
  126. package/generated/versions/defold-1.13.0/timer.d.ts +5 -3
  127. package/generated/versions/defold-1.13.0/vmath.d.ts +0 -21
  128. package/generated/versions/defold-1.13.0/window.d.ts +1 -16
  129. package/generated/versions/defold-1.13.1/b2d.d.ts +33 -0
  130. package/generated/versions/defold-1.13.1/b2d_body.d.ts +636 -0
  131. package/generated/versions/defold-1.13.1/b2d_chain.d.ts +106 -0
  132. package/generated/versions/defold-1.13.1/b2d_fixture.d.ts +157 -0
  133. package/generated/versions/defold-1.13.1/b2d_joint.d.ts +823 -0
  134. package/generated/versions/defold-1.13.1/b2d_shape.d.ts +400 -0
  135. package/generated/versions/defold-1.13.1/b2d_world.d.ts +320 -0
  136. package/generated/versions/defold-1.13.1/buffer.d.ts +189 -0
  137. package/generated/versions/defold-1.13.1/camera.d.ts +303 -0
  138. package/generated/versions/defold-1.13.1/collectionfactory.d.ts +151 -0
  139. package/generated/versions/defold-1.13.1/collectionproxy.d.ts +93 -0
  140. package/generated/versions/defold-1.13.1/compute.d.ts +237 -0
  141. package/generated/versions/defold-1.13.1/crash.d.ts +143 -0
  142. package/generated/versions/defold-1.13.1/editor-vm/http.d.ts +56 -0
  143. package/generated/versions/defold-1.13.1/editor-vm/image.d.ts +48 -0
  144. package/generated/versions/defold-1.13.1/editor-vm/json.d.ts +10 -0
  145. package/generated/versions/defold-1.13.1/editor-vm/localization.d.ts +42 -0
  146. package/generated/versions/defold-1.13.1/editor-vm/tilemap_tiles.d.ts +80 -0
  147. package/generated/versions/defold-1.13.1/editor-vm/zip.d.ts +10 -0
  148. package/generated/versions/defold-1.13.1/editor-vm/zlib.d.ts +24 -0
  149. package/generated/versions/defold-1.13.1/editor.d.ts +1121 -0
  150. package/generated/versions/defold-1.13.1/factory.d.ts +124 -0
  151. package/generated/versions/defold-1.13.1/font.d.ts +81 -0
  152. package/generated/versions/defold-1.13.1/go.d.ts +1107 -0
  153. package/generated/versions/defold-1.13.1/graphics.d.ts +411 -0
  154. package/generated/versions/defold-1.13.1/gui.d.ts +2353 -0
  155. package/generated/versions/defold-1.13.1/html5.d.ts +55 -0
  156. package/generated/versions/defold-1.13.1/http.d.ts +77 -0
  157. package/generated/versions/defold-1.13.1/image.d.ts +131 -0
  158. package/generated/versions/defold-1.13.1/index.d.ts +57 -0
  159. package/generated/versions/defold-1.13.1/json.d.ts +80 -0
  160. package/generated/versions/defold-1.13.1/kinds/editor-script.d.ts +14 -0
  161. package/generated/versions/defold-1.13.1/label.d.ts +93 -0
  162. package/generated/versions/defold-1.13.1/liveupdate.d.ts +142 -0
  163. package/generated/versions/defold-1.13.1/material.d.ts +408 -0
  164. package/generated/versions/defold-1.13.1/model.d.ts +272 -0
  165. package/generated/versions/defold-1.13.1/msg.d.ts +10 -0
  166. package/generated/versions/defold-1.13.1/particlefx.d.ts +163 -0
  167. package/generated/versions/defold-1.13.1/physics.d.ts +559 -0
  168. package/generated/versions/defold-1.13.1/profiler.d.ts +235 -0
  169. package/generated/versions/defold-1.13.1/render.d.ts +1190 -0
  170. package/generated/versions/defold-1.13.1/resource.d.ts +1523 -0
  171. package/generated/versions/defold-1.13.1/socket.d.ts +784 -0
  172. package/generated/versions/defold-1.13.1/sound.d.ts +292 -0
  173. package/generated/versions/defold-1.13.1/sprite.d.ts +175 -0
  174. package/generated/versions/defold-1.13.1/sys.d.ts +678 -0
  175. package/generated/versions/defold-1.13.1/tilemap.d.ts +208 -0
  176. package/generated/versions/defold-1.13.1/timer.d.ts +125 -0
  177. package/generated/versions/defold-1.13.1/types.d.ts +61 -0
  178. package/generated/versions/defold-1.13.1/vmath.d.ts +774 -0
  179. package/generated/versions/defold-1.13.1/window.d.ts +183 -0
  180. package/generated/versions/defold-1.13.1/zlib.d.ts +41 -0
  181. package/generated/vmath.d.ts +1 -21
  182. package/generated/window.d.ts +71 -71
  183. package/identity-vocabulary.json +561 -0
  184. package/index.d.ts +7 -0
  185. package/package.json +18 -2
  186. package/scripts/example-store-io.ts +12 -1
  187. package/scripts/extension-goldens.ts +1 -0
  188. package/scripts/fidelity-baseline.json +146 -46
  189. package/scripts/generate-api-availability.ts +90 -12
  190. package/scripts/generate-api-signatures.ts +12 -2
  191. package/scripts/import-defold-release.ts +106 -26
  192. package/scripts/prose-constants.ts +77 -16
  193. package/scripts/regen.ts +391 -77
  194. package/scripts/shared-handle-methods.ts +53 -0
  195. package/scripts/signature-store-fs.ts +1 -0
  196. package/scripts/sync-api-docs.ts +48 -10
  197. package/src/api-availability.ts +0 -0
  198. package/src/api-doc.ts +201 -3
  199. package/src/api-identity.ts +252 -0
  200. package/src/core-types.ts +26 -3
  201. package/src/correction-pins.ts +49 -0
  202. package/src/doc-comment.ts +104 -11
  203. package/src/doc-corrections.ts +108 -0
  204. package/src/editor-vm-globals.d.ts +5 -2
  205. package/src/emit-dts.ts +2064 -281
  206. package/src/emit-messages.ts +52 -0
  207. package/src/example-store.ts +125 -14
  208. package/src/field-correction-coverage.ts +204 -0
  209. package/src/fnv1a.ts +16 -0
  210. package/src/go-overloads.d.ts +25 -6
  211. package/src/index-base-table.ts +145 -0
  212. package/src/index-slot-classifications.ts +588 -0
  213. package/src/index.ts +38 -5
  214. package/src/library-index-slot-classifications.ts +332 -0
  215. package/src/lifecycle.ts +61 -199
  216. package/src/luals-type-expr.ts +354 -0
  217. package/src/msg-overloads.d.ts +0 -1
  218. package/src/param-correction-provenance.ts +8 -11
  219. package/src/render-overloads.d.ts +0 -15
  220. package/src/return-correction-provenance.ts +58 -16
  221. package/src/sys-overloads.d.ts +48 -0
  222. package/src/vmath-overloads.d.ts +27 -1
  223. package/src/window-event-guard.d.ts +6 -9
  224. package/url-parameters.json +1 -2
@@ -0,0 +1,354 @@
1
+ /**
2
+ * The structural half of the LuaLS type-expression grammar (unions, `?`, `T[]`,
3
+ * grouping parentheses, `fun(...)`, `table<K, V>`, inline records, string, numeric
4
+ * and boolean literals), shared by the engine lane (`emit-dts.ts`
5
+ * `defaultMapType`) and the library lane
6
+ * (`packages/library-types/scripts/map-luals-types.ts`). Pure and deterministic.
7
+ *
8
+ * Every name that is not structure — `integer`, `table`, `function`, `...`,
9
+ * `vmath.vector3`, `druid.component` — is a leaf handed to the caller's
10
+ * `resolveLeaf`, so each lane keeps its own vocabulary and precedence. A leaf the
11
+ * resolver answers `undefined` for lowers to `unknown` and is reported in
12
+ * `unknowns`.
13
+ */
14
+
15
+ import { luaMultiReturn } from "./library-signature";
16
+
17
+ export type LualsLeafResolver = (leaf: string) => string | undefined;
18
+
19
+ /**
20
+ * Who supplies the value a type describes: `"input"` for a slot the caller fills
21
+ * (a parameter, a field of a table passed as one, a callback's return), `"output"`
22
+ * for one the engine or library hands back (a return, a property read back, a
23
+ * callback's parameters). Only `"input"` widens a string-keyed `table<K, V>` to also
24
+ * accept an object literal, so `"output"` renders exactly what an unpositioned
25
+ * mapping does.
26
+ */
27
+ export type LualsPosition = "input" | "output";
28
+
29
+ export interface LualsMapResult {
30
+ ts: string;
31
+ unknowns: string[];
32
+ }
33
+
34
+ /**
35
+ * LuaLS's throwaway param name `_` declares no type at all, so lowering it to
36
+ * `unknown` loses nothing an author wrote. An untyped `self` or `ctx` *is* an
37
+ * upstream omission and stays recorded.
38
+ */
39
+ const LUALS_THROWAWAY_PARAM = "_";
40
+ export const LUALS_VARARG_TOKEN = "...";
41
+
42
+ const NUMERIC_LITERAL = /^-?\d+(\.\d+)?$/;
43
+ const TUPLE_KEY = /^\[(\d+)\](\??)$/;
44
+ const INDEX_KEY = /^\[(.+)\]\??$/;
45
+
46
+ /**
47
+ * Split `s` on every top-level occurrence of the single-character `sep`, honoring
48
+ * bracket depth and double-quoted string literals so a separator nested inside
49
+ * `<...>`, `(...)`, `[...]`, `{...}`, or a `"..."` literal does not split.
50
+ */
51
+ export function splitTopLevel(s: string, sep: string): string[] {
52
+ const parts: string[] = [];
53
+ let depth = 0;
54
+ let inQuote = false;
55
+ let start = 0;
56
+ for (let i = 0; i < s.length; i++) {
57
+ const c = s[i];
58
+ if (inQuote) {
59
+ if (c === '"') inQuote = false;
60
+ continue;
61
+ }
62
+ if (c === '"') inQuote = true;
63
+ else if (c === "<" || c === "(" || c === "[" || c === "{") depth++;
64
+ else if (c === ">" || c === ")" || c === "]" || c === "}") depth = Math.max(0, depth - 1);
65
+ else if (depth === 0 && c === sep) {
66
+ parts.push(s.slice(start, i));
67
+ start = i + 1;
68
+ }
69
+ }
70
+ parts.push(s.slice(start));
71
+ return parts;
72
+ }
73
+
74
+ /** Index of the matching close bracket for the opener at `open`, or -1 if unbalanced. */
75
+ export function matchBracket(s: string, open: number): number {
76
+ const closers: Record<string, string> = { "<": ">", "(": ")", "[": "]", "{": "}" };
77
+ const want = closers[s[open] as string];
78
+ let depth = 0;
79
+ let inQuote = false;
80
+ for (let i = open; i < s.length; i++) {
81
+ const c = s[i];
82
+ if (inQuote) {
83
+ if (c === '"') inQuote = false;
84
+ continue;
85
+ }
86
+ if (c === '"') inQuote = true;
87
+ else if (c === "<" || c === "(" || c === "[" || c === "{") depth++;
88
+ else if (c === ">" || c === ")" || c === "]" || c === "}") {
89
+ depth--;
90
+ if (depth === 0) return c === want ? i : -1;
91
+ }
92
+ }
93
+ return -1;
94
+ }
95
+
96
+ function isWrappedInParens(s: string): boolean {
97
+ return s.startsWith("(") && matchBracket(s, 0) === s.length - 1;
98
+ }
99
+
100
+ /** True when a top-level `=>` (an arrow function type) appears in a mapped result. */
101
+ function hasTopLevelArrow(tsExpr: string): boolean {
102
+ let depth = 0;
103
+ for (let i = 0; i + 1 < tsExpr.length; i++) {
104
+ const c = tsExpr[i];
105
+ if (c === "<" || c === "(" || c === "[" || c === "{") depth++;
106
+ else if (c === ">" || c === ")" || c === "]" || c === "}") depth = Math.max(0, depth - 1);
107
+ else if (depth === 0 && c === "=" && tsExpr[i + 1] === ">") return true;
108
+ }
109
+ return false;
110
+ }
111
+
112
+ /** A union member needs parentheses when it is itself a function type. */
113
+ function wrapForUnion(tsExpr: string): string {
114
+ return hasTopLevelArrow(tsExpr) ? `(${tsExpr})` : tsExpr;
115
+ }
116
+
117
+ /** An array element needs parentheses when it is a union, a function, or an object. */
118
+ export function needsArrayParens(tsExpr: string): boolean {
119
+ return (
120
+ splitTopLevel(tsExpr, "|").length > 1 || hasTopLevelArrow(tsExpr) || tsExpr.startsWith("{")
121
+ );
122
+ }
123
+
124
+ /**
125
+ * `LuaTable<K, V>` constrains `K` to `AnyNotNil`, so a mapped key that admits nil is
126
+ * not a compilable key however faithfully it renders the annotation. LuaLS `any` maps
127
+ * to `unknown` everywhere else, and `nil` to `undefined`; in key position both fail the
128
+ * constraint and `tsc` rejects the emitted declaration. `AnyNotNil` is the faithful
129
+ * target — "any non-nil Lua value" is exactly what a table key may be — so drop a nil
130
+ * arm from a key union and fall back to `AnyNotNil` when nothing survives.
131
+ */
132
+ function luaTableKey(mapped: string): string {
133
+ const arms = splitTopLevel(mapped, "|")
134
+ .map((arm) => arm.trim())
135
+ .filter((arm) => arm !== "undefined" && arm !== "unknown");
136
+ return arms.length === 0 ? "AnyNotNil" : arms.join(" | ");
137
+ }
138
+
139
+ /**
140
+ * TSTL's `LuaTable` is built with `new LuaTable()`, so an object literal is not
141
+ * assignable to it although both compile to the same Lua table. A caller-supplied
142
+ * table whose key admits `string` (`AnyNotNil` does) also takes
143
+ * `Record<string, V>`; a `Hash` or numeric key cannot be spelled as an object
144
+ * literal's key, so it takes only a Lua table.
145
+ */
146
+ function acceptsObjectLiteral(key: string): boolean {
147
+ return splitTopLevel(key, "|").some((arm) => ["string", "AnyNotNil"].includes(arm.trim()));
148
+ }
149
+
150
+ interface Walk {
151
+ resolveLeaf: LualsLeafResolver;
152
+ unknowns: string[];
153
+ position: LualsPosition;
154
+ }
155
+
156
+ /**
157
+ * The mapped `(params)` list and `ret` type of a `fun(...)` token, shared by the
158
+ * arrow form and the colon-return call signature. A return list wrapped in one pair
159
+ * of parentheses (`fun(): (a, b)`) is the same multi-return as the bare `fun(): a, b`.
160
+ */
161
+ function functionParts(token: string, walk: Walk): { paramList: string; ret: string } {
162
+ const open = token.indexOf("(");
163
+ const close = matchBracket(token, open);
164
+ const paramsStr = token.slice(open + 1, close).trim();
165
+ const afterClose = token.slice(close + 1).trim();
166
+
167
+ const params = paramsStr === "" ? [] : splitTopLevel(paramsStr, ",");
168
+ // A callback's params are values the engine hands over. A returned or stored
169
+ // function's params keep `"output"` too: widening them would reject a callback
170
+ // with the narrower `LuaTable` param a caller assigns to a writable field.
171
+ const paramWalk: Walk = { ...walk, position: "output" };
172
+ const paramList = params
173
+ .map((raw) => raw.trim())
174
+ .map((part) => {
175
+ if (part.startsWith(LUALS_VARARG_TOKEN)) {
176
+ const after = part.slice(3).trim();
177
+ const element = after.startsWith(":")
178
+ ? mapToken(after.slice(1).trim(), paramWalk)
179
+ : "unknown";
180
+ return `...args: ${needsArrayParens(element) ? `(${element})[]` : `${element}[]`}`;
181
+ }
182
+ const colon = splitTopLevel(part, ":");
183
+ if (colon.length < 2) {
184
+ if (part !== LUALS_THROWAWAY_PARAM) walk.unknowns.push(part);
185
+ return `${part}: unknown`;
186
+ }
187
+ const name = colon[0]?.trim() ?? "";
188
+ const typeExpr = colon.slice(1).join(":").trim();
189
+ return `${name}: ${mapToken(typeExpr, paramWalk)}`;
190
+ })
191
+ .join(", ");
192
+
193
+ let ret = "void";
194
+ if (afterClose.startsWith(":")) {
195
+ const retStr = afterClose.slice(1).trim();
196
+ let retTokens = retStr === "" ? [] : splitTopLevel(retStr, ",").map((r) => r.trim());
197
+ if (retTokens.length === 1 && isWrappedInParens(retStr)) {
198
+ const grouped = splitTopLevel(retStr.slice(1, -1), ",").map((r) => r.trim());
199
+ if (grouped.length > 1) retTokens = grouped;
200
+ }
201
+ if (retTokens.length === 1) {
202
+ ret = mapToken(retTokens[0] as string, walk);
203
+ } else if (retTokens.length > 1) {
204
+ const restTail = retTokens.at(-1) === LUALS_VARARG_TOKEN;
205
+ ret = luaMultiReturn(
206
+ retTokens.map((r) => mapToken(r, walk)),
207
+ restTail,
208
+ );
209
+ }
210
+ }
211
+ return { paramList, ret };
212
+ }
213
+
214
+ /**
215
+ * An inline record. A numeric `[N]` key is a tuple slot and renders as the property
216
+ * key `N`. Any other `[K]` key is an index signature; TypeScript accepts only
217
+ * `string`/`number` there, so it renders as a `string` index when `K` maps to
218
+ * `string` and a `number` index otherwise (the upstream instance keys a numeric
219
+ * enum), intersected with the named entries. The key's own leaves never reach the
220
+ * output, so they are not reported.
221
+ */
222
+ function mapObject(token: string, walk: Walk): string {
223
+ const inner = token.slice(1, -1).trim();
224
+ if (inner === "") return "{}";
225
+ const entries: string[] = [];
226
+ const indexes: string[] = [];
227
+ for (const part of splitTopLevel(inner, ",")) {
228
+ const trimmed = part.trim();
229
+ if (trimmed.length === 0) continue;
230
+ const colon = splitTopLevel(trimmed, ":");
231
+ const key = colon[0]?.trim() ?? "";
232
+ const value = mapToken(colon.slice(1).join(":").trim(), walk);
233
+ const tuple = TUPLE_KEY.exec(key);
234
+ if (tuple !== null) {
235
+ entries.push(`${tuple[1]}${tuple[2]}: ${value}`);
236
+ continue;
237
+ }
238
+ const index = INDEX_KEY.exec(key);
239
+ if (index !== null) {
240
+ const keyType = mapToken(index[1] as string, { ...walk, unknowns: [] });
241
+ indexes.push(`{ [key: ${keyType === "string" ? "string" : "number"}]: ${value} }`);
242
+ continue;
243
+ }
244
+ entries.push(`${key}: ${value}`);
245
+ }
246
+ const parts = entries.length > 0 || indexes.length === 0 ? [`{ ${entries.join("; ")} }`] : [];
247
+ return [...parts, ...indexes].join(" & ");
248
+ }
249
+
250
+ function mapToken(raw: string, walk: Walk): string {
251
+ let token = raw.trim();
252
+
253
+ // Strip a redundant pair of outer parentheses (LuaLS grouping) so `(a | b)[]`
254
+ // reaches the union handler rather than falling through to a leaf lookup.
255
+ while (isWrappedInParens(token)) {
256
+ token = token.slice(1, -1).trim();
257
+ }
258
+
259
+ if (token === "") return "unknown";
260
+
261
+ // A `fun(...)` whose return follows the `)` keeps its return-type `|` and `?` inside
262
+ // the function; splitting the union first would cut `fun(): a|b` into `(fun) | b`, and
263
+ // peeling the optional suffix first would turn `fun(): number?` — a function with an
264
+ // optional *return* — into an optional function. The whole-function optional is spelled
265
+ // with explicit parentheses, `(fun(): number)?`, which does not match here.
266
+ // `fun()|nil` (a `|` right after the `)`) falls through to the union split.
267
+ if (/^fun\s*\(/.test(token)) {
268
+ const close = matchBracket(token, token.indexOf("("));
269
+ const afterClose = close === -1 ? "" : token.slice(close + 1).trim();
270
+ if (close !== -1 && afterClose.startsWith(":")) {
271
+ return mapFunction(token, walk);
272
+ }
273
+ }
274
+
275
+ // Optional suffix.
276
+ if (token.length > 1 && token.endsWith("?")) {
277
+ const base = mapToken(token.slice(0, -1), walk);
278
+ const members = splitTopLevel(base, "|").map((m) => m.trim());
279
+ return members.includes("undefined") ? base : `${wrapForUnion(base)} | undefined`;
280
+ }
281
+
282
+ // Top-level union.
283
+ const unionParts = splitTopLevel(token, "|");
284
+ if (unionParts.length > 1) {
285
+ return unionParts.map((p) => wrapForUnion(mapToken(p.trim(), walk))).join(" | ");
286
+ }
287
+
288
+ // Trailing array.
289
+ if (token.endsWith("[]")) {
290
+ const element = mapToken(token.slice(0, -2), walk);
291
+ return needsArrayParens(element) ? `(${element})[]` : `${element}[]`;
292
+ }
293
+
294
+ if (/^fun\s*\(/.test(token)) return mapFunction(token, walk);
295
+
296
+ if (token.startsWith("table<") && token.endsWith(">")) {
297
+ const args = splitTopLevel(token.slice(6, -1), ",").map((a) => mapToken(a.trim(), walk));
298
+ if (args.length > 0) args[0] = luaTableKey(args[0] as string);
299
+ // A caller may build the table with either TSTL constructor. `LuaMap` takes
300
+ // both, since a `LuaTable` is assignable to it; the engine hands back a
301
+ // `LuaTable`, which a caller may still store as a `LuaMap`.
302
+ if (walk.position !== "input") return `LuaTable<${args.join(", ")}>`;
303
+ const table = `LuaMap<${args.join(", ")}>`;
304
+ const [key, value] = args;
305
+ if (args.length === 2 && acceptsObjectLiteral(key as string)) {
306
+ return `${table} | Record<string, ${value}>`;
307
+ }
308
+ return table;
309
+ }
310
+
311
+ if (token.startsWith("{") && token.endsWith("}")) return mapObject(token, walk);
312
+
313
+ if (token.startsWith('"') && token.endsWith('"')) return token;
314
+ if (NUMERIC_LITERAL.test(token) || token === "true" || token === "false") return token;
315
+
316
+ const leaf = walk.resolveLeaf(token);
317
+ if (leaf !== undefined) return leaf;
318
+ walk.unknowns.push(token);
319
+ return "unknown";
320
+ }
321
+
322
+ function mapFunction(token: string, walk: Walk): string {
323
+ const { paramList, ret } = functionParts(token, walk);
324
+ return `(${paramList}) => ${ret}`;
325
+ }
326
+
327
+ /** Map one raw LuaLS type expression to a TypeScript type string. */
328
+ export function mapLualsExpression(
329
+ token: string,
330
+ resolveLeaf: LualsLeafResolver,
331
+ position: LualsPosition = "output",
332
+ ): LualsMapResult {
333
+ const walk: Walk = { resolveLeaf, unknowns: [], position };
334
+ return { ts: mapToken(token, walk), unknowns: walk.unknowns };
335
+ }
336
+
337
+ /**
338
+ * Map a `fun(...)` expression to a TypeScript **call signature** — the colon-return
339
+ * form `(params): ret` an interface uses to become callable, not the `=>` arrow a
340
+ * field or param function type takes. Throws on a non-`fun` token.
341
+ */
342
+ export function mapLualsCallSignatureExpression(
343
+ token: string,
344
+ resolveLeaf: LualsLeafResolver,
345
+ position: LualsPosition = "output",
346
+ ): LualsMapResult {
347
+ const trimmed = token.trim();
348
+ if (!/^fun\s*\(/.test(trimmed)) {
349
+ throw new Error(`mapLualsCallSignature: expected a "fun(...)" token, got "${token}".`);
350
+ }
351
+ const walk: Walk = { resolveLeaf, unknowns: [], position };
352
+ const { paramList, ret } = functionParts(trimmed, walk);
353
+ return { ts: `(${paramList}): ${ret}`, unknowns: walk.unknowns };
354
+ }
@@ -48,7 +48,6 @@ declare global {
48
48
  * The following receiver shorthands are available:
49
49
  *
50
50
  * - `"."` the current game object
51
- *
52
51
  * - `"#"` the current component
53
52
  *
54
53
  * There is a 2 kilobyte limit to the message parameter table size.
@@ -1,4 +1,5 @@
1
1
  import { type ApiModule, parseDefoldApiDoc } from "./api-doc";
2
+ import { correctionPins, pinMatches } from "./correction-pins";
2
3
  import type { ParamTypeCorrection } from "./emit-dts";
3
4
  import type { ProvenanceSurface } from "./optional-correction-provenance";
4
5
 
@@ -11,16 +12,12 @@ export interface ParamTypeProvenance {
11
12
 
12
13
  const PARAM_SEPARATOR = ":param:";
13
14
 
14
- // `nil` is optionality, which `isDocOptional` owns; the correction replaces only
15
- // the concrete tokens, so only those are evidence.
16
- function baseTokens(tokens: readonly string[]): string {
17
- return tokens.filter((token) => token !== "nil").join("|");
18
- }
19
-
20
15
  // A target needs a correction while any declaration of the slot there still
21
- // states the pinned tokens, so an overload that shows the defect keeps it alive.
22
- // Any other declared token set — fixed or retyped — no longer carries the
23
- // contradiction the entry records, and the entry goes once no target needs it.
16
+ // states one of its pins, so an overload that shows the defect keeps it alive.
17
+ // `nil` is optionality, which `isDocOptional` owns, so `pinMatches` compares
18
+ // only the concrete tokens. Any other declared token set — fixed, or retyped
19
+ // without a `retypedUpstream` pin — no longer carries the contradiction the
20
+ // entry records, and the entry goes once no target needs it.
24
21
  export function paramCorrectionProvenance(
25
22
  entries: readonly [string, ParamTypeCorrection][],
26
23
  surfaces: readonly ProvenanceSurface[],
@@ -41,7 +38,7 @@ export function paramCorrectionProvenance(
41
38
  const element = key.slice(0, separator);
42
39
  const slot = key.slice(separator + PARAM_SEPARATOR.length);
43
40
  const namespace = element.slice(0, element.lastIndexOf("."));
44
- const pinned = baseTokens(correction.upstream);
41
+ const pins = correctionPins(correction);
45
42
 
46
43
  const neededByTarget = new Map<string, boolean>();
47
44
  for (const surface of surfaces) {
@@ -51,7 +48,7 @@ export function paramCorrectionProvenance(
51
48
  for (const parameter of fn.parameters) {
52
49
  if (parameter.name !== slot) continue;
53
50
  const needed = neededByTarget.get(surface.target) ?? false;
54
- neededByTarget.set(surface.target, needed || baseTokens(parameter.types) === pinned);
51
+ neededByTarget.set(surface.target, needed || pinMatches(parameter.types, pins));
55
52
  }
56
53
  }
57
54
  }
@@ -25,20 +25,5 @@ declare global {
25
25
  name: string,
26
26
  parameters: Record<string | number, unknown>,
27
27
  ): Opaque<"render_target">;
28
- /**
29
- * The rendering context was lost. Rendering is paused and all graphics
30
- * resources become invalid. Passed to the `render.set_listener` callback.
31
- */
32
- const CONTEXT_EVENT_CONTEXT_LOST: number & {
33
- readonly __brand: "render.CONTEXT_EVENT_CONTEXT_LOST";
34
- };
35
- /**
36
- * The rendering context was restored. Rendering is still paused and graphics
37
- * resources are still invalid, but can be reloaded. Passed to the
38
- * `render.set_listener` callback.
39
- */
40
- const CONTEXT_EVENT_CONTEXT_RESTORED: number & {
41
- readonly __brand: "render.CONTEXT_EVENT_CONTEXT_RESTORED";
42
- };
43
28
  }
44
29
  }
@@ -3,6 +3,7 @@
3
3
  // evidence a return-side correction rests on lives in the slot's HTML prose and
4
4
  // the parser discards it.
5
5
 
6
+ import { correctionPins, pinMatches } from "./correction-pins";
6
7
  import type { ReturnFieldOptionalityCorrection, ReturnTypeCorrection } from "./emit-dts";
7
8
  import type { ProvenanceSurface } from "./optional-correction-provenance";
8
9
 
@@ -87,6 +88,28 @@ function isRecord(value: unknown): value is Record<string, unknown> {
87
88
  return typeof value === "object" && value !== null && !Array.isArray(value);
88
89
  }
89
90
 
91
+ // A slot that names a STRUCT (`sys.interface_info[]`) carries its fields as that
92
+ // struct's members rather than a `<dl>`; a member name ending in `?` is the
93
+ // struct's own optionality mark. True when the named struct marks `field`
94
+ // optional.
95
+ function structMarksOptional(doc: unknown, slot: RawSlot, field: string): boolean {
96
+ if (!isRecord(doc) || !Array.isArray(doc.elements)) return false;
97
+ const names = new Set(
98
+ (slot.types ?? [])
99
+ .filter((token) => token !== "nil")
100
+ .map((token) => token.replace(/\[\]$/, "")),
101
+ );
102
+ return doc.elements.some(
103
+ (candidate) =>
104
+ isRecord(candidate) &&
105
+ candidate.type === "STRUCT" &&
106
+ typeof candidate.name === "string" &&
107
+ names.has(candidate.name) &&
108
+ Array.isArray(candidate.members) &&
109
+ candidate.members.some((member) => isRecord(member) && member.name === `${field}?`),
110
+ );
111
+ }
112
+
90
113
  // Every `returnvalues` entry of every FUNCTION in the surface named `element`,
91
114
  // unfiltered by slot: one target can declare the element more than once.
92
115
  function returnSlots(doc: unknown, element: string): RawSlot[] {
@@ -101,9 +124,10 @@ function returnSlots(doc: unknown, element: string): RawSlot[] {
101
124
  );
102
125
  }
103
126
 
104
- // The first `returnvalues` entry of each declaration of `element`, one per
105
- // declaration so a target that declares the element twice is folded, not sliced.
106
- function firstReturnSlots(doc: unknown, element: string): RawSlot[] {
127
+ // The `returnvalues` entry a correction rewrites in each declaration of
128
+ // `element`: the one named `slot`, or the first. One per declaration, so a
129
+ // target that declares the element twice is folded, not sliced.
130
+ function correctedReturnSlots(doc: unknown, element: string, slot?: string): RawSlot[] {
107
131
  if (!isRecord(doc) || !Array.isArray(doc.elements)) return [];
108
132
  return doc.elements.flatMap((candidate) => {
109
133
  if (
@@ -114,8 +138,9 @@ function firstReturnSlots(doc: unknown, element: string): RawSlot[] {
114
138
  ) {
115
139
  return [];
116
140
  }
117
- const first = candidate.returnvalues[0];
118
- return isRecord(first) ? [first] : [];
141
+ const values = candidate.returnvalues.filter(isRecord);
142
+ const corrected = slot === undefined ? values[0] : values.find((value) => value.name === slot);
143
+ return corrected === undefined ? [] : [corrected];
119
144
  });
120
145
  }
121
146
 
@@ -151,6 +176,9 @@ export interface ReturnFieldProvenance {
151
176
  // therefore prose- and token-shaped: the evidence sentence is gone from the
152
177
  // field's `<dd>`, or its type span now declares `nil` itself.
153
178
  //
179
+ // A slot that names a STRUCT resolves the field when the struct marks that
180
+ // member optional, since the struct is where that target now declares it.
181
+ //
154
182
  // `missingFieldIn` is deliberately not a resolution. A field upstream dropped
155
183
  // from a slot the target still declares makes the correction stale, and
156
184
  // `applyFieldOptionalityCorrections` throws rather than no-op for it, so that
@@ -179,7 +207,7 @@ export function fieldCorrectionProvenance(
179
207
 
180
208
  let verdict: FieldVerdict;
181
209
  if (prose === undefined) {
182
- verdict = "missing";
210
+ verdict = structMarksOptional(surface.doc, slot, field) ? "resolved" : "missing";
183
211
  } else if (!prose.includes(correction.evidence) || (tokens ?? []).includes("nil")) {
184
212
  verdict = "resolved";
185
213
  } else {
@@ -235,10 +263,6 @@ const RETURN_VERDICT_RANK: Record<ReturnVerdict, number> = {
235
263
  resolved: 0,
236
264
  };
237
265
 
238
- function baseTokens(tokens: readonly string[]): string {
239
- return tokens.filter((token) => token !== "nil").join("|");
240
- }
241
-
242
266
  // The return-type class has the same two-sided evidence: the declared tokens
243
267
  // still say what the correction contradicts, and the slot prose still states the
244
268
  // contradiction. A target that fixes either half no longer needs the entry.
@@ -255,24 +279,24 @@ export function returnCorrectionProvenance(
255
279
  ): ReturnTypeProvenance[] {
256
280
  return entries.map(([key, correction]) => {
257
281
  const namespace = namespaceOf(key);
258
- const pinned = baseTokens(correction.upstream);
282
+ const pins = correctionPins(correction);
259
283
 
260
284
  const verdicts = new Map<string, ReturnVerdict>();
261
285
  const drift = new Map<string, Set<string>>();
262
286
  for (const surface of surfaces) {
263
287
  if (surface.namespace !== namespace) continue;
264
- // The correction rewrites the first return only, so only that slot is
265
- // evidence; a declaration with no returns at all sights nothing.
266
- for (const slot of firstReturnSlots(surface.doc, key)) {
288
+ // The correction rewrites one return only, so only that slot is evidence;
289
+ // a declaration without it sights nothing.
290
+ for (const slot of correctedReturnSlots(surface.doc, key, correction.slot)) {
267
291
  const tokens = slot.types ?? [];
268
292
 
269
293
  let verdict: ReturnVerdict;
270
- if (baseTokens(tokens) !== pinned) {
294
+ if (!pinMatches(tokens, pins)) {
271
295
  verdict = "drift";
272
296
  const messages = drift.get(surface.target) ?? new Set<string>();
273
297
  drift.set(surface.target, messages);
274
298
  messages.add(
275
- `${surface.target}: pinned ${correction.upstream.join("|")}, found ${tokens.join("|")}`,
299
+ `${surface.target}: pinned ${pins.map((pin) => pin.join("|")).join(" or ")}, found ${tokens.join("|")}`,
276
300
  );
277
301
  } else if (
278
302
  tokens.includes("nil") ||
@@ -304,3 +328,21 @@ export function returnCorrectionProvenance(
304
328
  };
305
329
  });
306
330
  }
331
+
332
+ // The `MISFILED_DECLARATIONS` keys no retained target still files: upstream
333
+ // moved or dropped the misfiled declaration, so the entry is due for deletion.
334
+ export function unfiledDeclarations(
335
+ keys: readonly string[],
336
+ surfaces: readonly ProvenanceSurface[],
337
+ ): string[] {
338
+ return keys.filter((key) => {
339
+ const split = key.lastIndexOf(":");
340
+ const element = key.slice(0, split);
341
+ const returnName = key.slice(split + 1);
342
+ return !surfaces.some(
343
+ (surface) =>
344
+ surface.namespace === namespaceOf(element) &&
345
+ correctedReturnSlots(surface.doc, element).some((slot) => slot.name === returnName),
346
+ );
347
+ });
348
+ }
@@ -0,0 +1,48 @@
1
+ /** @noSelfInFile */
2
+
3
+ declare global {
4
+ namespace sys {
5
+ /**
6
+ * Disables engine throttling.
7
+ *
8
+ * @param enable - false to disable throttling
9
+ */
10
+ function set_engine_throttle(enable: false): void;
11
+ /**
12
+ * Enables engine throttling. The engine reads `cooldown` whenever `enable` is
13
+ * true.
14
+ *
15
+ * @param enable - true if throttling should be enabled
16
+ * @param cooldown - the time period to do update + render for (seconds)
17
+ */
18
+ function set_engine_throttle(enable: boolean, cooldown: number): void;
19
+ /**
20
+ * Get string config value from the game.project configuration file, or nil
21
+ * when the key does not exist.
22
+ *
23
+ * @param key - key to get value for. The syntax is SECTION.KEY
24
+ * @returns config value as a string, or nil if the config key does not exist.
25
+ * @example
26
+ * ```ts
27
+ * const text = sys.get_config_string("my_game.text");
28
+ * if (text !== undefined) print(text);
29
+ * ```
30
+ */
31
+ function get_config_string(key: string): string | undefined;
32
+ /**
33
+ * Get string config value from the game.project configuration file with
34
+ * a default value.
35
+ *
36
+ * @param key - key to get value for. The syntax is SECTION.KEY
37
+ * @param default_value - default value to return if the value does not exist
38
+ * @returns config value as a string. default_value if the config key does not exist.
39
+ * @example
40
+ * ```ts
41
+ * const text = sys.get_config_string("my_game.text", "default text");
42
+ * ```
43
+ */
44
+ function get_config_string(key: string, default_value: string): string;
45
+ }
46
+ }
47
+
48
+ export {};
@@ -1,6 +1,6 @@
1
1
  /** @noSelfInFile */
2
2
 
3
- import type { Quaternion, Vector3, Vector4 } from "./core-types";
3
+ import type { Quaternion, Vector, Vector3, Vector4 } from "./core-types";
4
4
 
5
5
  declare global {
6
6
  namespace vmath {
@@ -124,5 +124,31 @@ declare global {
124
124
  * @returns the slerped quaternion
125
125
  */
126
126
  function slerp(t: number, q1: Quaternion, q2: Quaternion): Quaternion;
127
+ /**
128
+ * Creates an empty vector. The engine raises on an explicit nil, so this
129
+ * form takes no argument at all.
130
+ *
131
+ * @returns new vector
132
+ */
133
+ function vector(): Vector;
134
+ /**
135
+ * Creates a vector of arbitrary size. The vector is initialized
136
+ * with numeric values from a table.
137
+ * The table values are converted to floating point
138
+ * values. If a value cannot be converted, a 0 is stored in that
139
+ * value position in the vector.
140
+ *
141
+ * @param t - table of numbers
142
+ * @returns new vector
143
+ * @example
144
+ * ```ts
145
+ * // How to create a vector with custom data to be used for animation easing:
146
+ * const values = [0, 0.5, 0];
147
+ * const vec = vmath.vector(values);
148
+ * print(vec); // => vmath.vector (size: 3)
149
+ * print(vec[2]); // => 0.5
150
+ * ```
151
+ */
152
+ function vector(t: number[]): Vector;
127
153
  }
128
154
  }