mirror of
https://github.com/lightbend/config.git
synced 2025-03-24 08:10:24 +08:00
If all concatenation elements are undefined, undefine the field
This is a spec change but the spec was wrong and the implementation previously just threw an exception. The spec claimed that ${?foo}${?bar} would become empty string, but it's more useful for it to just become undefined. You can add an explicit empty string with "" if you want it to be empty string. Fixes #161.
This commit is contained in:
parent
6218174704
commit
08c4fe3950
11
HOCON.md
11
HOCON.md
@ -575,12 +575,13 @@ If a substitution with the `${?foo}` syntax is undefined:
|
||||
be created. If the field would have overridden a previously-set
|
||||
value for the same field, then the previous value remains.
|
||||
- if it is an array element then the element should not be added.
|
||||
- if it is part of a value concatenation then it should become an
|
||||
empty string.
|
||||
- if it is part of a value concatenation with another string then
|
||||
it should become an empty string; if part of a value
|
||||
concatenation with an object or array it should become an empty
|
||||
object or array.
|
||||
- `foo : ${?bar}` would avoid creating field `foo` if `bar` is
|
||||
undefined, but `foo : ${?bar}${?baz}` would be a value
|
||||
concatenation so if `bar` or `baz` are not defined, the result
|
||||
is an empty string.
|
||||
undefined. `foo : ${?bar}${?baz}` would also avoid creating the
|
||||
field if _both_ `bar` and `baz` are undefined.
|
||||
|
||||
Substitutions are only allowed in field values and array
|
||||
elements (value concatenations), they are not allowed in keys or
|
||||
|
@ -189,11 +189,13 @@ final class ConfigConcatenation extends AbstractConfigValue implements Unmergeab
|
||||
// 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);
|
||||
else
|
||||
else if (joined.isEmpty())
|
||||
return null; // we had just a list of optional references using ${?}
|
||||
else if (joined.size() == 1)
|
||||
return joined.get(0);
|
||||
else
|
||||
throw new ConfigException.BugOrBroken("Bug in the library; resolved list was joined to too many values: "
|
||||
+ joined);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -368,4 +368,65 @@ class ConcatenationTest extends TestUtils {
|
||||
assertTrue(e.getMessage.contains("limitation"))
|
||||
System.err.println("==============")
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatUndefinedSubstitutionWithString() {
|
||||
val conf = parseConfig("""a = foo${?bar}""").resolve()
|
||||
assertEquals("foo", conf.getString("a"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatDefinedOptionalSubstitutionWithString() {
|
||||
val conf = parseConfig("""bar=bar, a = foo${?bar}""").resolve()
|
||||
assertEquals("foobar", conf.getString("a"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatUndefinedSubstitutionWithArray() {
|
||||
val conf = parseConfig("""a = [1] ${?bar}""").resolve()
|
||||
assertEquals(Seq(1), conf.getIntList("a").asScala.toList)
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatDefinedOptionalSubstitutionWithArray() {
|
||||
val conf = parseConfig("""bar=[2], a = [1] ${?bar}""").resolve()
|
||||
assertEquals(Seq(1, 2), conf.getIntList("a").asScala.toList)
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatUndefinedSubstitutionWithObject() {
|
||||
val conf = parseConfig("""a = { x : "foo" } ${?bar}""").resolve()
|
||||
assertEquals("foo", conf.getString("a.x"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatDefinedOptionalSubstitutionWithObject() {
|
||||
val conf = parseConfig("""bar={ y : 42 }, a = { x : "foo" } ${?bar}""").resolve()
|
||||
assertEquals("foo", conf.getString("a.x"))
|
||||
assertEquals(42, conf.getInt("a.y"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatTwoUndefinedSubstitutions() {
|
||||
val conf = parseConfig("""a = ${?foo}${?bar}""").resolve()
|
||||
assertFalse("no field 'a'", conf.hasPath("a"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatSeveralUndefinedSubstitutions() {
|
||||
val conf = parseConfig("""a = ${?foo}${?bar}${?baz}${?woooo}""").resolve()
|
||||
assertFalse("no field 'a'", conf.hasPath("a"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatTwoUndefinedSubstitutionsWithASpace() {
|
||||
val conf = parseConfig("""a = ${?foo} ${?bar}""").resolve()
|
||||
assertEquals(" ", conf.getString("a"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def concatTwoUndefinedSubstitutionsWithEmptyString() {
|
||||
val conf = parseConfig("""a = ""${?foo}${?bar}""").resolve()
|
||||
assertEquals("", conf.getString("a"))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user