use of com.google.devtools.build.lib.syntax.EvalException.EvalExceptionWithJavaCause in project bazel by bazelbuild.
the class FuncallExpression method invokeObjectMethod.
/**
* Call a method depending on the type of an object it is called on.
*
* <p>Public for reflection by the compiler and access from generated byte code.
*
* @param positionals The first object is expected to be the object the method is called on.
* @param call the original expression that caused this call, needed for rules especially
*/
public Object invokeObjectMethod(String method, ImmutableList<Object> positionals, ImmutableMap<String, Object> keyWordArgs, FuncallExpression call, Environment env) throws EvalException, InterruptedException {
Location location = call.getLocation();
Object value = positionals.get(0);
ImmutableList<Object> positionalArgs = positionals.subList(1, positionals.size());
BaseFunction function = Runtime.getFunction(EvalUtils.getSkylarkType(value.getClass()), method);
if (function != null) {
if (!isNamespace(value.getClass())) {
// Use self as an implicit parameter in front.
positionalArgs = positionals;
}
return function.call(positionalArgs, ImmutableMap.<String, Object>copyOf(keyWordArgs), call, env);
} else if (value instanceof ClassObject) {
Object fieldValue = ((ClassObject) value).getValue(method);
if (fieldValue == null) {
throw new EvalException(location, String.format("struct has no method '%s'", method));
}
if (!(fieldValue instanceof BaseFunction)) {
throw new EvalException(location, String.format("struct field '%s' is not a function", method));
}
function = (BaseFunction) fieldValue;
return function.call(positionalArgs, ImmutableMap.<String, Object>copyOf(keyWordArgs), call, env);
} else {
// When calling a Java method, the name is not in the Environment,
// so evaluating 'func' would fail.
Class<?> objClass;
Object obj;
if (value instanceof Class<?>) {
// Static call
obj = null;
objClass = (Class<?>) value;
} else {
obj = value;
objClass = value.getClass();
}
Pair<MethodDescriptor, List<Object>> javaMethod = call.findJavaMethod(objClass, method, positionalArgs, keyWordArgs);
if (javaMethod.first.getAnnotation().structField()) {
// Not a method but a callable attribute
try {
return callFunction(javaMethod.first.getMethod().invoke(obj), env);
} catch (IllegalAccessException e) {
throw new EvalException(getLocation(), "method invocation failed: " + e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof FuncallException) {
throw new EvalException(getLocation(), e.getCause().getMessage());
} else if (e.getCause() != null) {
throw new EvalExceptionWithJavaCause(getLocation(), e.getCause());
} else {
// This is unlikely to happen
throw new EvalException(getLocation(), "method invocation failed: " + e);
}
}
}
return callMethod(javaMethod.first, method, obj, javaMethod.second.toArray(), location, env);
}
}
use of com.google.devtools.build.lib.syntax.EvalException.EvalExceptionWithJavaCause in project bazel by bazelbuild.
the class FuncallExpression method callMethod.
static Object callMethod(MethodDescriptor methodDescriptor, String methodName, Object obj, Object[] args, Location loc, Environment env) throws EvalException {
try {
Method method = methodDescriptor.getMethod();
if (obj == null && !Modifier.isStatic(method.getModifiers())) {
throw new EvalException(loc, "method '" + methodName + "' is not static");
}
// This happens when the interface is public but the implementation classes
// have reduced visibility.
method.setAccessible(true);
Object result = method.invoke(obj, args);
if (method.getReturnType().equals(Void.TYPE)) {
return Runtime.NONE;
}
if (result == null) {
if (methodDescriptor.getAnnotation().allowReturnNones()) {
return Runtime.NONE;
} else {
throw new EvalException(loc, "method invocation returned None, please file a bug report: " + methodName + Printer.listString(ImmutableList.copyOf(args), "(", ", ", ")", null));
}
}
// TODO(bazel-team): get rid of this, by having everyone use the Skylark data structures
result = SkylarkType.convertToSkylark(result, method, env);
if (result != null && !EvalUtils.isSkylarkAcceptable(result.getClass())) {
throw new EvalException(loc, Printer.format("method '%s' returns an object of invalid type %r", methodName, result.getClass()));
}
return result;
} catch (IllegalAccessException e) {
// and an argument is missing or has the wrong type.
throw new EvalException(loc, "Method invocation failed: " + e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof FuncallException) {
throw new EvalException(loc, e.getCause().getMessage());
} else if (e.getCause() != null) {
throw new EvalExceptionWithJavaCause(loc, e.getCause());
} else {
// This is unlikely to happen
throw new EvalException(loc, "method invocation failed: " + e);
}
}
}
Aggregations