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:
Havoc Pennington 2012-04-05 14:02:37 -04:00
parent 683e72cbbe
commit 06ed4d24e1
4 changed files with 47 additions and 31 deletions

View File

@ -57,7 +57,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
* @param key
* @return the unmodified raw value or null
*/
protected final AbstractConfigValue peekAssumingResolved(String key, String originalPath) {
protected final AbstractConfigValue peekAssumingResolved(String key, Path originalPath) {
try {
return attemptPeekWithPartialResolve(key);
} catch (ConfigException.NotResolved e) {
@ -138,7 +138,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
}
}
} catch (ConfigException.NotResolved e) {
throw ConfigImpl.improveNotResolved(path.render(), e);
throw ConfigImpl.improveNotResolved(path, e);
}
}

View File

@ -526,9 +526,10 @@ public class ConfigImpl {
// toplevel error message. the "original" exception may however have extra
// detail about what happened. call this if you have a better "what" than
// further down on the stack.
static ConfigException.NotResolved improveNotResolved(String what,
static ConfigException.NotResolved improveNotResolved(Path what,
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()";
if (newMessage.equals(original.getMessage()))
return original;

View File

@ -123,6 +123,23 @@ final class Path implements Serializable {
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
public boolean equals(Object other) {
if (other instanceof Path) {

View File

@ -72,7 +72,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
try {
peeked = object.peekPath(path);
} catch (ConfigException.NotResolved e) {
throw ConfigImpl.improveNotResolved(pathExpression, e);
throw ConfigImpl.improveNotResolved(path, e);
}
return peeked != null && peeked.valueType() != ConfigValueType.NULL;
}
@ -107,33 +107,27 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
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,
ConfigValueType expected, String originalPath) {
ConfigValueType expected, Path originalPath) {
AbstractConfigValue v = self.peekAssumingResolved(key, originalPath);
if (v == null)
throw new ConfigException.Missing(originalPath);
throw new ConfigException.Missing(originalPath.render());
if (expected != null)
v = DefaultTransformer.transform(v, expected);
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);
else if (expected != null && v.valueType() != expected)
throw new ConfigException.WrongType(v.origin(), originalPath, expected.name(), v
.valueType().name());
throw new ConfigException.WrongType(v.origin(), originalPath.render(), expected.name(),
v.valueType().name());
else
return v;
}
static private AbstractConfigValue find(AbstractConfigObject self, Path path,
ConfigValueType expected, String originalPath) {
ConfigValueType expected, Path originalPath) {
try {
String key = path.first();
Path next = path.remainder();
@ -141,33 +135,38 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
return findKey(self, key, expected, originalPath);
} else {
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
return find(o, next, expected, originalPath);
}
} catch (ConfigException.NotResolved e) {
throw ConfigImpl.improveNotResolved(path.render(), e);
throw ConfigImpl.improveNotResolved(path, e);
}
}
AbstractConfigValue find(String pathExpression, ConfigValueType expected,
String originalPath) {
AbstractConfigValue find(Path pathExpression, ConfigValueType expected, Path originalPath) {
return find(object, pathExpression, expected, originalPath);
}
AbstractConfigValue find(String pathExpression, ConfigValueType expected) {
Path path = Path.newPath(pathExpression);
return find(path, expected, path);
}
@Override
public AbstractConfigValue getValue(String path) {
return find(path, null, path);
return find(path, null);
}
@Override
public boolean getBoolean(String path) {
ConfigValue v = find(path, ConfigValueType.BOOLEAN, path);
ConfigValue v = find(path, ConfigValueType.BOOLEAN);
return (Boolean) v.unwrapped();
}
private ConfigNumber getConfigNumber(String path) {
ConfigValue v = find(path, ConfigValueType.NUMBER, path);
ConfigValue v = find(path, ConfigValueType.NUMBER);
return (ConfigNumber) v;
}
@ -194,20 +193,19 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
@Override
public String getString(String path) {
ConfigValue v = find(path, ConfigValueType.STRING, path);
ConfigValue v = find(path, ConfigValueType.STRING);
return (String) v.unwrapped();
}
@Override
public ConfigList getList(String path) {
AbstractConfigValue v = find(path, ConfigValueType.LIST, path);
AbstractConfigValue v = find(path, ConfigValueType.LIST);
return (ConfigList) v;
}
@Override
public AbstractConfigObject getObject(String path) {
AbstractConfigObject obj = (AbstractConfigObject) find(path,
ConfigValueType.OBJECT, path);
AbstractConfigObject obj = (AbstractConfigObject) find(path, ConfigValueType.OBJECT);
return obj;
}
@ -218,7 +216,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
@Override
public Object getAnyRef(String path) {
ConfigValue v = find(path, null, path);
ConfigValue v = find(path, null);
return v.unwrapped();
}
@ -228,7 +226,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
try {
size = getLong(path);
} catch (ConfigException.WrongType e) {
ConfigValue v = find(path, ConfigValueType.STRING, path);
ConfigValue v = find(path, ConfigValueType.STRING);
size = parseBytes((String) v.unwrapped(),
v.origin(), path);
}
@ -248,7 +246,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
try {
ns = TimeUnit.MILLISECONDS.toNanos(getLong(path));
} 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);
}
return ns;