From 91e5e8199551da60a64f48b41f2151b7573dc681 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 10 Feb 2014 15:51:04 -0500 Subject: [PATCH] Handle a concatenation that doesn't resolve Fixes #140 --- .../com/typesafe/config/impl/ConfigConcatenation.java | 9 +++++++-- .../test/scala/com/typesafe/config/impl/ConfigTest.scala | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) 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 958d82e5..77c0fabf 100644 --- a/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java +++ b/config/src/main/java/com/typesafe/config/impl/ConfigConcatenation.java @@ -185,10 +185,15 @@ final class ConfigConcatenation extends AbstractConfigValue implements Unmergeab // now need to concat everything List joined = consolidate(resolved); - if (joined.size() != 1) + // if unresolved is allowed we can just become another + // ConfigConcatenation + if (joined.size() > 1 && context.options().getAllowUnresolved()) + return new ConfigConcatenation(this.origin(), joined); + else if (joined.size() != 1) throw new ConfigException.BugOrBroken( "Resolved list should always join to exactly one value, not " + joined); - return joined.get(0); + else + return joined.get(0); } @Override diff --git a/config/src/test/scala/com/typesafe/config/impl/ConfigTest.scala b/config/src/test/scala/com/typesafe/config/impl/ConfigTest.scala index d26cb997..a68f3897 100644 --- a/config/src/test/scala/com/typesafe/config/impl/ConfigTest.scala +++ b/config/src/test/scala/com/typesafe/config/impl/ConfigTest.scala @@ -1122,7 +1122,7 @@ class ConfigTest extends TestUtils { def allowUnresolvedDoesAllowUnresolved() { val values = ConfigFactory.parseString("{ foo = 1, bar = 2, m = 3, n = 4}") assertTrue("config with no substitutions starts as resolved", values.isResolved) - val unresolved = ConfigFactory.parseString("a = ${foo}, b = ${bar}, c { x = ${m}, y = ${n} }, alwaysResolveable=${alwaysValue}, alwaysValue=42") + val unresolved = ConfigFactory.parseString("a = ${foo}, b = ${bar}, c { x = ${m}, y = ${n}, z = foo${m}bar }, alwaysResolveable=${alwaysValue}, alwaysValue=42") assertFalse("config with substitutions starts as not resolved", unresolved.isResolved) // resolve() by default throws with unresolveable substs @@ -1140,6 +1140,8 @@ class ConfigTest extends TestUtils { for (k <- Seq("a", "b", "c.x", "c.y")) { intercept[ConfigException.NotResolved] { allowedUnresolved.getInt(k) } } + intercept[ConfigException.NotResolved] { allowedUnresolved.getString("c.z") } + // and the partially-resolved thing is not resolved assertFalse("partially-resolved object is not resolved", allowedUnresolved.isResolved) @@ -1150,6 +1152,7 @@ class ConfigTest extends TestUtils { for (kv <- Seq("a" -> 1, "b" -> 2, "c.x" -> 3, "c.y" -> 4)) { assertEquals(kv._2, resolved.getInt(kv._1)) } + assertEquals("foo3bar", resolved.getString("c.z")) assertTrue("fully resolved object is resolved", resolved.isResolved) } @@ -1159,6 +1162,7 @@ class ConfigTest extends TestUtils { for (kv <- Seq("a" -> 1, "b" -> 2, "c.x" -> 3, "c.y" -> 4)) { assertEquals(kv._2, resolved.getInt(kv._1)) } + assertEquals("foo3bar", resolved.getString("c.z")) assertTrue("fully resolved object is resolved", resolved.isResolved) } }