mirror of
https://github.com/lightbend/config.git
synced 2025-02-24 02:00:46 +08:00
fix error message for type errors mid-path
If you looked up "a.b.c" and b is not an object, it said "a.b.c is a FOO and not an OBJECT" now it says "a.b is a FOO and not an OBJECT"
This commit is contained in:
parent
683e72cbbe
commit
06ed4d24e1
@ -57,7 +57,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
|
|||||||
* @param key
|
* @param key
|
||||||
* @return the unmodified raw value or null
|
* @return the unmodified raw value or null
|
||||||
*/
|
*/
|
||||||
protected final AbstractConfigValue peekAssumingResolved(String key, String originalPath) {
|
protected final AbstractConfigValue peekAssumingResolved(String key, Path originalPath) {
|
||||||
try {
|
try {
|
||||||
return attemptPeekWithPartialResolve(key);
|
return attemptPeekWithPartialResolve(key);
|
||||||
} catch (ConfigException.NotResolved e) {
|
} catch (ConfigException.NotResolved e) {
|
||||||
@ -138,7 +138,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ConfigException.NotResolved e) {
|
} catch (ConfigException.NotResolved e) {
|
||||||
throw ConfigImpl.improveNotResolved(path.render(), e);
|
throw ConfigImpl.improveNotResolved(path, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,9 +526,10 @@ public class ConfigImpl {
|
|||||||
// toplevel error message. the "original" exception may however have extra
|
// toplevel error message. the "original" exception may however have extra
|
||||||
// detail about what happened. call this if you have a better "what" than
|
// detail about what happened. call this if you have a better "what" than
|
||||||
// further down on the stack.
|
// further down on the stack.
|
||||||
static ConfigException.NotResolved improveNotResolved(String what,
|
static ConfigException.NotResolved improveNotResolved(Path what,
|
||||||
ConfigException.NotResolved original) {
|
ConfigException.NotResolved original) {
|
||||||
String newMessage = what + " has not been resolved, you need to call Config#resolve(),"
|
String newMessage = what.render()
|
||||||
|
+ " has not been resolved, you need to call Config#resolve(),"
|
||||||
+ " see API docs for Config#resolve()";
|
+ " see API docs for Config#resolve()";
|
||||||
if (newMessage.equals(original.getMessage()))
|
if (newMessage.equals(original.getMessage()))
|
||||||
return original;
|
return original;
|
||||||
|
@ -123,6 +123,23 @@ final class Path implements Serializable {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Path subPath(int firstIndex, int lastIndex) {
|
||||||
|
if (lastIndex < firstIndex)
|
||||||
|
throw new ConfigException.BugOrBroken("bad call to subPath");
|
||||||
|
|
||||||
|
Path from = subPath(firstIndex);
|
||||||
|
PathBuilder pb = new PathBuilder();
|
||||||
|
int count = lastIndex - firstIndex;
|
||||||
|
while (count > 0) {
|
||||||
|
count -= 1;
|
||||||
|
pb.appendKey(from.first());
|
||||||
|
from = from.remainder();
|
||||||
|
if (from == null)
|
||||||
|
throw new ConfigException.BugOrBroken("subPath lastIndex out of range " + lastIndex);
|
||||||
|
}
|
||||||
|
return pb.result();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (other instanceof Path) {
|
if (other instanceof Path) {
|
||||||
|
@ -72,7 +72,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
|||||||
try {
|
try {
|
||||||
peeked = object.peekPath(path);
|
peeked = object.peekPath(path);
|
||||||
} catch (ConfigException.NotResolved e) {
|
} catch (ConfigException.NotResolved e) {
|
||||||
throw ConfigImpl.improveNotResolved(pathExpression, e);
|
throw ConfigImpl.improveNotResolved(path, e);
|
||||||
}
|
}
|
||||||
return peeked != null && peeked.valueType() != ConfigValueType.NULL;
|
return peeked != null && peeked.valueType() != ConfigValueType.NULL;
|
||||||
}
|
}
|
||||||
@ -107,33 +107,27 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
static private AbstractConfigValue find(AbstractConfigObject self,
|
|
||||||
String pathExpression, ConfigValueType expected, String originalPath) {
|
|
||||||
Path path = Path.newPath(pathExpression);
|
|
||||||
return find(self, path, expected, originalPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
static private AbstractConfigValue findKey(AbstractConfigObject self, String key,
|
static private AbstractConfigValue findKey(AbstractConfigObject self, String key,
|
||||||
ConfigValueType expected, String originalPath) {
|
ConfigValueType expected, Path originalPath) {
|
||||||
AbstractConfigValue v = self.peekAssumingResolved(key, originalPath);
|
AbstractConfigValue v = self.peekAssumingResolved(key, originalPath);
|
||||||
if (v == null)
|
if (v == null)
|
||||||
throw new ConfigException.Missing(originalPath);
|
throw new ConfigException.Missing(originalPath.render());
|
||||||
|
|
||||||
if (expected != null)
|
if (expected != null)
|
||||||
v = DefaultTransformer.transform(v, expected);
|
v = DefaultTransformer.transform(v, expected);
|
||||||
|
|
||||||
if (v.valueType() == ConfigValueType.NULL)
|
if (v.valueType() == ConfigValueType.NULL)
|
||||||
throw new ConfigException.Null(v.origin(), originalPath,
|
throw new ConfigException.Null(v.origin(), originalPath.render(),
|
||||||
expected != null ? expected.name() : null);
|
expected != null ? expected.name() : null);
|
||||||
else if (expected != null && v.valueType() != expected)
|
else if (expected != null && v.valueType() != expected)
|
||||||
throw new ConfigException.WrongType(v.origin(), originalPath, expected.name(), v
|
throw new ConfigException.WrongType(v.origin(), originalPath.render(), expected.name(),
|
||||||
.valueType().name());
|
v.valueType().name());
|
||||||
else
|
else
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static private AbstractConfigValue find(AbstractConfigObject self, Path path,
|
static private AbstractConfigValue find(AbstractConfigObject self, Path path,
|
||||||
ConfigValueType expected, String originalPath) {
|
ConfigValueType expected, Path originalPath) {
|
||||||
try {
|
try {
|
||||||
String key = path.first();
|
String key = path.first();
|
||||||
Path next = path.remainder();
|
Path next = path.remainder();
|
||||||
@ -141,33 +135,38 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
|||||||
return findKey(self, key, expected, originalPath);
|
return findKey(self, key, expected, originalPath);
|
||||||
} else {
|
} else {
|
||||||
AbstractConfigObject o = (AbstractConfigObject) findKey(self, key,
|
AbstractConfigObject o = (AbstractConfigObject) findKey(self, key,
|
||||||
ConfigValueType.OBJECT, originalPath);
|
ConfigValueType.OBJECT,
|
||||||
|
originalPath.subPath(0, originalPath.length() - next.length()));
|
||||||
assert (o != null); // missing was supposed to throw
|
assert (o != null); // missing was supposed to throw
|
||||||
return find(o, next, expected, originalPath);
|
return find(o, next, expected, originalPath);
|
||||||
}
|
}
|
||||||
} catch (ConfigException.NotResolved e) {
|
} catch (ConfigException.NotResolved e) {
|
||||||
throw ConfigImpl.improveNotResolved(path.render(), e);
|
throw ConfigImpl.improveNotResolved(path, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractConfigValue find(String pathExpression, ConfigValueType expected,
|
AbstractConfigValue find(Path pathExpression, ConfigValueType expected, Path originalPath) {
|
||||||
String originalPath) {
|
|
||||||
return find(object, pathExpression, expected, originalPath);
|
return find(object, pathExpression, expected, originalPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AbstractConfigValue find(String pathExpression, ConfigValueType expected) {
|
||||||
|
Path path = Path.newPath(pathExpression);
|
||||||
|
return find(path, expected, path);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractConfigValue getValue(String path) {
|
public AbstractConfigValue getValue(String path) {
|
||||||
return find(path, null, path);
|
return find(path, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getBoolean(String path) {
|
public boolean getBoolean(String path) {
|
||||||
ConfigValue v = find(path, ConfigValueType.BOOLEAN, path);
|
ConfigValue v = find(path, ConfigValueType.BOOLEAN);
|
||||||
return (Boolean) v.unwrapped();
|
return (Boolean) v.unwrapped();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigNumber getConfigNumber(String path) {
|
private ConfigNumber getConfigNumber(String path) {
|
||||||
ConfigValue v = find(path, ConfigValueType.NUMBER, path);
|
ConfigValue v = find(path, ConfigValueType.NUMBER);
|
||||||
return (ConfigNumber) v;
|
return (ConfigNumber) v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,20 +193,19 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getString(String path) {
|
public String getString(String path) {
|
||||||
ConfigValue v = find(path, ConfigValueType.STRING, path);
|
ConfigValue v = find(path, ConfigValueType.STRING);
|
||||||
return (String) v.unwrapped();
|
return (String) v.unwrapped();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigList getList(String path) {
|
public ConfigList getList(String path) {
|
||||||
AbstractConfigValue v = find(path, ConfigValueType.LIST, path);
|
AbstractConfigValue v = find(path, ConfigValueType.LIST);
|
||||||
return (ConfigList) v;
|
return (ConfigList) v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbstractConfigObject getObject(String path) {
|
public AbstractConfigObject getObject(String path) {
|
||||||
AbstractConfigObject obj = (AbstractConfigObject) find(path,
|
AbstractConfigObject obj = (AbstractConfigObject) find(path, ConfigValueType.OBJECT);
|
||||||
ConfigValueType.OBJECT, path);
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +216,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getAnyRef(String path) {
|
public Object getAnyRef(String path) {
|
||||||
ConfigValue v = find(path, null, path);
|
ConfigValue v = find(path, null);
|
||||||
return v.unwrapped();
|
return v.unwrapped();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +226,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
|||||||
try {
|
try {
|
||||||
size = getLong(path);
|
size = getLong(path);
|
||||||
} catch (ConfigException.WrongType e) {
|
} catch (ConfigException.WrongType e) {
|
||||||
ConfigValue v = find(path, ConfigValueType.STRING, path);
|
ConfigValue v = find(path, ConfigValueType.STRING);
|
||||||
size = parseBytes((String) v.unwrapped(),
|
size = parseBytes((String) v.unwrapped(),
|
||||||
v.origin(), path);
|
v.origin(), path);
|
||||||
}
|
}
|
||||||
@ -248,7 +246,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
|||||||
try {
|
try {
|
||||||
ns = TimeUnit.MILLISECONDS.toNanos(getLong(path));
|
ns = TimeUnit.MILLISECONDS.toNanos(getLong(path));
|
||||||
} catch (ConfigException.WrongType e) {
|
} catch (ConfigException.WrongType e) {
|
||||||
ConfigValue v = find(path, ConfigValueType.STRING, path);
|
ConfigValue v = find(path, ConfigValueType.STRING);
|
||||||
ns = parseDuration((String) v.unwrapped(), v.origin(), path);
|
ns = parseDuration((String) v.unwrapped(), v.origin(), path);
|
||||||
}
|
}
|
||||||
return ns;
|
return ns;
|
||||||
|
Loading…
Reference in New Issue
Block a user