Skip to content

Commit

Permalink
toml: Allow dotted keys in inline tables, resolve #174
Browse files Browse the repository at this point in the history
  • Loading branch information
TheElectronWill committed May 21, 2024
1 parent 2ca3b8c commit 54a6841
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 20 deletions.
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/night-config-lib.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ project.afterEvaluate {

// Set project metadata for publishing
group = "com.electronwill.night-config"
version = "3.7.1"
version = "3.7.2"

// Publish the library as a Maven artifact.
publishing {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,10 @@ static <T extends CommentedConfig> T parseInline(CharacterInput input, TomlParse
if (keyFirst == '}') {
return config;// handles {} and {k1=v1,... ,}
}
String key = parseKey(input, keyFirst, parser);
char sep = Toml.readNonSpaceChar(input, false);
checkInvalidSeparator(sep, key, parser);
List<String> key = parseDottedKey(input, keyFirst, parser);

Object value = ValueParser.parse(input, parser, config);
Object previous = parser.getParsingMode().put(config.valueMap(), key, value);
Object previous = parser.getParsingMode().put(config, key, value);
checkDuplicateKey(key, previous, true);

char after = Toml.readNonSpaceChar(input, false);
Expand Down Expand Up @@ -90,13 +88,6 @@ private static void checkDuplicateKey(Object key, Object previousValue, boolean
}
}

private static void checkInvalidSeparator(char sep, String key, TomlParser parser) {
if (!Toml.isKeyValueSeparator(sep, parser.isLenientWithSeparators())) {
throw new ParsingException(
"Invalid separator '" + sep + "'after key \"" + key + "\" in some table.");
}
}

static CommentedConfig parseNormal(CommentedConfig parentConfig, CharacterInput input, TomlParser parser) {
return parseNormal(input, parser, parentConfig.createSubConfig());
}
Expand All @@ -108,7 +99,7 @@ static List<String> parseTableName(CharacterInput input, TomlParser parser, bool
if (firstChar == ']') {
throw new ParsingException("Tables names must not be empty.");
}
String key = parseKey(input, firstChar, parser);
String key = parseNonDottedKey(input, firstChar, parser);
list.add(key);

char separator = Toml.readNonSpaceChar(input, false);
Expand Down Expand Up @@ -138,11 +129,17 @@ static List<String> parseTableName(CharacterInput input, TomlParser parser, bool
}
}

/**
* Parses a key that can be dotted (e.g. {@code a.b.c}, quoted {@code "abc"} or bare {@code abc}).
* The next non-space character is also read, and an exception is thrown if it's not a key-value separator.
*
* @return the components of the key
*/
static List<String> parseDottedKey(CharacterInput input, char firstChar, TomlParser parser) {
List<String> list = parser.createList();
char first = firstChar;
while (true) {
String part = parseKey(input, first, parser);
String part = parseNonDottedKey(input, first, parser);
list.add(part);

char sep = Toml.readNonSpaceChar(input, false);
Expand All @@ -155,7 +152,7 @@ static List<String> parseDottedKey(CharacterInput input, char firstChar, TomlPar
}
}

static String parseKey(CharacterInput input, char firstChar, TomlParser parser) {
static String parseNonDottedKey(CharacterInput input, char firstChar, TomlParser parser) {
// Note that a key can't be multiline
// Empty keys are allowed if and only if they are quoted (with double or single quotes)
if (firstChar == '\"') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.electronwill.nightconfig.core.CommentedConfig;
import com.electronwill.nightconfig.core.Config;
import com.electronwill.nightconfig.core.Config.Entry;
import com.electronwill.nightconfig.core.ConfigFormat;
import com.electronwill.nightconfig.core.concurrent.StampedConfig;
import com.electronwill.nightconfig.core.concurrent.SynchronizedConfig;
Expand Down Expand Up @@ -142,10 +143,11 @@ private Config getSubTable(Config parentTable, List<String> path) {
}
Config currentConfig = parentTable;
for (String key : path) {
Object value = currentConfig.valueMap().get(key);
List<String> singleKey = Collections.singletonList(key);
Object value = currentConfig.get(singleKey);
if (value == null) {
Config sub = parentTable.createSubConfig();
currentConfig.valueMap().put(key, sub);
currentConfig.set(singleKey, sub);
currentConfig = sub;
} else if (value instanceof Config) {
currentConfig = (Config)value;
Expand All @@ -169,8 +171,8 @@ private Config getSubTable(Config parentTable, List<String> path) {
}

private void checkContainsOnlySubtables(Config table, List<String> path) {
for (Object value : table.valueMap().values()) {
if (!(value instanceof Config)) {
for (Entry entry : table.entrySet()) {
if (!(entry.getValue() instanceof Config)) {
throw new ParsingException("Table with path " + path + " has been declared twice.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Arrays;

import static org.junit.jupiter.api.Assertions.*;

Expand Down Expand Up @@ -306,4 +307,14 @@ private void testInlineTableArraySubtable2() {
+ " test = 'success'\n";
parseAndPrint(toml);
}
}

@Test
public void testInlineTables() {
String toml = "dotted_key_in_inline_table = { version.number = \"1.2.3\", \"a.b.c\" = \"normal key\" }";
CommentedConfig config = new TomlParser().parse(toml);
CommentedConfig sub = config.get("dotted_key_in_inline_table");
assertEquals(2, sub.size());
assertEquals("1.2.3", sub.get(Arrays.asList("version", "number")));
assertEquals("normal key", sub.get(Arrays.asList("a.b.c")));
}
}
2 changes: 2 additions & 0 deletions toml/test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ dotted.key = 12
dotted.sub.subsub.key = { a = "b", c = "d", d = 12, e = 3.14, f = true }# more comments
dotted.more_data = 'some string' # comments here!

dotted_key_in_inline_table = { version.number = "1.2.3", "a.b.c" = "normal key" }

# Numbers in different bases
hexa = 0xabcdef
hexa2 = 0x01234
Expand Down

0 comments on commit 54a6841

Please sign in to comment.