mirror of
https://github.com/lightbend/config.git
synced 2025-01-28 21:20:07 +08:00
Fix single-line config bug
Previously, there was a bug wherein building out a config starting from an empty ConfigDocument would cause the entire config to exist on a single line. Fix this bug by modifying the addition of new maps along a path to add multi-line maps instead of single-line maps if the object is an empty root or if the object being added to is a multi-line map.
This commit is contained in:
parent
d7d0a51776
commit
398406378d
@ -121,6 +121,9 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
||||
private Collection<AbstractConfigNode> indentation() {
|
||||
boolean seenNewLine = false;
|
||||
ArrayList<AbstractConfigNode> indentation = new ArrayList<AbstractConfigNode>();
|
||||
if (children.isEmpty()) {
|
||||
return indentation;
|
||||
}
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
if (!seenNewLine) {
|
||||
if (children.get(i) instanceof ConfigNodeSingleToken &&
|
||||
@ -141,19 +144,18 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
||||
}
|
||||
if (indentation.isEmpty()) {
|
||||
indentation.add(new ConfigNodeSingleToken(Tokens.newIgnoredWhitespace(null, " ")));
|
||||
return indentation;
|
||||
} else {
|
||||
// Calculate the indentation of the ending curly-brace to get the indentation of the root object
|
||||
AbstractConfigNode last = children.get(children.size() - 1);
|
||||
if (last instanceof ConfigNodeSingleToken && ((ConfigNodeSingleToken) last).token() == Tokens.CLOSE_CURLY) {
|
||||
AbstractConfigNode beforeLast = children.get(children.size() - 2);
|
||||
String indent = "";
|
||||
if (beforeLast instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isIgnoredWhitespace(((ConfigNodeSingleToken) beforeLast).token())) {
|
||||
String indent = ((ConfigNodeSingleToken) beforeLast).token().tokenText();
|
||||
indent += " ";
|
||||
indentation.add(new ConfigNodeSingleToken(Tokens.newIgnoredWhitespace(null, indent)));
|
||||
return indentation;
|
||||
}
|
||||
Tokens.isIgnoredWhitespace(((ConfigNodeSingleToken) beforeLast).token()))
|
||||
indent = ((ConfigNodeSingleToken) beforeLast).token().tokenText();
|
||||
indent += " ";
|
||||
indentation.add(new ConfigNodeSingleToken(Tokens.newIgnoredWhitespace(null, indent)));
|
||||
return indentation;
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,7 +175,7 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
||||
} else {
|
||||
indentedValue = value;
|
||||
}
|
||||
boolean sameLine = !(indentation.get(0) instanceof ConfigNodeSingleToken &&
|
||||
boolean sameLine = !(indentation.size() > 0 && indentation.get(0) instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isNewline(((ConfigNodeSingleToken) indentation.get(0)).token()));
|
||||
|
||||
// If the path is of length greater than one, see if the value needs to be added further down
|
||||
@ -209,7 +211,10 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
||||
// If the path is of length greater than one add the required new objects along the path
|
||||
ArrayList<AbstractConfigNode> newObjectNodes = new ArrayList<AbstractConfigNode>();
|
||||
newObjectNodes.add(new ConfigNodeSingleToken(Tokens.OPEN_CURLY));
|
||||
newObjectNodes.add(new ConfigNodeSingleToken(Tokens.newIgnoredWhitespace(null, " ")));
|
||||
if (indentation.isEmpty()) {
|
||||
newObjectNodes.add(new ConfigNodeSingleToken(Tokens.newLine(null)));
|
||||
}
|
||||
newObjectNodes.addAll(indentation);
|
||||
newObjectNodes.add(new ConfigNodeSingleToken(Tokens.CLOSE_CURLY));
|
||||
ConfigNodeObject newObject = new ConfigNodeObject(newObjectNodes);
|
||||
newNodes.add(newObject.addValueOnPath(desiredPath.subPath(1), indentedValue, flavor));
|
||||
|
@ -171,14 +171,14 @@ class ConfigDocumentTest extends TestUtils {
|
||||
@Test
|
||||
def configDocumentSetNewValueMultiLevelConf {
|
||||
val origText = "a:b\nc:d"
|
||||
val finalText = "a:b\nc:d\ne : { f : { g : 12 } }"
|
||||
val finalText = "a:b\nc:d\ne : {\n f : {\n g : 12\n }\n}"
|
||||
configDocumentReplaceConfTest(origText, finalText, "12", "e.f.g")
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentSetNewValueMultiLevelJson {
|
||||
val origText = "{\"a\":\"b\",\n\"c\":\"d\"}"
|
||||
val finalText = "{\"a\":\"b\",\n\"c\":\"d\",\n\"e\" : { \"f\" : { \"g\" : 12 } }}"
|
||||
val finalText = "{\"a\":\"b\",\n\"c\":\"d\",\n \"e\" : {\n \"f\" : {\n \"g\" : 12\n }\n }}"
|
||||
configDocumentReplaceJsonTest(origText, finalText, "12", "e.f.g")
|
||||
}
|
||||
|
||||
@ -342,13 +342,13 @@ class ConfigDocumentTest extends TestUtils {
|
||||
var configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a {\n b: c\n e : f\n}", configDocument.withValueText("a.e", "f").render())
|
||||
|
||||
assertEquals("a {\n b: c\n d : { e : { f : g } }\n}", configDocument.withValueText("a.d.e.f", "g").render())
|
||||
assertEquals("a {\n b: c\n d : {\n e : {\n f : g\n }\n }\n}", configDocument.withValueText("a.d.e.f", "g").render())
|
||||
|
||||
origText = "a {\n b: c\n}\n"
|
||||
configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a {\n b: c\n}\nd : e\n", configDocument.withValueText("d", "e").render())
|
||||
|
||||
assertEquals("a {\n b: c\n}\nd : { e : { f : g } }\n", configDocument.withValueText("d.e.f", "g").render())
|
||||
assertEquals("a {\n b: c\n}\nd : {\n e : {\n f : g\n }\n}\n", configDocument.withValueText("d.e.f", "g").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -435,7 +435,7 @@ class ConfigDocumentTest extends TestUtils {
|
||||
val origText = ""
|
||||
val configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
|
||||
assertEquals(" a : 1", configDocument.withValueText("a", "1").render)
|
||||
assertEquals("a : 1", configDocument.withValueText("a", "1").render)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -447,7 +447,5 @@ class ConfigDocumentTest extends TestUtils {
|
||||
|
||||
assertEquals("{ a : {\n # hardcoded value\n \"a\" : 1,\n # hardcoded value\n \"b\" : 2\n } }",
|
||||
configDocument.withValue("a", configVal).render)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ class ConfigNodeTest extends TestUtils {
|
||||
nodeCloseBrace))
|
||||
assertEquals(origText, origNode.render())
|
||||
val finalText = "foo : bar\nbaz : {\n\t\"abc.def\" : true\n\t//This is a comment about the below setting\n\n\tabc : {\n\t\t" +
|
||||
"def : false\n\t\t\n\t\t\"this.does.not.exist@@@+$#\" : { end : doesnotexist }\n\t}\n}\n\nbaz.abc.ghi : randomunquotedString\n}"
|
||||
"def : false\n\t\t\n\t\t\"this.does.not.exist@@@+$#\" : {\n\t\t end : doesnotexist\n\t\t}\n\t}\n}\n\nbaz.abc.ghi : randomunquotedString\n}"
|
||||
|
||||
//Can replace settings in nested maps
|
||||
// Paths with quotes in the name are treated as a single Path, rather than multiple sub-paths
|
||||
|
Loading…
Reference in New Issue
Block a user