From a1d8fc1af965c4de6428aa8676f5963e6214ed5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Tue, 31 Oct 2023 18:27:17 +0100 Subject: [PATCH] Polish & fix editor help cache generation - Isolated the generation of extensions's docs. They're now not cached and refreshed as needed. - Removed superfluous sorting of the class list. - Removed some superfluous/unused elements. - Renamed some items for clarity. --- core/object/class_db.cpp | 17 ++++++++++++- core/object/class_db.h | 3 +++ editor/doc_tools.cpp | 28 ++++++++++++-------- editor/doc_tools.h | 6 ++++- editor/editor_help.cpp | 55 ++++++++++++++++++---------------------- editor/editor_help.h | 5 ++-- main/main.cpp | 6 ++--- 7 files changed, 71 insertions(+), 49 deletions(-) diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index 8c54db3c2cf3..bf1bd0de93ad 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -98,9 +98,24 @@ void ClassDB::get_class_list(List *p_classes) { p_classes->push_back(E.key); } - p_classes->sort(); + p_classes->sort_custom(); } +#ifdef TOOLS_ENABLED +void ClassDB::get_extensions_class_list(List *p_classes) { + OBJTYPE_RLOCK; + + for (const KeyValue &E : classes) { + if (E.value.api != API_EXTENSION && E.value.api != API_EDITOR_EXTENSION) { + continue; + } + p_classes->push_back(E.key); + } + + p_classes->sort_custom(); +} +#endif + void ClassDB::get_inheriters_from_class(const StringName &p_class, List *p_classes) { OBJTYPE_RLOCK; diff --git a/core/object/class_db.h b/core/object/class_db.h index 5c2c59d508bc..7a4ee1afa451 100644 --- a/core/object/class_db.h +++ b/core/object/class_db.h @@ -251,6 +251,9 @@ public: } static void get_class_list(List *p_classes); +#ifdef TOOLS_ENABLED + static void get_extensions_class_list(List *p_classes); +#endif static void get_inheriters_from_class(const StringName &p_class, List *p_classes); static void get_direct_inheriters_from_class(const StringName &p_class, List *p_classes); static StringName get_parent_class_nocheck(const StringName &p_class); diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index ef3981fd3f64..a7e3c03250f3 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -355,20 +355,27 @@ static Variant get_documentation_default_value(const StringName &p_class_name, c return default_value; } -void DocTools::generate(bool p_basic_types) { +void DocTools::generate(BitField p_flags) { + // This may involve instantiating classes that are only usable from the main thread + // (which is in fact the case of the core API). + ERR_FAIL_COND(!Thread::is_main_thread()); + // Add ClassDB-exposed classes. { List classes; - ClassDB::get_class_list(&classes); - classes.sort_custom(); - // Move ProjectSettings, so that other classes can register properties there. - classes.move_to_back(classes.find("ProjectSettings")); + if (p_flags.has_flag(GENERATE_FLAG_EXTENSION_CLASSES_ONLY)) { + ClassDB::get_extensions_class_list(&classes); + } else { + ClassDB::get_class_list(&classes); + // Move ProjectSettings, so that other classes can register properties there. + classes.move_to_back(classes.find("ProjectSettings")); + } bool skip_setter_getter_methods = true; // Populate documentation data for each exposed class. while (classes.size()) { - String name = classes.front()->get(); + const String &name = classes.front()->get(); if (!ClassDB::is_class_exposed(name)) { print_verbose(vformat("Class '%s' is not exposed, skipping.", name)); classes.pop_front(); @@ -675,6 +682,10 @@ void DocTools::generate(bool p_basic_types) { } } + if (p_flags.has_flag(GENERATE_FLAG_SKIP_BASIC_TYPES)) { + return; + } + // Add a dummy Variant entry. { // This allows us to document the concept of Variant even though @@ -683,11 +694,6 @@ void DocTools::generate(bool p_basic_types) { class_list["Variant"].name = "Variant"; } - // If we don't want to populate basic types, break here. - if (!p_basic_types) { - return; - } - // Add Variant data types. for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (i == Variant::NIL) { diff --git a/editor/doc_tools.h b/editor/doc_tools.h index 2d4a45bda008..5fffb6be3821 100644 --- a/editor/doc_tools.h +++ b/editor/doc_tools.h @@ -45,7 +45,11 @@ public: 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); - void generate(bool p_basic_types = false); + enum GenerateFlags { + GENERATE_FLAG_SKIP_BASIC_TYPES = (1 << 0), + GENERATE_FLAG_EXTENSION_CLASSES_ONLY = (1 << 1), + }; + void generate(BitField p_flags = {}); Error load_classes(const String &p_dir); Error save_classes(const String &p_default_path, const HashMap &p_class_path, bool p_include_xml_schema = true); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 0ab6e20b015a..10ab733c2bd5 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -2361,13 +2361,11 @@ void EditorHelp::_add_text(const String &p_bbcode) { } String EditorHelp::doc_version_hash; -bool EditorHelp::doc_gen_first_attempt = true; -bool EditorHelp::doc_gen_use_threads = true; -Thread EditorHelp::gen_thread; +Thread EditorHelp::worker_thread; void EditorHelp::_wait_for_thread() { - if (gen_thread.is_started()) { - gen_thread.wait_to_finish(); + if (worker_thread.is_started()) { + worker_thread.wait_to_finish(); } } @@ -2381,18 +2379,18 @@ String EditorHelp::get_cache_full_path() { } void EditorHelp::_load_doc_thread(void *p_udata) { - DEV_ASSERT(doc_gen_first_attempt); - Ref cache_res = ResourceLoader::load(get_cache_full_path()); if (cache_res.is_valid() && cache_res->get_meta("version_hash", "") == doc_version_hash) { Array classes = cache_res->get_meta("classes", Array()); for (int i = 0; i < classes.size(); i++) { doc->add_doc(DocData::ClassDoc::from_dict(classes[i])); } + + // Extensions' docs are not cached. Generate them now (on the main thread). + callable_mp_static(&EditorHelp::_gen_extensions_docs).call_deferred(); } else { - // We have to go back to the main thread to start from scratch. - doc_gen_first_attempt = false; - callable_mp_static(&EditorHelp::generate_doc).bind(true).call_deferred(); + // We have to go back to the main thread to start from scratch, bypassing any possibly existing cache. + callable_mp_static(&EditorHelp::generate_doc).bind(false).call_deferred(); } } @@ -2406,6 +2404,12 @@ void EditorHelp::_gen_doc_thread(void *p_udata) { cache_res->set_meta("version_hash", doc_version_hash); Array classes; for (const KeyValue &E : doc->class_list) { + if (ClassDB::class_exists(E.value.name)) { + ClassDB::APIType api = ClassDB::get_api_type(E.value.name); + if (api == ClassDB::API_EXTENSION || api == ClassDB::API_EDITOR_EXTENSION) { + continue; + } + } classes.push_back(DocData::ClassDoc::to_dict(E.value)); } cache_res->set_meta("classes", classes); @@ -2415,14 +2419,15 @@ void EditorHelp::_gen_doc_thread(void *p_udata) { } } +void EditorHelp::_gen_extensions_docs() { + doc->generate((DocTools::GENERATE_FLAG_SKIP_BASIC_TYPES | DocTools::GENERATE_FLAG_EXTENSION_CLASSES_ONLY)); +} + void EditorHelp::generate_doc(bool p_use_cache) { OS::get_singleton()->benchmark_begin_measure("EditorHelp::generate_doc"); - if (doc_gen_use_threads) { - // In case not the first attempt. - _wait_for_thread(); - } - DEV_ASSERT(doc_gen_first_attempt == (doc == nullptr)); + // In case not the first attempt. + _wait_for_thread(); if (!doc) { doc = memnew(DocTools); @@ -2432,24 +2437,14 @@ void EditorHelp::generate_doc(bool p_use_cache) { _compute_doc_version_hash(); } - if (p_use_cache && doc_gen_first_attempt && FileAccess::exists(get_cache_full_path())) { - if (doc_gen_use_threads) { - gen_thread.start(_load_doc_thread, nullptr); - } else { - _load_doc_thread(nullptr); - } + if (p_use_cache && FileAccess::exists(get_cache_full_path())) { + worker_thread.start(_load_doc_thread, nullptr); } else { print_verbose("Regenerating editor help cache"); - - // Not doable on threads unfortunately, since it instantiates all sorts of classes to get default values. - doc->generate(true); - - if (doc_gen_use_threads) { - gen_thread.start(_gen_doc_thread, nullptr); - } else { - _gen_doc_thread(nullptr); - } + doc->generate(); + worker_thread.start(_gen_doc_thread, nullptr); } + OS::get_singleton()->benchmark_end_measure("EditorHelp::generate_doc"); } diff --git a/editor/editor_help.h b/editor/editor_help.h index 1f813f930c67..d2d05a860318 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -188,13 +188,12 @@ class EditorHelp : public VBoxContainer { void _toggle_scripts_pressed(); static String doc_version_hash; - static bool doc_gen_first_attempt; - static bool doc_gen_use_threads; - static Thread gen_thread; + static Thread worker_thread; static void _wait_for_thread(); static void _load_doc_thread(void *p_udata); static void _gen_doc_thread(void *p_udata); + static void _gen_extensions_docs(); static void _compute_doc_version_hash(); protected: diff --git a/main/main.cpp b/main/main.cpp index dff661d20783..fa4d13932105 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -2767,7 +2767,7 @@ bool Main::start() { #ifdef TOOLS_ENABLED String doc_tool_path; - bool doc_base = true; + BitField gen_flags; String _export_preset; bool export_debug = false; bool export_pack_only = false; @@ -2792,7 +2792,7 @@ bool Main::start() { check_only = true; #ifdef TOOLS_ENABLED } else if (args[i] == "--no-docbase") { - doc_base = false; + gen_flags.set_flag(DocTools::GENERATE_FLAG_SKIP_BASIC_TYPES); #ifndef DISABLE_DEPRECATED } else if (args[i] == "--convert-3to4") { converting_project = true; @@ -2903,7 +2903,7 @@ bool Main::start() { Error err; DocTools doc; - doc.generate(doc_base); + doc.generate(gen_flags); DocTools docsrc; HashMap doc_data_classes;