mirror of
https://github.com/lightbend/config.git
synced 2025-03-24 08:10:24 +08:00
add methods to ConfigOrigin for filename, resource, url, and lineNumber
Play wanted to use these to jump to the problematic spot in a config file when an exception occurs.
This commit is contained in:
parent
2e283367de
commit
21d9b8b358
src
main/java/com/typesafe/config
test/scala/com/typesafe/config/impl
@ -9,9 +9,12 @@ package com.typesafe.config;
|
||||
public class ConfigException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
final private ConfigOrigin origin;
|
||||
|
||||
protected ConfigException(ConfigOrigin origin, String message,
|
||||
Throwable cause) {
|
||||
super(origin.description() + ": " + message, cause);
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
protected ConfigException(ConfigOrigin origin, String message) {
|
||||
@ -20,12 +23,26 @@ public class ConfigException extends RuntimeException {
|
||||
|
||||
protected ConfigException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.origin = null;
|
||||
}
|
||||
|
||||
protected ConfigException(String message) {
|
||||
this(message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an "origin" (such as a filename and line number) for the
|
||||
* exception, or null if none is available. If there's no sensible origin
|
||||
* for a given exception, or the kind of exception doesn't meaningfully
|
||||
* relate to a particular origin file, this returns null. Never assume this
|
||||
* will return non-null, it can always return null.
|
||||
*
|
||||
* @return origin of the problem, or null if unknown/inapplicable
|
||||
*/
|
||||
public ConfigOrigin origin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception indicating that the type of a value does not match the type you
|
||||
* requested.
|
||||
|
@ -3,10 +3,21 @@
|
||||
*/
|
||||
package com.typesafe.config;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
|
||||
/**
|
||||
* Represents the origin (such as filename and line number) of a
|
||||
* {@link ConfigValue} for use in error messages. Obtain the origin of a value
|
||||
* with {@link ConfigValue#origin}.
|
||||
* with {@link ConfigValue#origin}. Exceptions may have an origin, see
|
||||
* {@link ConfigException#origin}, but be careful because
|
||||
* <code>ConfigException.origin()</code> may return null.
|
||||
*
|
||||
* <p>
|
||||
* It's best to use this interface only for debugging; its accuracy is
|
||||
* "best effort" rather than guaranteed, and a potentially-noticeable amount of
|
||||
* memory could probably be saved if origins were not kept around, so in the
|
||||
* future there might be some option to discard origins.
|
||||
*
|
||||
* <p>
|
||||
* <em>Do not implement this interface</em>; it should only be implemented by
|
||||
@ -16,5 +27,43 @@ package com.typesafe.config;
|
||||
* implementations will break.
|
||||
*/
|
||||
public interface ConfigOrigin {
|
||||
/**
|
||||
* Returns a string describing the origin of a value or exception. This will
|
||||
* never return null.
|
||||
*
|
||||
* @return string describing the origin
|
||||
*/
|
||||
public String description();
|
||||
|
||||
/**
|
||||
* Returns a filename describing the origin. This will return null if the
|
||||
* origin was not a file.
|
||||
*
|
||||
* @return filename of the origin or null
|
||||
*/
|
||||
public String filename();
|
||||
|
||||
/**
|
||||
* Returns a URL describing the origin. This will return null if the origin
|
||||
* has no meaningful URL.
|
||||
*
|
||||
* @return url of the origin or null
|
||||
*/
|
||||
public URL url();
|
||||
|
||||
/**
|
||||
* Returns a classpath resource name describing the origin. This will return
|
||||
* null if the origin was not a classpath resource.
|
||||
*
|
||||
* @return resource name of the origin or null
|
||||
*/
|
||||
public String resource();
|
||||
|
||||
/**
|
||||
* Returns a line number where the value or exception originated. This will
|
||||
* return -1 if there's no meaningful line number.
|
||||
*
|
||||
* @return line number or -1 if none is available
|
||||
*/
|
||||
public int lineNumber();
|
||||
}
|
||||
|
@ -164,18 +164,13 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements
|
||||
if (stack.isEmpty())
|
||||
throw new ConfigException.BugOrBroken(
|
||||
"can't merge origins on empty list");
|
||||
final String prefix = "merge of ";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<ConfigOrigin> origins = new ArrayList<ConfigOrigin>();
|
||||
ConfigOrigin firstOrigin = null;
|
||||
int numMerged = 0;
|
||||
for (AbstractConfigValue v : stack) {
|
||||
if (firstOrigin == null)
|
||||
firstOrigin = v.origin();
|
||||
|
||||
String desc = v.origin().description();
|
||||
if (desc.startsWith(prefix))
|
||||
desc = desc.substring(prefix.length());
|
||||
|
||||
if (v instanceof AbstractConfigObject
|
||||
&& ((AbstractConfigObject) v).resolveStatus() == ResolveStatus.RESOLVED
|
||||
&& ((ConfigObject) v).isEmpty()) {
|
||||
@ -183,22 +178,17 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements
|
||||
// config in the description, since they are
|
||||
// likely to be "implementation details"
|
||||
} else {
|
||||
sb.append(desc);
|
||||
sb.append(",");
|
||||
origins.add(v.origin());
|
||||
numMerged += 1;
|
||||
}
|
||||
}
|
||||
if (numMerged > 0) {
|
||||
sb.setLength(sb.length() - 1); // chop comma
|
||||
if (numMerged > 1) {
|
||||
return new SimpleConfigOrigin(prefix + sb.toString());
|
||||
} else {
|
||||
return new SimpleConfigOrigin(sb.toString());
|
||||
}
|
||||
} else {
|
||||
// the configs were all empty.
|
||||
return firstOrigin;
|
||||
|
||||
if (numMerged == 0) {
|
||||
// the configs were all empty, so just use the first one
|
||||
origins.add(firstOrigin);
|
||||
}
|
||||
|
||||
return SimpleConfigOrigin.mergeOrigins(origins);
|
||||
}
|
||||
|
||||
static ConfigOrigin mergeOrigins(AbstractConfigObject... stack) {
|
||||
|
@ -44,8 +44,7 @@ public class ConfigImpl {
|
||||
obj = p.parse(p.options().setAllowMissing(
|
||||
options.getAllowMissing()));
|
||||
} else {
|
||||
obj = SimpleConfigObject.emptyMissing(new SimpleConfigOrigin(
|
||||
name));
|
||||
obj = SimpleConfigObject.emptyMissing(SimpleConfigOrigin.newSimple(name));
|
||||
}
|
||||
} else {
|
||||
ConfigParseable confHandle = source.nameToParseable(name + ".conf");
|
||||
@ -55,13 +54,13 @@ public class ConfigImpl {
|
||||
|
||||
if (!options.getAllowMissing() && confHandle == null
|
||||
&& jsonHandle == null && propsHandle == null) {
|
||||
throw new ConfigException.IO(new SimpleConfigOrigin(name),
|
||||
throw new ConfigException.IO(SimpleConfigOrigin.newSimple(name),
|
||||
"No config files {.conf,.json,.properties} found");
|
||||
}
|
||||
|
||||
ConfigSyntax syntax = options.getSyntax();
|
||||
|
||||
obj = SimpleConfigObject.empty(new SimpleConfigOrigin(name));
|
||||
obj = SimpleConfigObject.empty(SimpleConfigOrigin.newSimple(name));
|
||||
if (confHandle != null
|
||||
&& (syntax == null || syntax == ConfigSyntax.CONF)) {
|
||||
obj = confHandle.parse(confHandle.options()
|
||||
@ -139,8 +138,8 @@ public class ConfigImpl {
|
||||
}
|
||||
|
||||
static AbstractConfigObject emptyObject(String originDescription) {
|
||||
ConfigOrigin origin = originDescription != null ? new SimpleConfigOrigin(
|
||||
originDescription) : null;
|
||||
ConfigOrigin origin = originDescription != null ? SimpleConfigOrigin
|
||||
.newSimple(originDescription) : null;
|
||||
return emptyObject(origin);
|
||||
}
|
||||
|
||||
@ -154,8 +153,8 @@ public class ConfigImpl {
|
||||
}
|
||||
|
||||
// default origin for values created with fromAnyRef and no origin specified
|
||||
final private static ConfigOrigin defaultValueOrigin = new SimpleConfigOrigin(
|
||||
"hardcoded value");
|
||||
final private static ConfigOrigin defaultValueOrigin = SimpleConfigOrigin
|
||||
.newSimple("hardcoded value");
|
||||
final private static ConfigBoolean defaultTrueValue = new ConfigBoolean(
|
||||
defaultValueOrigin, true);
|
||||
final private static ConfigBoolean defaultFalseValue = new ConfigBoolean(
|
||||
@ -188,7 +187,7 @@ public class ConfigImpl {
|
||||
if (originDescription == null)
|
||||
return defaultValueOrigin;
|
||||
else
|
||||
return new SimpleConfigOrigin(originDescription);
|
||||
return SimpleConfigOrigin.newSimple(originDescription);
|
||||
}
|
||||
|
||||
/** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */
|
||||
@ -386,10 +385,11 @@ public class ConfigImpl {
|
||||
Map<String, AbstractConfigValue> m = new HashMap<String, AbstractConfigValue>();
|
||||
for (Map.Entry<String, String> entry : env.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
m.put(key, new ConfigString(
|
||||
new SimpleConfigOrigin("env var " + key), entry.getValue()));
|
||||
m.put(key,
|
||||
new ConfigString(SimpleConfigOrigin.newSimple("env var " + key), entry
|
||||
.getValue()));
|
||||
}
|
||||
return new SimpleConfigObject(new SimpleConfigOrigin("env variables"),
|
||||
return new SimpleConfigObject(SimpleConfigOrigin.newSimple("env variables"),
|
||||
m, ResolveStatus.RESOLVED, false /* ignoresFallbacks */);
|
||||
}
|
||||
|
||||
|
8
src/main/java/com/typesafe/config/impl/OriginType.java
Normal file
8
src/main/java/com/typesafe/config/impl/OriginType.java
Normal file
@ -0,0 +1,8 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
enum OriginType {
|
||||
GENERIC,
|
||||
FILE,
|
||||
URL,
|
||||
RESOURCE
|
||||
}
|
@ -54,9 +54,6 @@ public abstract class Parseable implements ConfigParseable {
|
||||
}
|
||||
ConfigParseOptions modified = baseOptions.setSyntax(syntax);
|
||||
|
||||
if (modified.getOriginDescription() == null)
|
||||
modified = modified.setOriginDescription(originDescription());
|
||||
|
||||
modified = modified.appendIncluder(ConfigImpl.defaultIncluder());
|
||||
|
||||
return modified;
|
||||
@ -109,13 +106,18 @@ public abstract class Parseable implements ConfigParseable {
|
||||
}
|
||||
|
||||
AbstractConfigValue parseValue(ConfigParseOptions baseOptions) {
|
||||
// note that we are NOT using our "options" and "origin" fields,
|
||||
// note that we are NOT using our "initialOptions",
|
||||
// but using the ones from the passed-in options. The idea is that
|
||||
// callers can get our original options and then parse with different
|
||||
// ones if they want.
|
||||
ConfigParseOptions options = fixupOptions(baseOptions);
|
||||
ConfigOrigin origin = new SimpleConfigOrigin(
|
||||
options.getOriginDescription());
|
||||
|
||||
// passed-in options can override origin
|
||||
ConfigOrigin origin;
|
||||
if (options.getOriginDescription() != null)
|
||||
origin = SimpleConfigOrigin.newSimple(options.getOriginDescription());
|
||||
else
|
||||
origin = origin();
|
||||
return parseValue(origin, options);
|
||||
}
|
||||
|
||||
@ -152,7 +154,7 @@ public abstract class Parseable implements ConfigParseable {
|
||||
return parseValue(options());
|
||||
}
|
||||
|
||||
abstract String originDescription();
|
||||
abstract ConfigOrigin origin();
|
||||
|
||||
@Override
|
||||
public URL url() {
|
||||
@ -242,8 +244,8 @@ public abstract class Parseable implements ConfigParseable {
|
||||
}
|
||||
|
||||
@Override
|
||||
String originDescription() {
|
||||
return "Reader";
|
||||
ConfigOrigin origin() {
|
||||
return SimpleConfigOrigin.newSimple("Reader");
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,8 +271,8 @@ public abstract class Parseable implements ConfigParseable {
|
||||
}
|
||||
|
||||
@Override
|
||||
String originDescription() {
|
||||
return "String";
|
||||
ConfigOrigin origin() {
|
||||
return SimpleConfigOrigin.newSimple("String");
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,8 +309,8 @@ public abstract class Parseable implements ConfigParseable {
|
||||
}
|
||||
|
||||
@Override
|
||||
String originDescription() {
|
||||
return input.toExternalForm();
|
||||
ConfigOrigin origin() {
|
||||
return SimpleConfigOrigin.newURL(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -359,8 +361,8 @@ public abstract class Parseable implements ConfigParseable {
|
||||
}
|
||||
|
||||
@Override
|
||||
String originDescription() {
|
||||
return input.getPath();
|
||||
ConfigOrigin origin() {
|
||||
return SimpleConfigOrigin.newFile(input.getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -430,8 +432,8 @@ public abstract class Parseable implements ConfigParseable {
|
||||
}
|
||||
|
||||
@Override
|
||||
String originDescription() {
|
||||
return resource + " on classpath";
|
||||
ConfigOrigin origin() {
|
||||
return SimpleConfigOrigin.newResource(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -478,8 +480,8 @@ public abstract class Parseable implements ConfigParseable {
|
||||
}
|
||||
|
||||
@Override
|
||||
String originDescription() {
|
||||
return "properties";
|
||||
ConfigOrigin origin() {
|
||||
return SimpleConfigOrigin.newSimple("properties");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -219,8 +219,7 @@ final class Parser {
|
||||
}
|
||||
|
||||
private ConfigOrigin lineOrigin() {
|
||||
return new SimpleConfigOrigin(baseOrigin.description() + ": line "
|
||||
+ lineNumber);
|
||||
return ((SimpleConfigOrigin) baseOrigin).addLineNumber(lineNumber);
|
||||
}
|
||||
|
||||
private ConfigException parseError(String message) {
|
||||
@ -681,7 +680,7 @@ final class Parser {
|
||||
return pb.result();
|
||||
}
|
||||
|
||||
static ConfigOrigin apiOrigin = new SimpleConfigOrigin("path parameter");
|
||||
static ConfigOrigin apiOrigin = SimpleConfigOrigin.newSimple("path parameter");
|
||||
|
||||
static Path parsePath(String path) {
|
||||
Path speculated = speculativeFastParsePath(path);
|
||||
|
@ -112,8 +112,8 @@ final class SimpleConfigObject extends AbstractConfigObject {
|
||||
}
|
||||
|
||||
final private static String EMPTY_NAME = "empty config";
|
||||
final private static SimpleConfigObject emptyInstance = empty(new SimpleConfigOrigin(
|
||||
EMPTY_NAME));
|
||||
final private static SimpleConfigObject emptyInstance = empty(SimpleConfigOrigin
|
||||
.newSimple(EMPTY_NAME));
|
||||
|
||||
final static SimpleConfigObject empty() {
|
||||
return emptyInstance;
|
||||
@ -128,7 +128,7 @@ final class SimpleConfigObject extends AbstractConfigObject {
|
||||
}
|
||||
|
||||
final static SimpleConfigObject emptyMissing(ConfigOrigin baseOrigin) {
|
||||
return new SimpleConfigObject(new SimpleConfigOrigin(
|
||||
return new SimpleConfigObject(SimpleConfigOrigin.newSimple(
|
||||
baseOrigin.description() + " (not found)"),
|
||||
Collections.<String, AbstractConfigValue> emptyMap());
|
||||
}
|
||||
|
@ -3,26 +3,62 @@
|
||||
*/
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.typesafe.config.ConfigException;
|
||||
import com.typesafe.config.ConfigOrigin;
|
||||
|
||||
final class SimpleConfigOrigin implements ConfigOrigin {
|
||||
|
||||
final private String description;
|
||||
final private int lineNumber;
|
||||
final private OriginType originType;
|
||||
|
||||
SimpleConfigOrigin(String description) {
|
||||
private SimpleConfigOrigin(String description, int lineNumber, OriginType originType) {
|
||||
this.lineNumber = lineNumber;
|
||||
this.originType = originType;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
static SimpleConfigOrigin newSimple(String description) {
|
||||
return new SimpleConfigOrigin(description, -1, OriginType.GENERIC);
|
||||
}
|
||||
|
||||
static SimpleConfigOrigin newFile(String filename) {
|
||||
return new SimpleConfigOrigin(filename, -1, OriginType.FILE);
|
||||
}
|
||||
|
||||
static SimpleConfigOrigin newURL(URL url) {
|
||||
return new SimpleConfigOrigin(url.toExternalForm(), -1, OriginType.URL);
|
||||
}
|
||||
|
||||
static SimpleConfigOrigin newResource(String resource) {
|
||||
return new SimpleConfigOrigin(resource, -1, OriginType.RESOURCE);
|
||||
}
|
||||
|
||||
// important, this should also be able to _change_ an existing line
|
||||
// number
|
||||
SimpleConfigOrigin addLineNumber(int lineNumber) {
|
||||
return new SimpleConfigOrigin(this.description, lineNumber, this.originType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return description;
|
||||
if (lineNumber < 0) {
|
||||
return description;
|
||||
} else {
|
||||
return description + ": " + lineNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof SimpleConfigOrigin) {
|
||||
return this.description
|
||||
.equals(((SimpleConfigOrigin) other).description);
|
||||
// two origins are equal if they are described to the user in the
|
||||
// same way, for now at least this seems fine
|
||||
return this.description.equals(((SimpleConfigOrigin) other).description);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -37,4 +73,81 @@ final class SimpleConfigOrigin implements ConfigOrigin {
|
||||
public String toString() {
|
||||
return "ConfigOrigin(" + description + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filename() {
|
||||
if (originType == OriginType.FILE) {
|
||||
return description;
|
||||
} else if (originType == OriginType.URL) {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(description);
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
if (url.getProtocol().equals("file")) {
|
||||
return url.getFile();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL url() {
|
||||
if (originType == OriginType.URL) {
|
||||
try {
|
||||
return new URL(description);
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
} else if (originType == OriginType.FILE) {
|
||||
try {
|
||||
return (new File(description)).toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resource() {
|
||||
if (originType == OriginType.RESOURCE) {
|
||||
return description;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
static final String MERGE_OF_PREFIX = "merge of ";
|
||||
|
||||
static ConfigOrigin mergeOrigins(Collection<? extends ConfigOrigin> stack) {
|
||||
if (stack.isEmpty()) {
|
||||
throw new ConfigException.BugOrBroken("can't merge empty list of origins");
|
||||
} else if (stack.size() == 1) {
|
||||
return stack.iterator().next();
|
||||
} else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (ConfigOrigin o : stack) {
|
||||
String desc = o.description();
|
||||
if (desc.startsWith(MERGE_OF_PREFIX))
|
||||
desc = desc.substring(MERGE_OF_PREFIX.length());
|
||||
|
||||
sb.append(desc);
|
||||
sb.append(",");
|
||||
}
|
||||
|
||||
sb.setLength(sb.length() - 1); // chop comma
|
||||
return newSimple(MERGE_OF_PREFIX + sb.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,8 +219,7 @@ final class Tokenizer {
|
||||
|
||||
private static ConfigOrigin lineOrigin(ConfigOrigin baseOrigin,
|
||||
int lineNumber) {
|
||||
return new SimpleConfigOrigin(baseOrigin.description() + ": line "
|
||||
+ lineNumber);
|
||||
return ((SimpleConfigOrigin) baseOrigin).addLineNumber(lineNumber);
|
||||
}
|
||||
|
||||
// chars JSON allows a number to start with
|
||||
|
@ -761,6 +761,27 @@ class ConfigTest extends TestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
def test01Origins() {
|
||||
val conf = ConfigFactory.load("test01")
|
||||
|
||||
val o1 = conf.getValue("ints.fortyTwo").origin()
|
||||
assertEquals("/test01.conf: 3", o1.description)
|
||||
assertEquals("/test01.conf", o1.resource)
|
||||
assertEquals(3, o1.lineNumber)
|
||||
|
||||
val o2 = conf.getValue("fromJson1").origin()
|
||||
assertEquals("/test01.json: 2", o2.description)
|
||||
assertEquals("/test01.json", o2.resource)
|
||||
assertEquals(2, o2.lineNumber)
|
||||
|
||||
val o3 = conf.getValue("fromProps.bool").origin()
|
||||
assertEquals("/test01.properties", o3.description)
|
||||
assertEquals("/test01.properties", o3.resource)
|
||||
// we don't have line numbers for properties files
|
||||
assertEquals(-1, o3.lineNumber)
|
||||
}
|
||||
|
||||
@Test
|
||||
def test02SubstitutionsWithWeirdPaths() {
|
||||
val conf = ConfigFactory.load("test02")
|
||||
|
@ -7,6 +7,7 @@ import org.junit.Assert._
|
||||
import org.junit._
|
||||
import com.typesafe.config.ConfigValue
|
||||
import java.util.Collections
|
||||
import java.net.URL
|
||||
import scala.collection.JavaConverters._
|
||||
import com.typesafe.config.ConfigObject
|
||||
import com.typesafe.config.ConfigList
|
||||
@ -18,9 +19,9 @@ class ConfigValueTest extends TestUtils {
|
||||
|
||||
@Test
|
||||
def configOriginEquality() {
|
||||
val a = new SimpleConfigOrigin("foo")
|
||||
val sameAsA = new SimpleConfigOrigin("foo")
|
||||
val b = new SimpleConfigOrigin("bar")
|
||||
val a = SimpleConfigOrigin.newSimple("foo")
|
||||
val sameAsA = SimpleConfigOrigin.newSimple("foo")
|
||||
val b = SimpleConfigOrigin.newSimple("bar")
|
||||
|
||||
checkEqualObjects(a, a)
|
||||
checkEqualObjects(a, sameAsA)
|
||||
@ -362,7 +363,7 @@ class ConfigValueTest extends TestUtils {
|
||||
val values = new java.util.HashMap[String, AbstractConfigValue]()
|
||||
if (!empty)
|
||||
values.put("hello", intValue(37))
|
||||
new SimpleConfigObject(new SimpleConfigOrigin(desc), values);
|
||||
new SimpleConfigObject(SimpleConfigOrigin.newSimple(desc), values);
|
||||
}
|
||||
def m(values: AbstractConfigObject*) = {
|
||||
AbstractConfigObject.mergeOrigins(values: _*).description()
|
||||
@ -446,4 +447,38 @@ class ConfigValueTest extends TestUtils {
|
||||
assertEquals(false, falses.getBoolean("b"))
|
||||
assertEquals(false, falses.getBoolean("c"))
|
||||
}
|
||||
|
||||
@Test
|
||||
def configOriginFileAndLine() {
|
||||
val hasFilename = SimpleConfigOrigin.newFile("foo")
|
||||
val noFilename = SimpleConfigOrigin.newSimple("bar")
|
||||
val filenameWithLine = hasFilename.addLineNumber(3)
|
||||
val noFilenameWithLine = noFilename.addLineNumber(4)
|
||||
|
||||
assertEquals("foo", hasFilename.filename())
|
||||
assertEquals("foo", filenameWithLine.filename())
|
||||
assertNull(noFilename.filename())
|
||||
assertNull(noFilenameWithLine.filename())
|
||||
|
||||
assertEquals("foo", hasFilename.description())
|
||||
assertEquals("bar", noFilename.description())
|
||||
|
||||
assertEquals(-1, hasFilename.lineNumber())
|
||||
assertEquals(-1, noFilename.lineNumber())
|
||||
|
||||
assertEquals("foo: 3", filenameWithLine.description())
|
||||
assertEquals("bar: 4", noFilenameWithLine.description());
|
||||
|
||||
assertEquals(3, filenameWithLine.lineNumber())
|
||||
assertEquals(4, noFilenameWithLine.lineNumber())
|
||||
|
||||
// the filename is made absolute when converting to url
|
||||
assertTrue(hasFilename.url.toExternalForm.contains("foo"))
|
||||
assertNull(noFilename.url)
|
||||
assertEquals("file:/baz", SimpleConfigOrigin.newFile("/baz").url.toExternalForm)
|
||||
|
||||
val urlOrigin = SimpleConfigOrigin.newURL(new URL("file:/foo"))
|
||||
assertEquals("/foo", urlOrigin.filename)
|
||||
assertEquals("file:/foo", urlOrigin.url.toExternalForm)
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class JsonTest extends TestUtils {
|
||||
block
|
||||
} catch {
|
||||
case e: lift.JsonParser.ParseException =>
|
||||
throw new ConfigException.Parse(new SimpleConfigOrigin("lift parser"), e.getMessage(), e)
|
||||
throw new ConfigException.Parse(SimpleConfigOrigin.newSimple("lift parser"), e.getMessage(), e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ abstract trait TestUtils {
|
||||
}
|
||||
|
||||
def fakeOrigin() = {
|
||||
new SimpleConfigOrigin("fake origin")
|
||||
SimpleConfigOrigin.newSimple("fake origin")
|
||||
}
|
||||
|
||||
def includer() = {
|
||||
@ -391,7 +391,7 @@ abstract trait TestUtils {
|
||||
}
|
||||
|
||||
def tokenize(input: Reader): java.util.Iterator[Token] = {
|
||||
tokenize(new SimpleConfigOrigin("anonymous Reader"), input)
|
||||
tokenize(SimpleConfigOrigin.newSimple("anonymous Reader"), input)
|
||||
}
|
||||
|
||||
def tokenize(s: String): java.util.Iterator[Token] = {
|
||||
|
Loading…
Reference in New Issue
Block a user