private static Artifact getExecutable(RuleContext ruleContext, Object target)
     throws EvalException {
   Artifact executable =
       ruleContext.getRule().getRuleClassObject().outputsDefaultExecutable()
           // This doesn't actually create a new Artifact just returns the one
           // created in SkylarkruleContext.
           ? ruleContext.createOutputArtifact()
           : null;
   if (target instanceof SkylarkClassObject) {
     SkylarkClassObject struct = (SkylarkClassObject) target;
     if (struct.getValue("executable") != null) {
       // We need this because of genrule.bzl. This overrides the default executable.
       executable = cast("executable", struct, Artifact.class, struct.getCreationLoc());
     }
   }
   return executable;
 }
  private static ConfiguredTarget addStructFields(
      RuleContext ruleContext,
      RuleConfiguredTargetBuilder builder,
      Object target,
      Artifact executable)
      throws EvalException {
    Location loc = null;
    Runfiles statelessRunfiles = null;
    Runfiles dataRunfiles = null;
    Runfiles defaultRunfiles = null;
    if (target instanceof SkylarkClassObject) {
      SkylarkClassObject struct = (SkylarkClassObject) target;
      loc = struct.getCreationLoc();
      for (String key : struct.getKeys()) {
        if (key.equals("files")) {
          // If we specify files_to_build we don't have the executable in it by default.
          builder.setFilesToBuild(
              cast("files", struct, SkylarkNestedSet.class, Artifact.class, loc)
                  .getSet(Artifact.class));
        } else if (key.equals("runfiles")) {
          statelessRunfiles = cast("runfiles", struct, Runfiles.class, loc);
        } else if (key.equals("data_runfiles")) {
          dataRunfiles = cast("data_runfiles", struct, Runfiles.class, loc);
        } else if (key.equals("default_runfiles")) {
          defaultRunfiles = cast("default_runfiles", struct, Runfiles.class, loc);
        } else if (!key.equals("executable")) {
          // We handled executable already.
          builder.addSkylarkTransitiveInfo(key, struct.getValue(key), loc);
        }
      }
    }

    if ((statelessRunfiles != null) && (dataRunfiles != null || defaultRunfiles != null)) {
      throw new EvalException(
          loc,
          "Cannot specify the provider 'runfiles' "
              + "together with 'data_runfiles' or 'default_runfiles'");
    }

    if (statelessRunfiles == null && dataRunfiles == null && defaultRunfiles == null) {
      // No runfiles specified, set default
      statelessRunfiles = Runfiles.EMPTY;
    }

    RunfilesProvider runfilesProvider =
        statelessRunfiles != null
            ? RunfilesProvider.simple(merge(statelessRunfiles, executable))
            : RunfilesProvider.withData(
                // The executable doesn't get into the default runfiles if we have runfiles states.
                // This is to keep skylark genrule consistent with the original genrule.
                defaultRunfiles != null ? defaultRunfiles : Runfiles.EMPTY,
                dataRunfiles != null ? dataRunfiles : Runfiles.EMPTY);
    builder.addProvider(RunfilesProvider.class, runfilesProvider);

    Runfiles computedDefaultRunfiles = runfilesProvider.getDefaultRunfiles();
    // This works because we only allowed to call a rule *_test iff it's a test type rule.
    boolean testRule = TargetUtils.isTestRuleName(ruleContext.getRule().getRuleClass());
    if (testRule && computedDefaultRunfiles.isEmpty()) {
      throw new EvalException(loc, "Test rules have to define runfiles");
    }
    if (executable != null || testRule) {
      RunfilesSupport runfilesSupport =
          computedDefaultRunfiles.isEmpty()
              ? null
              : RunfilesSupport.withExecutable(ruleContext, computedDefaultRunfiles, executable);
      builder.setRunfilesSupport(runfilesSupport, executable);
    }
    try {
      return builder.build();
    } catch (IllegalArgumentException e) {
      throw new EvalException(loc, e.getMessage());
    }
  }