diff --git a/core/src/main/java/org/spongepowered/configurate/AbstractConfigurationNode.java b/core/src/main/java/org/spongepowered/configurate/AbstractConfigurationNode.java index cf08a7aa1..68c60cfe6 100644 --- a/core/src/main/java/org/spongepowered/configurate/AbstractConfigurationNode.java +++ b/core/src/main/java/org/spongepowered/configurate/AbstractConfigurationNode.java @@ -671,7 +671,7 @@ private A attachChild(final A child, final boolean onlyIfAbsent) { } } else { // if the existing value isn't a map, we need to update it's type - if (ListConfigValue.likelyListKey(child.key)) { + if (ListConfigValue.likelyNewListKey(child.key) || ListConfigValue.likelyListKey(oldValue, child.key)) { // if child.key is an integer, we can infer that the type of this node should be a list if (oldValue instanceof NullConfigValue) { // if the oldValue was null, we can just replace it with an empty list diff --git a/core/src/main/java/org/spongepowered/configurate/ListConfigValue.java b/core/src/main/java/org/spongepowered/configurate/ListConfigValue.java index a004e9de2..b42004186 100644 --- a/core/src/main/java/org/spongepowered/configurate/ListConfigValue.java +++ b/core/src/main/java/org/spongepowered/configurate/ListConfigValue.java @@ -50,15 +50,34 @@ public String toString() { }; /** - * Return whether a key is likely to be an index into a list. + * Return whether a key is likely to create a new list. * * @param key key to check - * @return if the key is likely to be a list index + * @return if the key is likely to create a new list. */ - static boolean likelyListKey(final @Nullable Object key) { + static boolean likelyNewListKey(final @Nullable Object key) { return (key instanceof Integer && ((Integer) key).intValue() == 0) || key == UNALLOCATED_IDX; } + /** + * Return whether a key is likely to be an index into a list. + * + * @param configValue the list to check + * @param key key to check + * @return if the key is likely to be an index into a list. + */ + static boolean likelyListKey(final @Nullable ConfigValue configValue, final @Nullable Object key) { + if (!(configValue instanceof ListConfigValue)) { + return false; + } + if (!(key instanceof Integer)) { + return false; + } + final ListConfigValue listConfigValue = (ListConfigValue) configValue; + final int keyAsInt = (Integer) key; + return keyAsInt >= 0 && keyAsInt <= listConfigValue.values.size(); + } + private final A holder; volatile List values = new ArrayList<>(); diff --git a/core/src/test/java/org/spongepowered/configurate/AbstractConfigurationNodeTest.java b/core/src/test/java/org/spongepowered/configurate/AbstractConfigurationNodeTest.java index b67f90780..7ca4feb4b 100644 --- a/core/src/test/java/org/spongepowered/configurate/AbstractConfigurationNodeTest.java +++ b/core/src/test/java/org/spongepowered/configurate/AbstractConfigurationNodeTest.java @@ -150,6 +150,15 @@ void testListUnpacking() { assertEquals("test2", root.node(1).raw()); } + @Test + void testLisUnpacking2() { + final ConfigurationNode root = BasicConfigurationNode.root(); + final ConfigurationNode subnode = root.node("subnode"); + subnode.node(0).raw("test1"); + subnode.node(1).raw("test2"); + assertEquals(TEST_LIST, subnode.raw()); + } + @Test void testListPacking() { final ConfigurationNode root = BasicConfigurationNode.root();