SPIGOT-4558: Preserve user order in the face of copied defaults in configurations

By: md_5 <git@md-5.net>
This commit is contained in:
Bukkit/Spigot 2018-12-31 17:10:56 +11:00
parent 1c116bb13c
commit 6a8d62ff22
2 changed files with 13 additions and 5 deletions

View file

@ -742,7 +742,12 @@ public class MemorySection implements ConfigurationSection {
MemorySection sec = (MemorySection) section;
for (Map.Entry<String, Object> entry : sec.map.entrySet()) {
output.put(createPath(section, entry.getKey(), this), entry.getValue());
// Because of the copyDefaults call potentially copying out of order, we must remove and then add in our saved order
// This means that default values we haven't set end up getting placed first
// See SPIGOT-4558 for an example using spigot.yml - watch subsections move around to default order
String childPath = createPath(section, entry.getKey(), this);
output.remove(childPath);
output.put(childPath, entry.getValue());
if (entry.getValue() instanceof ConfigurationSection) {
if (deep) {

View file

@ -69,18 +69,21 @@ public abstract class ConfigurationSectionTest {
ConfigurationSection section = getConfigurationSection();
section.getRoot().options().copyDefaults(true);
// Fix for SPIGOT-4558 means that defaults will always be first
// This is a little bit unintuitive for section defaults when deep iterating keys / values as shown below
// But the API doesn't guarantee order & when serialized (using shallow getters) all is well
section.set("bool", true);
section.set("subsection.string", "test");
section.addDefault("subsection.long", Long.MAX_VALUE);
section.addDefault("int", 42);
Map<String, Object> shallowValues = section.getValues(false);
assertArrayEquals(new String[] { "subsection", "int", "bool" }, shallowValues.keySet().toArray());
assertArrayEquals(new Object[] { section.getConfigurationSection("subsection"), 42, true }, shallowValues.values().toArray());
assertArrayEquals(new String[] { "int", "bool", "subsection" }, shallowValues.keySet().toArray());
assertArrayEquals(new Object[] { 42, true, section.getConfigurationSection("subsection") }, shallowValues.values().toArray());
Map<String, Object> deepValues = section.getValues(true);
assertArrayEquals(new String[] { "subsection", "subsection.long", "int", "bool", "subsection.string" }, deepValues.keySet().toArray());
assertArrayEquals(new Object[] { section.getConfigurationSection("subsection"), Long.MAX_VALUE, 42, true, "test" }, deepValues.values().toArray());
assertArrayEquals(new String[] { "subsection.long", "int", "bool", "subsection", "subsection.string" }, deepValues.keySet().toArray());
assertArrayEquals(new Object[] { Long.MAX_VALUE, 42, true, section.getConfigurationSection("subsection"), "test" }, deepValues.values().toArray());
}
@Test