diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java | 77 |
1 files changed, 52 insertions, 25 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 2639c2735d..841a94ac13 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 @@ -261,18 +261,18 @@ public final class FuncallExpression extends Expression { return numPositionalArgs; } - @Override - public void prettyPrint(Appendable buffer) throws IOException { - function.prettyPrint(buffer); - buffer.append('('); - String sep = ""; - for (Argument.Passed arg : arguments) { - buffer.append(sep); - arg.prettyPrint(buffer); - sep = ", "; - } - buffer.append(')'); - } + @Override + public void prettyPrint(Appendable buffer) throws IOException { + function.prettyPrint(buffer); + buffer.append('('); + String sep = ""; + for (Argument.Passed arg : arguments) { + buffer.append(sep); + arg.prettyPrint(buffer); + sep = ", "; + } + buffer.append(')'); + } @Override public String toString() { @@ -361,7 +361,7 @@ public final class FuncallExpression extends Expression { "method invocation returned None, please file a bug report: " + methodName + Printer.printAbbreviatedList( - ImmutableList.copyOf(args), "(", ", ", ")", null)); + ImmutableList.copyOf(args), "(", ", ", ")", null)); } } // TODO(bazel-team): get rid of this, by having everyone use the Skylark data structures @@ -394,7 +394,11 @@ public final class FuncallExpression extends Expression { // exactly and copy that behaviour. // Throws an EvalException when it cannot find a matching function. private Pair<MethodDescriptor, List<Object>> findJavaMethod( - Class<?> objClass, String methodName, List<Object> args, Map<String, Object> kwargs) + Class<?> objClass, + String methodName, + List<Object> args, + Map<String, Object> kwargs, + Environment environment) throws EvalException { Pair<MethodDescriptor, List<Object>> matchingMethod = null; List<MethodDescriptor> methods = getMethods(objClass, methodName); @@ -402,9 +406,10 @@ public final class FuncallExpression extends Expression { if (methods != null) { for (MethodDescriptor method : methods) { if (method.getAnnotation().structField()) { + // TODO(cparsons): Allow structField methods to accept interpreter-supplied arguments. return new Pair<>(method, null); } else { - argumentListConversionResult = convertArgumentList(args, kwargs, method); + argumentListConversionResult = convertArgumentList(args, kwargs, method, environment); if (argumentListConversionResult.getArguments() != null) { if (matchingMethod == null) { matchingMethod = new Pair<>(method, argumentListConversionResult.getArguments()); @@ -471,26 +476,36 @@ public final class FuncallExpression extends Expression { * any. If there is a type or argument mismatch, returns a result containing an error message. */ private ArgumentListConversionResult convertArgumentList( - List<Object> args, Map<String, Object> kwargs, MethodDescriptor method) { + List<Object> args, + Map<String, Object> kwargs, + MethodDescriptor method, + Environment environment) { ImmutableList.Builder<Object> builder = ImmutableList.builder(); - Class<?>[] params = method.getMethod().getParameterTypes(); + Class<?>[] javaMethodSignatureParams = method.getMethod().getParameterTypes(); SkylarkCallable callable = method.getAnnotation(); + int numExtraInterpreterParams = 0; + numExtraInterpreterParams += callable.useLocation() ? 1 : 0; + numExtraInterpreterParams += callable.useAst() ? 1 : 0; + numExtraInterpreterParams += callable.useEnvironment() ? 1 : 0; + int mandatoryPositionals = callable.mandatoryPositionals(); if (mandatoryPositionals < 0) { if (callable.parameters().length > 0) { mandatoryPositionals = 0; } else { - mandatoryPositionals = params.length; + mandatoryPositionals = javaMethodSignatureParams.length - numExtraInterpreterParams; } } - if (mandatoryPositionals > args.size() - || args.size() > mandatoryPositionals + callable.parameters().length) { + if (mandatoryPositionals > args.size()) { + return ArgumentListConversionResult.fromError("too few arguments"); + } + if (args.size() > mandatoryPositionals + callable.parameters().length) { return ArgumentListConversionResult.fromError("too many arguments"); } // First process the legacy positional parameters. int i = 0; if (mandatoryPositionals > 0) { - for (Class<?> param : params) { + for (Class<?> param : javaMethodSignatureParams) { Object value = args.get(i); if (!param.isAssignableFrom(value.getClass())) { return ArgumentListConversionResult.fromError( @@ -500,7 +515,7 @@ public final class FuncallExpression extends Expression { } builder.add(value); i++; - if (mandatoryPositionals >= 0 && i >= mandatoryPositionals) { + if (i >= mandatoryPositionals) { // Stops for specified parameters instead. break; } @@ -554,9 +569,21 @@ public final class FuncallExpression extends Expression { if (!keys.isEmpty()) { return ArgumentListConversionResult.fromError( String.format("unexpected keyword%s %s", - keys.size() > 1 ? "s" : "", - Joiner.on(",").join(Iterables.transform(keys, s -> "'" + s + "'")))); + keys.size() > 1 ? "s" : "", + Joiner.on(",").join(Iterables.transform(keys, s -> "'" + s + "'")))); + } + + // Then add any skylark-info arguments (for example the Environment). + if (callable.useLocation()) { + builder.add(getLocation()); } + if (callable.useAst()) { + builder.add(this); + } + if (callable.useEnvironment()) { + builder.add(environment); + } + return ArgumentListConversionResult.fromArgumentList(builder.build()); } @@ -690,7 +717,7 @@ public final class FuncallExpression extends Expression { objClass = value.getClass(); } Pair<MethodDescriptor, List<Object>> javaMethod = - call.findJavaMethod(objClass, method, positionalArgs, keyWordArgs); + call.findJavaMethod(objClass, method, positionalArgs, keyWordArgs, env); if (javaMethod.first.getAnnotation().structField()) { // Not a method but a callable attribute try { |