Browse Source

Change ClassDB::get_class_list and related stuff.

Yufeng Ying 9 months ago
parent
commit
a50fc5acd8

+ 6 - 4
core/core_bind.cpp

@@ -1545,14 +1545,16 @@ namespace Special {
 ////// ClassDB //////
 ////// ClassDB //////
 
 
 PackedStringArray ClassDB::get_class_list() const {
 PackedStringArray ClassDB::get_class_list() const {
-	List<StringName> classes;
-	::ClassDB::get_class_list(&classes);
+	LocalVector<StringName> 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) {
-		ret.set(idx++, E);
+	for (const StringName &cls : classes) {
+		ptrw[idx] = cls;
+		idx++;
 	}
 	}
 
 
 	return ret;
 	return ret;

+ 12 - 12
core/debugger/remote_debugger.cpp

@@ -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;
-				ClassDB::get_class_list(&native_types);
-				for (const StringName &E : native_types) {
-					if (!ClassDB::is_class_exposed(E) || !Engine::get_singleton()->has_singleton(E) || Engine::get_singleton()->is_singleton_editor_only(E)) {
+				LocalVector<StringName> native_types;
+				ClassDB::get_class_list(native_types);
+				for (const StringName &class_name : native_types) {
+					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_vals.append(Engine::get_singleton()->get_singleton_object(E));
+					input_names.append(class_name);
+					input_vals.append(Engine::get_singleton()->get_singleton_object(class_name));
 				}
 				}
 
 
-				List<StringName> user_types;
-				ScriptServer::get_global_class_list(&user_types);
-				for (const StringName &S : user_types) {
-					String scr_path = ScriptServer::get_global_class_path(S);
+				LocalVector<StringName> user_types;
+				ScriptServer::get_global_class_list(user_types);
+				for (const StringName &class_name : user_types) {
+					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);
 				}
 				}
 
 

+ 2 - 4
core/extension/extension_api_dump.cpp

@@ -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);
-
-		class_list.sort_custom<StringName::AlphCompare>();
+		ClassDB::get_class_list(class_list);
 
 
 		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)) {

+ 2 - 2
core/io/resource_loader.cpp

@@ -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;
-	ScriptServer::get_global_class_list(&global_classes);
+	LocalVector<StringName> 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);

+ 2 - 2
core/io/resource_saver.cpp

@@ -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;
-	ScriptServer::get_global_class_list(&global_classes);
+	LocalVector<StringName> 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);

+ 26 - 7
core/object/class_db.cpp

@@ -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) {
-		p_classes->push_back(E.key);
+	if (classes.is_empty()) {
+		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) {

+ 2 - 2
core/object/class_db.h

@@ -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

+ 17 - 13
core/object/script_language.cpp

@@ -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) {
-	List<StringName> classes;
-	for (const KeyValue<StringName, GlobalScriptClass> &E : global_classes) {
-		classes.push_back(E.key);
+// This function only sorts items added by this function.
+// If `r_global_classes` is not empty before calling and a global sort is needed, caller must handle that separately.
+void ScriptServer::get_global_class_list(LocalVector<StringName> &r_global_classes) {
+	if (global_classes.is_empty()) {
+		return;
 	}
 	}
-	classes.sort_custom<StringName::AlphCompare>();
-	for (const StringName &E : classes) {
-		r_global_classes->push_back(E);
+	r_global_classes.reserve(r_global_classes.size() + global_classes.size());
+	for (const KeyValue<StringName, GlobalScriptClass> &global_class : global_classes) {
+		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;
-	get_global_class_list(&gc);
+	LocalVector<StringName> gc;
+	get_global_class_list(gc);
 	Array gcarr;
 	Array gcarr;
-	for (const StringName &E : gc) {
-		const GlobalScriptClass &global_class = global_classes[E];
+	for (const StringName &class_name : gc) {
+		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);

+ 1 - 1
core/object/script_language.h

@@ -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();
 
 

+ 7 - 9
editor/doc/doc_tools.cpp

@@ -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()) {
-			const String &name = classes.front()->get();
+		for (uint32_t classes_idx = 0; classes_idx < classes.size(); classes_idx++) {
+			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();
 		}
 		}
 	}
 	}
 
 

+ 2 - 2
editor/editor_data.cpp

@@ -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;
-	ScriptServer::get_global_class_list(&global_classes);
+	LocalVector<StringName> 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;

+ 2 - 2
editor/file_system/editor_file_system.cpp

@@ -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);

+ 3 - 3
editor/gui/create_dialog.cpp

@@ -81,9 +81,9 @@ void CreateDialog::for_inherit() {
 }
 }
 
 
 void CreateDialog::_fill_type_list() {
 void CreateDialog::_fill_type_list() {
-	List<StringName> complete_type_list;
-	ClassDB::get_class_list(&complete_type_list);
-	ScriptServer::get_global_class_list(&complete_type_list);
+	LocalVector<StringName> complete_type_list;
+	ClassDB::get_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;

+ 2 - 2
editor/project_upgrade/project_converter_3_to_4.cpp

@@ -1191,8 +1191,8 @@ bool ProjectConverter3To4::test_array_names() {
 		//	}
 		//	}
 		//}
 		//}
 
 
-		List<StringName> classes_list;
-		ClassDB::get_class_list(&classes_list);
+		LocalVector<StringName> 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);

+ 8 - 8
editor/script/script_editor_plugin.cpp

@@ -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;
-	ClassDB::get_class_list(&types);
-	for (const StringName &E : types) {
-		highlighter->add_keyword_color(E, type_color);
+	LocalVector<StringName> types;
+	ClassDB::get_class_list(types);
+	for (const StringName &type : types) {
+		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;
-	ScriptServer::get_global_class_list(&global_classes);
-	for (const StringName &E : global_classes) {
-		highlighter->add_keyword_color(E, usertype_color);
+	LocalVector<StringName> global_classes;
+	ScriptServer::get_global_class_list(global_classes);
+	for (const StringName &class_name : global_classes) {
+		highlighter->add_keyword_color(class_name, usertype_color);
 	}
 	}
 
 
 	/* Autoloads. */
 	/* Autoloads. */

+ 6 - 6
editor/settings/editor_build_profile.cpp

@@ -944,20 +944,20 @@ void EditorBuildProfileManager::_detect_from_project() {
 
 
 	edited->clear_disabled_classes();
 	edited->clear_disabled_classes();
 
 
-	List<StringName> all_classes;
-	ClassDB::get_class_list(&all_classes);
+	LocalVector<StringName> all_classes;
+	ClassDB::get_class_list(all_classes);
 
 
-	for (const StringName &E : all_classes) {
-		if (String(E).begins_with("Editor") || ClassDB::get_api_type(E) != ClassDB::API_CORE || all_used_classes.has(E)) {
+	for (const StringName &class_name : all_classes) {
+		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);
 		}
 		}
 	}
 	}
 
 

+ 11 - 11
editor/shader/visual_shader_editor_plugin.cpp

@@ -2158,12 +2158,12 @@ void VisualShaderEditor::_update_nodes() {
 
 
 	// Add GDScript classes.
 	// Add GDScript classes.
 	{
 	{
-		List<StringName> class_list;
-		ScriptServer::get_global_class_list(&class_list);
+		LocalVector<StringName> class_list;
+		ScriptServer::get_global_class_list(class_list);
 
 
-		for (const StringName &E : class_list) {
-			if (ScriptServer::get_global_class_native_base(E) == "VisualShaderNodeCustom") {
-				String script_path = ScriptServer::get_global_class_path(E);
+		for (const StringName &class_name : class_list) {
+			if (ScriptServer::get_global_class_native_base(class_name) == "VisualShaderNodeCustom") {
+				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;
-		ClassDB::get_class_list(&class_list);
+		LocalVector<StringName> class_list;
+		ClassDB::get_class_list(class_list);
 
 
-		for (const StringName &E : class_list) {
-			if (ClassDB::get_parent_class(E) == "VisualShaderNodeCustom") {
-				Object *instance = ClassDB::instantiate(E);
+		for (const StringName &class_name : class_list) {
+			if (ClassDB::get_parent_class(class_name) == "VisualShaderNodeCustom") {
+				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;

+ 9 - 9
modules/gdscript/editor/gdscript_highlighter.cpp

@@ -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;
-	ClassDB::get_class_list(&types);
-	for (const StringName &E : types) {
-		if (ClassDB::is_class_exposed(E)) {
-			class_names[E] = types_color;
+	LocalVector<StringName> types;
+	ClassDB::get_class_list(types);
+	for (const StringName &type : types) {
+		if (ClassDB::is_class_exposed(type)) {
+			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;
-	ScriptServer::get_global_class_list(&global_classes);
-	for (const StringName &E : global_classes) {
-		class_names[E] = usertype_color;
+	LocalVector<StringName> global_classes;
+	ScriptServer::get_global_class_list(global_classes);
+	for (const StringName &class_name : global_classes) {
+		class_names[class_name] = usertype_color;
 	}
 	}
 
 
 	/* Autoloads. */
 	/* Autoloads. */

+ 6 - 6
modules/gdscript/gdscript.cpp

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

+ 18 - 18
modules/gdscript/gdscript_editor.cpp

@@ -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;
-		ScriptServer::get_global_class_list(&global_script_classes);
-		for (const StringName &E : global_script_classes) {
-			if (!ClassDB::is_parent_class(ScriptServer::get_global_class_native_base(E), "Node")) {
+		LocalVector<StringName> global_script_classes;
+		ScriptServer::get_global_class_list(global_script_classes);
+		for (const StringName &class_name : global_script_classes) {
+			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;
-	ClassDB::get_class_list(&native_types);
-	for (const StringName &E : native_types) {
-		if (ClassDB::is_class_exposed(E) && !Engine::get_singleton()->has_singleton(E)) {
-			ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS);
+	LocalVector<StringName> native_types;
+	ClassDB::get_class_list(native_types);
+	for (const StringName &type : native_types) {
+		if (ClassDB::is_class_exposed(type) && !Engine::get_singleton()->has_singleton(type)) {
+			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;
-	ScriptServer::get_global_class_list(&global_classes);
-	for (const StringName &E : global_classes) {
-		ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE);
+	LocalVector<StringName> global_classes;
+	ScriptServer::get_global_class_list(global_classes);
+	for (const StringName &class_name : global_classes) {
+		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;
-	ScriptServer::get_global_class_list(&global_classes);
-	for (const StringName &E : global_classes) {
-		ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE);
+	LocalVector<StringName> global_classes;
+	ScriptServer::get_global_class_list(global_classes);
+	for (const StringName &class_name : global_classes) {
+		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);
 	}
 	}
 }
 }

+ 4 - 6
modules/mono/class_db_api_json.cpp

@@ -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;
-	ClassDB::get_class_list(&class_list);
-	// Must be alphabetically sorted for hash to compute.
-	class_list.sort_custom<StringName::AlphCompare>();
+	LocalVector<StringName> class_list;
+	ClassDB::get_class_list(class_list);
 
 
-	for (const StringName &E : class_list) {
-		ClassDB::ClassInfo *t = ClassDB::classes.getptr(E);
+	for (const StringName &class_name : class_list) {
+		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;

+ 3 - 12
modules/mono/editor/bindings_generator.cpp

@@ -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;
-	ClassDB::get_class_list(&class_list);
-	class_list.sort_custom<StringName::AlphCompare>();
-
-	while (class_list.size()) {
-		StringName type_cname = class_list.front()->get();
+	LocalVector<StringName> class_list;
+	ClassDB::get_class_list(class_list);
 
 
+	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;

+ 4 - 9
tests/core/object/test_class_db.h

@@ -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;
-	ClassDB::get_class_list(&class_list);
-	class_list.sort_custom<StringName::AlphCompare>();
+	LocalVector<StringName> class_list;
+	ClassDB::get_class_list(class_list);
 
 
-	while (class_list.size()) {
-		StringName class_name = class_list.front()->get();
+	for (uint32_t class_list_idx = 0; class_list_idx < class_list.size(); class_list_idx++) {
+		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();
 	}
 	}
 }
 }