From 9c235117a7dfd8c6b4ec48854c0280276b166748 Mon Sep 17 00:00:00 2001 From: ocean Date: Mon, 19 Aug 2024 17:03:03 -0400 Subject: [PATCH] Scripting: Add script documentation cache to project This PR adds a script documentation cache in the project folder. It is loaded at alongside native documentation caches. This makes scripts fully accessible through Search Help, including their members, etc, right from project start, without having to compile every single script. --- editor/doc_tools.cpp | 8 +++++++ editor/doc_tools.h | 1 + editor/editor_file_system.cpp | 5 +++++ editor/editor_help.cpp | 39 +++++++++++++++++++++++++++++++++++ editor/editor_help.h | 3 +++ editor/editor_node.cpp | 4 ++++ 6 files changed, 60 insertions(+) diff --git a/editor/doc_tools.cpp b/editor/doc_tools.cpp index bf5b717c19dc..cc21a18aece9 100644 --- a/editor/doc_tools.cpp +++ b/editor/doc_tools.cpp @@ -365,6 +365,14 @@ void DocTools::remove_doc(const String &p_class_name) { class_list.erase(p_class_name); } +void DocTools::remove_script_doc_by_path(const String &p_path) { + for (KeyValue &E : class_list) + if (E.value.is_script_doc && E.value.script_path == p_path) { + remove_doc(E.key); + return; + } +} + bool DocTools::has_doc(const String &p_class_name) { if (p_class_name.is_empty()) { return false; diff --git a/editor/doc_tools.h b/editor/doc_tools.h index 3be59bf233cf..43d302c873c7 100644 --- a/editor/doc_tools.h +++ b/editor/doc_tools.h @@ -45,6 +45,7 @@ class DocTools { void merge_from(const DocTools &p_data); void add_doc(const DocData::ClassDoc &p_class_doc); void remove_doc(const String &p_class_name); + void remove_script_doc_by_path(const String &p_path); bool has_doc(const String &p_class_name); enum GenerateFlags { GENERATE_FLAG_SKIP_BASIC_TYPES = (1 << 0), diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index f75e438582c8..1652131b4933 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -1864,6 +1864,11 @@ void EditorFileSystem::_update_script_documentation() { if (!efd || index < 0) { // The file was removed + DocTools *doc = EditorHelp::get_doc_data(); + if (doc) + doc->remove_script_doc_by_path(path); + else + ERR_PRINT("Cannot update documentation for deleted file: EditorHelp::DocTools not initialized."); continue; } diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 683e4e5cdaac..fa6d33b75ad6 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -36,6 +36,7 @@ #include "core/input/input.h" #include "core/object/script_language.h" #include "core/os/keyboard.h" +#include "core/os/time.h" #include "core/string/string_builder.h" #include "core/version_generated.gen.h" #include "editor/doc_data_compressed.gen.h" @@ -2859,6 +2860,10 @@ String EditorHelp::get_cache_full_path() { return EditorPaths::get_singleton()->get_cache_dir().path_join(vformat("editor_doc_cache-%d.%d.res", VERSION_MAJOR, VERSION_MINOR)); } +String EditorHelp::get_script_doc_cache_full_path() { + return EditorPaths::get_singleton()->get_project_data_dir().path_join("editor_script_doc_cache.res"); +} + void EditorHelp::load_xml_buffer(const uint8_t *p_buffer, int p_size) { if (!ext_doc) { ext_doc = memnew(DocTools); @@ -2889,6 +2894,7 @@ void EditorHelp::_load_doc_thread(void *p_udata) { doc->add_doc(DocData::ClassDoc::from_dict(classes[i])); } + _load_script_doc_cache(); // Extensions' docs are not cached. Generate them now (on the main thread). callable_mp_static(&EditorHelp::_gen_extensions_docs).call_deferred(); } else { @@ -2923,6 +2929,9 @@ void EditorHelp::_gen_doc_thread(void *p_udata) { ERR_PRINT("Cannot save editor help cache (" + get_cache_full_path() + ")."); } + // Load script docs after native ones are cached so native cache doesn't contain script docs. + _load_script_doc_cache(); + OS::get_singleton()->benchmark_end_measure("EditorHelp", vformat("Generate Documentation (Run %d)", doc_generation_count)); } @@ -2935,6 +2944,36 @@ void EditorHelp::_gen_extensions_docs() { } } +// Called in 1) _load_doc_thread() from worker thread after other caches have been read, +// or 2) in _gen_doc_thread() **only from main thread**. This avoids worker thread loading +// script cache and main thread generating native cache accessing DocTools simultaneously. +void EditorHelp::_load_script_doc_cache() { + Ref script_doc_cache_res = ResourceLoader::load(get_script_doc_cache_full_path()); + if (script_doc_cache_res.is_valid()) { + Array classes = script_doc_cache_res->get_meta("classes", Array()); + for (int i = 0; i < classes.size(); i++) { + DocData::ClassDoc cd = DocData::ClassDoc::from_dict(classes[i]); + if (FileAccess::create(FileAccess::ACCESS_RESOURCES)->file_exists(cd.script_path)) + doc->add_doc(cd); + } + } +} + +void EditorHelp::save_script_doc_cache() { + Ref cache_res; + cache_res.instantiate(); + Array classes; + for (const KeyValue &E : doc->class_list) + if (E.value.is_script_doc) + classes.push_back(DocData::ClassDoc::to_dict(E.value)); + + cache_res->set_meta("classes", classes); + Error err = ResourceSaver::save(cache_res, get_script_doc_cache_full_path(), ResourceSaver::FLAG_COMPRESS); + if (err) { + ERR_PRINT("Cannot save editor help script documentation cache (" + get_script_doc_cache_full_path() + ")."); + } +} + void EditorHelp::generate_doc(bool p_use_cache) { doc_generation_count++; OS::get_singleton()->benchmark_begin_measure("EditorHelp", vformat("Generate Documentation (Run %d)", doc_generation_count)); diff --git a/editor/editor_help.h b/editor/editor_help.h index 93f74cb2c123..d3da2421f2ed 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -199,6 +199,7 @@ class EditorHelp : public VBoxContainer { static void _load_doc_thread(void *p_udata); static void _gen_doc_thread(void *p_udata); static void _gen_extensions_docs(); + static void _load_script_doc_cache(); static void _compute_doc_version_hash(); struct PropertyCompare { @@ -221,7 +222,9 @@ class EditorHelp : public VBoxContainer { static void generate_doc(bool p_use_cache = true); static DocTools *get_doc_data(); static void cleanup_doc(); + static void save_script_doc_cache(); static String get_cache_full_path(); + static String get_script_doc_cache_full_path(); static void load_xml_buffer(const uint8_t *p_buffer, int p_size); static void remove_class(const String &p_class); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index d1dffba2ab56..3806939ca95e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -813,6 +813,10 @@ void EditorNode::_notification(int p_what) { } #endif } break; + + case NOTIFICATION_PREDELETE: { + EditorHelp::save_script_doc_cache(); + } break; } }