Skip to content

Commit

Permalink
fix!(Exception): Remove 'key' special member
Browse files Browse the repository at this point in the history
Key was simply an extension of 'path' and served an odd special case.
Instead fold it into path and only special case it for the one
Exception that need it.

BREAKING CHANGE: Remove a visible member ('key') from the exception types.
  • Loading branch information
Geod24 committed Sep 17, 2024
1 parent be14b9c commit 99f4f70
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 50 deletions.
56 changes: 22 additions & 34 deletions source/configy/Exceptions.d
Original file line number Diff line number Diff line change
Expand Up @@ -48,32 +48,19 @@ public abstract class ConfigException : Exception
/// Position at which the error happened
public Mark yamlPosition;

/// The path at which the key resides
/// The path in the configuration structure at which the error resides
public string path;

/// If non-empty, the key under 'path' which triggered the error
/// If empty, the key should be considered part of 'path'
public string key;

/// Constructor
public this (string path, string key, Mark position,
public this (string path, Mark position,
string file = __FILE__, size_t line = __LINE__)
@safe pure nothrow @nogc
{
super(null, file, line);
this.path = path;
this.key = key;
this.yamlPosition = position;
}

/// Ditto
public this (string path, Mark position,
string file = __FILE__, size_t line = __LINE__)
@safe pure nothrow @nogc
{
this(path, null, position, file, line);
}

/***************************************************************************
Overrides `Throwable.toString` and its sink overload
Expand Down Expand Up @@ -135,13 +122,10 @@ public abstract class ConfigException : Exception
if (useColors) sink(Reset);
sink("): ");

if (this.path.length || this.key.length)
if (this.path.length)
{
if (useColors) sink(Yellow);
sink(this.path);
if (this.path.length && this.key.length)
sink(".");
sink(this.key);
if (useColors) sink(Reset);
sink(": ");
}
Expand Down Expand Up @@ -188,14 +172,14 @@ package final class ConfigExceptionImpl : ConfigException
string file = __FILE__, size_t line = __LINE__)
@safe pure nothrow @nogc
{
this(msg, null, null, position, file, line);
this(msg, null, position, file, line);
}

public this (string msg, string path, string key, Mark position,
public this (string msg, string path, Mark position,
string file = __FILE__, size_t line = __LINE__)
@safe pure nothrow @nogc
{
super(path, key, position, file, line);
super(path, position, file, line);
this.msg = msg;
}

Expand All @@ -217,20 +201,20 @@ package final class TypeConfigException : ConfigException
public string expected;

/// Constructor
public this (Node node, string expected, string path, string key = null,
public this (Node node, string expected, string path,
string file = __FILE__, size_t line = __LINE__)
@safe nothrow
{
this(node.nodeTypeString(), expected, path, key, node.startMark(),
this(node.nodeTypeString(), expected, path, node.startMark(),
file, line);
}

/// Ditto
public this (string actual, string expected, string path, string key,
Mark position, string file = __FILE__, size_t line = __LINE__)
public this (string actual, string expected, string path, Mark position,
string file = __FILE__, size_t line = __LINE__)
@safe pure nothrow @nogc
{
super(path, key, position, file, line);
super(path, position, file, line);
this.actual = actual;
this.expected = expected;
}
Expand Down Expand Up @@ -267,7 +251,7 @@ package final class DurationTypeConfigException : ConfigException
public this (Node node, string path, string file = __FILE__, size_t line = __LINE__)
@safe nothrow
{
super(path, null, node.startMark(), file, line);
super(path, node.startMark(), file, line);
this.actual = node.nodeTypeString();
}

Expand All @@ -293,12 +277,16 @@ public class UnknownKeyConfigException : ConfigException
/// The list of valid field names
public immutable string[] fieldNames;

/// The erroring key
public string key;

/// Constructor
public this (string path, string key, immutable string[] fieldNames,
Mark position, string file = __FILE__, size_t line = __LINE__)
@safe pure nothrow @nogc
@safe pure nothrow
{
super(path, key, position, file, line);
super(path.addPath(key), position, file, line);
this.key = key;
this.fieldNames = fieldNames;
}

Expand Down Expand Up @@ -341,11 +329,11 @@ public class UnknownKeyConfigException : ConfigException
public class MissingKeyException : ConfigException
{
/// Constructor
public this (string path, string key, Mark position,
public this (string path, Mark position,
string file = __FILE__, size_t line = __LINE__)
@safe pure nothrow @nogc
{
super(path, key, position, file, line);
super(path, position, file, line);
}

/// Format the message with or without colors
Expand Down Expand Up @@ -389,14 +377,14 @@ public class ArrayLengthException : ConfigException

/// Constructor
public this (size_t actual, size_t expected,
string path, string key, Mark position,
string path, Mark position,
string file = __FILE__, size_t line = __LINE__)
@safe pure nothrow @nogc
{
assert(actual != expected);
this.actual = actual;
this.expected = expected;
super(path, key, position, file, line);
super(path, position, file, line);
}

/// Format the message with or without colors
Expand Down
26 changes: 10 additions & 16 deletions source/configy/Read.d
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,8 @@ private TLFR.Type parseMapping (alias TLFR)
FR.Name.paint(Cyan), path.paint(Cyan), FR.FieldName.paint(Cyan));

if (ctx.strict && FR.FieldName in node)
throw new ConfigExceptionImpl("'Key' field is specified twice", path, FR.FieldName, node.startMark());
throw new ConfigExceptionImpl("'Key' field is specified twice",
path.addPath(FR.FieldName), node.startMark());
return (*ptr).parseField!(FR)(path.addPath(FR.FieldName), default_, ctx)
.dbgWriteRet("Using value '%s' from fieldDefaults for field '%s'",
FR.FieldName.paint(Cyan));
Expand Down Expand Up @@ -612,7 +613,7 @@ private TLFR.Type parseMapping (alias TLFR)
return Node(aa).parseMapping!(FR)(npath, default_, ctx, null);
}
else
throw new MissingKeyException(path, FR.Name, node.startMark());
throw new MissingKeyException(path.addPath(FR.Name), node.startMark());
}

FR.Type convert (alias FR) ()
Expand Down Expand Up @@ -785,7 +786,7 @@ package FR.Type parseField (alias FR)
throw new TypeConfigException(
"sequence of " ~ pair.value.nodeTypeString(),
"sequence of mapping (array of objects)",
path, null, node.startMark());
path, node.startMark());

return pair.value.parseMapping!(StructFieldRef!E)(
path.addPath(pair.key.as!string),
Expand All @@ -803,7 +804,7 @@ package FR.Type parseField (alias FR)
{
if (res.length != k)
throw new ArrayLengthException(
res.length, k, path, null, node.startMark());
res.length, k, path, node.startMark());
return res[0 .. k];
}
else
Expand All @@ -830,18 +831,18 @@ package FR.Type parseField (alias FR)
}

/// Parse a node as a scalar
private T parseScalar (T) (Node node, string path, string key = null)
private T parseScalar (T) (Node node, lazy string path)
{
if (node.nodeID != NodeID.scalar)
throw new TypeConfigException(node, "a value of type " ~ T.stringof, path, key);
throw new TypeConfigException(node, "a value of type " ~ T.stringof, path);

try {
static if (is(T == enum))
return node.as!string.to!(T);
else
return node.as!(T);
} catch (Exception exc) {
throw new TypeConfigException(node, "a value of type " ~ T.stringof, path, key);
throw new TypeConfigException(node, "a value of type " ~ T.stringof, path);
}
}

Expand Down Expand Up @@ -1007,13 +1008,13 @@ private EnabledState isMappingEnabled (M) (Node node, string path, auto ref M de
"` conflicts with `disabled` field `" ~ DMT[0].FieldName ~ "`");

if (auto ptr = "enabled" in node)
return EnabledState(EnabledState.Field.Enabled, (*ptr).parseScalar!(bool)(path, "enabled"));
return EnabledState(EnabledState.Field.Enabled, (*ptr).parseScalar!(bool)(path.addPath("enabled")));
return EnabledState(EnabledState.Field.Enabled, __traits(getMember, default_, EMT[0].FieldName));
}
else static if (DMT.length)
{
if (auto ptr = "disabled" in node)
return EnabledState(EnabledState.Field.Disabled, (*ptr).parseScalar!(bool)(path, "disabled"));
return EnabledState(EnabledState.Field.Disabled, (*ptr).parseScalar!(bool)(path.addPath("disabled")));
return EnabledState(EnabledState.Field.Disabled, __traits(getMember, default_, DMT[0].FieldName));
}
else
Expand Down Expand Up @@ -1090,10 +1091,3 @@ unittest
static assert(!hasFieldWiseCtor!(StructFieldRef!PubKey));
static assert( hasStringCtor!PubKey);
}

/// Convenience function to extend a YAML path
private string addPath (string opath, string newPart) @safe pure
in(newPart.length)
do {
return opath.length ? format("%s.%s", opath, newPart) : newPart;
}
7 changes: 7 additions & 0 deletions source/configy/Utils.d
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ import std.format;
/// Type of sink used by the `toString`
package alias SinkType = void delegate (in char[]) @safe;

/// Convenience function to extend a path
package string addPath (string opath, string newPart) @safe pure nothrow
in(newPart.length)
do {
return opath.length ? (opath ~ "." ~ newPart) : newPart;
}

/*******************************************************************************
Debugging utility for config filler
Expand Down

0 comments on commit 99f4f70

Please sign in to comment.