diff --git a/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java b/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java index bde6fb64..a38b0003 100644 --- a/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java +++ b/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java @@ -84,9 +84,18 @@ final class ConfigConcatenation extends AbstractConfigValue implements Unmergeab /** * Add left and right, or their merger, to builder. */ - private static void join(ArrayList<AbstractConfigValue> builder, - AbstractConfigValue right) { + private static void join(ArrayList<AbstractConfigValue> builder, AbstractConfigValue origRight) { AbstractConfigValue left = builder.get(builder.size() - 1); + AbstractConfigValue right = origRight; + + // check for an object which can be converted to a list + // (this will be an object with numeric keys, like foo.0, foo.1) + if (left instanceof ConfigObject && right instanceof SimpleConfigList) { + left = DefaultTransformer.transform(left, ConfigValueType.LIST); + } else if (left instanceof SimpleConfigList && right instanceof ConfigObject) { + right = DefaultTransformer.transform(right, ConfigValueType.LIST); + } + // Since this depends on the type of two instances, I couldn't think // of much alternative to an instanceof chain. Visitors are sometimes // used for multiple dispatch but seems like overkill. diff --git a/config/src/test/scala/com/typesafe/config/impl/PropertiesTest.scala b/config/src/test/scala/com/typesafe/config/impl/PropertiesTest.scala index 1088abf2..35c4ac5d 100644 --- a/config/src/test/scala/com/typesafe/config/impl/PropertiesTest.scala +++ b/config/src/test/scala/com/typesafe/config/impl/PropertiesTest.scala @@ -10,6 +10,7 @@ import com.typesafe.config.Config import com.typesafe.config.ConfigParseOptions import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigException +import com.typesafe.config.ConfigResolveOptions class PropertiesTest extends TestUtils { @Test @@ -152,4 +153,27 @@ class PropertiesTest extends TestUtils { } assertTrue("expected exception thrown", e.getMessage.contains("LIST")) } + + @Test + def makeListWithNumericKeysAndMerge() { + import scala.collection.JavaConverters._ + + val props = new Properties() + props.setProperty("a.0", "0") + props.setProperty("a.1", "1") + props.setProperty("a.2", "2") + + val conf1 = ConfigFactory.parseProperties(props, ConfigParseOptions.defaults()) + assertEquals(Seq(0, 1, 2), conf1.getIntList("a").asScala.toSeq) + + val conf2 = ConfigFactory.parseString(""" + a += 3 + a += 4 + a = ${a} [ 5, 6 ] + a = [-2, -1] ${a} + """) + val conf = conf2.withFallback(conf1).resolve() + + assertEquals(Seq(-2, -1, 0, 1, 2, 3, 4, 5, 6), conf.getIntList("a").asScala.toSeq) + } }