mirror of
https://github.com/lightbend/config.git
synced 2025-01-15 14:50:23 +08:00
Merge pull request #298 from fpringvaldsen/task/improve-indentation
Improve indentation
This commit is contained in:
commit
ea78c17381
@ -6,4 +6,9 @@ final class ConfigNodeArray extends ConfigNodeComplexValue {
|
||||
ConfigNodeArray(Collection<AbstractConfigNode> children) {
|
||||
super(children);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConfigNodeArray newNode(Collection<AbstractConfigNode> nodes) {
|
||||
return new ConfigNodeArray(nodes);
|
||||
}
|
||||
}
|
||||
|
@ -24,4 +24,29 @@ abstract class ConfigNodeComplexValue extends AbstractConfigNodeValue {
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
protected ConfigNodeComplexValue indentText(AbstractConfigNode indentation) {
|
||||
ArrayList<AbstractConfigNode> childrenCopy = new ArrayList<AbstractConfigNode>(children);
|
||||
for (int i = 0; i < childrenCopy.size(); i++) {
|
||||
AbstractConfigNode child = childrenCopy.get(i);
|
||||
if (child instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isNewline(((ConfigNodeSingleToken) child).token())) {
|
||||
childrenCopy.add(i + 1, indentation);
|
||||
i++;
|
||||
} else if (child instanceof ConfigNodeField) {
|
||||
AbstractConfigNode value = ((ConfigNodeField) child).value();
|
||||
if (value instanceof ConfigNodeComplexValue) {
|
||||
childrenCopy.set(i, ((ConfigNodeField) child).replaceValue(((ConfigNodeComplexValue) value).indentText(indentation)));
|
||||
}
|
||||
} else if (child instanceof ConfigNodeComplexValue) {
|
||||
childrenCopy.set(i, ((ConfigNodeComplexValue) child).indentText(indentation));
|
||||
}
|
||||
}
|
||||
return newNode(childrenCopy);
|
||||
}
|
||||
|
||||
// This method will just call into the object's constructor, but it's needed
|
||||
// for use in the indentText() method so we can avoid a gross if/else statement
|
||||
// checking the type of this
|
||||
abstract ConfigNodeComplexValue newNode(Collection<AbstractConfigNode> nodes);
|
||||
}
|
||||
|
@ -6,4 +6,9 @@ final class ConfigNodeConcatenation extends ConfigNodeComplexValue {
|
||||
ConfigNodeConcatenation(Collection<AbstractConfigNode> children) {
|
||||
super(children);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConfigNodeConcatenation newNode(Collection<AbstractConfigNode> nodes) {
|
||||
return new ConfigNodeConcatenation(nodes);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,30 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
final class ConfigNodeInclude extends ConfigNodeComplexValue {
|
||||
final class ConfigNodeInclude extends AbstractConfigNode {
|
||||
final private ArrayList<AbstractConfigNode> children;
|
||||
final private ConfigIncludeKind kind;
|
||||
|
||||
ConfigNodeInclude(Collection<AbstractConfigNode> children, ConfigIncludeKind kind) {
|
||||
super(children);
|
||||
this.children = new ArrayList<AbstractConfigNode>(children);
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
final public Collection<AbstractConfigNode> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Token> tokens() {
|
||||
ArrayList<Token> tokens = new ArrayList();
|
||||
for (AbstractConfigNode child : children) {
|
||||
tokens.addAll(child.tokens());
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
protected ConfigIncludeKind kind() {
|
||||
return kind;
|
||||
}
|
||||
|
@ -10,6 +10,11 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
||||
super(children);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConfigNodeObject newNode(Collection<AbstractConfigNode> nodes) {
|
||||
return new ConfigNodeObject(nodes);
|
||||
}
|
||||
|
||||
public boolean hasValue(Path desiredPath) {
|
||||
for (AbstractConfigNode node : children) {
|
||||
if (node instanceof ConfigNodeField) {
|
||||
@ -69,7 +74,15 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
||||
}
|
||||
} else if (key.equals(desiredPath)) {
|
||||
seenNonMatching = true;
|
||||
childrenCopy.set(i, node.replaceValue(value));
|
||||
AbstractConfigNodeValue indentedValue;
|
||||
AbstractConfigNode before = i - 1 > 0 ? childrenCopy.get(i - 1) : null;
|
||||
if (value instanceof ConfigNodeComplexValue &&
|
||||
before instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isIgnoredWhitespace(((ConfigNodeSingleToken) before).token()))
|
||||
indentedValue = ((ConfigNodeComplexValue) value).indentText(before);
|
||||
else
|
||||
indentedValue = value;
|
||||
childrenCopy.set(i, node.replaceValue(indentedValue));
|
||||
valueCopy = null;
|
||||
} else if (desiredPath.startsWith(key)) {
|
||||
seenNonMatching = true;
|
||||
@ -105,9 +118,65 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
||||
return node;
|
||||
}
|
||||
|
||||
private Collection<AbstractConfigNode> indentation() {
|
||||
boolean seenNewLine = false;
|
||||
ArrayList<AbstractConfigNode> indentation = new ArrayList<AbstractConfigNode>();
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
if (!seenNewLine) {
|
||||
if (children.get(i) instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isNewline(((ConfigNodeSingleToken) children.get(i)).token())) {
|
||||
seenNewLine = true;
|
||||
indentation.add(new ConfigNodeSingleToken(Tokens.newLine(null)));
|
||||
}
|
||||
} else {
|
||||
if (children.get(i) instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isIgnoredWhitespace(((ConfigNodeSingleToken) children.get(i)).token()) &&
|
||||
i + 1 < children.size() && (children.get(i+1) instanceof ConfigNodeField ||
|
||||
children.get(i+1) instanceof ConfigNodeInclude)) {
|
||||
// Return the indentation of the first setting on its own line
|
||||
indentation.add(children.get(i));
|
||||
return indentation;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The object has no curly braces and is at the root level, so don't indent
|
||||
return indentation;
|
||||
}
|
||||
|
||||
protected ConfigNodeObject addValueOnPath(ConfigNodePath desiredPath, AbstractConfigNodeValue value, ConfigSyntax flavor) {
|
||||
Path path = desiredPath.value();
|
||||
ArrayList<AbstractConfigNode> childrenCopy = new ArrayList<AbstractConfigNode>(super.children);
|
||||
ArrayList<AbstractConfigNode> indentation = new ArrayList<AbstractConfigNode>(indentation());
|
||||
|
||||
// If the value we're inserting is a complex value, we'll need to indent it for insertion
|
||||
AbstractConfigNodeValue indentedValue;
|
||||
if (value instanceof ConfigNodeComplexValue) {
|
||||
indentedValue = ((ConfigNodeComplexValue) value).indentText(indentation.get(indentation.size() - 1));
|
||||
} else {
|
||||
indentedValue = value;
|
||||
}
|
||||
boolean sameLine = !(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
|
||||
if (path.length() > 1) {
|
||||
for (int i = super.children.size() - 1; i >= 0; i--) {
|
||||
if (!(super.children.get(i) instanceof ConfigNodeField)) {
|
||||
@ -123,44 +192,79 @@ final class ConfigNodeObject extends ConfigNodeComplexValue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, construct the new setting
|
||||
boolean startsWithBrace = super.children.get(0) instanceof ConfigNodeSingleToken &&
|
||||
((ConfigNodeSingleToken) super.children.get(0)).token() == Tokens.OPEN_CURLY;
|
||||
ArrayList<AbstractConfigNode> newNodes = new ArrayList<AbstractConfigNode>();
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.newLine(null)));
|
||||
newNodes.addAll(indentation);
|
||||
newNodes.add(desiredPath.first());
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.newIgnoredWhitespace(null, " ")));
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.COLON));
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.newIgnoredWhitespace(null, " ")));
|
||||
|
||||
if (path.length() == 1) {
|
||||
newNodes.add(value);
|
||||
newNodes.add(indentedValue);
|
||||
} else {
|
||||
// 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, " ")));
|
||||
newObjectNodes.add(new ConfigNodeSingleToken(Tokens.CLOSE_CURLY));
|
||||
ConfigNodeObject newObject = new ConfigNodeObject(newObjectNodes);
|
||||
newNodes.add(newObject.addValueOnPath(desiredPath.subPath(1), value, flavor));
|
||||
newNodes.add(newObject.addValueOnPath(desiredPath.subPath(1), indentedValue, flavor));
|
||||
}
|
||||
newNodes.add(new ConfigNodeSingleToken(Tokens.newLine(null)));
|
||||
|
||||
// Combine these two cases so that we only have to iterate once
|
||||
if (flavor == ConfigSyntax.JSON || startsWithBrace) {
|
||||
if (flavor == ConfigSyntax.JSON || startsWithBrace || sameLine) {
|
||||
for (int i = childrenCopy.size() - 1; i >= 0; i--) {
|
||||
|
||||
// Valid JSON requires all key-value pairs except the last one to be succeeded by a comma,
|
||||
// so we'll need to add a comma when adding a value
|
||||
if (flavor == ConfigSyntax.JSON && childrenCopy.get(i) instanceof ConfigNodeField) {
|
||||
// If we are in JSON or are adding a setting on the same line, we need to add a comma to the
|
||||
// last setting
|
||||
if ((flavor == ConfigSyntax.JSON || sameLine) && childrenCopy.get(i) instanceof ConfigNodeField) {
|
||||
if (i+1 >= childrenCopy.size() ||
|
||||
!(childrenCopy.get(i+1) instanceof ConfigNodeSingleToken
|
||||
&& ((ConfigNodeSingleToken) childrenCopy.get(i+1)).token() == Tokens.COMMA))
|
||||
childrenCopy.add(i+1, new ConfigNodeSingleToken(Tokens.COMMA));
|
||||
break;
|
||||
}
|
||||
|
||||
// Add the value into the copy of the children map, keeping any whitespace/newlines
|
||||
// before the close curly brace
|
||||
if (startsWithBrace && childrenCopy.get(i) instanceof ConfigNodeSingleToken &&
|
||||
((ConfigNodeSingleToken) childrenCopy.get(i)).token == Tokens.CLOSE_CURLY) {
|
||||
childrenCopy.add(i, new ConfigNodeField(newNodes));
|
||||
AbstractConfigNode previous = childrenCopy.get(i - 1);
|
||||
if (previous instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isNewline(((ConfigNodeSingleToken) previous).token())) {
|
||||
childrenCopy.add(i - 1, new ConfigNodeField(newNodes));
|
||||
i--;
|
||||
} else if (previous instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isIgnoredWhitespace(((ConfigNodeSingleToken) previous).token())) {
|
||||
AbstractConfigNode beforePrevious = childrenCopy.get(i - 2);
|
||||
if (sameLine) {
|
||||
childrenCopy.add(i - 1, new ConfigNodeField(newNodes));
|
||||
i--;
|
||||
}
|
||||
else if (beforePrevious instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isNewline(((ConfigNodeSingleToken) beforePrevious).token())) {
|
||||
childrenCopy.add(i - 2, new ConfigNodeField(newNodes));
|
||||
i -= 2;
|
||||
} else {
|
||||
childrenCopy.add(i, new ConfigNodeField(newNodes));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
childrenCopy.add(i, new ConfigNodeField(newNodes));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!startsWithBrace) {
|
||||
childrenCopy.add(new ConfigNodeField(newNodes));
|
||||
if (childrenCopy.get(childrenCopy.size() - 1) instanceof ConfigNodeSingleToken &&
|
||||
Tokens.isNewline(((ConfigNodeSingleToken) childrenCopy.get(childrenCopy.size() - 1)).token()))
|
||||
childrenCopy.add(childrenCopy.size() - 1, new ConfigNodeField(newNodes));
|
||||
else
|
||||
childrenCopy.add(new ConfigNodeField(newNodes));
|
||||
}
|
||||
return new ConfigNodeObject(childrenCopy);
|
||||
}
|
||||
|
@ -15,6 +15,11 @@ final class ConfigNodeRoot extends ConfigNodeComplexValue {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConfigNodeRoot newNode(Collection<AbstractConfigNode> nodes) {
|
||||
throw new ConfigException.BugOrBroken("Tried to indent the root object");
|
||||
}
|
||||
|
||||
protected ConfigNodeComplexValue value() {
|
||||
for (AbstractConfigNode node : children) {
|
||||
if (node instanceof ConfigNodeComplexValue) {
|
||||
|
@ -270,7 +270,6 @@ final class ConfigParser {
|
||||
valueNode = ((ConfigNodeField) node).value();
|
||||
|
||||
// comments from the key token go to the value token
|
||||
//newValue = parseValue(valueToken.prepend(keyToken.comments));
|
||||
newValue = parseValue(valueNode, comments);
|
||||
|
||||
if (((ConfigNodeField) node).separator() == Tokens.PLUS_EQUALS) {
|
||||
|
@ -148,14 +148,14 @@ class ConfigDocumentTest extends TestUtils {
|
||||
|
||||
origText = "{a.b.c: d}"
|
||||
configDoc = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("{\na : 2\n}", configDoc.setValue("a", "2").render())
|
||||
assertEquals("{ a : 2}", configDoc.setValue("a", "2").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentSetNewValueBraceRoot {
|
||||
val origText = "{\n\t\"a\":\"b\",\n\t\"c\":\"d\"\n}"
|
||||
val finalTextConf = "{\n\t\"a\":\"b\",\n\t\"c\":\"d\"\n\n\"e\" : \"f\"\n}"
|
||||
val finalTextJson = "{\n\t\"a\":\"b\",\n\t\"c\":\"d\",\n\n\"e\" : \"f\"\n}"
|
||||
val finalTextConf = "{\n\t\"a\":\"b\",\n\t\"c\":\"d\"\n\t\"e\" : \"f\"\n}"
|
||||
val finalTextJson = "{\n\t\"a\":\"b\",\n\t\"c\":\"d\",\n\t\"e\" : \"f\"\n}"
|
||||
configDocumentReplaceConfTest(origText, finalTextConf, "\"f\"", "\"e\"")
|
||||
configDocumentReplaceJsonTest(origText, finalTextJson, "\"f\"", "\"e\"")
|
||||
}
|
||||
@ -163,21 +163,21 @@ class ConfigDocumentTest extends TestUtils {
|
||||
@Test
|
||||
def configDocumentSetNewValueNoBraces {
|
||||
val origText = "\"a\":\"b\",\n\"c\":\"d\"\n"
|
||||
val finalText = "\"a\":\"b\",\n\"c\":\"d\"\n\n\"e\" : \"f\"\n"
|
||||
val finalText = "\"a\":\"b\",\n\"c\":\"d\"\n\"e\" : \"f\"\n"
|
||||
configDocumentReplaceConfTest(origText, finalText, "\"f\"", "\"e\"")
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentSetNewValueMultiLevelConf {
|
||||
val origText = "a:b\nc:d"
|
||||
val finalText = "a:b\nc:d\ne : {\nf : {\ng : 12\n}\n}\n"
|
||||
val finalText = "a:b\nc:d\ne : { f : { g : 12 } }"
|
||||
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\" : {\n\"f\" : {\n\"g\" : 12\n}\n}\n}"
|
||||
val finalText = "{\"a\":\"b\",\n\"c\":\"d\",\n\"e\" : { \"f\" : { \"g\" : 12 } }}"
|
||||
configDocumentReplaceJsonTest(origText, finalText, "12", "e.f.g")
|
||||
}
|
||||
|
||||
@ -325,4 +325,122 @@ class ConfigDocumentTest extends TestUtils {
|
||||
assertEquals(configDocumentFile.render(), configDocument.render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationSingleLineObject {
|
||||
// Proper insertion for single-line objects
|
||||
var origText = "a { b: c }"
|
||||
var configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a { b: c, d : e }", configDocument.setValue("a.d", "e").render())
|
||||
|
||||
origText = "a { b: c }, d: e"
|
||||
configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a { b: c }, d: e, f : g", configDocument.setValue("f", "g").render())
|
||||
|
||||
origText = "a { b: c }, d: e,"
|
||||
configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a { b: c }, d: e, f : g", configDocument.setValue("f", "g").render())
|
||||
|
||||
assertEquals("a { b: c }, d: e, f : { g : { h : i } }", configDocument.setValue("f.g.h", "i").render())
|
||||
|
||||
origText = "{a { b: c }, d: e}"
|
||||
configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("{a { b: c }, d: e, f : g}", configDocument.setValue("f", "g").render())
|
||||
|
||||
assertEquals("{a { b: c }, d: e, f : { g : { h : i } }}", configDocument.setValue("f.g.h", "i").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationMultiLineObject {
|
||||
var origText = "a {\n b: c\n}"
|
||||
var configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a {\n b: c\n e : f\n}", configDocument.setValue("a.e", "f").render())
|
||||
|
||||
assertEquals("a {\n b: c\n d : { e : { f : g } }\n}", configDocument.setValue("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.setValue("d", "e").render())
|
||||
|
||||
assertEquals("a {\n b: c\n}\nd : { e : { f : g } }\n", configDocument.setValue("d.e.f", "g").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationNested {
|
||||
var origText = "a { b { c { d: e } } }"
|
||||
var configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a { b { c { d: e, f : g } } }", configDocument.setValue("a.b.c.f", "g").render())
|
||||
|
||||
origText = "a {\n b {\n c {\n d: e\n }\n }\n}"
|
||||
configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a {\n b {\n c {\n d: e\n f : g\n }\n }\n}", configDocument.setValue("a.b.c.f", "g").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationEmptyObject {
|
||||
var origText = "a { }"
|
||||
var configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a { b : c }", configDocument.setValue("a.b", "c").render())
|
||||
|
||||
origText = "a {\n b {\n }\n}"
|
||||
configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a {\n b {\n c : d\n }\n}", configDocument.setValue("a.b.c", "d").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationMultiLineValue {
|
||||
val origText = "a {\n b {\n c {\n d: e\n }\n }\n}"
|
||||
val configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a {\n b {\n c {\n d: e\n f : {\n g: h\n i: j\n k: {\n l: m\n }\n }\n }\n }\n}",
|
||||
configDocument.setValue("a.b.c.f", "{\n g: h\n i: j\n k: {\n l: m\n }\n}").render())
|
||||
|
||||
assertEquals("a {\n b {\n c {\n d: e\n f : 12 13 [1,\n 2,\n 3,\n {\n a:b\n }]\n }\n }\n}",
|
||||
configDocument.setValue("a.b.c.f", "12 13 [1,\n2,\n3,\n{\n a:b\n}]").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationMultiLineValueSingleLineObject {
|
||||
// Weird indentation occurs when adding a multi-line value to a single-line object
|
||||
val origText = "a { b { } }"
|
||||
val configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
assertEquals("a { b { c : {\n c:d\n } } }", configDocument.setValue("a.b.c", "{\n c:d\n}").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationSingleLineObjectContainingMultiLineValue {
|
||||
val origText = "a { b {\n c: d\n} }"
|
||||
val configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
|
||||
assertEquals("a { b {\n c: d\n}, e : f }", configDocument.setValue("a.e", "f").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationReplacingWithMultiLineValue {
|
||||
var origText = "a {\n b {\n c : 22\n }\n}"
|
||||
var configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
|
||||
assertEquals("a {\n b {\n c : {\n d:e\n }\n }\n}", configDocument.setValue("a.b.c", "{\n d:e\n}").render())
|
||||
|
||||
origText = "a {\n b {\n f : 10\n c : 22\n }\n}"
|
||||
configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
|
||||
assertEquals("a {\n b {\n f : 10\n c : {\n d:e\n }\n }\n}", configDocument.setValue("a.b.c", "{\n d:e\n}").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationValueWithIncludeTest {
|
||||
val origText = "a {\n b {\n c : 22\n }\n}"
|
||||
val configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
|
||||
assertEquals("a {\n b {\n c : 22\n d : {\n include \"foo\"\n e:f\n }\n }\n}",
|
||||
configDocument.setValue("a.b.d", "{\n include \"foo\"\n e:f\n}").render())
|
||||
}
|
||||
|
||||
@Test
|
||||
def configDocumentIndentationBadedOnIncludeNode {
|
||||
val origText = "a : b\n include \"foo\"\n"
|
||||
val configDocument = ConfigDocumentFactory.parseString(origText)
|
||||
|
||||
assertEquals("a : b\n include \"foo\"\n c : d\n", configDocument.setValue("c", "d").render())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ class ConfigNodeTest extends TestUtils {
|
||||
val node = configNodeObject(List(nodeKeyValuePair(configNodeKey("bar"), nodeInt(15))))
|
||||
assertEquals("bar : 15", node.render())
|
||||
val newNode = node.setValueOnPath("foo", value)
|
||||
val finalText = "bar : 15\nfoo : " + value.render() + "\n"
|
||||
val finalText = "bar : 15, foo : " + value.render()
|
||||
assertEquals(finalText, newNode.render())
|
||||
}
|
||||
|
||||
@ -195,24 +195,24 @@ class ConfigNodeTest extends TestUtils {
|
||||
// Test that all features of node replacement in a map work in a complex map containing nested maps
|
||||
val origText = "foo : bar\nbaz : {\n\t\"abc.def\" : 123\n\t//This is a comment about the below setting\n\n\tabc : {\n\t\t" +
|
||||
"def : \"this is a string\"\n\t\tghi : ${\"a.b\"}\n\t}\n}\nbaz.abc.ghi : 52\nbaz.abc.ghi : 53\n}"
|
||||
val lowestLevelMap = configNodeObject(List(nodeOpenBrace, nodeLine(6),
|
||||
nodeKeyValuePair(nodeWhitespace("\t\t"), configNodeKey("def"), configNodeSimpleValue(tokenString("this is a string")), nodeLine(7)),
|
||||
nodeKeyValuePair(nodeWhitespace("\t\t"), configNodeKey("ghi"), configNodeSimpleValue(tokenKeySubstitution("a.b")), nodeLine(8)),
|
||||
val lowestLevelMap = configNodeObject(List(nodeOpenBrace, nodeLine(6), nodeWhitespace("\t\t"),
|
||||
nodeKeyValuePair(configNodeKey("def"), configNodeSimpleValue(tokenString("this is a string"))), nodeLine(7),
|
||||
nodeWhitespace("\t\t"), nodeKeyValuePair(configNodeKey("ghi"), configNodeSimpleValue(tokenKeySubstitution("a.b"))), nodeLine(8),
|
||||
nodeWhitespace("\t"), nodeCloseBrace))
|
||||
val higherLevelMap = configNodeObject(List(nodeOpenBrace, nodeLine(2),
|
||||
nodeKeyValuePair(nodeWhitespace("\t"), configNodeKey("\"abc.def\""), configNodeSimpleValue(tokenInt(123)), nodeLine(3)),
|
||||
nodeWhitespace("\t"), nodeKeyValuePair(configNodeKey("\"abc.def\""), configNodeSimpleValue(tokenInt(123))), nodeLine(3),
|
||||
nodeWhitespace("\t"), configNodeBasic(tokenCommentDoubleSlash("This is a comment about the below setting")),
|
||||
nodeLine(4), nodeLine(5),
|
||||
nodeKeyValuePair(nodeWhitespace("\t"), configNodeKey("abc"), lowestLevelMap, nodeLine(9)), nodeWhitespace(""),
|
||||
nodeWhitespace("\t"), nodeKeyValuePair(configNodeKey("abc"), lowestLevelMap), nodeLine(9), nodeWhitespace(""),
|
||||
nodeCloseBrace))
|
||||
val origNode = configNodeObject(List(nodeKeyValuePair(configNodeKey("foo"), configNodeSimpleValue(tokenUnquoted("bar")), nodeLine(1)),
|
||||
nodeKeyValuePair(configNodeKey("baz"), higherLevelMap, nodeLine(10)),
|
||||
nodeKeyValuePair(configNodeKey("baz.abc.ghi"), configNodeSimpleValue(tokenInt(52)), nodeLine(11)),
|
||||
nodeKeyValuePair(configNodeKey("baz.abc.ghi"), configNodeSimpleValue(tokenInt(53)), nodeLine(12)),
|
||||
nodeKeyValuePair(configNodeKey("baz"), higherLevelMap), nodeLine(10),
|
||||
nodeKeyValuePair(configNodeKey("baz.abc.ghi"), configNodeSimpleValue(tokenInt(52))), nodeLine(11),
|
||||
nodeKeyValuePair(configNodeKey("baz.abc.ghi"), configNodeSimpleValue(tokenInt(53))), nodeLine(12),
|
||||
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\n\"this.does.not.exist@@@+$#\" : {\nend : doesnotexist\n}\n}\n}\nbaz.abc.ghi : randomunquotedString\n}"
|
||||
"def : false\n\t\t\n\t\t\"this.does.not.exist@@@+$#\" : { end : doesnotexist }\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