Browse Source

Merge pull request #77554 from AThousandShips/doc_hierarchy

Add inheriting classes to `DocTools`
Rémi Verschelde 1 năm trước cách đây
mục cha
commit
107f2961cc
5 tập tin đã thay đổi với 93 bổ sung62 xóa
  1. 19 8
      editor/doc_tools.cpp
  2. 2 1
      editor/doc_tools.h
  3. 13 23
      editor/editor_help.cpp
  4. 58 30
      editor/editor_help_search.cpp
  5. 1 0
      editor/editor_help_search.h

+ 19 - 8
editor/doc_tools.cpp

@@ -307,21 +307,21 @@ void DocTools::merge_from(const DocTools &p_data) {
 	}
 }
 
-void DocTools::remove_from(const DocTools &p_data) {
-	for (const KeyValue<String, DocData::ClassDoc> &E : p_data.class_list) {
-		if (class_list.has(E.key)) {
-			class_list.erase(E.key);
-		}
-	}
-}
-
 void DocTools::add_doc(const DocData::ClassDoc &p_class_doc) {
 	ERR_FAIL_COND(p_class_doc.name.is_empty());
 	class_list[p_class_doc.name] = p_class_doc;
+	inheriting[p_class_doc.inherits].insert(p_class_doc.name);
 }
 
 void DocTools::remove_doc(const String &p_class_name) {
 	ERR_FAIL_COND(p_class_name.is_empty() || !class_list.has(p_class_name));
+	const String &inherits = class_list[p_class_name].inherits;
+	if (inheriting.has(inherits)) {
+		inheriting[inherits].erase(p_class_name);
+		if (inheriting[inherits].is_empty()) {
+			inheriting.erase(inherits);
+		}
+	}
 	class_list.erase(p_class_name);
 }
 
@@ -391,6 +391,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 			c.name = cname;
 			c.inherits = ClassDB::get_parent_class(name);
 
+			inheriting[c.inherits].insert(cname);
+
 			List<PropertyInfo> properties;
 			List<PropertyInfo> own_properties;
 
@@ -692,6 +694,7 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 		// it's not a ClassDB-exposed class.
 		class_list["Variant"] = DocData::ClassDoc();
 		class_list["Variant"].name = "Variant";
+		inheriting[""].insert("Variant");
 	}
 
 	// Add Variant data types.
@@ -709,6 +712,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 		DocData::ClassDoc &c = class_list[cname];
 		c.name = cname;
 
+		inheriting[""].insert(cname);
+
 		Callable::CallError cerror;
 		Variant v;
 		Variant::construct(Variant::Type(i), v, nullptr, 0, cerror);
@@ -870,6 +875,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 		DocData::ClassDoc &c = class_list[cname];
 		c.name = cname;
 
+		inheriting[""].insert(cname);
+
 		// Global constants.
 		for (int i = 0; i < CoreConstants::get_global_constant_count(); i++) {
 			DocData::ConstantDoc cd;
@@ -953,6 +960,8 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
 			DocData::ClassDoc c;
 			c.name = cname;
 
+			inheriting[""].insert(cname);
+
 			// Get functions.
 			List<MethodInfo> minfo;
 			lang->get_public_functions(&minfo);
@@ -1195,6 +1204,8 @@ Error DocTools::_load(Ref<XMLParser> parser) {
 			c.inherits = parser->get_named_attribute_value("inherits");
 		}
 
+		inheriting[c.inherits].insert(name);
+
 		if (parser->has_attribute("is_deprecated")) {
 			c.is_deprecated = parser->get_named_attribute_value("is_deprecated").to_lower() == "true";
 		}

+ 2 - 1
editor/doc_tools.h

@@ -32,16 +32,17 @@
 #define DOC_TOOLS_H
 
 #include "core/doc_data.h"
+#include "core/templates/rb_set.h"
 
 class DocTools {
 public:
 	String version;
 	HashMap<String, DocData::ClassDoc> class_list;
+	HashMap<String, RBSet<String, NaturalNoCaseComparator>> inheriting;
 
 	static Error erase_classes(const String &p_dir);
 
 	void merge_from(const DocTools &p_data);
-	void remove_from(const DocTools &p_data);
 	void add_doc(const DocData::ClassDoc &p_class_doc);
 	void remove_doc(const String &p_class_name);
 	bool has_doc(const String &p_class_name);

+ 13 - 23
editor/editor_help.cpp

@@ -812,35 +812,25 @@ void EditorHelp::_update_doc() {
 		class_desc->add_newline();
 	}
 
-	// Descendents
-	if (cd.is_script_doc || ClassDB::class_exists(cd.name)) {
-		bool found = false;
-		bool prev = false;
-
+	// Descendants
+	if ((cd.is_script_doc || ClassDB::class_exists(cd.name)) && doc->inheriting.has(cd.name)) {
 		_push_normal_font();
-		for (const KeyValue<String, DocData::ClassDoc> &E : doc->class_list) {
-			if (E.value.inherits == cd.name) {
-				if (!found) {
-					class_desc->push_color(theme_cache.title_color);
-					class_desc->add_text(TTR("Inherited by:") + " ");
-					found = true;
-				}
+		class_desc->push_color(theme_cache.title_color);
+		class_desc->add_text(TTR("Inherited by:") + " ");
 
-				if (prev) {
-					class_desc->add_text(" , ");
-				}
-				_add_type_icon(E.value.name, theme_cache.doc_font_size, "ArrowRight");
-				class_desc->add_text(non_breaking_space); // Otherwise icon borrows hyperlink from _add_type().
-				_add_type(E.value.name);
-				prev = true;
+		for (RBSet<String, NaturalNoCaseComparator>::Element *itr = doc->inheriting[cd.name].front(); itr; itr = itr->next()) {
+			if (itr->prev()) {
+				class_desc->add_text(" , ");
 			}
+
+			_add_type_icon(itr->get(), theme_cache.doc_font_size, "ArrowRight");
+			class_desc->add_text(non_breaking_space); // Otherwise icon borrows hyperlink from _add_type().
+			_add_type(itr->get());
 		}
 		_pop_normal_font();
 
-		if (found) {
-			class_desc->pop();
-			class_desc->add_newline();
-		}
+		class_desc->pop();
+		class_desc->add_newline();
 	}
 
 	// Note if deprecated.

+ 58 - 30
editor/editor_help_search.cpp

@@ -317,7 +317,13 @@ bool EditorHelpSearch::Runner::_slice() {
 }
 
 bool EditorHelpSearch::Runner::_phase_match_classes_init() {
-	iterator_doc = EditorHelp::get_doc_data()->class_list.begin();
+	iterator_doc = nullptr;
+	iterator_stack.clear();
+	if (search_flags & SEARCH_SHOW_HIERARCHY) {
+		iterator_stack.push_back(EditorHelp::get_doc_data()->inheriting[""].front());
+	} else {
+		iterator_doc = EditorHelp::get_doc_data()->class_list.begin();
+	}
 	matches.clear();
 	matched_item = nullptr;
 	match_highest_score = 0;
@@ -331,81 +337,103 @@ bool EditorHelpSearch::Runner::_phase_match_classes_init() {
 }
 
 bool EditorHelpSearch::Runner::_phase_match_classes() {
-	if (!iterator_doc) {
+	if (!iterator_doc && iterator_stack.is_empty()) {
 		return true;
 	}
 
-	DocData::ClassDoc &class_doc = iterator_doc->value;
-	if (class_doc.name.is_empty()) {
-		++iterator_doc;
-		return false;
+	DocData::ClassDoc *class_doc = nullptr;
+	if (iterator_doc) {
+		class_doc = &iterator_doc->value;
+	} else if (!iterator_stack.is_empty() && iterator_stack[iterator_stack.size() - 1]) {
+		class_doc = EditorHelp::get_doc_data()->class_list.getptr(iterator_stack[iterator_stack.size() - 1]->get());
+	}
+
+	if (class_doc && class_doc->name.is_empty()) {
+		class_doc = nullptr;
 	}
 
-	if (!_is_class_disabled_by_feature_profile(class_doc.name)) {
+	if (class_doc && !_is_class_disabled_by_feature_profile(class_doc->name)) {
 		ClassMatch match;
-		match.doc = &class_doc;
+		match.doc = class_doc;
 
 		// Match class name.
 		if (search_flags & SEARCH_CLASSES) {
 			// If the search term is empty, add any classes which are not script docs or which don't start with
 			// a double-quotation. This will ensure that only C++ classes and explicitly named classes will
 			// be added.
-			match.name = (term.is_empty() && (!class_doc.is_script_doc || class_doc.name[0] != '\"')) || _match_string(term, class_doc.name);
+			match.name = (term.is_empty() && (!class_doc->is_script_doc || class_doc->name[0] != '\"')) || _match_string(term, class_doc->name);
 		}
 
 		// Match members only if the term is long enough, to avoid slow performance from building a large tree.
 		// Make an exception for annotations, since there are not that many of them.
 		if (term.length() > 1 || term == "@") {
 			if (search_flags & SEARCH_CONSTRUCTORS) {
-				_match_method_name_and_push_back(class_doc.constructors, &match.constructors);
+				_match_method_name_and_push_back(class_doc->constructors, &match.constructors);
 			}
 			if (search_flags & SEARCH_METHODS) {
-				_match_method_name_and_push_back(class_doc.methods, &match.methods);
+				_match_method_name_and_push_back(class_doc->methods, &match.methods);
 			}
 			if (search_flags & SEARCH_OPERATORS) {
-				_match_method_name_and_push_back(class_doc.operators, &match.operators);
+				_match_method_name_and_push_back(class_doc->operators, &match.operators);
 			}
 			if (search_flags & SEARCH_SIGNALS) {
-				for (int i = 0; i < class_doc.signals.size(); i++) {
-					if (_all_terms_in_name(class_doc.signals[i].name)) {
-						match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc.signals[i]));
+				for (int i = 0; i < class_doc->signals.size(); i++) {
+					if (_all_terms_in_name(class_doc->signals[i].name)) {
+						match.signals.push_back(const_cast<DocData::MethodDoc *>(&class_doc->signals[i]));
 					}
 				}
 			}
 			if (search_flags & SEARCH_CONSTANTS) {
-				for (int i = 0; i < class_doc.constants.size(); i++) {
-					if (_all_terms_in_name(class_doc.constants[i].name)) {
-						match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc.constants[i]));
+				for (int i = 0; i < class_doc->constants.size(); i++) {
+					if (_all_terms_in_name(class_doc->constants[i].name)) {
+						match.constants.push_back(const_cast<DocData::ConstantDoc *>(&class_doc->constants[i]));
 					}
 				}
 			}
 			if (search_flags & SEARCH_PROPERTIES) {
-				for (int i = 0; i < class_doc.properties.size(); i++) {
-					if (_all_terms_in_name(class_doc.properties[i].name)) {
-						match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc.properties[i]));
+				for (int i = 0; i < class_doc->properties.size(); i++) {
+					if (_all_terms_in_name(class_doc->properties[i].name)) {
+						match.properties.push_back(const_cast<DocData::PropertyDoc *>(&class_doc->properties[i]));
 					}
 				}
 			}
 			if (search_flags & SEARCH_THEME_ITEMS) {
-				for (int i = 0; i < class_doc.theme_properties.size(); i++) {
-					if (_all_terms_in_name(class_doc.theme_properties[i].name)) {
-						match.theme_properties.push_back(const_cast<DocData::ThemeItemDoc *>(&class_doc.theme_properties[i]));
+				for (int i = 0; i < class_doc->theme_properties.size(); i++) {
+					if (_all_terms_in_name(class_doc->theme_properties[i].name)) {
+						match.theme_properties.push_back(const_cast<DocData::ThemeItemDoc *>(&class_doc->theme_properties[i]));
 					}
 				}
 			}
 			if (search_flags & SEARCH_ANNOTATIONS) {
-				for (int i = 0; i < class_doc.annotations.size(); i++) {
-					if (_match_string(term, class_doc.annotations[i].name)) {
-						match.annotations.push_back(const_cast<DocData::MethodDoc *>(&class_doc.annotations[i]));
+				for (int i = 0; i < class_doc->annotations.size(); i++) {
+					if (_match_string(term, class_doc->annotations[i].name)) {
+						match.annotations.push_back(const_cast<DocData::MethodDoc *>(&class_doc->annotations[i]));
 					}
 				}
 			}
 		}
-		matches[class_doc.name] = match;
+		matches[class_doc->name] = match;
+	}
+
+	if (iterator_doc) {
+		++iterator_doc;
+		return !iterator_doc;
+	}
+
+	if (!iterator_stack.is_empty()) {
+		if (iterator_stack[iterator_stack.size() - 1]) {
+			iterator_stack[iterator_stack.size() - 1] = iterator_stack[iterator_stack.size() - 1]->next();
+		}
+		if (!iterator_stack[iterator_stack.size() - 1]) {
+			iterator_stack.resize(iterator_stack.size() - 1);
+		}
+	}
+
+	if (class_doc && EditorHelp::get_doc_data()->inheriting.has(class_doc->name)) {
+		iterator_stack.push_back(EditorHelp::get_doc_data()->inheriting[class_doc->name].front());
 	}
 
-	++iterator_doc;
-	return !iterator_doc;
+	return iterator_stack.is_empty();
 }
 
 bool EditorHelpSearch::Runner::_phase_class_items_init() {

+ 1 - 0
editor/editor_help_search.h

@@ -124,6 +124,7 @@ class EditorHelpSearch::Runner : public RefCounted {
 	Color disabled_color;
 
 	HashMap<String, DocData::ClassDoc>::Iterator iterator_doc;
+	LocalVector<RBSet<String, NaturalNoCaseComparator>::Element *> iterator_stack;
 	HashMap<String, ClassMatch> matches;
 	HashMap<String, ClassMatch>::Iterator iterator_match;
 	TreeItem *root_item = nullptr;