Browse Source

Optionally include documentation in GDExtension API dump

Ricardo Buring 1 year ago
parent
commit
8ee04c5f87
3 changed files with 234 additions and 8 deletions
  1. 217 4
      core/extension/extension_api_dump.cpp
  2. 2 2
      core/extension/extension_api_dump.h
  3. 15 2
      main/main.cpp

+ 217 - 4
core/extension/extension_api_dump.cpp

@@ -39,6 +39,7 @@
 #include "core/version.h"
 #include "core/version.h"
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
+#include "editor/editor_help.h"
 
 
 static String get_builtin_or_variant_type_name(const Variant::Type p_type) {
 static String get_builtin_or_variant_type_name(const Variant::Type p_type) {
 	if (p_type == Variant::NIL) {
 	if (p_type == Variant::NIL) {
@@ -88,7 +89,16 @@ static String get_type_meta_name(const GodotTypeInfo::Metadata metadata) {
 	return argmeta[metadata];
 	return argmeta[metadata];
 }
 }
 
 
-Dictionary GDExtensionAPIDump::generate_extension_api() {
+static String fix_doc_description(const String &p_bbcode) {
+	// Based on what EditorHelp does.
+
+	return p_bbcode.dedent()
+			.replace("\t", "")
+			.replace("\r", "")
+			.strip_edges();
+}
+
+Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
 	Dictionary api_dump;
 	Dictionary api_dump;
 
 
 	{
 	{
@@ -460,12 +470,22 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 		api_dump["builtin_class_member_offsets"] = core_type_member_offsets;
 		api_dump["builtin_class_member_offsets"] = core_type_member_offsets;
 	}
 	}
 
 
+	if (p_include_docs) {
+		EditorHelp::generate_doc(false);
+	}
+
 	{
 	{
 		// Global enums and constants.
 		// Global enums and constants.
 		Array constants;
 		Array constants;
 		HashMap<String, List<Pair<String, int64_t>>> enum_list;
 		HashMap<String, List<Pair<String, int64_t>>> enum_list;
 		HashMap<String, bool> enum_is_bitfield;
 		HashMap<String, bool> enum_is_bitfield;
 
 
+		const DocData::ClassDoc *global_scope_doc = nullptr;
+		if (p_include_docs) {
+			global_scope_doc = EditorHelp::get_doc_data()->class_list.getptr("@GlobalScope");
+			CRASH_COND_MSG(!global_scope_doc, "Could not find '@GlobalScope' in DocData.");
+		}
+
 		for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
 		for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
 			int64_t value = CoreConstants::get_global_constant_value(i);
 			int64_t value = CoreConstants::get_global_constant_value(i);
 			String enum_name = CoreConstants::get_global_constant_enum(i);
 			String enum_name = CoreConstants::get_global_constant_enum(i);
@@ -479,6 +499,14 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 				d["name"] = name;
 				d["name"] = name;
 				d["value"] = value;
 				d["value"] = value;
 				d["is_bitfield"] = bitfield;
 				d["is_bitfield"] = bitfield;
+				if (p_include_docs) {
+					for (const DocData::ConstantDoc &constant_doc : global_scope_doc->constants) {
+						if (constant_doc.name == name) {
+							d["documentation"] = fix_doc_description(constant_doc.description);
+							break;
+						}
+					}
+				}
 				constants.push_back(d);
 				constants.push_back(d);
 			}
 			}
 		}
 		}
@@ -490,11 +518,25 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 			Dictionary d1;
 			Dictionary d1;
 			d1["name"] = E.key;
 			d1["name"] = E.key;
 			d1["is_bitfield"] = enum_is_bitfield[E.key];
 			d1["is_bitfield"] = enum_is_bitfield[E.key];
+			if (p_include_docs) {
+				const DocData::EnumDoc *enum_doc = global_scope_doc->enums.getptr(E.key);
+				if (enum_doc) {
+					d1["documentation"] = fix_doc_description(enum_doc->description);
+				}
+			}
 			Array values;
 			Array values;
 			for (const Pair<String, int64_t> &F : E.value) {
 			for (const Pair<String, int64_t> &F : E.value) {
 				Dictionary d2;
 				Dictionary d2;
 				d2["name"] = F.first;
 				d2["name"] = F.first;
 				d2["value"] = F.second;
 				d2["value"] = F.second;
+				if (p_include_docs) {
+					for (const DocData::ConstantDoc &constant_doc : global_scope_doc->constants) {
+						if (constant_doc.name == F.first) {
+							d2["documentation"] = fix_doc_description(constant_doc.description);
+							break;
+						}
+					}
+				}
 				values.push_back(d2);
 				values.push_back(d2);
 			}
 			}
 			d1["values"] = values;
 			d1["values"] = values;
@@ -509,6 +551,12 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 		List<StringName> utility_func_names;
 		List<StringName> utility_func_names;
 		Variant::get_utility_function_list(&utility_func_names);
 		Variant::get_utility_function_list(&utility_func_names);
 
 
+		const DocData::ClassDoc *global_scope_doc = nullptr;
+		if (p_include_docs) {
+			global_scope_doc = EditorHelp::get_doc_data()->class_list.getptr("@GlobalScope");
+			CRASH_COND_MSG(!global_scope_doc, "Could not find '@GlobalScope' in DocData.");
+		}
+
 		for (const StringName &name : utility_func_names) {
 		for (const StringName &name : utility_func_names) {
 			Dictionary func;
 			Dictionary func;
 			func["name"] = String(name);
 			func["name"] = String(name);
@@ -545,6 +593,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 				func["arguments"] = arguments;
 				func["arguments"] = arguments;
 			}
 			}
 
 
+			if (p_include_docs) {
+				for (const DocData::MethodDoc &method_doc : global_scope_doc->methods) {
+					if (method_doc.name == name) {
+						func["documentation"] = fix_doc_description(method_doc.description);
+						break;
+					}
+				}
+			}
+
 			utility_funcs.push_back(func);
 			utility_funcs.push_back(func);
 		}
 		}
 
 
@@ -571,6 +628,12 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 
 
 			d["is_keyed"] = Variant::is_keyed(type);
 			d["is_keyed"] = Variant::is_keyed(type);
 
 
+			DocData::ClassDoc *builtin_doc = nullptr;
+			if (p_include_docs && d["name"] != "Nil") {
+				builtin_doc = EditorHelp::get_doc_data()->class_list.getptr(d["name"]);
+				CRASH_COND_MSG(!builtin_doc, vformat("Could not find '%s' in DocData.", d["name"]));
+			}
+
 			{
 			{
 				//members
 				//members
 				Array members;
 				Array members;
@@ -581,6 +644,14 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 					Dictionary d2;
 					Dictionary d2;
 					d2["name"] = String(member_name);
 					d2["name"] = String(member_name);
 					d2["type"] = get_builtin_or_variant_type_name(Variant::get_member_type(type, member_name));
 					d2["type"] = get_builtin_or_variant_type_name(Variant::get_member_type(type, member_name));
+					if (p_include_docs) {
+						for (const DocData::PropertyDoc &property_doc : builtin_doc->properties) {
+							if (property_doc.name == member_name) {
+								d2["documentation"] = fix_doc_description(property_doc.description);
+								break;
+							}
+						}
+					}
 					members.push_back(d2);
 					members.push_back(d2);
 				}
 				}
 				if (members.size()) {
 				if (members.size()) {
@@ -599,6 +670,14 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 					Variant constant = Variant::get_constant_value(type, constant_name);
 					Variant constant = Variant::get_constant_value(type, constant_name);
 					d2["type"] = get_builtin_or_variant_type_name(constant.get_type());
 					d2["type"] = get_builtin_or_variant_type_name(constant.get_type());
 					d2["value"] = constant.get_construct_string();
 					d2["value"] = constant.get_construct_string();
+					if (p_include_docs) {
+						for (const DocData::ConstantDoc &constant_doc : builtin_doc->constants) {
+							if (constant_doc.name == constant_name) {
+								d2["documentation"] = fix_doc_description(constant_doc.description);
+								break;
+							}
+						}
+					}
 					constants.push_back(d2);
 					constants.push_back(d2);
 				}
 				}
 				if (constants.size()) {
 				if (constants.size()) {
@@ -624,9 +703,24 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 						Dictionary values_dict;
 						Dictionary values_dict;
 						values_dict["name"] = String(enumeration);
 						values_dict["name"] = String(enumeration);
 						values_dict["value"] = Variant::get_enum_value(type, enum_name, enumeration);
 						values_dict["value"] = Variant::get_enum_value(type, enum_name, enumeration);
+						if (p_include_docs) {
+							for (const DocData::ConstantDoc &constant_doc : builtin_doc->constants) {
+								if (constant_doc.name == enumeration) {
+									values_dict["documentation"] = fix_doc_description(constant_doc.description);
+									break;
+								}
+							}
+						}
 						values.push_back(values_dict);
 						values.push_back(values_dict);
 					}
 					}
 
 
+					if (p_include_docs) {
+						const DocData::EnumDoc *enum_doc = builtin_doc->enums.getptr(enum_name);
+						if (enum_doc) {
+							enum_dict["documentation"] = fix_doc_description(enum_doc->description);
+						}
+					}
+
 					if (values.size()) {
 					if (values.size()) {
 						enum_dict["values"] = values;
 						enum_dict["values"] = values;
 					}
 					}
@@ -646,11 +740,22 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 						Variant::Type rt = Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j));
 						Variant::Type rt = Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j));
 						if (rt != Variant::NIL) {
 						if (rt != Variant::NIL) {
 							Dictionary d2;
 							Dictionary d2;
-							d2["name"] = Variant::get_operator_name(Variant::Operator(k));
+							String operator_name = Variant::get_operator_name(Variant::Operator(k));
+							d2["name"] = operator_name;
 							if (k != Variant::OP_NEGATE && k != Variant::OP_POSITIVE && k != Variant::OP_NOT && k != Variant::OP_BIT_NEGATE) {
 							if (k != Variant::OP_NEGATE && k != Variant::OP_POSITIVE && k != Variant::OP_NOT && k != Variant::OP_BIT_NEGATE) {
 								d2["right_type"] = get_builtin_or_variant_type_name(Variant::Type(j));
 								d2["right_type"] = get_builtin_or_variant_type_name(Variant::Type(j));
 							}
 							}
 							d2["return_type"] = get_builtin_or_variant_type_name(Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j)));
 							d2["return_type"] = get_builtin_or_variant_type_name(Variant::get_operator_return_type(Variant::Operator(k), type, Variant::Type(j)));
+
+							if (p_include_docs && builtin_doc != nullptr) {
+								for (const DocData::MethodDoc &operator_doc : builtin_doc->operators) {
+									if (operator_doc.name == "operator " + operator_name) {
+										d2["documentation"] = fix_doc_description(operator_doc.description);
+										break;
+									}
+								}
+							}
+
 							operators.push_back(d2);
 							operators.push_back(d2);
 						}
 						}
 					}
 					}
@@ -697,6 +802,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 						d2["arguments"] = arguments;
 						d2["arguments"] = arguments;
 					}
 					}
 
 
+					if (p_include_docs) {
+						for (const DocData::MethodDoc &method_doc : builtin_doc->methods) {
+							if (method_doc.name == method_name) {
+								d2["documentation"] = fix_doc_description(method_doc.description);
+								break;
+							}
+						}
+					}
+
 					methods.push_back(d2);
 					methods.push_back(d2);
 				}
 				}
 				if (methods.size()) {
 				if (methods.size()) {
@@ -722,6 +836,28 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 					if (arguments.size()) {
 					if (arguments.size()) {
 						d2["arguments"] = arguments;
 						d2["arguments"] = arguments;
 					}
 					}
+
+					if (p_include_docs && builtin_doc) {
+						for (const DocData::MethodDoc &constructor_doc : builtin_doc->constructors) {
+							if (constructor_doc.arguments.size() != argcount) {
+								continue;
+							}
+							bool constructor_found = true;
+							for (int k = 0; k < argcount; k++) {
+								const DocData::ArgumentDoc &argument_doc = constructor_doc.arguments[k];
+								const Dictionary &argument_dict = arguments[k];
+								const String &argument_string = argument_dict["type"];
+								if (argument_doc.type != argument_string) {
+									constructor_found = false;
+									break;
+								}
+							}
+							if (constructor_found) {
+								d2["documentation"] = fix_doc_description(constructor_doc.description);
+							}
+						}
+					}
+
 					constructors.push_back(d2);
 					constructors.push_back(d2);
 				}
 				}
 
 
@@ -734,6 +870,10 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 				d["has_destructor"] = Variant::has_destructor(type);
 				d["has_destructor"] = Variant::has_destructor(type);
 			}
 			}
 
 
+			if (p_include_docs && builtin_doc != nullptr) {
+				d["documentation"] = fix_doc_description(builtin_doc->description);
+			}
+
 			builtins.push_back(d);
 			builtins.push_back(d);
 		}
 		}
 
 
@@ -763,6 +903,12 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 				d["inherits"] = String(parent_class);
 				d["inherits"] = String(parent_class);
 			}
 			}
 
 
+			DocData::ClassDoc *class_doc = nullptr;
+			if (p_include_docs) {
+				class_doc = EditorHelp::get_doc_data()->class_list.getptr(class_name);
+				CRASH_COND_MSG(!class_doc, vformat("Could not find '%s' in DocData.", class_name));
+			}
+
 			{
 			{
 				ClassDB::APIType api = ClassDB::get_api_type(class_name);
 				ClassDB::APIType api = ClassDB::get_api_type(class_name);
 				static const char *api_type[5] = { "core", "editor", "extension", "editor_extension" };
 				static const char *api_type[5] = { "core", "editor", "extension", "editor_extension" };
@@ -784,6 +930,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 					d2["name"] = String(F);
 					d2["name"] = String(F);
 					d2["value"] = ClassDB::get_integer_constant(class_name, F);
 					d2["value"] = ClassDB::get_integer_constant(class_name, F);
 
 
+					if (p_include_docs) {
+						for (const DocData::ConstantDoc &constant_doc : class_doc->constants) {
+							if (constant_doc.name == F) {
+								d2["documentation"] = fix_doc_description(constant_doc.description);
+								break;
+							}
+						}
+					}
+
 					constants.push_back(d2);
 					constants.push_back(d2);
 				}
 				}
 
 
@@ -808,11 +963,28 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 						Dictionary d3;
 						Dictionary d3;
 						d3["name"] = String(G->get());
 						d3["name"] = String(G->get());
 						d3["value"] = ClassDB::get_integer_constant(class_name, G->get());
 						d3["value"] = ClassDB::get_integer_constant(class_name, G->get());
+
+						if (p_include_docs) {
+							for (const DocData::ConstantDoc &constant_doc : class_doc->constants) {
+								if (constant_doc.name == G->get()) {
+									d3["documentation"] = fix_doc_description(constant_doc.description);
+									break;
+								}
+							}
+						}
+
 						values.push_back(d3);
 						values.push_back(d3);
 					}
 					}
 
 
 					d2["values"] = values;
 					d2["values"] = values;
 
 
+					if (p_include_docs) {
+						const DocData::EnumDoc *enum_doc = class_doc->enums.getptr(F);
+						if (enum_doc) {
+							d2["documentation"] = fix_doc_description(enum_doc->description);
+						}
+					}
+
 					enums.push_back(d2);
 					enums.push_back(d2);
 				}
 				}
 
 
@@ -864,6 +1036,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 							d2["arguments"] = arguments;
 							d2["arguments"] = arguments;
 						}
 						}
 
 
+						if (p_include_docs) {
+							for (const DocData::MethodDoc &method_doc : class_doc->methods) {
+								if (method_doc.name == method_name) {
+									d2["documentation"] = fix_doc_description(method_doc.description);
+									break;
+								}
+							}
+						}
+
 						methods.push_back(d2);
 						methods.push_back(d2);
 
 
 					} else if (F.name.begins_with("_")) {
 					} else if (F.name.begins_with("_")) {
@@ -932,6 +1113,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 							d2["arguments"] = arguments;
 							d2["arguments"] = arguments;
 						}
 						}
 
 
+						if (p_include_docs) {
+							for (const DocData::MethodDoc &method_doc : class_doc->methods) {
+								if (method_doc.name == method_name) {
+									d2["documentation"] = fix_doc_description(method_doc.description);
+									break;
+								}
+							}
+						}
+
 						methods.push_back(d2);
 						methods.push_back(d2);
 					}
 					}
 				}
 				}
@@ -966,6 +1156,15 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 						d2["arguments"] = arguments;
 						d2["arguments"] = arguments;
 					}
 					}
 
 
+					if (p_include_docs) {
+						for (const DocData::MethodDoc &signal_doc : class_doc->signals) {
+							if (signal_doc.name == signal_name) {
+								d2["documentation"] = fix_doc_description(signal_doc.description);
+								break;
+							}
+						}
+					}
+
 					signals.push_back(d2);
 					signals.push_back(d2);
 				}
 				}
 
 
@@ -1005,6 +1204,16 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 					if (index != -1) {
 					if (index != -1) {
 						d2["index"] = index;
 						d2["index"] = index;
 					}
 					}
+
+					if (p_include_docs) {
+						for (const DocData::PropertyDoc &property_doc : class_doc->properties) {
+							if (property_doc.name == property_name) {
+								d2["documentation"] = fix_doc_description(property_doc.description);
+								break;
+							}
+						}
+					}
+
 					properties.push_back(d2);
 					properties.push_back(d2);
 				}
 				}
 
 
@@ -1013,6 +1222,10 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 				}
 				}
 			}
 			}
 
 
+			if (p_include_docs && class_doc != nullptr) {
+				d["documentation"] = fix_doc_description(class_doc->description);
+			}
+
 			classes.push_back(d);
 			classes.push_back(d);
 		}
 		}
 
 
@@ -1065,8 +1278,8 @@ Dictionary GDExtensionAPIDump::generate_extension_api() {
 	return api_dump;
 	return api_dump;
 }
 }
 
 
-void GDExtensionAPIDump::generate_extension_json_file(const String &p_path) {
-	Dictionary api = generate_extension_api();
+void GDExtensionAPIDump::generate_extension_json_file(const String &p_path, bool p_include_docs) {
+	Dictionary api = generate_extension_api(p_include_docs);
 	Ref<JSON> json;
 	Ref<JSON> json;
 	json.instantiate();
 	json.instantiate();
 
 

+ 2 - 2
core/extension/extension_api_dump.h

@@ -37,8 +37,8 @@
 
 
 class GDExtensionAPIDump {
 class GDExtensionAPIDump {
 public:
 public:
-	static Dictionary generate_extension_api();
-	static void generate_extension_json_file(const String &p_path);
+	static Dictionary generate_extension_api(bool p_include_docs = false);
+	static void generate_extension_json_file(const String &p_path, bool p_include_docs = false);
 	static Error validate_extension_json_file(const String &p_path);
 	static Error validate_extension_json_file(const String &p_path);
 };
 };
 #endif
 #endif

+ 15 - 2
main/main.cpp

@@ -224,6 +224,7 @@ static bool print_fps = false;
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 static bool dump_gdextension_interface = false;
 static bool dump_gdextension_interface = false;
 static bool dump_extension_api = false;
 static bool dump_extension_api = false;
+static bool include_docs_in_extension_api_dump = false;
 static bool validate_extension_api = false;
 static bool validate_extension_api = false;
 static String validate_extension_api_file;
 static String validate_extension_api_file;
 #endif
 #endif
@@ -513,7 +514,8 @@ void Main::print_help(const char *p_binary) {
 	OS::get_singleton()->print("  --build-solutions                 Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
 	OS::get_singleton()->print("  --build-solutions                 Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n");
 	OS::get_singleton()->print("  --dump-gdextension-interface      Generate GDExtension header file 'gdextension_interface.h' in the current folder. This file is the base file required to implement a GDExtension.\n");
 	OS::get_singleton()->print("  --dump-gdextension-interface      Generate GDExtension header file 'gdextension_interface.h' in the current folder. This file is the base file required to implement a GDExtension.\n");
 	OS::get_singleton()->print("  --dump-extension-api              Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.\n");
 	OS::get_singleton()->print("  --dump-extension-api              Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.\n");
-	OS::get_singleton()->print("  --validate-extension-api <path>   Validate an extension API file dumped (with the option above) from a previous version of the engine to ensure API compatibility. If incompatibilities or errors are detected, the return code will be non zero.\n");
+	OS::get_singleton()->print("  --dump-extension-api-with-docs    Generate JSON dump of the Godot API like the previous option, but including documentation.\n");
+	OS::get_singleton()->print("  --validate-extension-api <path>   Validate an extension API file dumped (with one of the two previous options) from a previous version of the engine to ensure API compatibility. If incompatibilities or errors are detected, the return code will be non zero.\n");
 	OS::get_singleton()->print("  --benchmark                       Benchmark the run time and print it to console.\n");
 	OS::get_singleton()->print("  --benchmark                       Benchmark the run time and print it to console.\n");
 	OS::get_singleton()->print("  --benchmark-file <path>           Benchmark the run time and save it to a given file in JSON format. The path should be absolute.\n");
 	OS::get_singleton()->print("  --benchmark-file <path>           Benchmark the run time and save it to a given file in JSON format. The path should be absolute.\n");
 #ifdef TESTS_ENABLED
 #ifdef TESTS_ENABLED
@@ -1249,6 +1251,17 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
 			// run the project instead of a cmdline tool.
 			// run the project instead of a cmdline tool.
 			// Needs full refactoring to fix properly.
 			// Needs full refactoring to fix properly.
 			main_args.push_back(I->get());
 			main_args.push_back(I->get());
+		} else if (I->get() == "--dump-extension-api-with-docs") {
+			// Register as an editor instance to use low-end fallback if relevant.
+			editor = true;
+			cmdline_tool = true;
+			dump_extension_api = true;
+			include_docs_in_extension_api_dump = true;
+			print_line("Dumping Extension API including documentation");
+			// Hack. Not needed but otherwise we end up detecting that this should
+			// run the project instead of a cmdline tool.
+			// Needs full refactoring to fix properly.
+			main_args.push_back(I->get());
 		} else if (I->get() == "--validate-extension-api") {
 		} else if (I->get() == "--validate-extension-api") {
 			// Register as an editor instance to use low-end fallback if relevant.
 			// Register as an editor instance to use low-end fallback if relevant.
 			editor = true;
 			editor = true;
@@ -2912,7 +2925,7 @@ bool Main::start() {
 	}
 	}
 
 
 	if (dump_extension_api) {
 	if (dump_extension_api) {
-		GDExtensionAPIDump::generate_extension_json_file("extension_api.json");
+		GDExtensionAPIDump::generate_extension_json_file("extension_api.json", include_docs_in_extension_api_dump);
 	}
 	}
 
 
 	if (dump_gdextension_interface || dump_extension_api) {
 	if (dump_gdextension_interface || dump_extension_api) {