Пример #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));
      }
    }
  }
Пример #2
0
 @Test
 public void testDataTypeNames() throws Exception {
   assertEquals("string", EvalUtils.getDataTypeName("foo"));
   assertEquals("int", EvalUtils.getDataTypeName(3));
   assertEquals("tuple", EvalUtils.getDataTypeName(Tuple.of(1, 2, 3)));
   assertEquals("list", EvalUtils.getDataTypeName(MutableList.of(null, 1, 2, 3)));
   assertEquals("dict", EvalUtils.getDataTypeName(makeDict()));
   assertEquals("NoneType", EvalUtils.getDataTypeName(Runtime.NONE));
 }
Пример #3
0
  /**
   * Prints the types of the first {@code howManyArgsToPrint} given arguments as "(type1, type2,
   * ...)"
   */
  protected String printTypeString(Object[] args, int howManyArgsToPrint) {
    StringBuilder builder = new StringBuilder();
    builder.append("(");

    int start = hasSelfArgument() ? 1 : 0;
    for (int pos = start; pos < howManyArgsToPrint; ++pos) {
      builder.append(EvalUtils.getDataTypeName(args[pos]));

      if (pos < howManyArgsToPrint - 1) {
        builder.append(", ");
      }
    }
    builder.append(")");
    return builder.toString();
  }
Пример #4
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);
  }
Пример #5
0
  @Override
  @Nullable
  public Object call(Object[] args, @Nullable FuncallExpression ast, @Nullable Environment env)
      throws EvalException, InterruptedException {
    final Location loc = (ast == null) ? location : ast.getLocation();

    // Add extra arguments, if needed
    if (extraArgs != null) {
      int i = args.length - extraArgs.length;
      for (BuiltinFunction.ExtraArgKind extraArg : extraArgs) {
        switch (extraArg) {
          case LOCATION:
            args[i] = loc;
            break;

          case SYNTAX_TREE:
            args[i] = ast;
            break;

          case ENVIRONMENT:
            args[i] = env;
            break;
        }
        i++;
      }
    }

    // Last but not least, actually make an inner call to the function with the resolved arguments.
    try {
      return invokeMethod.invoke(this, args);
    } catch (InvocationTargetException x) {
      Throwable e = x.getCause();
      if (e instanceof EvalException) {
        throw ((EvalException) e).ensureLocation(loc);
      } else if (e instanceof InterruptedException) {
        throw (InterruptedException) e;
      } else if (e instanceof ClassCastException
          || e instanceof ExecutionException
          || e instanceof IllegalStateException) {
        throw new EvalException(loc, "in call to " + getName(), e);
      } else if (e instanceof IllegalArgumentException) {
        throw new EvalException(loc, "Illegal argument in call to " + getName(), e);
      } else {
        throw badCallException(loc, e, args);
      }
    } catch (IllegalArgumentException e) {
      // Either this was thrown by Java itself, or it's a bug
      // To cover the first case, let's manually check the arguments.
      final int len = args.length - ((extraArgs == null) ? 0 : extraArgs.length);
      final Class<?>[] types = invokeMethod.getParameterTypes();
      for (int i = 0; i < args.length; i++) {
        if (args[i] != null && !types[i].isAssignableFrom(args[i].getClass())) {
          String paramName =
              i < len ? signature.getSignature().getNames().get(i) : extraArgs[i - len].name();
          int extraArgsCount = (extraArgs == null) ? 0 : extraArgs.length;
          throw new EvalException(
              loc,
              String.format(
                  "Method %s is not applicable for arguments %s: '%s' is %s, but should be %s",
                  getShortSignature(true),
                  printTypeString(args, args.length - extraArgsCount),
                  paramName,
                  EvalUtils.getDataTypeName(args[i]),
                  EvalUtils.getDataTypeNameFromClass(types[i])));
        }
      }
      throw badCallException(loc, e, args);
    } catch (IllegalAccessException e) {
      throw badCallException(loc, e, args);
    }
  }