@defold-typescript/types 0.33.0 → 0.33.1

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.
@@ -526,7 +526,7 @@ declare global {
526
526
  * });
527
527
  * ```
528
528
  */
529
- function create_texture(path: string, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer: Opaque<"buffer">): Hash;
529
+ function create_texture(path: string, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer?: Opaque<"buffer">): Hash;
530
530
  /**
531
531
  * Creates a new texture resource that can be used in the same way as any texture created during build time.
532
532
  * The path used for creating the texture must be unique, trying to create a resource at a path that is already
@@ -715,7 +715,7 @@ declare global {
715
715
  * });
716
716
  * ```
717
717
  */
718
- function create_texture_async(path: string | Hash, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer: Opaque<"buffer">, callback: (...args: unknown[]) => unknown): LuaMultiReturn<[Hash, number]>;
718
+ function create_texture_async(path: string | Hash, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer?: Opaque<"buffer">, callback?: (...args: unknown[]) => unknown): LuaMultiReturn<[Hash, number]>;
719
719
  /**
720
720
  * Constructor-like function with two purposes:
721
721
  *
@@ -607,7 +607,7 @@ declare global {
607
607
  * sys.set_engine_throttle(true, 1.5);
608
608
  * ```
609
609
  */
610
- function set_engine_throttle(enable: boolean, cooldown: number): void;
610
+ function set_engine_throttle(enable: boolean, cooldown?: number): void;
611
611
  /**
612
612
  * Set the Lua error handler function.
613
613
  * The error handler is a function which is called whenever a lua runtime error occurs.
@@ -1366,7 +1366,7 @@ declare global {
1366
1366
  * gui.set_texture(n, path);
1367
1367
  * ```
1368
1368
  */
1369
- function new_texture(texture_id: string | Hash, width: number, height: number, type: string | Opaque<"constant">, buffer: string, flip: boolean): LuaMultiReturn<[boolean, number]>;
1369
+ function new_texture(texture_id: string | Hash, width: number, height: number, type: string | Opaque<"constant">, buffer: string, flip?: boolean): LuaMultiReturn<[boolean, number]>;
1370
1370
  /**
1371
1371
  * This is a callback-function, which is called by the engine when user input is sent to the instance of the gui component.
1372
1372
  * It can be used to take action on the input, e.g. modify the gui according to the input.
@@ -2229,7 +2229,7 @@ declare global {
2229
2229
  * });
2230
2230
  * ```
2231
2231
  */
2232
- function set_texture_data(texture: string | Hash, width: number, height: number, type: string | Opaque<"constant">, buffer: string, flip: boolean): boolean;
2232
+ function set_texture_data(texture: string | Hash, width: number, height: number, type: string | Opaque<"constant">, buffer: string, flip?: boolean): boolean;
2233
2233
  /**
2234
2234
  * Sets the tracking value of a text node. This value is used to
2235
2235
  * adjust the vertical spacing of characters in the text.
@@ -18,7 +18,7 @@ declare global {
18
18
  * @param id - product to buy
19
19
  * @param options - optional parameters as properties. The following parameters can be set
20
20
  */
21
- function buy(id: string, options: { request_id?: string; token?: string }): void;
21
+ function buy(id: string, options?: { request_id?: string; token?: string }): void;
22
22
  /**
23
23
  * Explicitly finish a product transaction. [icon:attention] Calling iap.finish is required on a successful transaction if `auto_finish_transactions` is disabled in project settings. Calling this function with `auto_finish_transactions` set will be ignored and a warning is printed. The `transaction.state` field must equal `iap.TRANS_STATE_PURCHASED`.
24
24
  *
@@ -526,7 +526,7 @@ declare global {
526
526
  * });
527
527
  * ```
528
528
  */
529
- function create_texture(path: string, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer: Opaque<"buffer">): Hash;
529
+ function create_texture(path: string, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer?: Opaque<"buffer">): Hash;
530
530
  /**
531
531
  * Creates a new texture resource that can be used in the same way as any texture created during build time.
532
532
  * The path used for creating the texture must be unique, trying to create a resource at a path that is already
@@ -715,7 +715,7 @@ declare global {
715
715
  * });
716
716
  * ```
717
717
  */
718
- function create_texture_async(path: string | Hash, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer: Opaque<"buffer">, callback: (...args: unknown[]) => unknown): LuaMultiReturn<[Hash, number]>;
718
+ function create_texture_async(path: string | Hash, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer?: Opaque<"buffer">, callback?: (...args: unknown[]) => unknown): LuaMultiReturn<[Hash, number]>;
719
719
  /**
720
720
  * Constructor-like function with two purposes:
721
721
  *
@@ -607,7 +607,7 @@ declare global {
607
607
  * sys.set_engine_throttle(true, 1.5);
608
608
  * ```
609
609
  */
610
- function set_engine_throttle(enable: boolean, cooldown: number): void;
610
+ function set_engine_throttle(enable: boolean, cooldown?: number): void;
611
611
  /**
612
612
  * Set the Lua error handler function.
613
613
  * The error handler is a function which is called whenever a lua runtime error occurs.
@@ -140,7 +140,7 @@ declare global {
140
140
  * b2d.fixture.set_shape(body, 2, { type: b2d.shape.SHAPE_TYPE_EDGE, v1: vmath.vector3(-32, 0, 0), v2: vmath.vector3(32, 0, 0) });
141
141
  * ```
142
142
  */
143
- function set_shape(body: Opaque<"b2Body">, fixture_index: number, shape: { type?: number; radius?: number; center?: Vector3; v0?: Vector3; v1?: Vector3; v2?: Vector3; v3?: Vector3; vertices?: Vector3[]; hx?: number; hy?: number; angle?: number; loop?: boolean; prev_vertex?: Vector3; next_vertex?: Vector3 }, update_mass: boolean): void;
143
+ function set_shape(body: Opaque<"b2Body">, fixture_index: number, shape: { type?: number; radius?: number; center?: Vector3; v0?: Vector3; v1?: Vector3; v2?: Vector3; v3?: Vector3; vertices?: Vector3[]; hx?: number; hy?: number; angle?: number; loop?: boolean; prev_vertex?: Vector3; next_vertex?: Vector3 }, update_mass?: boolean): void;
144
144
  /**
145
145
  * Test a point against a fixture.
146
146
  *
@@ -83,7 +83,7 @@ declare global {
83
83
  * @param definition - optional definition with `local_anchor_a`, `local_anchor_b`, `length`, `frequency`, `damping_ratio`, and `collide_connected`
84
84
  * @returns created joint
85
85
  */
86
- function create_distance(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; length?: number; frequency?: number; damping_ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
86
+ function create_distance(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; length?: number; frequency?: number; damping_ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
87
87
  /**
88
88
  * Create a filter joint.
89
89
  *
@@ -92,7 +92,7 @@ declare global {
92
92
  * @param definition - optional definition table
93
93
  * @returns created joint
94
94
  */
95
- function create_filter(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: Record<string | number, unknown>): Opaque<"b2Joint">;
95
+ function create_filter(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: Record<string | number, unknown>): Opaque<"b2Joint">;
96
96
  /**
97
97
  * Create a friction joint.
98
98
  *
@@ -101,7 +101,7 @@ declare global {
101
101
  * @param definition - optional definition with `local_anchor_a`, `local_anchor_b`, `max_force`, `max_torque`, and `collide_connected`
102
102
  * @returns created joint
103
103
  */
104
- function create_friction(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; max_force?: number; max_torque?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
104
+ function create_friction(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; max_force?: number; max_torque?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
105
105
  /**
106
106
  * Create a gear joint.
107
107
  *
@@ -110,7 +110,7 @@ declare global {
110
110
  * @param definition - optional definition with `ratio`
111
111
  * @returns created joint
112
112
  */
113
- function create_gear(joint1: Opaque<"b2Joint">, joint2: Opaque<"b2Joint">, definition: { ratio?: number }): Opaque<"b2Joint">;
113
+ function create_gear(joint1: Opaque<"b2Joint">, joint2: Opaque<"b2Joint">, definition?: { ratio?: number }): Opaque<"b2Joint">;
114
114
  /**
115
115
  * Create a motor joint.
116
116
  *
@@ -119,7 +119,7 @@ declare global {
119
119
  * @param definition - optional definition with `linear_offset`, `angular_offset`, `max_force`, `max_torque`, `correction_factor`, and `collide_connected`
120
120
  * @returns created joint
121
121
  */
122
- function create_motor(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { linear_offset?: Vector3; angular_offset?: number; max_force?: number; max_torque?: number; correction_factor?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
122
+ function create_motor(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { linear_offset?: Vector3; angular_offset?: number; max_force?: number; max_torque?: number; correction_factor?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
123
123
  /**
124
124
  * Create a mouse joint.
125
125
  *
@@ -128,7 +128,7 @@ declare global {
128
128
  * @param definition - optional definition with `target`, `max_force`, `frequency`, `damping_ratio`, and `collide_connected`
129
129
  * @returns created joint
130
130
  */
131
- function create_mouse(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { target?: Vector3; max_force?: number; frequency?: number; damping_ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
131
+ function create_mouse(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { target?: Vector3; max_force?: number; frequency?: number; damping_ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
132
132
  /**
133
133
  * Create a prismatic joint.
134
134
  *
@@ -137,7 +137,7 @@ declare global {
137
137
  * @param definition - optional definition with `local_anchor_a`, `local_anchor_b`, `local_axis_a`, `reference_angle`, `enable_limit`, `lower_translation`, `upper_translation`, `enable_motor`, `max_motor_force`, `motor_speed`, and `collide_connected`
138
138
  * @returns created joint
139
139
  */
140
- function create_prismatic(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; local_axis_a?: Vector3; reference_angle?: number; enable_limit?: boolean; lower_translation?: number; upper_translation?: number; enable_motor?: boolean; max_motor_force?: number; motor_speed?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
140
+ function create_prismatic(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; local_axis_a?: Vector3; reference_angle?: number; enable_limit?: boolean; lower_translation?: number; upper_translation?: number; enable_motor?: boolean; max_motor_force?: number; motor_speed?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
141
141
  /**
142
142
  * Create a pulley joint.
143
143
  *
@@ -146,7 +146,7 @@ declare global {
146
146
  * @param definition - optional definition with `ground_anchor_a`, `ground_anchor_b`, `local_anchor_a`, `local_anchor_b`, `length_a`, `length_b`, `ratio`, and `collide_connected`
147
147
  * @returns created joint
148
148
  */
149
- function create_pulley(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { ground_anchor_a?: Vector3; ground_anchor_b?: Vector3; local_anchor_a?: Vector3; local_anchor_b?: Vector3; length_a?: number; length_b?: number; ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
149
+ function create_pulley(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { ground_anchor_a?: Vector3; ground_anchor_b?: Vector3; local_anchor_a?: Vector3; local_anchor_b?: Vector3; length_a?: number; length_b?: number; ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
150
150
  /**
151
151
  * Create a revolute joint.
152
152
  *
@@ -155,7 +155,7 @@ declare global {
155
155
  * @param definition - optional definition with `local_anchor_a`, `local_anchor_b`, `reference_angle`, `enable_limit`, `lower_angle`, `upper_angle`, `enable_motor`, `max_motor_torque`, `motor_speed`, and `collide_connected`
156
156
  * @returns created joint
157
157
  */
158
- function create_revolute(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; reference_angle?: number; enable_limit?: boolean; lower_angle?: number; upper_angle?: number; enable_motor?: boolean; max_motor_torque?: number; motor_speed?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
158
+ function create_revolute(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; reference_angle?: number; enable_limit?: boolean; lower_angle?: number; upper_angle?: number; enable_motor?: boolean; max_motor_torque?: number; motor_speed?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
159
159
  /**
160
160
  * Create a rope joint.
161
161
  *
@@ -164,7 +164,7 @@ declare global {
164
164
  * @param definition - optional definition with `local_anchor_a`, `local_anchor_b`, `max_length`, and `collide_connected`
165
165
  * @returns created joint
166
166
  */
167
- function create_rope(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; max_length?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
167
+ function create_rope(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; max_length?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
168
168
  /**
169
169
  * Create a weld joint.
170
170
  *
@@ -173,7 +173,7 @@ declare global {
173
173
  * @param definition - optional definition with `local_anchor_a`, `local_anchor_b`, `reference_angle`, `frequency`, `damping_ratio`, and `collide_connected`
174
174
  * @returns created joint
175
175
  */
176
- function create_weld(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; reference_angle?: number; frequency?: number; damping_ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
176
+ function create_weld(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; reference_angle?: number; frequency?: number; damping_ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
177
177
  /**
178
178
  * Create a wheel joint.
179
179
  *
@@ -182,7 +182,7 @@ declare global {
182
182
  * @param definition - optional definition with `local_anchor_a`, `local_anchor_b`, `local_axis_a`, `enable_motor`, `max_motor_torque`, `motor_speed`, `frequency`, `damping_ratio`, and `collide_connected`
183
183
  * @returns created joint
184
184
  */
185
- function create_wheel(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; local_axis_a?: Vector3; enable_motor?: boolean; max_motor_torque?: number; motor_speed?: number; frequency?: number; damping_ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
185
+ function create_wheel(body_a: Opaque<"b2Body">, body_b: Opaque<"b2Body">, definition?: { local_anchor_a?: Vector3; local_anchor_b?: Vector3; local_axis_a?: Vector3; enable_motor?: boolean; max_motor_torque?: number; motor_speed?: number; frequency?: number; damping_ratio?: number; collide_connected?: boolean }): Opaque<"b2Joint">;
186
186
  /**
187
187
  * Destroy a joint created by `b2d.joint`.
188
188
  *
@@ -183,7 +183,7 @@ declare global {
183
183
  * @param max_fraction - optional maximum translation fraction, defaults to 1
184
184
  * @returns hit table with `point`, `normal`, `fraction`, and `iterations`, or nil
185
185
  */
186
- function ray_cast(shape_id: Opaque<"b2Shape">, origin: Vector3, translation: Vector3, max_fraction: number): { point: Vector3; normal: Vector3; fraction: number; iterations: number };
186
+ function ray_cast(shape_id: Opaque<"b2Shape">, origin: Vector3, translation: Vector3, max_fraction?: number): { point: Vector3; normal: Vector3; fraction: number; iterations: number };
187
187
  /**
188
188
  * Set shape material id.
189
189
  *
@@ -1364,7 +1364,7 @@ declare global {
1364
1364
  * gui.set_texture(n, path);
1365
1365
  * ```
1366
1366
  */
1367
- function new_texture(texture_id: string | Hash, width: number, height: number, type: string | Opaque<"constant">, buffer: string, flip: boolean): LuaMultiReturn<[boolean, number]>;
1367
+ function new_texture(texture_id: string | Hash, width: number, height: number, type: string | Opaque<"constant">, buffer: string, flip?: boolean): LuaMultiReturn<[boolean, number]>;
1368
1368
  /**
1369
1369
  * This is a callback-function, which is called by the engine when user input is sent to the instance of the gui component.
1370
1370
  * It can be used to take action on the input, e.g. modify the gui according to the input.
@@ -2227,7 +2227,7 @@ declare global {
2227
2227
  * });
2228
2228
  * ```
2229
2229
  */
2230
- function set_texture_data(texture: string | Hash, width: number, height: number, type: string | Opaque<"constant">, buffer: string, flip: boolean): boolean;
2230
+ function set_texture_data(texture: string | Hash, width: number, height: number, type: string | Opaque<"constant">, buffer: string, flip?: boolean): boolean;
2231
2231
  /**
2232
2232
  * Sets the tracking value of a text node. This value is used to
2233
2233
  * adjust the vertical spacing of characters in the text.
@@ -18,7 +18,7 @@ declare global {
18
18
  * @param id - product to buy
19
19
  * @param options - optional parameters as properties. The following parameters can be set
20
20
  */
21
- function buy(id: string, options: { request_id?: string; token?: string }): void;
21
+ function buy(id: string, options?: { request_id?: string; token?: string }): void;
22
22
  /**
23
23
  * Explicitly finish a product transaction. [icon:attention] Calling iap.finish is required on a successful transaction if `auto_finish_transactions` is disabled in project settings. Calling this function with `auto_finish_transactions` set will be ignored and a warning is printed. The `transaction.state` field must equal `iap.TRANS_STATE_PURCHASED`.
24
24
  *
@@ -526,7 +526,7 @@ declare global {
526
526
  * });
527
527
  * ```
528
528
  */
529
- function create_texture(path: string, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer: Opaque<"buffer">): Hash;
529
+ function create_texture(path: string, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer?: Opaque<"buffer">): Hash;
530
530
  /**
531
531
  * Creates a new texture resource that can be used in the same way as any texture created during build time.
532
532
  * The path used for creating the texture must be unique, trying to create a resource at a path that is already
@@ -715,7 +715,7 @@ declare global {
715
715
  * });
716
716
  * ```
717
717
  */
718
- function create_texture_async(path: string | Hash, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer: Opaque<"buffer">, callback: (...args: unknown[]) => unknown): LuaMultiReturn<[Hash, number]>;
718
+ function create_texture_async(path: string | Hash, table: { type?: number; width?: number; height?: number; depth?: number; format?: number; flags?: number; max_mipmaps?: number; compression_type?: number }, buffer?: Opaque<"buffer">, callback?: (...args: unknown[]) => unknown): LuaMultiReturn<[Hash, number]>;
719
719
  /**
720
720
  * Constructor-like function with two purposes:
721
721
  *
@@ -607,7 +607,7 @@ declare global {
607
607
  * sys.set_engine_throttle(true, 1.5);
608
608
  * ```
609
609
  */
610
- function set_engine_throttle(enable: boolean, cooldown: number): void;
610
+ function set_engine_throttle(enable: boolean, cooldown?: number): void;
611
611
  /**
612
612
  * Set the Lua error handler function.
613
613
  * The error handler is a function which is called whenever a lua runtime error occurs.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defold-typescript/types",
3
- "version": "0.33.0",
3
+ "version": "0.33.1",
4
4
  "description": "TypeScript types for the Defold engine's Lua APIs.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,4 +1,5 @@
1
1
  import { resolve } from "node:path";
2
+ import { type ApiFunction, parseDefoldApiDoc } from "../src/api-doc";
2
3
  import { DEFOLD_TYPE_MAP } from "../src/core-types";
3
4
  import {
4
5
  ARBITRARY_TABLE_SLOT_KEYS,
@@ -8,6 +9,7 @@ import {
8
9
  buildTableDocResolver,
9
10
  HANDLE_METHOD_LOCAL,
10
11
  HOMOGENEOUS_ARRAY_SLOTS,
12
+ isDocOptional,
11
13
  isRecordsCollectionSlot,
12
14
  isSlotLevelList,
13
15
  MAPPING_TABLE_SLOTS,
@@ -18,6 +20,7 @@ import {
18
20
  TABLE_SLOT_CURATIONS,
19
21
  type TableSlotCuration,
20
22
  TS_IDENTIFIER,
23
+ trailingOptionalCutoff,
21
24
  } from "../src/emit-dts";
22
25
  import { parseMessagesDoc } from "../src/emit-messages";
23
26
  import {
@@ -87,6 +90,207 @@ export function countDroppedHandleMethods(doc: unknown, namespace: string, emit
87
90
  return dropped;
88
91
  }
89
92
 
93
+ // Upstream ships `examples`, `description` and `brief` as syntax-highlighted HTML
94
+ // — every token in its own span, quotes as entities — so a call site is invisible
95
+ // to any parser until the markup is gone. `&amp;` decodes last so an escaped
96
+ // entity stays literal.
97
+ function plainText(html: string): string {
98
+ return html
99
+ .replace(/<[^>]*>/g, "")
100
+ .replace(/&quot;/g, '"')
101
+ .replace(/&#39;/g, "'")
102
+ .replace(/&lt;/g, "<")
103
+ .replace(/&gt;/g, ">")
104
+ .replace(/&amp;/g, "&");
105
+ }
106
+
107
+ // The arguments of the call whose `(` ends just before `start`, split on
108
+ // top-level commas only: a comma inside a nested call, table, index or string
109
+ // literal belongs to that argument. Null when the text ends before the call does.
110
+ function splitArguments(text: string, start: number): string[] | null {
111
+ const args: string[] = [];
112
+ let current = "";
113
+ let depth = 0;
114
+ let quote: string | null = null;
115
+ for (let i = start; i < text.length; i += 1) {
116
+ const ch = text[i] as string;
117
+ if (quote !== null) {
118
+ current += ch;
119
+ if (ch === "\\") {
120
+ current += text[i + 1] ?? "";
121
+ i += 1;
122
+ } else if (ch === quote) {
123
+ quote = null;
124
+ }
125
+ continue;
126
+ }
127
+ if (ch === '"' || ch === "'") {
128
+ quote = ch;
129
+ } else if (ch === "(" || ch === "{" || ch === "[") {
130
+ depth += 1;
131
+ } else if (ch === ")" || ch === "}" || ch === "]") {
132
+ if (depth === 0) {
133
+ if (ch !== ")") return null;
134
+ const last = current.trim();
135
+ if (last !== "" || args.length > 0) args.push(last);
136
+ return args;
137
+ }
138
+ depth -= 1;
139
+ } else if (ch === "," && depth === 0) {
140
+ args.push(current.trim());
141
+ current = "";
142
+ continue;
143
+ }
144
+ current += ch;
145
+ }
146
+ return null;
147
+ }
148
+
149
+ // Inline `<code>` in example prose names a function rather than calling it
150
+ // (`<code>gui.set_texture()</code> is sufficient`). A highlighted block's `<code>`
151
+ // always wraps token spans, so only the prose kind is bare text.
152
+ const INLINE_CODE = /<code>[^<]*<\/code>/g;
153
+
154
+ const exampleCallCache = new WeakMap<ApiFunction, readonly (readonly string[])[]>();
155
+
156
+ // Every `<fqn>(…)` call in the function's upstream examples, as argument lists.
157
+ function exampleCalls(fn: ApiFunction): readonly (readonly string[])[] {
158
+ const cached = exampleCallCache.get(fn);
159
+ if (cached !== undefined) return cached;
160
+ const text = plainText((fn.examples ?? "").replace(INLINE_CODE, ""));
161
+ const escaped = fn.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
162
+ const calls: string[][] = [];
163
+ for (const match of text.matchAll(new RegExp(`(?<![\\w.:])${escaped}\\s*\\(`, "g"))) {
164
+ const args = splitArguments(text, match.index + match[0].length);
165
+ if (args !== null) calls.push(args);
166
+ }
167
+ exampleCallCache.set(fn, calls);
168
+ return calls;
169
+ }
170
+
171
+ // Whether a call passing `count` arguments fits this declaration's arity, with
172
+ // the emitter's own trailing-optional cutoff as the floor.
173
+ function acceptsArgumentCount(fn: ApiFunction, count: number): boolean {
174
+ const params = fn.parameters;
175
+ if (count < trailingOptionalCutoff(params, fn.name)) return false;
176
+ return count <= params.length || params.some((p) => p.isVararg === true);
177
+ }
178
+
179
+ // The ref-doc documents an overload as a separate element sharing the name, and
180
+ // an element's examples often call a sibling (`vmath.vector3(2.0)` beside the
181
+ // `x, y, z` form). A call another same-named declaration accepts is that
182
+ // declaration's call, not an omission from this one.
183
+ function ownExampleCalls(
184
+ fn: ApiFunction,
185
+ overloads: readonly ApiFunction[],
186
+ ): readonly (readonly string[])[] {
187
+ return exampleCalls(fn).filter(
188
+ (args) => !overloads.some((other) => other !== fn && acceptsArgumentCount(other, args.length)),
189
+ );
190
+ }
191
+
192
+ // A table parameter's `<dl>`/`<ul>` describes its fields, so an optional field
193
+ // there says nothing about whether the argument itself may be omitted.
194
+ const FIELD_LIST = /<(dl|ul|ol|table)\b[\s\S]*?<\/\1>/g;
195
+ const OPENS_OPTIONAL = /^\s*optional\b/i;
196
+ const OMISSION_PHRASE = /\bdefaults? to\b|\b(?:if|when|can be|may be) omitted\b/i;
197
+
198
+ type OptionalityAxis = (
199
+ fn: ApiFunction,
200
+ index: number,
201
+ overloads: readonly ApiFunction[],
202
+ ) => boolean;
203
+
204
+ // The three ways a ref-doc evidences that a parameter may be omitted, each read
205
+ // from one function element and its same-named overloads. `is_optional` is not
206
+ // among them: a slot upstream marks optional is already emitted omissible, so
207
+ // only the unmarked ones can be lost.
208
+ export const OPTIONALITY_EVIDENCE: Readonly<
209
+ Record<"prose" | "exampleArity" | "exampleNil", OptionalityAxis>
210
+ > = {
211
+ // The parameter's own prose opens with "optional", or names a default or an
212
+ // omission outside any field list.
213
+ prose: (fn, index) => {
214
+ const doc = fn.parameters[index]?.doc ?? "";
215
+ return (
216
+ OPENS_OPTIONAL.test(plainText(doc)) ||
217
+ OMISSION_PHRASE.test(plainText(doc.replace(FIELD_LIST, " ")))
218
+ );
219
+ },
220
+ // An upstream example stops before this parameter. A trailing `...` forwards
221
+ // an unknown number of values, so it proves nothing about arity.
222
+ exampleArity: (fn, index, overloads) =>
223
+ ownExampleCalls(fn, overloads).some((args) => args.length <= index && args.at(-1) !== "..."),
224
+ // An upstream example passes a bare `nil` in this position.
225
+ exampleNil: (fn, index, overloads) =>
226
+ ownExampleCalls(fn, overloads).some((args) => args[index] === "nil"),
227
+ };
228
+
229
+ const ARITY_OVERLOAD_REASON =
230
+ "the example `vmath.euler_to_quat(v)` passes one vector3 for all three angles: " +
231
+ "y and z are required in the three-number form, and the one-argument call needs " +
232
+ "an overload the declaration lacks, not an omissible slot";
233
+
234
+ // Slots the evidence flags that are genuinely required, keyed like
235
+ // `OPTIONAL_SLOT_CORRECTIONS`. Each value is the recorded reason, so an
236
+ // exemption is a decision someone can re-check rather than a silent skip.
237
+ export const OPTIONALITY_EVIDENCE_EXEMPTIONS: ReadonlyMap<string, string> = new Map([
238
+ [
239
+ "render.render_target:param:parameters",
240
+ "both upstream examples pass the parameters table first, in place of `name`: an " +
241
+ "argument shifted into another slot rather than this one omitted, which an " +
242
+ "overload the declaration lacks would express",
243
+ ],
244
+ ["vmath.euler_to_quat:param:y", ARITY_OVERLOAD_REASON],
245
+ ["vmath.euler_to_quat:param:z", ARITY_OVERLOAD_REASON],
246
+ ]);
247
+
248
+ export interface EvidencedSlot {
249
+ readonly key: string;
250
+ readonly emittedRequired: boolean;
251
+ }
252
+
253
+ // Every `<element>:param:<slot>` the ref-doc evidences as omissible, and whether
254
+ // the emitted surface still requires it. A slot is emitted omissible when any
255
+ // same-named declaration makes that position omissible under `isDocOptional`,
256
+ // the emitter's own predicate, corrections included. Skipped functions are
257
+ // hand-authored, so their slots are not the generator's to lose.
258
+ export function evidencedOptionalSlots(
259
+ entry: Pick<ModuleManifestEntry, "doc" | "skipFunctions">,
260
+ ): EvidencedSlot[] {
261
+ const skipFunctions = new Set(entry.skipFunctions ?? []);
262
+ const functions = parseDefoldApiDoc(entry.doc).functions;
263
+ const overloadsByName = new Map<string, ApiFunction[]>();
264
+ for (const fn of functions) {
265
+ overloadsByName.set(fn.name, [...(overloadsByName.get(fn.name) ?? []), fn]);
266
+ }
267
+ const emittedRequired = new Map<string, boolean>();
268
+ for (const fn of functions) {
269
+ if (skipFunctions.has(stripNamespace(fn.name))) continue;
270
+ const overloads = overloadsByName.get(fn.name) ?? [fn];
271
+ fn.parameters.forEach((param, index) => {
272
+ if (param.isVararg === true) return;
273
+ if (!Object.values(OPTIONALITY_EVIDENCE).some((axis) => axis(fn, index, overloads))) return;
274
+ const omissible = overloads.some((other) => {
275
+ const slot = other.parameters[index];
276
+ return slot?.name === param.name && isDocOptional(slot, other.name);
277
+ });
278
+ const key = tableSlotKey(fn.name, "param", param.name);
279
+ emittedRequired.set(key, (emittedRequired.get(key) ?? false) || !omissible);
280
+ });
281
+ }
282
+ return [...emittedRequired].map(([key, required]) => ({ key, emittedRequired: required }));
283
+ }
284
+
285
+ // The evidenced slots the emitted declaration still requires, before exemptions.
286
+ export function unmarkedOptionalSlots(
287
+ entry: Pick<ModuleManifestEntry, "doc" | "skipFunctions">,
288
+ ): string[] {
289
+ return evidencedOptionalSlots(entry)
290
+ .filter((slot) => slot.emittedRequired)
291
+ .map((slot) => slot.key);
292
+ }
293
+
90
294
  function auditEntry(
91
295
  entry: ModuleManifestEntry,
92
296
  knownConstantFqns: ReadonlySet<string>,
@@ -99,9 +303,13 @@ function auditEntry(
99
303
  // multiReturn is fully recovered: emitReturn emits LuaMultiReturn<[...]> for
100
304
  // every >1-return function, so no documented multi-return is a loss anymore.
101
305
  const multiReturn = 0;
102
- // optionalAsRequired is fully recovered: emitParameter expresses an interior
103
- // doc-optional param as `| undefined`, so no doc-optional param is a loss.
104
- const optionalAsRequired = 0;
306
+ // Every param upstream marks optional is recovered: emitParameter expresses an
307
+ // interior one as `| undefined` and a trailing one as `?`. What stays lost is a
308
+ // slot the ref-doc evidences as omissible without marking it, which neither an
309
+ // OPTIONAL_SLOT_CORRECTIONS entry nor a stated exemption accounts for.
310
+ const optionalAsRequired = unmarkedOptionalSlots(entry).filter(
311
+ (key) => !OPTIONALITY_EVIDENCE_EXEMPTIONS.has(key),
312
+ ).length;
105
313
  const unknown = new Set<string>();
106
314
 
107
315
  const constantFqns = new Set<string>();
@@ -394,7 +602,8 @@ function auditEntry(
394
602
  );
395
603
  // Interior doc-optional params (a required param follows) are no longer a
396
604
  // loss: emitParameter expresses them as `| undefined`, mirroring the
397
- // emitted surface. optionalAsRequired stays in the report shape reading 0.
605
+ // emitted surface. optionalAsRequired counts the unmarked ones instead,
606
+ // through unmarkedOptionalSlots above.
398
607
  });
399
608
  for (const ret of returns) {
400
609
  const tableSlotCuration =