aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
diff options
context:
space:
mode:
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.java77
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 {