use of com.google.devtools.build.lib.skylarkinterface.Param in project bazel by bazelbuild.
the class FuncallExpression method convertArgumentList.
/**
* Constructs the parameters list to actually pass to the method, filling with default values if
* 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) {
ImmutableList.Builder<Object> builder = ImmutableList.builder();
Class<?>[] params = method.getMethod().getParameterTypes();
SkylarkCallable callable = method.getAnnotation();
int mandatoryPositionals = callable.mandatoryPositionals();
if (mandatoryPositionals < 0) {
if (callable.parameters().length > 0) {
mandatoryPositionals = 0;
} else {
mandatoryPositionals = params.length;
}
}
if (mandatoryPositionals > args.size() || 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) {
Object value = args.get(i);
if (!param.isAssignableFrom(value.getClass())) {
return ArgumentListConversionResult.fromError(String.format("Cannot convert parameter at position %d from type %s to type %s", i, EvalUtils.getDataTypeName(value), param.toString()));
}
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);
if (param.noneable()) {
type = SkylarkType.Union.of(type, SkylarkType.NONE);
}
Object value = null;
if (i < args.size()) {
value = args.get(i);
if (!param.positional()) {
return ArgumentListConversionResult.fromError(String.format("Parameter '%s' is not positional", param.name()));
} else if (!type.contains(value)) {
return ArgumentListConversionResult.fromError(String.format("Cannot convert parameter '%s' to type %s", param.name(), type.toString()));
}
i++;
} else if (param.named() && keys.remove(param.name())) {
// Named parameters
value = kwargs.get(param.name());
if (!type.contains(value)) {
return ArgumentListConversionResult.fromError(String.format("Cannot convert parameter '%s' to type %s", param.name(), type.toString()));
}
} else {
// Use default value
if (param.defaultValue().isEmpty()) {
return ArgumentListConversionResult.fromError(String.format("parameter '%s' has no default value", param.name()));
}
value = SkylarkSignatureProcessor.getDefaultValue(param, null);
}
builder.add(value);
if (!param.noneable() && value instanceof NoneType) {
return ArgumentListConversionResult.fromError(String.format("parameter '%s' cannot be None", param.name()));
}
}
if (i < args.size() || !keys.isEmpty()) {
return ArgumentListConversionResult.fromError("too many arguments");
}
return ArgumentListConversionResult.fromArgumentList(builder.build());
}
use of com.google.devtools.build.lib.skylarkinterface.Param in project bazel by bazelbuild.
the class SkylarkSignatureProcessor method getSignature.
/**
* Extracts a {@code FunctionSignature.WithValues<Object, SkylarkType>} from an annotation
* @param name the name of the function
* @param annotation the annotation
* @param defaultValues an optional list of default values
* @param paramDoc an optional list into which to store documentation strings
* @param enforcedTypesList an optional list into which to store effective types to enforce
*/
// NB: the two arguments paramDoc and enforcedTypesList are used to "return" extra values via
// side-effects, and that's ugly
// TODO(bazel-team): use AutoValue to declare a value type to use as return value?
public static FunctionSignature.WithValues<Object, SkylarkType> getSignature(String name, SkylarkSignature annotation, @Nullable Iterable<Object> defaultValues, @Nullable List<String> paramDoc, @Nullable List<SkylarkType> enforcedTypesList) {
Preconditions.checkArgument(name.equals(annotation.name()), "%s != %s", name, annotation.name());
ArrayList<Parameter<Object, SkylarkType>> paramList = new ArrayList<>();
HashMap<String, SkylarkType> enforcedTypes = enforcedTypesList == null ? null : new HashMap<String, SkylarkType>();
HashMap<String, String> doc = new HashMap<>();
boolean documented = annotation.documented();
if (annotation.doc().isEmpty() && documented) {
throw new RuntimeException(String.format("function %s is undocumented", name));
}
Iterator<Object> defaultValuesIterator = defaultValues == null ? null : defaultValues.iterator();
try {
boolean named = false;
for (Param param : annotation.parameters()) {
boolean mandatory = param.defaultValue() != null && param.defaultValue().isEmpty();
Object defaultValue = mandatory ? null : getDefaultValue(param, defaultValuesIterator);
if (param.named() && !param.positional() && !named) {
named = true;
@Nullable Param starParam = null;
if (!annotation.extraPositionals().name().isEmpty()) {
starParam = annotation.extraPositionals();
}
paramList.add(getParameter(name, starParam, enforcedTypes, doc, documented, /*mandatory=*/
false, /*star=*/
true, /*starStar=*/
false, /*defaultValue=*/
null));
}
paramList.add(getParameter(name, param, enforcedTypes, doc, documented, mandatory, /*star=*/
false, /*starStar=*/
false, defaultValue));
}
if (!annotation.extraPositionals().name().isEmpty() && !named) {
paramList.add(getParameter(name, annotation.extraPositionals(), enforcedTypes, doc, documented, /*mandatory=*/
false, /*star=*/
true, /*starStar=*/
false, /*defaultValue=*/
null));
}
if (!annotation.extraKeywords().name().isEmpty()) {
paramList.add(getParameter(name, annotation.extraKeywords(), enforcedTypes, doc, documented, /*mandatory=*/
false, /*star=*/
false, /*starStar=*/
true, /*defaultValue=*/
null));
}
FunctionSignature.WithValues<Object, SkylarkType> signature = FunctionSignature.WithValues.<Object, SkylarkType>of(paramList);
for (String paramName : signature.getSignature().getNames()) {
if (enforcedTypesList != null) {
enforcedTypesList.add(enforcedTypes.get(paramName));
}
if (paramDoc != null) {
paramDoc.add(doc.get(paramName));
}
}
return signature;
} catch (FunctionSignature.SignatureException e) {
throw new RuntimeException(String.format("Invalid signature while configuring BuiltinFunction %s", name), e);
}
}
use of com.google.devtools.build.lib.skylarkinterface.Param in project bazel by bazelbuild.
the class SkylarkMethodDoc method getParameterString.
private String getParameterString(Method method) {
SkylarkCallable annotation = SkylarkInterfaceUtils.getSkylarkCallable(method);
int nbPositional = annotation.mandatoryPositionals();
if (annotation.parameters().length > 0 && nbPositional < 0) {
nbPositional = 0;
}
List<String> argList = new ArrayList<>();
for (int i = 0; i < nbPositional; i++) {
argList.add("arg" + i + ":" + getTypeAnchor(method.getParameterTypes()[i]));
}
boolean named = false;
for (Param param : annotation.parameters()) {
if (param.named() && !param.positional() && !named) {
named = true;
if (!argList.isEmpty()) {
argList.add("*");
}
}
argList.add(formatParameter(param));
}
return Joiner.on(", ").join(argList);
}
use of com.google.devtools.build.lib.skylarkinterface.Param in project bazel by bazelbuild.
the class SkylarkMethodDoc method getSignature.
protected String getSignature(String objectName, SkylarkSignature method) {
List<String> argList = new ArrayList<>();
boolean named = false;
for (Param param : adjustedParameters(method)) {
if (param.named() && !param.positional() && !named) {
named = true;
if (!method.extraPositionals().name().isEmpty()) {
argList.add("*" + method.extraPositionals().name());
}
if (!argList.isEmpty()) {
argList.add("*");
}
}
argList.add(formatParameter(param));
}
if (!named && !method.extraPositionals().name().isEmpty()) {
argList.add("*" + method.extraPositionals().name());
}
if (!method.extraKeywords().name().isEmpty()) {
argList.add("**" + method.extraKeywords().name());
}
String args = "(" + Joiner.on(", ").join(argList) + ")";
if (!objectName.equals(TOP_LEVEL_ID)) {
return String.format("%s %s.%s%s\n", getTypeAnchor(method.returnType()), objectName, method.name(), args);
} else {
return String.format("%s %s%s\n", getTypeAnchor(method.returnType()), method.name(), args);
}
}
Aggregations