The general idea here is to permit future syntax extensions;
as a rule, new syntax can only be added by using one of these
characters that can't be a string.
Backtick ` in particular is in the current ECMAScript drafts
for multiline strings, so supporting multiline strings with
that would be a very natural thing to do.
The other characters added here (^, !, ?, @, *, &) are
more or less arbitrary. &, ! and * have special meaning
in YAML so might be natural ones to use for similar
purposes. ? would have some natural "let this be missing"
meaning, @ is often used in template-like things, and ^
could be used for some unforeseen need.
This is clearer about what the object represents and how it relates
to the Config. I didn't name it root() before because it might have
implied some relationship to ConfigRoot. But since ConfigRoot
is now gone, toObject() can have the nicer name root().
This was intended to make resolve() typesafe (only allowed on root objects).
However, in practice it was not safe because it was too easy to create a
root by merging a non-root object into a root object. To fix it, we'd
have to prohibit that (root objects can only merge with other roots).
But it seems simpler to just document that resolving on subtrees
will do the wrong thing, and hopefully it won't be an issue in practice.
Also add some tests and fix some correctness issues.
If we fall back to a value that has ignoresFallbacks()=true, then we need
to "catch" its ignoresFallbacks.
Don't create new RootConfig objects if the underlying has not changed.
Get rid of ConfigImpl.merge() utility, no longer useful.
Had previously fixed AbstractConfigObject.merge() in the same way. For this
patch, factor out the code from AbstractConfigObject and use it everywhere.
Add some tests for merges with substitutions involved.
Also write some docs for ConfigMergeable explaining the easy way
to do it wrong.
This separates ConfigObject, which is:
- a tree of maps
- that can contain ConfigValueType.NULL
from Config, which is:
- a one-level map from path to non-map values
- which never returns a ConfigValueType.NULL
Share implementation of this with the Properties parser;
it makes the Properties parser somewhat less efficient due
to creating the intermediate Path objects, but should not matter.
This was causing at least a couple bugs; in one test, a properties file
was being parsed with conf syntax; and includes suddenly could not
be missing if the parent file could not be missing.
The spec described parsing this as a 1-element path but
the implementation parsed it as 2 elements which is probably
a better behavior because it's less surprising. The simple
rule is now "only quoted periods are special".
The AbstractConfigObject.merge() method was wrong; it merged in the
wrong order, which produced incorrect results. But there was a test
verifying that the results were wrong! So it's OK right?
Anyway, fix the test, fix the code, be sure it's crystal clear in spec.