config
config copied to clipboard
Merge objects before resolve
This is an alternate fix for #599 ... maybe still a bit of a hack.
Previously, if we had something like this:
foo : "" foo : { bar : ${undefined} } foo : { bar : 42 }
Then it was possible to end up with the value of foo as a delayed merge with multiple adjacent objects in its stack.
We then would resolve each value in the stack, and only after that merge all the values. But we need to merge objects BEFORE we try to resolve them, in case some of the unresolved substitutions just go away.
This was only happening with the bottom of the stack as a non-object, since if the bottom was an object, we were merging the objects as we went along anyway.
So, I didn't try it yet, but this may not handle something like:
containsundefined = { bar : ${undefined} }
foo = ""
foo = ${containsundefined}
foo = { bar : 42 }
To handle that, we'd have to actually fix the resolve method on ConfigDelayedMerge/ConfigDelayedMergeObject to resolve only until it gets something mergeable, instead of resolving until nothing is left unresolved.
Maybe this would require introducing some way to "resolve only until mergeable" instead of the full "resolveSubstitutions"
I played with it some and the real fix here gets extremely complicated to understand, though I'm not sure it would be a large patch once understood. It may be worth merging something like this PR for now.
A test case this PR doesn't fix is:
@Test
def ignoreHiddenUndefinedSubstIndirectlyNestedInsideObjectWhenOverridingNonObject() {
val obj = parseObject("""
containsundefined {
bar = ${override-me}
}
foo = ""
foo = ${containsundefined}
foo {
bar = "bar"
}
""")
val resolved = resolve(obj)
assertEquals("bar", resolved.getString("foo.bar"))
}
We do not intend to extend the functionality of "Typesafe Config" further. See https://github.com/lightbend/config#maintained-by