Prechádzať zdrojové kódy

Merge pull request #97542 from AThousandShips/dict_sort_fix

[Core] Fix sorting of `Dictionary` keys
Thaddeus Crews 10 mesiacov pred
rodič
commit
5fb22327ee

+ 1 - 1
core/io/json.cpp

@@ -121,7 +121,7 @@ String JSON::_stringify(const Variant &p_var, const String &p_indent, int p_cur_
 			d.get_key_list(&keys);
 
 			if (p_sort_keys) {
-				keys.sort();
+				keys.sort_custom<StringLikeVariantOrder>();
 			}
 
 			bool first_key = true;

+ 13 - 0
core/variant/variant.h

@@ -854,6 +854,19 @@ struct StringLikeVariantComparator {
 	static bool compare(const Variant &p_lhs, const Variant &p_rhs);
 };
 
+struct StringLikeVariantOrder {
+	static _ALWAYS_INLINE_ bool compare(const Variant &p_lhs, const Variant &p_rhs) {
+		if (p_lhs.is_string() && p_rhs.is_string()) {
+			return p_lhs.operator String() < p_rhs.operator String();
+		}
+		return p_lhs < p_rhs;
+	}
+
+	_ALWAYS_INLINE_ bool operator()(const Variant &p_lhs, const Variant &p_rhs) const {
+		return compare(p_lhs, p_rhs);
+	}
+};
+
 Variant::ObjData &Variant::_get_obj() {
 	return *reinterpret_cast<ObjData *>(&_data._mem[0]);
 }

+ 1 - 1
core/variant/variant_parser.cpp

@@ -2245,7 +2245,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
 			} else {
 				List<Variant> keys;
 				dict.get_key_list(&keys);
-				keys.sort();
+				keys.sort_custom<StringLikeVariantOrder>();
 
 				if (keys.is_empty()) {
 					// Avoid unnecessary line break.

+ 4 - 5
editor/plugins/visual_shader_editor_plugin.cpp

@@ -2128,12 +2128,11 @@ void VisualShaderEditor::_update_nodes() {
 		}
 	}
 
-	Array keys = added.keys();
-	keys.sort();
-
-	for (int i = 0; i < keys.size(); i++) {
-		const Variant &key = keys.get(i);
+	List<Variant> keys;
+	added.get_key_list(&keys);
+	keys.sort_custom<StringLikeVariantOrder>();
 
+	for (const Variant &key : keys) {
 		const Dictionary &value = (Dictionary)added[key];
 
 		add_custom_type(value["name"], value["type"], value["script"], value["description"], value["return_icon_type"], value["category"], value["highend"]);

+ 1 - 1
modules/gdscript/editor/gdscript_docgen.cpp

@@ -217,7 +217,7 @@ String GDScriptDocGen::_docvalue_from_variant(const Variant &p_variant, int p_re
 
 				List<Variant> keys;
 				dict.get_key_list(&keys);
-				keys.sort();
+				keys.sort_custom<StringLikeVariantOrder>();
 
 				for (List<Variant>::Element *E = keys.front(); E; E = E->next()) {
 					if (E->prev()) {

+ 8 - 0
tests/core/variant/test_variant.h

@@ -1806,6 +1806,14 @@ TEST_CASE("[Variant] Writer and parser dictionary") {
 	CHECK_MESSAGE(d_parsed == Variant(d), "Should parse back.");
 }
 
+TEST_CASE("[Variant] Writer key sorting") {
+	Dictionary d = build_dictionary(StringName("C"), 3, "A", 1, StringName("B"), 2, "D", 4);
+	String d_str;
+	VariantWriter::write_to_string(d, d_str);
+
+	CHECK_EQ(d_str, "{\n\"A\": 1,\n&\"B\": 2,\n&\"C\": 3,\n\"D\": 4\n}");
+}
+
 TEST_CASE("[Variant] Writer recursive dictionary") {
 	// There is no way to accurately represent a recursive dictionary,
 	// the only thing we can do is make sure the writer doesn't blow up