aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java50
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java42
2 files changed, 65 insertions, 27 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 1e49c91330..e5aa180426 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
@@ -29,6 +29,7 @@ import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.syntax.EvalException.EvalExceptionWithJavaCause;
+import com.google.devtools.build.lib.syntax.Runtime.NoneType;
import com.google.devtools.build.lib.syntax.compiler.ByteCodeMethodCalls;
import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils;
import com.google.devtools.build.lib.syntax.compiler.DebugInfo;
@@ -436,54 +437,61 @@ public final class FuncallExpression extends Expression {
ImmutableList.Builder<Object> builder = ImmutableList.builder();
Class<?>[] params = method.getMethod().getParameterTypes();
SkylarkCallable callable = method.getAnnotation();
- int i = 0;
- int nbPositional = callable.mandatoryPositionals();
- if (nbPositional < 0) {
+ int mandatoryPositionals = callable.mandatoryPositionals();
+ if (mandatoryPositionals < 0) {
if (callable.parameters().length > 0) {
- nbPositional = 0;
+ mandatoryPositionals = 0;
} else {
- nbPositional = params.length;
+ mandatoryPositionals = params.length;
}
}
- if (nbPositional > args.size() || args.size() > nbPositional + callable.parameters().length) {
+ if (mandatoryPositionals > args.size()
+ || args.size() > mandatoryPositionals + callable.parameters().length) {
return null;
}
// First process the legacy positional parameters
- for (Class<?> param : params) {
- Object value = args.get(i);
- if (!param.isAssignableFrom(value.getClass())) {
- return null;
- }
- builder.add(value);
- i++;
- if (nbPositional >= 0 && i >= nbPositional) {
- // Stops for specified parameters instead.
- break;
+ int i = 0;
+ if (mandatoryPositionals > 0) {
+ for (Class<?> param : params) {
+ Object value = args.get(i);
+ if (!param.isAssignableFrom(value.getClass())) {
+ return null;
+ }
+ builder.add(value);
+ i++;
+ if (mandatoryPositionals >= 0 && i >= mandatoryPositionals) {
+ // Stops for specified parameters instead.
+ break;
+ }
}
}
// Then the parameters specified in callable.parameters()
Set<String> keys = new HashSet<>(kwargs.keySet());
for (Param param : callable.parameters()) {
SkylarkType type = getType(param);
+ Object value = null;
if (i < args.size()) {
- if (!param.positional() || !type.contains(args.get(i))) {
+ value = args.get(i);
+ if (!param.positional() || !type.contains(value)) {
return null; // next positional argument is not of the good type
}
- builder.add(args.get(i));
i++;
} else if (param.named() && keys.remove(param.name())) {
// Named parameters
- Object value = kwargs.get(param.name());
+ value = kwargs.get(param.name());
if (!type.contains(value)) {
return null; // type does not match
}
- builder.add(value);
} else {
// Use default value
if (param.defaultValue().isEmpty()) {
return null; // no default value
}
- builder.add(SkylarkSignatureProcessor.getDefaultValue(param, null));
+ value = SkylarkSignatureProcessor.getDefaultValue(param, null);
+ }
+ builder.add(value);
+ if (!param.noneable() && value instanceof NoneType) {
+ return null; // cannot be None
}
}
if (i < args.size() || !keys.isEmpty()) {
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
index 7061bf6311..8f0a6f0c2f 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
@@ -124,11 +124,32 @@ public class SkylarkEvaluationTest extends EvaluationTest {
defaultValue = "False",
positional = false,
named = true
- )
+ ),
+ @Param(
+ name = "nonNoneable",
+ type = Object.class,
+ defaultValue = "\"a\"",
+ positional = false,
+ named = true
+ ),
+ @Param(
+ name = "noneable",
+ type = Object.class,
+ defaultValue = "None",
+ noneable = true,
+ positional = false,
+ named = true
+ ),
}
)
public String withParams(
- Integer pos1, boolean pos2, boolean posOrNamed, boolean named, boolean optionalNamed) {
+ Integer pos1,
+ boolean pos2,
+ boolean posOrNamed,
+ boolean named,
+ boolean optionalNamed,
+ Object nonNoneable,
+ Object noneable) {
return "with_params("
+ pos1
+ ", "
@@ -139,6 +160,8 @@ public class SkylarkEvaluationTest extends EvaluationTest {
+ named
+ ", "
+ optionalNamed
+ + ", "
+ + nonNoneable.toString()
+ ")";
}
@@ -647,7 +670,7 @@ public class SkylarkEvaluationTest extends EvaluationTest {
new SkylarkTest()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True)")
- .testLookup("b", "with_params(1, true, false, true, false)");
+ .testLookup("b", "with_params(1, true, false, true, false, a)");
new SkylarkTest()
.update("mock", new Mock())
.setUp("")
@@ -662,21 +685,28 @@ public class SkylarkEvaluationTest extends EvaluationTest {
new SkylarkTest()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, True, named=True)")
- .testLookup("b", "with_params(1, true, true, true, false)");
+ .testLookup("b", "with_params(1, true, true, true, false, a)");
new SkylarkTest()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True, posOrNamed=True)")
- .testLookup("b", "with_params(1, true, true, true, false)");
+ .testLookup("b", "with_params(1, true, true, true, false, a)");
new SkylarkTest()
.update("mock", new Mock())
.setUp("b = mock.with_params(1, True, named=True, posOrNamed=True, optionalNamed=True)")
- .testLookup("b", "with_params(1, true, true, true, true)");
+ .testLookup("b", "with_params(1, true, true, true, true, a)");
new SkylarkTest()
.update("mock", new Mock())
.setUp("")
.testIfExactError(
"Type Mock has no function with_params(int, bool, bool named, bool posOrNamed, int n)",
"mock.with_params(1, True, named=True, posOrNamed=True, n=2)");
+ new SkylarkTest()
+ .update("mock", new Mock())
+ .setUp("")
+ .testIfExactError(
+ "Type Mock has no function with_params(int, bool, bool, bool named, bool optionalNamed,"
+ + " NoneType nonNoneable)",
+ "mock.with_params(1, True, True, named=True, optionalNamed=False, nonNoneable=None)");
}
@Test