Skip to content

Commit f2c53ee

Browse files
committed
Validator: tighten table and key semantics
1 parent e75cce3 commit f2c53ee

File tree

1 file changed

+25
-3
lines changed

1 file changed

+25
-3
lines changed

src/Tomlyn/Syntax/SyntaxValidator.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ private bool KeyNameToObjectPath(KeySyntax key, ObjectKind kind, bool fromDotted
221221
}
222222

223223
var name = GetStringFromBasic(key.Key!);
224-
if (string.IsNullOrWhiteSpace(name)) return false;
224+
if (name is null) return false;
225225

226226
_currentPath.Add(name!);
227227

@@ -230,7 +230,7 @@ private bool KeyNameToObjectPath(KeySyntax key, ObjectKind kind, bool fromDotted
230230
{
231231
AddObjectPath(key, kind, true, fromDottedKeys);
232232
var dotItem = GetStringFromBasic(items.GetChild(i)!.Key!)!;
233-
if (string.IsNullOrWhiteSpace(dotItem)) return false;
233+
if (dotItem is null) return false;
234234
_currentPath.Add(dotItem);
235235
}
236236

@@ -249,6 +249,18 @@ private ObjectPathValue AddObjectPath(SyntaxNode node, ObjectKind kind, bool isI
249249

250250
if (_maps.TryGetValue(currentPath, out var existingValue))
251251
{
252+
// TOML 1.1: if a super-table was created implicitly by a dotted table header (e.g. `[a.b]`),
253+
// defining it later explicitly (`[a]`) is invalid (toml-test: super-twice.toml, append-with-dotted-keys-04.toml).
254+
if (existingValue.Kind == ObjectKind.Table &&
255+
existingValue.IsImplicit &&
256+
!existingValue.FromDottedKeys &&
257+
kind == ObjectKind.Table &&
258+
!isImplicit)
259+
{
260+
_diagnostics.Error(node.Span, $"The table `{currentPath}` was implicitly created by a dotted table header and cannot be defined explicitly.");
261+
return existingValue;
262+
}
263+
252264
// The following tests are the trickiest to get right with the spec, as the behavior
253265
// of TOML Table/TableArray with implicit/non implicit and dotted keys is quite complicated.
254266

@@ -273,6 +285,16 @@ private ObjectPathValue AddObjectPath(SyntaxNode node, ObjectKind kind, bool isI
273285
{
274286
_currentPath.Add(existingValue.ArrayIndex);
275287
}
288+
else if (existingValue.IsImplicit && !isImplicit)
289+
{
290+
// Upgrade an implicit table created by dotted keys to an explicit table so further redefinitions are rejected.
291+
var upgraded = new ObjectPathValue(node, existingValue.Kind, isImplicit: false, existingValue.FromDottedKeys)
292+
{
293+
ArrayIndex = existingValue.ArrayIndex,
294+
};
295+
_maps[currentPath] = upgraded;
296+
existingValue = upgraded;
297+
}
276298
}
277299
else
278300
{
@@ -489,4 +511,4 @@ private enum KeySource
489511
KeyValue
490512
}
491513
}
492-
}
514+
}

0 commit comments

Comments
 (0)