Beispiel #1
0
 @Override
 public Environment createEnvironment(EventHandler eventHandler, Environment environment) {
   return Environment.builder(Mutability.create("build test"))
       .setGlobals(environment == null ? Environment.BUILD : environment.getGlobals())
       .setEventHandler(eventHandler)
       .build();
 }
Beispiel #2
0
 private static Environment.Frame createConstantsGlobals() {
   try (Mutability mutability = Mutability.create("CONSTANTS")) {
     Environment env = Environment.builder(mutability).build();
     Runtime.setupConstants(env);
     return env.getGlobals();
   }
 }
Beispiel #3
0
 private static Environment.Frame createSkylarkGlobals() {
   try (Mutability mutability = Mutability.create("SKYLARK")) {
     Environment env = Environment.builder(mutability).setSkylark().build();
     Runtime.setupConstants(env);
     Runtime.setupMethodEnvironment(env, MethodLibrary.skylarkGlobalFunctions);
     return env.getGlobals();
   }
 }
Beispiel #4
0
 @Override
 public Environment createEnvironment(EventHandler eventHandler, Environment environment) {
   return Environment.builder(Mutability.create("skylark test"))
       .setSkylark()
       .setGlobals(environment == null ? Environment.SKYLARK : environment.getGlobals())
       .setEventHandler(eventHandler)
       .build();
 }
  /**
   * Create a Rule Configured Target from the ruleContext and the ruleImplementation. The
   * registeredProviderTypes map indicates which keys in structs returned by skylark rules should be
   * interpreted as native TransitiveInfoProvider instances of type (map value).
   */
  public static ConfiguredTarget buildRule(
      RuleContext ruleContext,
      BaseFunction ruleImplementation,
      Map<String, Class<? extends TransitiveInfoProvider>> registeredProviderTypes)
      throws InterruptedException {
    String expectFailure = ruleContext.attributes().get("expect_failure", Type.STRING);
    try (Mutability mutability = Mutability.create("configured target")) {
      SkylarkRuleContext skylarkRuleContext = new SkylarkRuleContext(ruleContext, Kind.RULE);
      Environment env =
          Environment.builder(mutability)
              .setSkylark()
              .setCallerLabel(ruleContext.getLabel())
              .setGlobals(
                  ruleContext
                      .getRule()
                      .getRuleClassObject()
                      .getRuleDefinitionEnvironment()
                      .getGlobals())
              .setEventHandler(ruleContext.getAnalysisEnvironment().getEventHandler())
              .build(); // NB: loading phase functions are not available: this is analysis already,
      // so we do *not* setLoadingPhase().
      Object target =
          ruleImplementation.call(
              ImmutableList.<Object>of(skylarkRuleContext),
              ImmutableMap.<String, Object>of(),
              /*ast=*/ null,
              env);

      if (ruleContext.hasErrors()) {
        return null;
      } else if (!(target instanceof SkylarkClassObject)
          && target != Runtime.NONE
          && !(target instanceof Iterable)) {
        ruleContext.ruleError(
            String.format(
                "Rule should return a return a struct or a list, but got %s",
                SkylarkType.typeOf(target)));
        return null;
      } else if (!expectFailure.isEmpty()) {
        ruleContext.ruleError("Expected failure not found: " + expectFailure);
        return null;
      }
      ConfiguredTarget configuredTarget =
          createTarget(ruleContext, target, registeredProviderTypes);
      SkylarkProviderValidationUtil.checkOrphanArtifacts(ruleContext);
      return configuredTarget;
    } catch (EvalException e) {
      addRuleToStackTrace(e, ruleContext.getRule(), ruleImplementation);
      // If the error was expected, return an empty target.
      if (!expectFailure.isEmpty() && getMessageWithoutStackTrace(e).matches(expectFailure)) {
        return new com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder(ruleContext)
            .add(RunfilesProvider.class, RunfilesProvider.EMPTY)
            .build();
      }
      ruleContext.ruleError("\n" + e.print());
      return null;
    }
  }
Beispiel #6
0
 /**
  * Checks that this Freezable object can be mutated from the given {@link Environment}.
  *
  * @param object a Freezable object that we check is still mutable.
  * @param env the {@link Environment} attempting the mutation.
  * @throws MutabilityException when the object was frozen already, or is from another context.
  */
 public static void checkMutable(Freezable object, Environment env) throws MutabilityException {
   if (!object.mutability().isMutable()) {
     throw new MutabilityException("trying to mutate a frozen object");
   }
   // Consider an {@link Environment} e1, in which is created {@link UserDefinedFunction} f1,
   // that closes over some variable v1 bound to list l1. If somehow, via the magic of callbacks,
   // f1 or l1 is passed as argument to some function f2 evaluated in {@link environment} e2
   // while e1 is be mutable, e2, being a different {@link Environment}, should not be
   // allowed to mutate objects from e1. It's a bug, that shouldn't happen in our current code
   // base, so we throw an AssertionError. If in the future such situations are allowed to happen,
   // then we should throw a MutabilityException instead.
   if (!object.mutability().equals(env.mutability())) {
     throw new AssertionError("trying to mutate an object from a different context");
   }
 }
  private Object callCompiledFunction(Object[] arguments, FuncallExpression ast, Environment env) {
    compilerDebug("Calling compiled function " + getLocationPathAndLine() + " " + getName());
    try {
      Profiler.instance()
          .startTask(
              ProfilerTask.SKYLARK_USER_COMPILED_FN, getLocationPathAndLine() + "#" + getName());
      env.enterScope(this, ast, definitionGlobals);

      return method
          .get()
          .invoke(null, ImmutableList.builder().add(arguments).add(env).build().toArray());

    } catch (IllegalAccessException e) {
      // this should never happen
      throw new RuntimeException(
          "Compiler created code that could not be accessed reflectively.", e);
    } catch (InvocationTargetException e) {
      compilerDebug("Error running compiled version", e.getCause());
      return null;
    } finally {
      Profiler.instance().completeTask(ProfilerTask.SKYLARK_USER_COMPILED_FN);
      env.exitScope();
    }
  }
Beispiel #8
0
  /**
   * If the rule was created by a macro, this method sets the appropriate values for the attributes
   * generator_{name, function, location} and returns all attributes.
   *
   * <p>Otherwise, it returns the given attributes without any changes.
   */
  private static AttributesAndLocation generatorAttributesForMacros(
      BuildLangTypedAttributeValuesMap args,
      @Nullable Environment env,
      Location location,
      Label label) {
    // Returns the original arguments if a) there is only the rule itself on the stack
    // trace (=> no macro) or b) the attributes have already been set by Python pre-processing.
    if (env == null) {
      return new AttributesAndLocation(args, location);
    }
    boolean hasName = args.containsAttributeNamed("generator_name");
    boolean hasFunc = args.containsAttributeNamed("generator_function");
    // TODO(bazel-team): resolve cases in our code where hasName && !hasFunc, or hasFunc && !hasName
    if (hasName || hasFunc) {
      return new AttributesAndLocation(args, location);
    }
    Pair<FuncallExpression, BaseFunction> topCall = env.getTopCall();
    if (topCall == null || !(topCall.second instanceof UserDefinedFunction)) {
      return new AttributesAndLocation(args, location);
    }

    FuncallExpression generator = topCall.first;
    BaseFunction function = topCall.second;
    String name = generator.getNameArg();

    ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
    for (String attributeName : args.getAttributeNames()) {
      builder.put(attributeName, args.getAttributeValue(attributeName));
    }
    builder.put("generator_name", (name == null) ? args.getAttributeValue("name") : name);
    builder.put("generator_function", function.getName());

    if (generator.getLocation() != null) {
      location = generator.getLocation();
    }
    String relativePath = maybeGetRelativeLocation(location, label);
    if (relativePath != null) {
      builder.put("generator_location", relativePath);
    }

    try {
      return new AttributesAndLocation(
          new BuildLangTypedAttributeValuesMap(builder.build()), location);
    } catch (IllegalArgumentException ex) {
      // We just fall back to the default case and swallow any messages.
      return new AttributesAndLocation(args, location);
    }
  }
  @Override
  public Object call(Object[] arguments, FuncallExpression ast, Environment env)
      throws EvalException, InterruptedException {
    if (!env.mutability().isMutable()) {
      throw new EvalException(getLocation(), "Trying to call in frozen environment");
    }
    if (env.getStackTrace().contains(this)) {
      throw new EvalException(
          getLocation(),
          String.format(
              "Recursion was detected when calling '%s' from '%s'",
              getName(), Iterables.getLast(env.getStackTrace()).getName()));
    }

    if (enableCompiler && method.isPresent()) {
      Object returnValue = callCompiledFunction(arguments, ast, env);
      if (returnValue != null) {
        return returnValue;
      }
    }

    Profiler.instance().startTask(ProfilerTask.SKYLARK_USER_FN, getName());
    try {
      env.enterScope(this, ast, definitionGlobals);
      ImmutableList<String> names = signature.getSignature().getNames();

      // Registering the functions's arguments as variables in the local Environment
      int i = 0;
      for (String name : names) {
        env.update(name, arguments[i++]);
      }

      try {
        for (Statement stmt : statements) {
          if (stmt instanceof ReturnStatement) {
            // Performance optimization.
            // Executing the statement would throw an exception, which is slow.
            return ((ReturnStatement) stmt).getReturnExpression().eval(env);
          } else {
            stmt.exec(env);
          }
        }
      } catch (ReturnStatement.ReturnException e) {
        return e.getValue();
      }
      return Runtime.NONE;
    } finally {
      Profiler.instance().completeTask(ProfilerTask.SKYLARK_USER_FN);
      env.exitScope();
    }
  }
Beispiel #10
0
  @Override
  void exec(Environment env) throws EvalException, InterruptedException {
    List<Expression> defaultExpressions = signature.getDefaultValues();
    ArrayList<Object> defaultValues = null;
    ArrayList<SkylarkType> types = null;

    if (defaultExpressions != null) {
      defaultValues = new ArrayList<>(defaultExpressions.size());
      for (Expression expr : defaultExpressions) {
        defaultValues.add(expr.eval(env));
      }
    }
    env.update(
        ident.getName(),
        new UserDefinedFunction(
            ident,
            FunctionSignature.WithValues.<Object, SkylarkType>create(
                signature.getSignature(), defaultValues, types),
            statements,
            (SkylarkEnvironment) env));
  }
Beispiel #11
0
 /**
  * Constructs an Extension by extracting the new global definitions from an Environment. Also
  * caches a hash code for the transitive content of the file and its dependencies.
  *
  * @param env the Environment from which to extract an Extension.
  */
 public Extension(Environment env) {
   super(env);
   this.transitiveContentHashCode = env.getTransitiveContentHashCode();
 }