Example #1
0
  /** check types and convert as required */
  protected void canonicalizeArguments(Object[] arguments, Location loc) throws EvalException {
    // TODO(bazel-team): maybe link syntax.SkylarkType and package.Type,
    // so we can simultaneously typecheck and convert?
    // Note that a BuiltinFunction already does typechecking of simple types.

    List<SkylarkType> types = getEnforcedArgumentTypes();

    // Check types, if supplied
    if (types == null) {
      return;
    }
    List<String> names = signature.getSignature().getNames();
    int length = types.size();
    for (int i = 0; i < length; i++) {
      Object value = arguments[i];
      SkylarkType type = types.get(i);
      if (value != null && type != null && !type.contains(value)) {
        throw new EvalException(
            loc,
            String.format(
                "expected %s for '%s' while calling %s but got %s instead: %s",
                type, names.get(i), getName(), EvalUtils.getDataTypeName(value, true), value));
      }
    }
  }
Example #2
0
  /** Configure the reflection mechanism */
  @Override
  protected void configure() {
    invokeMethod = findMethod("invoke");

    int arguments = signature.getSignature().getShape().getArguments();
    innerArgumentCount = arguments + (extraArgs == null ? 0 : extraArgs.length);
    Class<?>[] parameterTypes = invokeMethod.getParameterTypes();
    Preconditions.checkArgument(
        innerArgumentCount == parameterTypes.length,
        "bad argument count for %s: method has %s arguments, type list has %s",
        getName(),
        innerArgumentCount,
        parameterTypes.length);

    if (enforcedArgumentTypes != null) {
      for (int i = 0; i < arguments; i++) {
        SkylarkType enforcedType = enforcedArgumentTypes.get(i);
        if (enforcedType != null) {
          Class<?> parameterType = parameterTypes[i];
          String msg =
              String.format(
                  "fun %s(%s), param %s, enforcedType: %s (%s); parameterType: %s",
                  getName(),
                  signature,
                  signature.getSignature().getNames().get(i),
                  enforcedType,
                  enforcedType.getType(),
                  parameterType);
          if (enforcedType instanceof SkylarkType.Simple
              || enforcedType instanceof SkylarkFunctionType) {
            Preconditions.checkArgument(enforcedType.getType() == parameterType, msg);
            // No need to enforce Simple types on the Skylark side, the JVM will do it for us.
            enforcedArgumentTypes.set(i, null);
          } else if (enforcedType instanceof SkylarkType.Combination) {
            Preconditions.checkArgument(enforcedType.getType() == parameterType, msg);
          } else {
            Preconditions.checkArgument(
                parameterType == Object.class || parameterType == null, msg);
          }
        }
      }
    }
    // No need for the enforcedArgumentTypes List if all the types were Simple
    enforcedArgumentTypes = FunctionSignature.<SkylarkType>valueListOrNull(enforcedArgumentTypes);

    if (returnType != null) {
      Class<?> type = returnType;
      if (type == HackHackEitherList.class) {
        type = Object.class;
      }
      Class<?> methodReturnType = invokeMethod.getReturnType();
      Preconditions.checkArgument(
          type == methodReturnType,
          "signature for function %s says it returns %s but its invoke method returns %s",
          getName(),
          returnType,
          methodReturnType);
    }
  }
Example #3
0
 private static SkylarkType checkType(SkylarkType builderType, SkylarkType itemType, Location loc)
     throws EvalException {
   if (SkylarkType.intersection(SkylarkType.Union.of(SkylarkType.DICT, SkylarkType.LIST), itemType)
       != SkylarkType.BOTTOM) {
     throw new EvalException(
         loc, String.format("sets cannot contain items of type '%s'", itemType));
   }
   SkylarkType newType = SkylarkType.intersection(builderType, itemType);
   if (newType == SkylarkType.BOTTOM) {
     throw new EvalException(
         loc,
         String.format("cannot add an item of type '%s' to a set of '%s'", itemType, builderType));
   }
   return newType;
 }
Example #4
0
 // Ensure that values are all acceptable to Skylark before to stuff them in a ClassObject
 private ImmutableMap<String, Object> copyValues(Map<String, Object> values) {
   ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
   for (Map.Entry<String, Object> e : values.entrySet()) {
     builder.put(e.getKey(), SkylarkType.convertToSkylark(e.getValue(), null));
   }
   return builder.build();
 }
Example #5
0
 /** Returns a value and try to cast it into specified type */
 public <TYPE> TYPE getValue(String key, Class<TYPE> type) throws EvalException {
   Object obj = values.get(key);
   if (obj == null) {
     return null;
   }
   SkylarkType.checkType(obj, type, key);
   return type.cast(obj);
 }
Example #6
0
 // The precondition ensures generic type safety
 @SuppressWarnings("unchecked")
 public <T> NestedSet<T> getSet(Class<T> type) {
   // Empty sets don't need have to have a type since they don't have items
   if (set.isEmpty()) {
     return (NestedSet<T>) set;
   }
   Preconditions.checkArgument(
       contentType.canBeCastTo(type),
       String.format(
           "Expected a set of '%s' but got a set of '%s'",
           EvalUtils.getDataTypeNameFromClass(type), contentType));
   return (NestedSet<T>) set;
 }
Example #7
0
  // This is safe because of the type checking
  @SuppressWarnings("unchecked")
  private SkylarkNestedSet(
      Order order,
      SkylarkType contentType,
      Object item,
      Location loc,
      List<Object> items,
      List<NestedSet<Object>> transitiveItems)
      throws EvalException {

    // Adding the item
    if (item instanceof SkylarkNestedSet) {
      SkylarkNestedSet nestedSet = (SkylarkNestedSet) item;
      if (!nestedSet.isEmpty()) {
        contentType = checkType(contentType, nestedSet.contentType, loc);
        transitiveItems.add((NestedSet<Object>) nestedSet.set);
      }
    } else if (item instanceof SkylarkList) {
      // TODO(bazel-team): we should check ImmutableList here but it screws up genrule at line 43
      for (Object object : (SkylarkList) item) {
        contentType = checkType(contentType, SkylarkType.of(object.getClass()), loc);
        checkImmutable(object, loc);
        items.add(object);
      }
    } else {
      throw new EvalException(
          loc,
          String.format("cannot add value of type '%s' to a set", EvalUtils.getDataTypeName(item)));
    }
    this.contentType = Preconditions.checkNotNull(contentType, "type cannot be null");

    // Initializing the real nested set
    NestedSetBuilder<Object> builder = new NestedSetBuilder<>(order);
    builder.addAll(items);
    try {
      for (NestedSet<Object> nestedSet : transitiveItems) {
        builder.addTransitive(nestedSet);
      }
    } catch (IllegalStateException e) {
      throw new EvalException(loc, e.getMessage());
    }
    this.set = builder.build();
    this.items = ImmutableList.copyOf(items);
    this.transitiveItems = ImmutableList.copyOf(transitiveItems);
  }
Example #8
0
 /**
  * A not type safe constructor for SkylarkNestedSet, specifying type as a Java class. It's
  * discouraged to use it unless type generic safety is guaranteed from the caller side.
  */
 public SkylarkNestedSet(Class<?> contentType, NestedSet<?> set) {
   this(SkylarkType.of(contentType), set);
 }
Example #9
0
 /** Returns a type safe SkylarkNestedSet. Use this instead of the constructor if possible. */
 public static <T> SkylarkNestedSet of(Class<T> contentType, NestedSet<T> set) {
   return of(SkylarkType.of(contentType), set);
 }