mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	Merge pull request #82331 from rburing/gdextension_dump_docs
Optionally include documentation in GDExtension API dump
This commit is contained in:
		
						commit
						251fb83d53
					
				
					 3 changed files with 234 additions and 8 deletions
				
			
		|  | @ -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) { | void GDExtensionAPIDump::generate_extension_json_file(const String &p_path, bool p_include_docs) { | ||||||
| 	Dictionary api = generate_extension_api(); | 	Dictionary api = generate_extension_api(p_include_docs); | ||||||
| 	Ref<JSON> json; | 	Ref<JSON> json; | ||||||
| 	json.instantiate(); | 	json.instantiate(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -37,8 +37,8 @@ | ||||||
| 
 | 
 | ||||||
| class GDExtensionAPIDump { | class GDExtensionAPIDump { | ||||||
| public: | public: | ||||||
| 	static Dictionary generate_extension_api(); | 	static Dictionary generate_extension_api(bool p_include_docs = false); | ||||||
| 	static void generate_extension_json_file(const String &p_path); | 	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 | ||||||
|  |  | ||||||
|  | @ -225,6 +225,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 | ||||||
|  | @ -521,7 +522,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 | ||||||
|  | @ -1255,6 +1257,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; | ||||||
|  | @ -2921,7 +2934,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) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Rémi Verschelde
						Rémi Verschelde