Search in sources :

Example 1 with Param

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());
}
Also used : SkylarkCallable(com.google.devtools.build.lib.skylarkinterface.SkylarkCallable) ImmutableList(com.google.common.collect.ImmutableList) NoneType(com.google.devtools.build.lib.syntax.Runtime.NoneType) Param(com.google.devtools.build.lib.skylarkinterface.Param) HashSet(java.util.HashSet)

Example 2 with Param

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);
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Param(com.google.devtools.build.lib.skylarkinterface.Param) Nullable(javax.annotation.Nullable)

Example 3 with Param

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);
}
Also used : SkylarkCallable(com.google.devtools.build.lib.skylarkinterface.SkylarkCallable) ArrayList(java.util.ArrayList) Param(com.google.devtools.build.lib.skylarkinterface.Param)

Example 4 with Param

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);
    }
}
Also used : ArrayList(java.util.ArrayList) Param(com.google.devtools.build.lib.skylarkinterface.Param)

Aggregations

Param (com.google.devtools.build.lib.skylarkinterface.Param)4 ArrayList (java.util.ArrayList)3 SkylarkCallable (com.google.devtools.build.lib.skylarkinterface.SkylarkCallable)2 ImmutableList (com.google.common.collect.ImmutableList)1 NoneType (com.google.devtools.build.lib.syntax.Runtime.NoneType)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Nullable (javax.annotation.Nullable)1