Skip to content

Commit 4431706

Browse files
committed
Add documentation support for builtins/classes in .pyi files
1 parent 3b756ad commit 4431706

File tree

13 files changed

+176
-47
lines changed

13 files changed

+176
-47
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ jobs:
105105
$GODOT_BIN --headless --version
106106
107107
mkdir $GDEXTENSION_DIR && pushd $GDEXTENSION_DIR
108-
$GODOT_BIN --headless --dump-extension-api
108+
$GODOT_BIN --headless --dump-extension-api-with-docs
109109
mkdir godot && pushd godot
110110
$GODOT_BIN --headless --dump-gdextension-interface
111111
popd && popd
@@ -200,7 +200,7 @@ jobs:
200200
$GODOT_BIN --headless --version
201201
202202
mkdir $GDEXTENSION_DIR && pushd $GDEXTENSION_DIR
203-
../$GODOT_BIN --headless --dump-extension-api
203+
../$GODOT_BIN --headless --dump-extension-api-with-docs
204204
mkdir godot && pushd godot
205205
../../$GODOT_BIN --headless --dump-gdextension-interface
206206
popd && popd

scripts/extension_api_parser/api.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def parse_global_enum(spec: dict) -> EnumTypeSpec:
4040
py_type=cooked_name,
4141
cy_type=cooked_name,
4242
is_bitfield=spec["is_bitfield"],
43-
values={x["name"]: x["value"] for x in spec["values"]},
43+
values=spec["values"],
4444
)
4545

4646

@@ -76,12 +76,14 @@ class UtilityFunctionSpec:
7676
is_vararg: bool
7777
hash: int
7878
arguments: list[UtilityFunctionArgumentSpec]
79+
description: str | None
7980

8081
@classmethod
8182
def parse(cls, item: dict) -> UtilityFunctionSpec:
8283
item.setdefault("original_name", item["name"])
8384
item.setdefault("arguments", [])
8485
item.setdefault("return_type", "Nil")
86+
item.setdefault("description", None)
8587
assert_api_consistency(cls, item)
8688
return cls(
8789
name=correct_name(item["name"]),
@@ -91,6 +93,7 @@ def parse(cls, item: dict) -> UtilityFunctionSpec:
9193
is_vararg=item["is_vararg"],
9294
hash=item["hash"],
9395
arguments=[UtilityFunctionArgumentSpec.parse(x) for x in item["arguments"]],
96+
description=item["description"],
9497
)
9598

9699

scripts/extension_api_parser/builtins.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class BuiltinConstructorSpec:
7878
index: int
7979
arguments: list[BuiltinMethodArgumentSpec]
8080
base_name: str
81+
description: str | None
8182

8283
@property
8384
def c_name(self) -> str:
@@ -92,13 +93,15 @@ def c_name(self) -> str:
9293
@classmethod
9394
def parse(cls, item: dict, snake_name: str) -> BuiltinConstructorSpec:
9495
item.setdefault("arguments", [])
96+
item.setdefault("description", None)
9597
args = [BuiltinMethodArgumentSpec.parse(x) for x in item["arguments"]]
9698
item["base_name"] = f"{snake_name}_new"
9799
assert_api_consistency(cls, item)
98100
return cls(
99101
index=item["index"],
100102
arguments=args,
101103
base_name=item["base_name"],
104+
description=item["description"],
102105
)
103106

104107

@@ -109,11 +112,13 @@ class BuiltinOperatorSpec:
109112
variant_operator_name: str
110113
right_type: TypeInUse | None
111114
return_type: TypeInUse
115+
description: str | None
112116

113117
@classmethod
114118
def parse(cls, item: dict) -> BuiltinOperatorSpec:
115119
item.setdefault("original_name", item["name"])
116120
item.setdefault("right_type", None)
121+
item.setdefault("description", None)
117122
item["name"], item["variant_operator_name"] = VARIANT_OPERATORS[item.pop("name")]
118123
if item["right_type"] is not None:
119124
right_type_snake_name = _builtin_snake_name(item["right_type"])
@@ -129,6 +134,7 @@ def parse(cls, item: dict) -> BuiltinOperatorSpec:
129134
# emptiness.
130135
right_type=None if item["right_type"] is None else TypeInUse.parse(item["right_type"]),
131136
return_type=TypeInUse.parse(item["return_type"]),
137+
description=item["description"],
132138
)
133139

134140

@@ -138,6 +144,7 @@ class BuiltinMemberSpec:
138144
original_name: str
139145
offset: int | None
140146
type: TypeInUse
147+
description: str | None
141148

142149
@property
143150
def is_in_struct(self) -> bool:
@@ -147,12 +154,14 @@ def is_in_struct(self) -> bool:
147154
def parse(cls, item: dict) -> BuiltinMemberSpec:
148155
item.setdefault("original_name", item["name"])
149156
item.setdefault("offset", None)
157+
item.setdefault("description", None)
150158
assert_api_consistency(cls, item)
151159
return cls(
152160
name=correct_name(item["name"]),
153161
original_name=item["original_name"],
154162
offset=item["offset"],
155163
type=TypeInUse.parse(item["type"]),
164+
description=item["description"],
156165
)
157166

158167

@@ -162,16 +171,19 @@ class BuiltinConstantSpec:
162171
original_name: str
163172
type: TypeInUse
164173
value: str
174+
description: str | None
165175

166176
@classmethod
167177
def parse(cls, item: dict) -> BuiltinConstantSpec:
168178
item.setdefault("original_name", item["name"])
179+
item.setdefault("description", None)
169180
assert_api_consistency(cls, item)
170181
return cls(
171182
name=correct_name(item["name"]),
172183
original_name=item["original_name"],
173184
type=TypeInUse.parse(item["type"]),
174185
value=item["value"],
186+
description=item["description"],
175187
)
176188

177189

@@ -185,6 +197,7 @@ class BuiltinMethodSpec:
185197
is_static: bool
186198
hash: int
187199
arguments: list[BuiltinMethodArgumentSpec]
200+
description: str | None
188201

189202
@property
190203
def contains_unsuported_types(self) -> bool:
@@ -203,6 +216,7 @@ def parse(cls, item: dict) -> BuiltinMethodSpec:
203216
item.setdefault("original_name", item["name"])
204217
item.setdefault("arguments", [])
205218
item.setdefault("return_type", "Nil")
219+
item.setdefault("description", None)
206220
assert_api_consistency(cls, item)
207221
return cls(
208222
name=correct_name(item["name"]),
@@ -213,6 +227,7 @@ def parse(cls, item: dict) -> BuiltinMethodSpec:
213227
is_static=item["is_static"],
214228
hash=item["hash"],
215229
arguments=[BuiltinMethodArgumentSpec.parse(x) for x in item["arguments"]],
230+
description=item["description"],
216231
)
217232

218233

@@ -224,7 +239,7 @@ def parse_builtin_enum(spec: dict, builtin_cy_type: str, builtin_py_type: str) -
224239
py_type=f"{builtin_py_type}.{spec['name']}",
225240
cy_type=f"{builtin_cy_type}.{spec['name']}",
226241
is_bitfield=spec["is_bitfield"],
227-
values={x["name"]: x["value"] for x in spec["values"]},
242+
values=spec["values"],
228243
)
229244

230245

@@ -243,6 +258,8 @@ class BuiltinTypeSpec(TypeSpec):
243258
members: list[BuiltinMemberSpec]
244259
constants: list[BuiltinConstantSpec]
245260
enums: list[EnumTypeSpec]
261+
description: str | None
262+
brief_description: str | None
246263

247264
@property
248265
def all_nested_scalar_members(self) -> Generator[str]:
@@ -367,6 +384,8 @@ def _parse_builtin(spec: dict) -> BuiltinTypeSpec:
367384
spec.setdefault("members", [])
368385
spec.setdefault("constants", [])
369386
spec.setdefault("enums", [])
387+
spec.setdefault("brief_description", None)
388+
spec.setdefault("description", None)
370389
assert spec.keys() == {
371390
"name",
372391
"indexing_return_type",
@@ -379,6 +398,8 @@ def _parse_builtin(spec: dict) -> BuiltinTypeSpec:
379398
"members",
380399
"constants",
381400
"enums",
401+
"brief_description",
402+
"description",
382403
}
383404

384405
original_name = spec["name"]
@@ -442,6 +463,8 @@ def _parse_builtin(spec: dict) -> BuiltinTypeSpec:
442463
members=members,
443464
constants=constants,
444465
enums=enums,
466+
description=spec["description"],
467+
brief_description=spec["brief_description"],
445468
)
446469
else:
447470
return OpaqueBuiltinTypeSpec(
@@ -463,6 +486,8 @@ def _parse_builtin(spec: dict) -> BuiltinTypeSpec:
463486
members=members,
464487
constants=constants,
465488
enums=enums,
489+
description=spec["description"],
490+
brief_description=spec["brief_description"],
466491
)
467492

468493

scripts/extension_api_parser/classes.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def parse_class_enum(spec: dict, class_name: str) -> EnumTypeSpec:
1818
py_type=f"{class_name}.{spec['name']}",
1919
cy_type=f"{class_name}.{spec['name']}",
2020
is_bitfield=spec["is_bitfield"],
21-
values={x["name"]: x["value"] for x in spec["values"]},
21+
values=spec["values"],
2222
)
2323

2424

@@ -66,6 +66,7 @@ class ClassMethodSpec:
6666
hash_compatibility: int | None
6767
return_type: TypeInUse
6868
arguments: list[ClassMethodArgumentSpec]
69+
description: str | None
6970

7071
@classmethod
7172
def parse(cls, item: dict) -> ClassMethodSpec:
@@ -82,6 +83,7 @@ def parse(cls, item: dict) -> ClassMethodSpec:
8283
item.setdefault("is_property_accessor", False)
8384
# Added in Godot 4.4 (see https://github.com/godotengine/godot/pull/93311)
8485
item.setdefault("is_required", False)
86+
item.setdefault("description", None)
8587
assert_api_consistency(cls, item)
8688
return cls(
8789
name=correct_name(item["name"]),
@@ -96,6 +98,7 @@ def parse(cls, item: dict) -> ClassMethodSpec:
9698
hash_compatibility=item["hash_compatibility"],
9799
return_type=item["return_type"],
98100
arguments=[ClassMethodArgumentSpec.parse(x) for x in item["arguments"]],
101+
description=item["description"],
99102
)
100103

101104

@@ -104,16 +107,19 @@ class ClassSignalSpec:
104107
original_name: str
105108
name: str
106109
arguments: list[ClassMethodArgumentSpec]
110+
description: str | None
107111

108112
@classmethod
109113
def parse(cls, item: dict) -> ClassSignalSpec:
110114
item.setdefault("original_name", item["name"])
111115
item.setdefault("arguments", [])
116+
item.setdefault("description", None)
112117
assert_api_consistency(cls, item)
113118
return cls(
114119
name=correct_name(item["name"]),
115120
original_name=item["original_name"],
116121
arguments=[ClassMethodArgumentSpec.parse(x) for x in item["arguments"]],
122+
description=item["description"],
117123
)
118124

119125

@@ -125,6 +131,7 @@ class ClassPropertySpec:
125131
getter: str
126132
setter: str | None
127133
index: int | None
134+
description: str | None
128135

129136
@classmethod
130137
def parse(cls, item: dict) -> ClassPropertySpec:
@@ -133,6 +140,7 @@ def parse(cls, item: dict) -> ClassPropertySpec:
133140
assert item["getter"] is not None
134141
item.setdefault("setter", None)
135142
item.setdefault("index", None)
143+
item.setdefault("description", None)
136144
assert_api_consistency(cls, item)
137145
return cls(
138146
name=correct_name(item["name"]),
@@ -141,9 +149,17 @@ def parse(cls, item: dict) -> ClassPropertySpec:
141149
getter=item["getter"],
142150
setter=item["setter"],
143151
index=item["index"],
152+
description=item["description"],
144153
)
145154

146155

156+
@dataclass(slots=True)
157+
class ClassTypeConstant:
158+
name: str
159+
value: int
160+
description: str | None
161+
162+
147163
@dataclass(slots=True)
148164
class ClassTypeSpec(TypeSpec):
149165
"""
@@ -162,7 +178,9 @@ class ClassTypeSpec(TypeSpec):
162178
methods: list[ClassMethodSpec]
163179
signals: list[ClassSignalSpec]
164180
properties: list[ClassPropertySpec]
165-
constants: dict[str, int]
181+
constants: list[ClassTypeConstant]
182+
description: str | None
183+
brief_description: str | None
166184

167185
@property
168186
def is_object(self) -> bool:
@@ -178,7 +196,16 @@ def __init__(self, **kwargs):
178196
self.methods = kwargs.pop("methods")
179197
self.signals = kwargs.pop("signals")
180198
self.properties = kwargs.pop("properties")
181-
self.constants = kwargs.pop("constants")
199+
self.constants = [
200+
ClassTypeConstant(
201+
name=c["name"],
202+
value=c["value"],
203+
description=c["description"],
204+
)
205+
for c in kwargs.pop("constants")
206+
]
207+
self.description = kwargs.pop("description")
208+
self.brief_description = kwargs.pop("brief_description")
182209
TypeSpec.__init__(
183210
self,
184211
c_type="gd_object_t",
@@ -197,6 +224,8 @@ def parse_class(spec: dict, object_size: int) -> ClassTypeSpec:
197224
spec.setdefault("methods", [])
198225
spec.setdefault("properties", [])
199226
spec.setdefault("constants", [])
227+
spec.setdefault("description", [])
228+
spec.setdefault("brief_description", [])
200229
spec["inherits"] = spec.get("inherits") or None
201230
assert spec.keys() == {
202231
"name",
@@ -209,6 +238,8 @@ def parse_class(spec: dict, object_size: int) -> ClassTypeSpec:
209238
"signals",
210239
"properties",
211240
"constants",
241+
"description",
242+
"brief_description",
212243
}, spec.keys()
213244

214245
original_name = spec["name"]
@@ -230,5 +261,7 @@ def parse_class(spec: dict, object_size: int) -> ClassTypeSpec:
230261
methods=[ClassMethodSpec.parse(x) for x in spec["methods"]],
231262
signals=[ClassSignalSpec.parse(x) for x in spec["signals"]],
232263
properties=[ClassPropertySpec.parse(x) for x in spec["properties"]],
233-
constants={x["name"]: x["value"] for x in spec["constants"]},
264+
constants=spec["constants"],
265+
description=spec["description"],
266+
brief_description=spec["brief_description"],
234267
)

0 commit comments

Comments
 (0)