mirror of
https://github.com/lightbend/config.git
synced 2025-02-23 09:41:01 +08:00
Delete SubstitutionResolver, so it's all in ResolveContext now
This commit is contained in:
parent
0101d9ef37
commit
a22924de6d
@ -86,9 +86,8 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
|
||||
*
|
||||
* @throws NotPossibleToResolve
|
||||
*/
|
||||
protected AbstractConfigValue peekPath(Path path, SubstitutionResolver resolver,
|
||||
ResolveContext context) throws NotPossibleToResolve {
|
||||
return peekPath(this, path, resolver, context);
|
||||
protected AbstractConfigValue peekPath(Path path, ResolveContext context) throws NotPossibleToResolve {
|
||||
return peekPath(this, path, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +96,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
|
||||
*/
|
||||
AbstractConfigValue peekPathWithExternalExceptions(Path path) {
|
||||
try {
|
||||
return peekPath(this, path, null, null);
|
||||
return peekPath(this, path, null);
|
||||
} catch (NotPossibleToResolve e) {
|
||||
throw e.exportException(origin(), path.render());
|
||||
}
|
||||
@ -107,24 +106,22 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
|
||||
// child being peeked, but NOT the child itself. Caller has to resolve
|
||||
// the child itself if needed.
|
||||
private static AbstractConfigValue peekPath(AbstractConfigObject self, Path path,
|
||||
SubstitutionResolver resolver, ResolveContext context) throws NotPossibleToResolve {
|
||||
ResolveContext context) throws NotPossibleToResolve {
|
||||
try {
|
||||
if (resolver != null) {
|
||||
if (context != null) {
|
||||
// walk down through the path resolving only things along that
|
||||
// path,
|
||||
// and then recursively call ourselves with no resolver.
|
||||
AbstractConfigValue partiallyResolved = context.restrict(path).resolve(resolver,
|
||||
self);
|
||||
// path, and then recursively call ourselves with no resolve
|
||||
// context.
|
||||
AbstractConfigValue partiallyResolved = context.restrict(path).resolve(self);
|
||||
if (partiallyResolved instanceof AbstractConfigObject) {
|
||||
return peekPath((AbstractConfigObject) partiallyResolved, path, null, null);
|
||||
return peekPath((AbstractConfigObject) partiallyResolved, path, null);
|
||||
} else {
|
||||
throw new ConfigException.BugOrBroken("resolved object to non-object " + self
|
||||
+ " to " + partiallyResolved);
|
||||
}
|
||||
} else {
|
||||
// with no resolver, we'll fail if anything along the path can't
|
||||
// be
|
||||
// looked at without resolving.
|
||||
// be looked at without resolving.
|
||||
Path next = path.remainder();
|
||||
AbstractConfigValue v = self.attemptPeekWithPartialResolve(path.first());
|
||||
|
||||
@ -132,7 +129,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
|
||||
return v;
|
||||
} else {
|
||||
if (v instanceof AbstractConfigObject) {
|
||||
return peekPath((AbstractConfigObject) v, next, null, null);
|
||||
return peekPath((AbstractConfigObject) v, next, null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -217,8 +214,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements Confi
|
||||
}
|
||||
|
||||
@Override
|
||||
abstract AbstractConfigObject resolveSubstitutions(SubstitutionResolver resolver,
|
||||
ResolveContext context) throws NotPossibleToResolve;
|
||||
abstract AbstractConfigObject resolveSubstitutions(ResolveContext context) throws NotPossibleToResolve;
|
||||
|
||||
@Override
|
||||
abstract AbstractConfigObject relativized(final Path prefix);
|
||||
|
@ -84,18 +84,13 @@ abstract class AbstractConfigValue implements ConfigValue, MergeableValue, Seria
|
||||
}
|
||||
|
||||
/**
|
||||
* Called only by SubstitutionResolver object. The "restrict to child"
|
||||
* parameter is to avoid unnecessary cycles as a side effect (any sibling of
|
||||
* the object we want to follow could cause a cycle, not just the object we
|
||||
* want to follow, otherwise).
|
||||
* Called only by ResolveContext.resolve().
|
||||
*
|
||||
* @param resolver
|
||||
* the resolver doing the resolving
|
||||
* @param context
|
||||
* state of the current resolve
|
||||
* @return a new value if there were changes, or this if no changes
|
||||
*/
|
||||
AbstractConfigValue resolveSubstitutions(SubstitutionResolver resolver, ResolveContext context)
|
||||
AbstractConfigValue resolveSubstitutions(ResolveContext context)
|
||||
throws NotPossibleToResolve {
|
||||
return this;
|
||||
}
|
||||
|
@ -64,15 +64,14 @@ final class ConfigDelayedMerge extends AbstractConfigValue implements Unmergeabl
|
||||
}
|
||||
|
||||
@Override
|
||||
AbstractConfigValue resolveSubstitutions(SubstitutionResolver resolver, ResolveContext context)
|
||||
AbstractConfigValue resolveSubstitutions(ResolveContext context)
|
||||
throws NotPossibleToResolve {
|
||||
return resolveSubstitutions(this, stack, resolver, context);
|
||||
return resolveSubstitutions(this, stack, context);
|
||||
}
|
||||
|
||||
// static method also used by ConfigDelayedMergeObject
|
||||
static AbstractConfigValue resolveSubstitutions(ReplaceableMergeStack replaceable,
|
||||
List<AbstractConfigValue> stack, SubstitutionResolver resolver, ResolveContext context)
|
||||
throws NotPossibleToResolve {
|
||||
List<AbstractConfigValue> stack, ResolveContext context) throws NotPossibleToResolve {
|
||||
// to resolve substitutions, we need to recursively resolve
|
||||
// the stack of stuff to merge, and merge the stack so
|
||||
// we won't be a delayed merge anymore. If restrictToChildOrNull
|
||||
@ -99,7 +98,7 @@ final class ConfigDelayedMerge extends AbstractConfigValue implements Unmergeabl
|
||||
|
||||
AbstractConfigValue resolved;
|
||||
try {
|
||||
resolved = context.resolve(resolver, v);
|
||||
resolved = context.resolve(v);
|
||||
} finally {
|
||||
if (replaced)
|
||||
context.unreplace((AbstractConfigValue) replaceable);
|
||||
|
@ -60,10 +60,9 @@ final class ConfigDelayedMergeObject extends AbstractConfigObject implements Unm
|
||||
}
|
||||
|
||||
@Override
|
||||
AbstractConfigObject resolveSubstitutions(SubstitutionResolver resolver, ResolveContext context)
|
||||
AbstractConfigObject resolveSubstitutions(ResolveContext context)
|
||||
throws NotPossibleToResolve {
|
||||
AbstractConfigValue merged = ConfigDelayedMerge.resolveSubstitutions(this, stack, resolver,
|
||||
context);
|
||||
AbstractConfigValue merged = ConfigDelayedMerge.resolveSubstitutions(this, stack, context);
|
||||
if (merged instanceof AbstractConfigObject) {
|
||||
return (AbstractConfigObject) merged;
|
||||
} else {
|
||||
|
@ -142,8 +142,8 @@ final class ConfigSubstitution extends AbstractConfigValue implements
|
||||
}
|
||||
};
|
||||
|
||||
private AbstractConfigValue resolveValueConcat(SubstitutionResolver resolver,
|
||||
ResolveContext context) throws NotPossibleToResolve {
|
||||
private AbstractConfigValue resolveValueConcat(ResolveContext context)
|
||||
throws NotPossibleToResolve {
|
||||
// need to concat everything into a string
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Object p : pieces) {
|
||||
@ -154,8 +154,8 @@ final class ConfigSubstitution extends AbstractConfigValue implements
|
||||
|
||||
// to concat into a string we have to do a full resolve,
|
||||
// so unrestrict the context
|
||||
AbstractConfigValue v = context.source().lookupSubst(resolver,
|
||||
context.unrestricted(), this, exp, prefixLength);
|
||||
AbstractConfigValue v = context.source().lookupSubst(context.unrestricted(), this,
|
||||
exp, prefixLength);
|
||||
|
||||
if (v == null) {
|
||||
if (exp.optional()) {
|
||||
@ -179,15 +179,15 @@ final class ConfigSubstitution extends AbstractConfigValue implements
|
||||
return new ConfigString(origin(), sb.toString());
|
||||
}
|
||||
|
||||
private AbstractConfigValue resolveSingleSubst(SubstitutionResolver resolver,
|
||||
ResolveContext context) throws NotPossibleToResolve {
|
||||
private AbstractConfigValue resolveSingleSubst(ResolveContext context)
|
||||
throws NotPossibleToResolve {
|
||||
|
||||
if (!(pieces.get(0) instanceof SubstitutionExpression))
|
||||
throw new ConfigException.BugOrBroken(
|
||||
"ConfigSubstitution should never contain a single String piece");
|
||||
|
||||
SubstitutionExpression exp = (SubstitutionExpression) pieces.get(0);
|
||||
AbstractConfigValue v = context.source().lookupSubst(resolver, context, this, exp,
|
||||
AbstractConfigValue v = context.source().lookupSubst(context, this, exp,
|
||||
prefixLength);
|
||||
|
||||
if (v == null && !exp.optional()) {
|
||||
@ -197,7 +197,7 @@ final class ConfigSubstitution extends AbstractConfigValue implements
|
||||
}
|
||||
|
||||
@Override
|
||||
AbstractConfigValue resolveSubstitutions(SubstitutionResolver resolver, ResolveContext context)
|
||||
AbstractConfigValue resolveSubstitutions(ResolveContext context)
|
||||
throws NotPossibleToResolve {
|
||||
AbstractConfigValue resolved;
|
||||
if (pieces.size() > 1) {
|
||||
@ -206,12 +206,12 @@ final class ConfigSubstitution extends AbstractConfigValue implements
|
||||
// get undefined, rather than "bar"
|
||||
context.replace(this, undefinedReplacer);
|
||||
try {
|
||||
resolved = resolveValueConcat(resolver, context);
|
||||
resolved = resolveValueConcat(context);
|
||||
} finally {
|
||||
context.unreplace(this);
|
||||
}
|
||||
} else {
|
||||
resolved = resolveSingleSubst(resolver, context);
|
||||
resolved = resolveSingleSubst(context);
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
@ -31,7 +31,9 @@ final class ResolveContext {
|
||||
final private LinkedList<Set<MemoKey>> traversedStack;
|
||||
final private ConfigResolveOptions options;
|
||||
// the current path restriction, used to ensure lazy
|
||||
// resolution and avoid gratuitous cycles.
|
||||
// resolution and avoid gratuitous cycles. without this,
|
||||
// any sibling of an object we're traversing could
|
||||
// cause a cycle "by side effect"
|
||||
// CAN BE NULL for a full resolve.
|
||||
final private Path restrictToChild;
|
||||
// if we try to resolve something in here, use the
|
||||
@ -164,7 +166,7 @@ final class ResolveContext {
|
||||
return restrict(null);
|
||||
}
|
||||
|
||||
AbstractConfigValue resolve(SubstitutionResolver resolver, AbstractConfigValue original)
|
||||
AbstractConfigValue resolve(AbstractConfigValue original)
|
||||
throws NotPossibleToResolve {
|
||||
|
||||
// a fully-resolved (no restrictToChild) object can satisfy a
|
||||
@ -198,14 +200,14 @@ final class ResolveContext {
|
||||
|
||||
if (replacement != original) {
|
||||
// start over, checking if replacement was memoized
|
||||
return resolve(resolver, replacement);
|
||||
return resolve(replacement);
|
||||
} else {
|
||||
AbstractConfigValue resolved;
|
||||
|
||||
if (forceUndefined)
|
||||
resolved = null;
|
||||
else
|
||||
resolved = original.resolveSubstitutions(resolver, this);
|
||||
resolved = original.resolveSubstitutions(this);
|
||||
|
||||
if (resolved == null || resolved.resolveStatus() == ResolveStatus.RESOLVED) {
|
||||
// if the resolved object is fully resolved by resolving
|
||||
@ -233,4 +235,22 @@ final class ResolveContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AbstractConfigValue resolve(AbstractConfigValue value, AbstractConfigObject root,
|
||||
ConfigResolveOptions options, Path restrictToChildOrNull) throws NotPossibleToResolve {
|
||||
ResolveContext context = new ResolveContext(root, options, restrictToChildOrNull);
|
||||
|
||||
return context.resolve(value);
|
||||
}
|
||||
|
||||
static AbstractConfigValue resolveWithExternalExceptions(AbstractConfigValue value,
|
||||
AbstractConfigObject root, ConfigResolveOptions options) {
|
||||
ResolveContext context = new ResolveContext(root, options, null /* restrictToChild */);
|
||||
|
||||
try {
|
||||
return context.resolve(value);
|
||||
} catch (NotPossibleToResolve e) {
|
||||
throw e.exportException(value.origin(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,25 +12,22 @@ final class ResolveSource {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
/** resolver is null if we should not have refs */
|
||||
static private AbstractConfigValue findInObject(final AbstractConfigObject obj,
|
||||
final SubstitutionResolver resolver, final ResolveContext context,
|
||||
ConfigSubstitution traversed, final SubstitutionExpression subst)
|
||||
throws NotPossibleToResolve {
|
||||
final ResolveContext context, ConfigSubstitution traversed,
|
||||
final SubstitutionExpression subst) throws NotPossibleToResolve {
|
||||
return context.traversing(traversed, subst, new ResolveContext.Resolver() {
|
||||
@Override
|
||||
public AbstractConfigValue call() throws NotPossibleToResolve {
|
||||
return obj.peekPath(subst.path(), resolver, context);
|
||||
return obj.peekPath(subst.path(), context);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AbstractConfigValue lookupSubst(final SubstitutionResolver resolver,
|
||||
final ResolveContext context, ConfigSubstitution traversed,
|
||||
AbstractConfigValue lookupSubst(final ResolveContext context, ConfigSubstitution traversed,
|
||||
final SubstitutionExpression subst, int prefixLength) throws NotPossibleToResolve {
|
||||
// First we look up the full path, which means relative to the
|
||||
// included file if we were not a root file
|
||||
AbstractConfigValue result = findInObject(root, resolver, context, traversed, subst);
|
||||
AbstractConfigValue result = findInObject(root, context, traversed, subst);
|
||||
|
||||
if (result == null) {
|
||||
// Then we want to check relative to the root file. We don't
|
||||
@ -40,12 +37,12 @@ final class ResolveSource {
|
||||
.changePath(subst.path().subPath(prefixLength));
|
||||
|
||||
if (result == null && prefixLength > 0) {
|
||||
result = findInObject(root, resolver, context, traversed, unprefixed);
|
||||
result = findInObject(root, context, traversed, unprefixed);
|
||||
}
|
||||
|
||||
if (result == null && context.options().getUseSystemEnvironment()) {
|
||||
result = findInObject(ConfigImpl.envVariablesAsConfigObject(), null, context,
|
||||
traversed, unprefixed);
|
||||
result = findInObject(ConfigImpl.envVariablesAsConfigObject(), context, traversed,
|
||||
unprefixed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,7 +51,7 @@ final class ResolveSource {
|
||||
result = context.traversing(traversed, subst, new ResolveContext.Resolver() {
|
||||
@Override
|
||||
public AbstractConfigValue call() throws NotPossibleToResolve {
|
||||
return context.resolve(resolver, unresolved);
|
||||
return context.resolve(unresolved);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
|
||||
@Override
|
||||
public SimpleConfig resolve(ConfigResolveOptions options) {
|
||||
AbstractConfigValue resolved = SubstitutionResolver.resolveWithExternalExceptions(object,
|
||||
AbstractConfigValue resolved = ResolveContext.resolveWithExternalExceptions(object,
|
||||
object, options);
|
||||
|
||||
if (resolved == object)
|
||||
@ -72,7 +72,7 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
Path path = Path.newPath(pathExpression);
|
||||
ConfigValue peeked;
|
||||
try {
|
||||
peeked = object.peekPath(path, null, null);
|
||||
peeked = object.peekPath(path, null);
|
||||
} catch (NotPossibleToResolve e) {
|
||||
throw e.exportException(origin(), pathExpression);
|
||||
} catch (ConfigException.NotResolved e) {
|
||||
|
@ -103,8 +103,7 @@ final class SimpleConfigList extends AbstractConfigValue implements ConfigList {
|
||||
}
|
||||
|
||||
@Override
|
||||
SimpleConfigList resolveSubstitutions(final SubstitutionResolver resolver,
|
||||
final ResolveContext context) throws NotPossibleToResolve {
|
||||
SimpleConfigList resolveSubstitutions(final ResolveContext context) throws NotPossibleToResolve {
|
||||
if (resolved)
|
||||
return this;
|
||||
|
||||
@ -118,7 +117,7 @@ final class SimpleConfigList extends AbstractConfigValue implements ConfigList {
|
||||
@Override
|
||||
public AbstractConfigValue modifyChildMayThrow(String key, AbstractConfigValue v)
|
||||
throws NotPossibleToResolve {
|
||||
return context.resolve(resolver, v);
|
||||
return context.resolve(v);
|
||||
}
|
||||
|
||||
}, ResolveStatus.RESOLVED);
|
||||
|
@ -259,8 +259,7 @@ final class SimpleConfigObject extends AbstractConfigObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
AbstractConfigObject resolveSubstitutions(final SubstitutionResolver resolver,
|
||||
final ResolveContext context) throws NotPossibleToResolve {
|
||||
AbstractConfigObject resolveSubstitutions(final ResolveContext context) throws NotPossibleToResolve {
|
||||
if (resolveStatus() == ResolveStatus.RESOLVED)
|
||||
return this;
|
||||
|
||||
@ -274,7 +273,7 @@ final class SimpleConfigObject extends AbstractConfigObject {
|
||||
if (key.equals(context.restrictToChild().first())) {
|
||||
Path remainder = context.restrictToChild().remainder();
|
||||
if (remainder != null) {
|
||||
return context.restrict(remainder).resolve(resolver, v);
|
||||
return context.restrict(remainder).resolve(v);
|
||||
} else {
|
||||
// we don't want to resolve the leaf child.
|
||||
return v;
|
||||
@ -285,7 +284,7 @@ final class SimpleConfigObject extends AbstractConfigObject {
|
||||
}
|
||||
} else {
|
||||
// no restrictToChild, resolve everything
|
||||
return context.unrestricted().resolve(resolver, v);
|
||||
return context.unrestricted().resolve(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2011-2012 Typesafe Inc. <http://typesafe.com>
|
||||
*/
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import com.typesafe.config.ConfigResolveOptions;
|
||||
import com.typesafe.config.impl.AbstractConfigValue.NotPossibleToResolve;
|
||||
|
||||
/**
|
||||
* TODO there is no reason for this class to exist, will remove in upcoming
|
||||
* commit
|
||||
*/
|
||||
final class SubstitutionResolver {
|
||||
SubstitutionResolver() {
|
||||
|
||||
}
|
||||
|
||||
static AbstractConfigValue resolve(AbstractConfigValue value, AbstractConfigObject root,
|
||||
ConfigResolveOptions options, Path restrictToChildOrNull) throws NotPossibleToResolve {
|
||||
SubstitutionResolver resolver = new SubstitutionResolver();
|
||||
ResolveContext context = new ResolveContext(root, options, restrictToChildOrNull);
|
||||
|
||||
return context.resolve(resolver, value);
|
||||
}
|
||||
|
||||
static AbstractConfigValue resolveWithExternalExceptions(AbstractConfigValue value,
|
||||
AbstractConfigObject root, ConfigResolveOptions options) {
|
||||
SubstitutionResolver resolver = new SubstitutionResolver();
|
||||
ResolveContext context = new ResolveContext(root, options, null /* restrictToChild */);
|
||||
|
||||
try {
|
||||
return context.resolve(resolver, value);
|
||||
} catch (NotPossibleToResolve e) {
|
||||
throw e.exportException(value.origin(), null);
|
||||
}
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ class ConfParserTest extends TestUtils {
|
||||
// interpolating arrays into strings
|
||||
tree match {
|
||||
case obj: AbstractConfigObject =>
|
||||
SubstitutionResolver.resolveWithExternalExceptions(tree, obj, ConfigResolveOptions.noSystem())
|
||||
ResolveContext.resolveWithExternalExceptions(tree, obj, ConfigResolveOptions.noSystem())
|
||||
case _ =>
|
||||
tree
|
||||
}
|
||||
|
@ -15,20 +15,20 @@ class ConfigSubstitutionTest extends TestUtils {
|
||||
|
||||
private def resolveWithoutFallbacks(v: AbstractConfigObject) = {
|
||||
val options = ConfigResolveOptions.noSystem()
|
||||
SubstitutionResolver.resolveWithExternalExceptions(v, v, options).asInstanceOf[AbstractConfigObject].toConfig
|
||||
ResolveContext.resolveWithExternalExceptions(v, v, options).asInstanceOf[AbstractConfigObject].toConfig
|
||||
}
|
||||
private def resolveWithoutFallbacks(s: ConfigSubstitution, root: AbstractConfigObject) = {
|
||||
val options = ConfigResolveOptions.noSystem()
|
||||
SubstitutionResolver.resolveWithExternalExceptions(s, root, options)
|
||||
ResolveContext.resolveWithExternalExceptions(s, root, options)
|
||||
}
|
||||
|
||||
private def resolve(v: AbstractConfigObject) = {
|
||||
val options = ConfigResolveOptions.defaults()
|
||||
SubstitutionResolver.resolveWithExternalExceptions(v, v, options).asInstanceOf[AbstractConfigObject].toConfig
|
||||
ResolveContext.resolveWithExternalExceptions(v, v, options).asInstanceOf[AbstractConfigObject].toConfig
|
||||
}
|
||||
private def resolve(s: ConfigSubstitution, root: AbstractConfigObject) = {
|
||||
val options = ConfigResolveOptions.defaults()
|
||||
SubstitutionResolver.resolveWithExternalExceptions(s, root, options)
|
||||
ResolveContext.resolveWithExternalExceptions(s, root, options)
|
||||
}
|
||||
|
||||
private val simpleObject = {
|
||||
|
@ -20,11 +20,11 @@ import com.typesafe.config.ConfigMergeable
|
||||
class ConfigTest extends TestUtils {
|
||||
|
||||
private def resolveNoSystem(v: AbstractConfigValue, root: AbstractConfigObject) = {
|
||||
SubstitutionResolver.resolveWithExternalExceptions(v, root, ConfigResolveOptions.noSystem())
|
||||
ResolveContext.resolveWithExternalExceptions(v, root, ConfigResolveOptions.noSystem())
|
||||
}
|
||||
|
||||
private def resolveNoSystem(v: SimpleConfig, root: SimpleConfig) = {
|
||||
SubstitutionResolver.resolveWithExternalExceptions(v.root, root.root,
|
||||
ResolveContext.resolveWithExternalExceptions(v.root, root.root,
|
||||
ConfigResolveOptions.noSystem()).asInstanceOf[AbstractConfigObject].toConfig
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ class EquivalentsTest extends TestUtils {
|
||||
// for purposes of these tests, substitutions are only
|
||||
// against the same file's root, and without looking at
|
||||
// system prop or env variable fallbacks.
|
||||
SubstitutionResolver.resolveWithExternalExceptions(v, v, ConfigResolveOptions.noSystem())
|
||||
ResolveContext.resolveWithExternalExceptions(v, v, ConfigResolveOptions.noSystem())
|
||||
case v =>
|
||||
v
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user