diff options
author | 2015-08-31 15:39:09 +0000 | |
---|---|---|
committer | 2015-08-31 19:20:53 +0000 | |
commit | 676905a9e828adc5cf6f43893703f93568f37dfe (patch) | |
tree | 14399691dc0f18bc3523ffe6c5e516d08c6cc84d /src/main/java/com | |
parent | b4d58a27680d84097a5d1d66ab15fdd2efb8eda6 (diff) |
Fixes to Skylark function call
Allow a call to a struct's field when it's a function.
Check whether a java method exists before issuing KwArg error.
--
MOS_MIGRATED_REVID=101937143
Diffstat (limited to 'src/main/java/com')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java index 2e90afd3f9..73e8d10c4f 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java @@ -355,10 +355,19 @@ public final class FuncallExpression extends Expression { // exactly and copy that behaviour. // TODO(bazel-team): check if this and SkylarkBuiltInFunctions.createObject can be merged. private Object invokeJavaMethod( - Object obj, Class<?> objClass, String methodName, List<Object> args) throws EvalException { + Object obj, Class<?> objClass, String methodName, List<Object> args, boolean hasKwArgs) + throws EvalException { MethodDescriptor matchingMethod = null; List<MethodDescriptor> methods = getMethods(objClass, methodName, args.size(), getLocation()); if (methods != null) { + if (hasKwArgs) { + throw new EvalException( + func.getLocation(), + String.format( + "Keyword arguments are not allowed when calling a java method" + + "\nwhile calling method '%s' on object of type %s", + func.getName(), EvalUtils.getDataTypeNameFromClass(objClass))); + } for (MethodDescriptor method : methods) { Class<?>[] params = method.getMethod().getParameterTypes(); int i = 0; @@ -508,25 +517,34 @@ public final class FuncallExpression extends Expression { return convertFromSkylark( function.call(posargs.build(), ImmutableMap.<String, Object>copyOf(kwargs), this, env), env); + } else if (objValue instanceof ClassObject) { + Object fieldValue = ((ClassObject) objValue).getValue(func.getName()); + if (fieldValue == null) { + throw new EvalException( + getLocation(), String.format("struct has no method '%s'", func.getName())); + } + if (!(fieldValue instanceof BaseFunction)) { + throw new EvalException( + getLocation(), String.format("struct field '%s' is not a function", func.getName())); + } + function = (BaseFunction) fieldValue; + evalArguments(posargs, kwargs, env, function); + return convertFromSkylark( + function.call(posargs.build(), ImmutableMap.<String, Object>copyOf(kwargs), this, env), + env); } else if (env.isSkylark()) { // Only allow native Java calls when using Skylark // When calling a Java method, the name is not in the Environment, // so evaluating 'func' would fail. evalArguments(posargs, kwargs, env, null); - if (!kwargs.isEmpty()) { - throw new EvalException( - func.getLocation(), - String.format( - "Keyword arguments are not allowed when calling a java method" - + "\nwhile calling method '%s' on object %s of type %s", - func.getName(), objValue, EvalUtils.getDataTypeName(objValue))); - } if (objValue instanceof Class<?>) { // Static Java method call. We can return the value from here directly because // invokeJavaMethod() has special checks. - return invokeJavaMethod(null, (Class<?>) objValue, func.getName(), posargs.build()); + return invokeJavaMethod( + null, (Class<?>) objValue, func.getName(), posargs.build(), !kwargs.isEmpty()); } else { - return invokeJavaMethod(objValue, objValue.getClass(), func.getName(), posargs.build()); + return invokeJavaMethod( + objValue, objValue.getClass(), func.getName(), posargs.build(), !kwargs.isEmpty()); } } else { throw new EvalException( |