Change ClassDB::get_class_list and related stuff.

This commit is contained in:
Yufeng Ying 2025-01-08 20:01:55 +08:00
parent 99a39ce6ea
commit a50fc5acd8
23 changed files with 155 additions and 150 deletions

View file

@ -1545,14 +1545,16 @@ namespace Special {
////// ClassDB ////// ////// ClassDB //////
PackedStringArray ClassDB::get_class_list() const { PackedStringArray ClassDB::get_class_list() const {
List<StringName> classes; LocalVector<StringName> classes;
::ClassDB::get_class_list(&classes); ::ClassDB::get_class_list(classes);
PackedStringArray ret; PackedStringArray ret;
ret.resize(classes.size()); ret.resize(classes.size());
String *ptrw = ret.ptrw();
int idx = 0; int idx = 0;
for (const StringName &E : classes) { for (const StringName &cls : classes) {
ret.set(idx++, E); ptrw[idx] = cls;
idx++;
} }
return ret; return ret;

View file

@ -566,25 +566,25 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
input_vals.append(V); input_vals.append(V);
} }
List<StringName> native_types; LocalVector<StringName> native_types;
ClassDB::get_class_list(&native_types); ClassDB::get_class_list(native_types);
for (const StringName &E : native_types) { for (const StringName &class_name : native_types) {
if (!ClassDB::is_class_exposed(E) || !Engine::get_singleton()->has_singleton(E) || Engine::get_singleton()->is_singleton_editor_only(E)) { if (!ClassDB::is_class_exposed(class_name) || !Engine::get_singleton()->has_singleton(class_name) || Engine::get_singleton()->is_singleton_editor_only(class_name)) {
continue; continue;
} }
input_names.append(E); input_names.append(class_name);
input_vals.append(Engine::get_singleton()->get_singleton_object(E)); input_vals.append(Engine::get_singleton()->get_singleton_object(class_name));
} }
List<StringName> user_types; LocalVector<StringName> user_types;
ScriptServer::get_global_class_list(&user_types); ScriptServer::get_global_class_list(user_types);
for (const StringName &S : user_types) { for (const StringName &class_name : user_types) {
String scr_path = ScriptServer::get_global_class_path(S); String scr_path = ScriptServer::get_global_class_path(class_name);
Ref<Script> scr = ResourceLoader::load(scr_path, "Script"); Ref<Script> scr = ResourceLoader::load(scr_path, "Script");
ERR_CONTINUE_MSG(scr.is_null(), vformat(R"(Could not load the global class %s from resource path: "%s".)", S, scr_path)); ERR_CONTINUE_MSG(scr.is_null(), vformat(R"(Could not load the global class %s from resource path: "%s".)", class_name, scr_path));
input_names.append(S); input_names.append(class_name);
input_vals.append(scr); input_vals.append(scr);
} }

View file

@ -900,11 +900,9 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
// classes // classes
Array classes; Array classes;
List<StringName> class_list; LocalVector<StringName> class_list;
ClassDB::get_class_list(&class_list); ClassDB::get_class_list(class_list);
class_list.sort_custom<StringName::AlphCompare>();
for (const StringName &class_name : class_list) { for (const StringName &class_name : class_list) {
if (!ClassDB::is_class_exposed(class_name)) { if (!ClassDB::is_class_exposed(class_name)) {

View file

@ -1465,8 +1465,8 @@ void ResourceLoader::add_custom_loaders() {
String custom_loader_base_class = ResourceFormatLoader::get_class_static(); String custom_loader_base_class = ResourceFormatLoader::get_class_static();
List<StringName> global_classes; LocalVector<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes); ScriptServer::get_global_class_list(global_classes);
for (const StringName &class_name : global_classes) { for (const StringName &class_name : global_classes) {
StringName base_class = ScriptServer::get_global_class_native_base(class_name); StringName base_class = ScriptServer::get_global_class_native_base(class_name);

View file

@ -255,8 +255,8 @@ void ResourceSaver::add_custom_savers() {
String custom_saver_base_class = ResourceFormatSaver::get_class_static(); String custom_saver_base_class = ResourceFormatSaver::get_class_static();
List<StringName> global_classes; LocalVector<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes); ScriptServer::get_global_class_list(global_classes);
for (const StringName &class_name : global_classes) { for (const StringName &class_name : global_classes) {
StringName base_class = ScriptServer::get_global_class_native_base(class_name); StringName base_class = ScriptServer::get_global_class_native_base(class_name);

View file

@ -33,6 +33,7 @@
#include "core/config/engine.h" #include "core/config/engine.h"
#include "core/io/resource_loader.h" #include "core/io/resource_loader.h"
#include "core/object/script_language.h" #include "core/object/script_language.h"
#include "core/templates/sort_array.h"
#include "core/version.h" #include "core/version.h"
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
@ -240,28 +241,46 @@ bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inh
return _is_parent_class(p_class, p_inherits); return _is_parent_class(p_class, p_inherits);
} }
void ClassDB::get_class_list(List<StringName> *p_classes) { // This function only sorts items added by this function.
// If `p_classes` is not empty before calling and a global sort is needed, caller must handle that separately.
void ClassDB::get_class_list(LocalVector<StringName> &p_classes) {
Locker::Lock lock(Locker::STATE_READ); Locker::Lock lock(Locker::STATE_READ);
for (const KeyValue<StringName, ClassInfo> &E : classes) { if (classes.is_empty()) {
p_classes->push_back(E.key); return;
} }
p_classes->sort_custom<StringName::AlphCompare>(); p_classes.reserve(p_classes.size() + classes.size());
for (const KeyValue<StringName, ClassInfo> &cls : classes) {
p_classes.push_back(cls.key);
}
SortArray<StringName> sorter;
sorter.sort(&p_classes[p_classes.size() - classes.size()], classes.size());
} }
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
void ClassDB::get_extensions_class_list(List<StringName> *p_classes) { // This function only sorts items added by this function.
// If `p_classes` is not empty before calling and a global sort is needed, caller must handle that separately.
void ClassDB::get_extensions_class_list(LocalVector<StringName> &p_classes) {
Locker::Lock lock(Locker::STATE_READ); Locker::Lock lock(Locker::STATE_READ);
uint32_t original_size = p_classes.size();
for (const KeyValue<StringName, ClassInfo> &E : classes) { for (const KeyValue<StringName, ClassInfo> &E : classes) {
if (E.value.api != API_EXTENSION && E.value.api != API_EDITOR_EXTENSION) { if (E.value.api != API_EXTENSION && E.value.api != API_EDITOR_EXTENSION) {
continue; continue;
} }
p_classes->push_back(E.key); p_classes.push_back(E.key);
} }
p_classes->sort_custom<StringName::AlphCompare>(); // Nothing appended.
if (p_classes.size() == original_size) {
return;
}
SortArray<StringName> sorter;
sorter.sort(&p_classes[original_size], p_classes.size() - original_size);
} }
void ClassDB::get_extension_class_list(const Ref<GDExtension> &p_extension, List<StringName> *p_classes) { void ClassDB::get_extension_class_list(const Ref<GDExtension> &p_extension, List<StringName> *p_classes) {

View file

@ -311,9 +311,9 @@ public:
T::register_custom_data_to_otdb(); T::register_custom_data_to_otdb();
} }
static void get_class_list(List<StringName> *p_classes); static void get_class_list(LocalVector<StringName> &p_classes);
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
static void get_extensions_class_list(List<StringName> *p_classes); static void get_extensions_class_list(LocalVector<StringName> &p_classes);
static void get_extension_class_list(const Ref<GDExtension> &p_extension, List<StringName> *p_classes); static void get_extension_class_list(const Ref<GDExtension> &p_extension, List<StringName> *p_classes);
static ObjectGDExtension *get_placeholder_extension(const StringName &p_class); static ObjectGDExtension *get_placeholder_extension(const StringName &p_class);
#endif #endif

View file

@ -35,6 +35,7 @@
#include "core/debugger/engine_debugger.h" #include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h" #include "core/debugger/script_debugger.h"
#include "core/io/resource_loader.h" #include "core/io/resource_loader.h"
#include "core/templates/sort_array.h"
ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES]; ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES];
int ScriptServer::_language_count = 0; int ScriptServer::_language_count = 0;
@ -507,15 +508,18 @@ bool ScriptServer::is_global_class_tool(const String &p_class) {
return global_classes[p_class].is_tool; return global_classes[p_class].is_tool;
} }
void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) { // This function only sorts items added by this function.
List<StringName> classes; // If `r_global_classes` is not empty before calling and a global sort is needed, caller must handle that separately.
for (const KeyValue<StringName, GlobalScriptClass> &E : global_classes) { void ScriptServer::get_global_class_list(LocalVector<StringName> &r_global_classes) {
classes.push_back(E.key); if (global_classes.is_empty()) {
return;
} }
classes.sort_custom<StringName::AlphCompare>(); r_global_classes.reserve(r_global_classes.size() + global_classes.size());
for (const StringName &E : classes) { for (const KeyValue<StringName, GlobalScriptClass> &global_class : global_classes) {
r_global_classes->push_back(E); r_global_classes.push_back(global_class.key);
} }
SortArray<StringName> sorter;
sorter.sort(&r_global_classes[r_global_classes.size() - global_classes.size()], global_classes.size());
} }
void ScriptServer::save_global_classes() { void ScriptServer::save_global_classes() {
@ -530,17 +534,17 @@ void ScriptServer::save_global_classes() {
class_icons[d["name"]] = d["icon"]; class_icons[d["name"]] = d["icon"];
} }
List<StringName> gc; LocalVector<StringName> gc;
get_global_class_list(&gc); get_global_class_list(gc);
Array gcarr; Array gcarr;
for (const StringName &E : gc) { for (const StringName &class_name : gc) {
const GlobalScriptClass &global_class = global_classes[E]; const GlobalScriptClass &global_class = global_classes[class_name];
Dictionary d; Dictionary d;
d["class"] = E; d["class"] = class_name;
d["language"] = global_class.language; d["language"] = global_class.language;
d["path"] = global_class.path; d["path"] = global_class.path;
d["base"] = global_class.base; d["base"] = global_class.base;
d["icon"] = class_icons.get(E, ""); d["icon"] = class_icons.get(class_name, "");
d["is_abstract"] = global_class.is_abstract; d["is_abstract"] = global_class.is_abstract;
d["is_tool"] = global_class.is_tool; d["is_tool"] = global_class.is_tool;
gcarr.push_back(d); gcarr.push_back(d);

View file

@ -98,7 +98,7 @@ public:
static StringName get_global_class_native_base(const String &p_class); static StringName get_global_class_native_base(const String &p_class);
static bool is_global_class_abstract(const String &p_class); static bool is_global_class_abstract(const String &p_class);
static bool is_global_class_tool(const String &p_class); static bool is_global_class_tool(const String &p_class);
static void get_global_class_list(List<StringName> *r_global_classes); static void get_global_class_list(LocalVector<StringName> &r_global_classes);
static void get_inheriters_list(const StringName &p_base_type, List<StringName> *r_classes); static void get_inheriters_list(const StringName &p_base_type, List<StringName> *r_classes);
static void save_global_classes(); static void save_global_classes();

View file

@ -405,23 +405,23 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
// Add ClassDB-exposed classes. // Add ClassDB-exposed classes.
{ {
List<StringName> classes; LocalVector<StringName> classes;
if (p_flags.has_flag(GENERATE_FLAG_EXTENSION_CLASSES_ONLY)) { if (p_flags.has_flag(GENERATE_FLAG_EXTENSION_CLASSES_ONLY)) {
ClassDB::get_extensions_class_list(&classes); ClassDB::get_extensions_class_list(classes);
} else { } else {
ClassDB::get_class_list(&classes); ClassDB::get_class_list(classes);
// Move ProjectSettings, so that other classes can register properties there. // Move ProjectSettings, so that other classes can register properties there.
classes.move_to_back(classes.find("ProjectSettings")); classes.erase("ProjectSettings");
classes.push_back("ProjectSettings");
} }
bool skip_setter_getter_methods = true; bool skip_setter_getter_methods = true;
// Populate documentation data for each exposed class. // Populate documentation data for each exposed class.
while (classes.size()) { for (uint32_t classes_idx = 0; classes_idx < classes.size(); classes_idx++) {
const String &name = classes.front()->get(); const String &name = classes[classes_idx];
if (!ClassDB::is_class_exposed(name)) { if (!ClassDB::is_class_exposed(name)) {
print_verbose(vformat("Class '%s' is not exposed, skipping.", name)); print_verbose(vformat("Class '%s' is not exposed, skipping.", name));
classes.pop_front();
continue; continue;
} }
@ -726,8 +726,6 @@ void DocTools::generate(BitField<GenerateFlags> p_flags) {
c.theme_properties.sort(); c.theme_properties.sort();
} }
classes.pop_front();
} }
} }

View file

@ -1045,8 +1045,8 @@ void EditorData::script_class_set_name(const String &p_path, const StringName &p
} }
void EditorData::script_class_save_global_classes() { void EditorData::script_class_save_global_classes() {
List<StringName> global_classes; LocalVector<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes); ScriptServer::get_global_class_list(global_classes);
Array array_classes; Array array_classes;
for (const StringName &class_name : global_classes) { for (const StringName &class_name : global_classes) {
Dictionary d; Dictionary d;

View file

@ -1649,9 +1649,9 @@ void EditorFileSystem::_thread_func_sources(void *_userdata) {
} }
bool EditorFileSystem::_remove_invalid_global_class_names(const HashSet<String> &p_existing_class_names) { bool EditorFileSystem::_remove_invalid_global_class_names(const HashSet<String> &p_existing_class_names) {
List<StringName> global_classes; LocalVector<StringName> global_classes;
bool must_save = false; bool must_save = false;
ScriptServer::get_global_class_list(&global_classes); ScriptServer::get_global_class_list(global_classes);
for (const StringName &class_name : global_classes) { for (const StringName &class_name : global_classes) {
if (!p_existing_class_names.has(class_name)) { if (!p_existing_class_names.has(class_name)) {
ScriptServer::remove_global_class(class_name); ScriptServer::remove_global_class(class_name);

View file

@ -81,9 +81,9 @@ void CreateDialog::for_inherit() {
} }
void CreateDialog::_fill_type_list() { void CreateDialog::_fill_type_list() {
List<StringName> complete_type_list; LocalVector<StringName> complete_type_list;
ClassDB::get_class_list(&complete_type_list); ClassDB::get_class_list(complete_type_list);
ScriptServer::get_global_class_list(&complete_type_list); ScriptServer::get_global_class_list(complete_type_list);
EditorData &ed = EditorNode::get_editor_data(); EditorData &ed = EditorNode::get_editor_data();
HashMap<String, DocData::ClassDoc> &class_docs_list = EditorHelp::get_doc_data()->class_list; HashMap<String, DocData::ClassDoc> &class_docs_list = EditorHelp::get_doc_data()->class_list;

View file

@ -1191,8 +1191,8 @@ bool ProjectConverter3To4::test_array_names() {
// } // }
//} //}
List<StringName> classes_list; LocalVector<StringName> classes_list;
ClassDB::get_class_list(&classes_list); ClassDB::get_class_list(classes_list);
for (StringName &name_of_class : classes_list) { for (StringName &name_of_class : classes_list) {
List<MethodInfo> method_list; List<MethodInfo> method_list;
ClassDB::get_method_list(name_of_class, &method_list, true); ClassDB::get_method_list(name_of_class, &method_list, true);

View file

@ -125,18 +125,18 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
/* Engine types. */ /* Engine types. */
const Color type_color = EDITOR_GET("text_editor/theme/highlighting/engine_type_color"); const Color type_color = EDITOR_GET("text_editor/theme/highlighting/engine_type_color");
List<StringName> types; LocalVector<StringName> types;
ClassDB::get_class_list(&types); ClassDB::get_class_list(types);
for (const StringName &E : types) { for (const StringName &type : types) {
highlighter->add_keyword_color(E, type_color); highlighter->add_keyword_color(type, type_color);
} }
/* User types. */ /* User types. */
const Color usertype_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color"); const Color usertype_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color");
List<StringName> global_classes; LocalVector<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes); ScriptServer::get_global_class_list(global_classes);
for (const StringName &E : global_classes) { for (const StringName &class_name : global_classes) {
highlighter->add_keyword_color(E, usertype_color); highlighter->add_keyword_color(class_name, usertype_color);
} }
/* Autoloads. */ /* Autoloads. */

View file

@ -944,20 +944,20 @@ void EditorBuildProfileManager::_detect_from_project() {
edited->clear_disabled_classes(); edited->clear_disabled_classes();
List<StringName> all_classes; LocalVector<StringName> all_classes;
ClassDB::get_class_list(&all_classes); ClassDB::get_class_list(all_classes);
for (const StringName &E : all_classes) { for (const StringName &class_name : all_classes) {
if (String(E).begins_with("Editor") || ClassDB::get_api_type(E) != ClassDB::API_CORE || all_used_classes.has(E)) { if (String(class_name).begins_with("Editor") || ClassDB::get_api_type(class_name) != ClassDB::API_CORE || all_used_classes.has(class_name)) {
// This class is valid or editor-only, do nothing. // This class is valid or editor-only, do nothing.
continue; continue;
} }
StringName p = ClassDB::get_parent_class(E); StringName p = ClassDB::get_parent_class(class_name);
if (!p || all_used_classes.has(p)) { if (!p || all_used_classes.has(p)) {
// If no parent, or if the parent is enabled, then add to disabled classes. // If no parent, or if the parent is enabled, then add to disabled classes.
// This way we avoid disabling redundant classes. // This way we avoid disabling redundant classes.
edited->set_disable_class(E, true); edited->set_disable_class(class_name, true);
} }
} }

View file

@ -2158,12 +2158,12 @@ void VisualShaderEditor::_update_nodes() {
// Add GDScript classes. // Add GDScript classes.
{ {
List<StringName> class_list; LocalVector<StringName> class_list;
ScriptServer::get_global_class_list(&class_list); ScriptServer::get_global_class_list(class_list);
for (const StringName &E : class_list) { for (const StringName &class_name : class_list) {
if (ScriptServer::get_global_class_native_base(E) == "VisualShaderNodeCustom") { if (ScriptServer::get_global_class_native_base(class_name) == "VisualShaderNodeCustom") {
String script_path = ScriptServer::get_global_class_path(E); String script_path = ScriptServer::get_global_class_path(class_name);
Ref<Resource> res = ResourceLoader::load(script_path); Ref<Resource> res = ResourceLoader::load(script_path);
ERR_CONTINUE(res.is_null()); ERR_CONTINUE(res.is_null());
ERR_CONTINUE(!res->is_class("Script")); ERR_CONTINUE(!res->is_class("Script"));
@ -2188,19 +2188,19 @@ void VisualShaderEditor::_update_nodes() {
// Add GDExtension classes. // Add GDExtension classes.
{ {
List<StringName> class_list; LocalVector<StringName> class_list;
ClassDB::get_class_list(&class_list); ClassDB::get_class_list(class_list);
for (const StringName &E : class_list) { for (const StringName &class_name : class_list) {
if (ClassDB::get_parent_class(E) == "VisualShaderNodeCustom") { if (ClassDB::get_parent_class(class_name) == "VisualShaderNodeCustom") {
Object *instance = ClassDB::instantiate(E); Object *instance = ClassDB::instantiate(class_name);
Ref<VisualShaderNodeCustom> ref = Object::cast_to<VisualShaderNodeCustom>(instance); Ref<VisualShaderNodeCustom> ref = Object::cast_to<VisualShaderNodeCustom>(instance);
ERR_CONTINUE(ref.is_null()); ERR_CONTINUE(ref.is_null());
if (!ref->is_available(visual_shader->get_mode(), get_current_shader_type())) { if (!ref->is_available(visual_shader->get_mode(), get_current_shader_type())) {
continue; continue;
} }
Dictionary dict = get_custom_node_data(ref); Dictionary dict = get_custom_node_data(ref);
dict["type"] = E; dict["type"] = class_name;
dict["script"] = Ref<Script>(); dict["script"] = Ref<Script>();
String key; String key;

View file

@ -715,11 +715,11 @@ void GDScriptSyntaxHighlighter::_update_cache() {
/* Engine types. */ /* Engine types. */
const Color types_color = EDITOR_GET("text_editor/theme/highlighting/engine_type_color"); const Color types_color = EDITOR_GET("text_editor/theme/highlighting/engine_type_color");
List<StringName> types; LocalVector<StringName> types;
ClassDB::get_class_list(&types); ClassDB::get_class_list(types);
for (const StringName &E : types) { for (const StringName &type : types) {
if (ClassDB::is_class_exposed(E)) { if (ClassDB::is_class_exposed(type)) {
class_names[E] = types_color; class_names[type] = types_color;
} }
} }
@ -732,10 +732,10 @@ void GDScriptSyntaxHighlighter::_update_cache() {
/* User types. */ /* User types. */
const Color usertype_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color"); const Color usertype_color = EDITOR_GET("text_editor/theme/highlighting/user_type_color");
List<StringName> global_classes; LocalVector<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes); ScriptServer::get_global_class_list(global_classes);
for (const StringName &E : global_classes) { for (const StringName &class_name : global_classes) {
class_names[E] = usertype_color; class_names[class_name] = usertype_color;
} }
/* Autoloads. */ /* Autoloads. */

View file

@ -2268,14 +2268,14 @@ void GDScriptLanguage::init() {
//populate native classes //populate native classes
List<StringName> class_list; LocalVector<StringName> class_list;
ClassDB::get_class_list(&class_list); ClassDB::get_class_list(class_list);
for (const StringName &n : class_list) { for (const StringName &class_name : class_list) {
if (globals.has(n)) { if (globals.has(class_name)) {
continue; continue;
} }
Ref<GDScriptNativeClass> nc = memnew(GDScriptNativeClass(n)); Ref<GDScriptNativeClass> nc = memnew(GDScriptNativeClass(class_name));
_add_global(n, nc); _add_global(class_name, nc);
} }
//populate singletons //populate singletons

View file

@ -955,13 +955,13 @@ static void _find_annotation_arguments(const GDScriptParser::AnnotationNode *p_a
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
List<StringName> global_script_classes; LocalVector<StringName> global_script_classes;
ScriptServer::get_global_class_list(&global_script_classes); ScriptServer::get_global_class_list(global_script_classes);
for (const StringName &E : global_script_classes) { for (const StringName &class_name : global_script_classes) {
if (!ClassDB::is_parent_class(ScriptServer::get_global_class_native_base(E), "Node")) { if (!ClassDB::is_parent_class(ScriptServer::get_global_class_native_base(class_name), "Node")) {
continue; continue;
} }
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS); ScriptLanguage::CodeCompletionOption option(class_name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
option.insert_text = option.display.quote(p_quote_style); option.insert_text = option.display.quote(p_quote_style);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
@ -1049,11 +1049,11 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
// Built-in Variant Types // Built-in Variant Types
_find_built_in_variants(r_result, true); _find_built_in_variants(r_result, true);
List<StringName> native_types; LocalVector<StringName> native_types;
ClassDB::get_class_list(&native_types); ClassDB::get_class_list(native_types);
for (const StringName &E : native_types) { for (const StringName &type : native_types) {
if (ClassDB::is_class_exposed(E) && !Engine::get_singleton()->has_singleton(E)) { if (ClassDB::is_class_exposed(type) && !Engine::get_singleton()->has_singleton(type)) {
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS); ScriptLanguage::CodeCompletionOption option(type, ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} }
@ -1103,10 +1103,10 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
} }
// Global scripts // Global scripts
List<StringName> global_classes; LocalVector<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes); ScriptServer::get_global_class_list(global_classes);
for (const StringName &E : global_classes) { for (const StringName &class_name : global_classes) {
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE); ScriptLanguage::CodeCompletionOption option(class_name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
@ -1626,10 +1626,10 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context
_find_global_enums(r_result); _find_global_enums(r_result);
// Global classes // Global classes
List<StringName> global_classes; LocalVector<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes); ScriptServer::get_global_class_list(global_classes);
for (const StringName &E : global_classes) { for (const StringName &class_name : global_classes) {
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE); ScriptLanguage::CodeCompletionOption option(class_name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} }

View file

@ -40,13 +40,11 @@
void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) { void class_db_api_to_json(const String &p_output_file, ClassDB::APIType p_api) {
Dictionary classes_dict; Dictionary classes_dict;
List<StringName> class_list; LocalVector<StringName> class_list;
ClassDB::get_class_list(&class_list); ClassDB::get_class_list(class_list);
// Must be alphabetically sorted for hash to compute.
class_list.sort_custom<StringName::AlphCompare>();
for (const StringName &E : class_list) { for (const StringName &class_name : class_list) {
ClassDB::ClassInfo *t = ClassDB::classes.getptr(E); ClassDB::ClassInfo *t = ClassDB::classes.getptr(class_name);
ERR_FAIL_NULL(t); ERR_FAIL_NULL(t);
if (t->api != p_api || !t->exposed) { if (t->api != p_api || !t->exposed) {
continue; continue;

View file

@ -3858,35 +3858,28 @@ struct SortMethodWithHashes {
bool BindingsGenerator::_populate_object_type_interfaces() { bool BindingsGenerator::_populate_object_type_interfaces() {
obj_types.clear(); obj_types.clear();
List<StringName> class_list; LocalVector<StringName> class_list;
ClassDB::get_class_list(&class_list); ClassDB::get_class_list(class_list);
class_list.sort_custom<StringName::AlphCompare>();
while (class_list.size()) {
StringName type_cname = class_list.front()->get();
for (const StringName &type_cname : class_list) {
ClassDB::APIType api_type = ClassDB::get_api_type(type_cname); ClassDB::APIType api_type = ClassDB::get_api_type(type_cname);
if (api_type == ClassDB::API_NONE) { if (api_type == ClassDB::API_NONE) {
class_list.pop_front();
continue; continue;
} }
if (ignored_types.has(type_cname)) { if (ignored_types.has(type_cname)) {
_log("Ignoring type '%s' because it's in the list of ignored types\n", String(type_cname).utf8().get_data()); _log("Ignoring type '%s' because it's in the list of ignored types\n", String(type_cname).utf8().get_data());
class_list.pop_front();
continue; continue;
} }
if (!ClassDB::is_class_exposed(type_cname)) { if (!ClassDB::is_class_exposed(type_cname)) {
_log("Ignoring type '%s' because it's not exposed\n", String(type_cname).utf8().get_data()); _log("Ignoring type '%s' because it's not exposed\n", String(type_cname).utf8().get_data());
class_list.pop_front();
continue; continue;
} }
if (!ClassDB::is_class_enabled(type_cname)) { if (!ClassDB::is_class_enabled(type_cname)) {
_log("Ignoring type '%s' because it's not enabled\n", String(type_cname).utf8().get_data()); _log("Ignoring type '%s' because it's not enabled\n", String(type_cname).utf8().get_data());
class_list.pop_front();
continue; continue;
} }
@ -4447,8 +4440,6 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
obj_types.insert(itype.name + CS_SINGLETON_INSTANCE_SUFFIX, itype); obj_types.insert(itype.name + CS_SINGLETON_INSTANCE_SUFFIX, itype);
} }
class_list.pop_front();
} }
return true; return true;

View file

@ -516,29 +516,25 @@ void validate_class(const Context &p_context, const ExposedClass &p_exposed_clas
} }
void add_exposed_classes(Context &r_context) { void add_exposed_classes(Context &r_context) {
List<StringName> class_list; LocalVector<StringName> class_list;
ClassDB::get_class_list(&class_list); ClassDB::get_class_list(class_list);
class_list.sort_custom<StringName::AlphCompare>();
while (class_list.size()) { for (uint32_t class_list_idx = 0; class_list_idx < class_list.size(); class_list_idx++) {
StringName class_name = class_list.front()->get(); StringName class_name = class_list[class_list_idx];
ClassDB::APIType api_type = ClassDB::get_api_type(class_name); ClassDB::APIType api_type = ClassDB::get_api_type(class_name);
if (api_type == ClassDB::API_NONE) { if (api_type == ClassDB::API_NONE) {
class_list.pop_front();
continue; continue;
} }
if (!ClassDB::is_class_exposed(class_name)) { if (!ClassDB::is_class_exposed(class_name)) {
INFO(vformat("Ignoring class '%s' because it's not exposed.", class_name)); INFO(vformat("Ignoring class '%s' because it's not exposed.", class_name));
class_list.pop_front();
continue; continue;
} }
if (!ClassDB::is_class_enabled(class_name)) { if (!ClassDB::is_class_enabled(class_name)) {
INFO(vformat("Ignoring class '%s' because it's not enabled.", class_name)); INFO(vformat("Ignoring class '%s' because it's not enabled.", class_name));
class_list.pop_front();
continue; continue;
} }
@ -815,7 +811,6 @@ void add_exposed_classes(Context &r_context) {
} }
r_context.exposed_classes.insert(class_name, exposed_class); r_context.exposed_classes.insert(class_name, exposed_class);
class_list.pop_front();
} }
} }