Omit return_value in gdextension_interface.json for void functions

This commit is contained in:
David Snopek
2026-01-07 08:39:38 -06:00
parent 76dda5c6c5
commit 74336ffcea
4 changed files with 33 additions and 432 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -214,7 +214,7 @@
}
}
},
"required": ["name", "kind", "return_value", "arguments"]
"required": ["name", "kind", "arguments"]
}
}
]
@@ -306,7 +306,6 @@
},
"required": [
"name",
"return_value",
"arguments",
"description",
"since"

View File

@@ -163,8 +163,14 @@ void GDExtensionInterfaceHeaderGenerator::write_enum_type(const Ref<FileAccess>
void GDExtensionInterfaceHeaderGenerator::write_function_type(const Ref<FileAccess> &p_fa, const Dictionary &p_func) {
String args_text = p_func.has("arguments") ? make_args_text(p_func["arguments"]) : "";
String name_and_args = vformat("(*%s)(%s)", p_func["name"], args_text);
Dictionary ret = p_func["return_value"];
p_fa->store_string(vformat("typedef %s;%s\n", format_type_and_name(ret["type"], name_and_args), make_deprecated_comment_for_type(p_func)));
String return_type;
if (p_func.has("return_value")) {
Dictionary ret = p_func["return_value"];
return_type = ret["type"];
} else {
return_type = "void";
}
p_fa->store_string(vformat("typedef %s;%s\n", format_type_and_name(return_type, name_and_args), make_deprecated_comment_for_type(p_func)));
}
void GDExtensionInterfaceHeaderGenerator::write_struct_type(const Ref<FileAccess> &p_fa, const Dictionary &p_struct) {
@@ -261,17 +267,15 @@ void GDExtensionInterfaceHeaderGenerator::write_interface(const Ref<FileAccess>
if (p_interface.has("return_value")) {
Dictionary ret = p_interface["return_value"];
if (ret["type"] != "void") {
String ret_string = String("@return");
if (ret.has("description")) {
Array arg_doc = ret["description"];
for (const Variant &d : arg_doc) {
ret_string += String(" ") + (String)d;
}
String ret_string = String("@return");
if (ret.has("description")) {
Array arg_doc = ret["description"];
for (const Variant &d : arg_doc) {
ret_string += String(" ") + (String)d;
}
doc.push_back("");
doc.push_back(ret_string);
}
doc.push_back("");
doc.push_back(ret_string);
}
if (p_interface.has("see")) {

View File

@@ -85,7 +85,7 @@ extern "C" {
check_allowed_keys(type, ["name", "kind", "values"], ["is_bitfield", "description", "deprecated"])
write_enum_type(file, type)
elif kind == "function":
check_allowed_keys(type, ["name", "kind", "return_value", "arguments"], ["description", "deprecated"])
check_allowed_keys(type, ["name", "kind", "arguments"], ["return_value", "description", "deprecated"])
write_function_type(file, type)
elif kind == "struct":
check_allowed_keys(type, ["name", "kind", "members"], ["description", "deprecated"])
@@ -108,8 +108,8 @@ extern "C" {
check_type("function", interface, valid_data_types)
check_allowed_keys(
interface,
["name", "return_value", "arguments", "since", "description"],
["see", "legacy_type_name", "deprecated"],
["name", "arguments", "since", "description"],
["return_value", "see", "legacy_type_name", "deprecated"],
)
valid_interfaces[interface["name"]] = interface
if "deprecated" in interface:
@@ -200,20 +200,27 @@ def format_type_and_name(type, name=None):
return ret
def is_valid_type(type, valid_data_types):
if type in ["void", "const void"]:
# The "void" type can only be used with the pointer modifier.
return False
return base_type_name(type) in valid_data_types
def check_type(kind, type, valid_data_types):
if kind == "alias":
if base_type_name(type["type"]) not in valid_data_types:
if not is_valid_type(type["type"], valid_data_types):
raise UnknownTypeError(type["type"], type["name"])
elif kind == "struct":
for member in type["members"]:
if base_type_name(member["type"]) not in valid_data_types:
if not is_valid_type(member["type"], valid_data_types):
raise UnknownTypeError(member["type"], type["name"], member["name"])
elif kind == "function":
for arg in type["arguments"]:
if base_type_name(arg["type"]) not in valid_data_types:
if not is_valid_type(arg["type"], valid_data_types):
raise UnknownTypeError(arg["type"], type["name"], arg.get("name"))
if "return_value" in type:
if base_type_name(type["return_value"]["type"]) not in valid_data_types:
if not is_valid_type(type["return_value"]["type"], valid_data_types):
raise UnknownTypeError(type["return_value"]["type"], type["name"])
@@ -277,9 +284,8 @@ def make_args_text(args):
def write_function_type(file, fn):
args_text = make_args_text(fn["arguments"]) if ("arguments" in fn) else ""
name_and_args = f"(*{fn['name']})({args_text})"
file.write(
f"typedef {format_type_and_name(fn['return_value']['type'], name_and_args)};{make_deprecated_comment_for_type(fn)}\n"
)
return_type = fn["return_value"]["type"] if "return_value" in fn else "void"
file.write(f"typedef {format_type_and_name(return_type, name_and_args)};{make_deprecated_comment_for_type(fn)}\n")
def write_struct_type(file, struct):
@@ -318,7 +324,7 @@ def write_interface(file, interface):
arg_doc = " ".join(arg["description"])
doc.append(f"@param {arg['name']} {arg_doc}")
if "return_value" in interface and interface["return_value"]["type"] != "void":
if "return_value" in interface:
if "description" not in interface["return_value"]:
raise Exception(f"Interface function {interface['name']} is missing docs for return value")
ret_doc = " ".join(interface["return_value"]["description"])