// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.analysis.skylark;

import static java.util.stream.Collectors.toList;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionLookupValue;
import com.google.devtools.build.lib.actions.ActionRegistry;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.CommandLine;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.RunfilesSupplier;
import com.google.devtools.build.lib.actions.extra.ExtraActionInfo;
import com.google.devtools.build.lib.actions.extra.SpawnInfo;
import com.google.devtools.build.lib.analysis.BashCommandConstructor;
import com.google.devtools.build.lib.analysis.CommandHelper;
import com.google.devtools.build.lib.analysis.ExecGroupCollection;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.PseudoAction;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.ShToolchain;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.actions.StarlarkAction;
import com.google.devtools.build.lib.analysis.actions.Substitution;
import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction;
import com.google.devtools.build.lib.collect.nestedset.Depset;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skylarkbuildapi.FileApi;
import com.google.devtools.build.lib.skylarkbuildapi.StarlarkActionFactoryApi;
import com.google.devtools.build.lib.syntax.Dict;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.Printer;
import com.google.devtools.build.lib.syntax.Sequence;
import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.protobuf.GeneratedMessage;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

/** Provides a Starlark interface for all action creation needs. */
public class StarlarkActionFactory implements StarlarkActionFactoryApi {
  private final StarlarkRuleContext context;
  private final StarlarkSemantics starlarkSemantics;
  private RuleContext ruleContext;
  /** Counter for actions.run_shell helper scripts. Every script must have a unique name. */
  private int runShellOutputCounter = 0;

  public StarlarkActionFactory(
      StarlarkRuleContext context, StarlarkSemantics starlarkSemantics, RuleContext ruleContext) {
    this.context = context;
    this.starlarkSemantics = starlarkSemantics;
    this.ruleContext = ruleContext;
  }

  ArtifactRoot newFileRoot() throws EvalException {
    return context.isForAspect()
        ? ruleContext.getConfiguration().getBinDirectory(ruleContext.getRule().getRepository())
        : ruleContext.getBinOrGenfilesDirectory();
  }

  /**
   * Returns a {@link ActionRegistry} object to register actions using this action factory.
   *
   * @throws EvalException if actions cannot be registered with this object
   */
  public ActionRegistry asActionRegistry(StarlarkActionFactory starlarkActionFactory)
      throws EvalException {
    validateActionCreation();
    return new ActionRegistry() {

      @Override
      public void registerAction(ActionAnalysisMetadata... actions) {
        ruleContext.registerAction(actions);
      }

      @Override
      public ActionLookupValue.ActionLookupKey getOwner() {
        return starlarkActionFactory
            .getActionConstructionContext()
            .getAnalysisEnvironment()
            .getOwner();
      }
    };
  }

  @Override
  public Artifact declareFile(String filename, Object sibling) throws EvalException {
    context.checkMutable("actions.declare_file");

    PathFragment fragment;
    if (Starlark.NONE.equals(sibling)) {
      fragment = ruleContext.getPackageDirectory().getRelative(PathFragment.create(filename));
    } else {
      PathFragment original = ((Artifact) sibling).getRootRelativePath();
      fragment = original.replaceName(filename);
    }

    if (!fragment.startsWith(ruleContext.getPackageDirectory())) {
      throw Starlark.errorf(
          "the output artifact '%s' is not under package directory '%s' for target '%s'",
          fragment, ruleContext.getPackageDirectory(), ruleContext.getLabel());
    }
    return ruleContext.getDerivedArtifact(fragment, newFileRoot());
  }

  @Override
  public Artifact declareDirectory(String filename, Object sibling) throws EvalException {
    context.checkMutable("actions.declare_directory");
    PathFragment fragment;

    if (Starlark.NONE.equals(sibling)) {
      fragment = ruleContext.getPackageDirectory().getRelative(PathFragment.create(filename));
    } else {
      PathFragment original = ((Artifact) sibling).getRootRelativePath();
      fragment = original.replaceName(filename);
    }

    if (!fragment.startsWith(ruleContext.getPackageDirectory())) {
      throw new EvalException(
          String.format(
              "the output directory '%s' is not under package directory '%s' for target '%s'",
              fragment, ruleContext.getPackageDirectory(), ruleContext.getLabel()));
    }

    Artifact result = ruleContext.getTreeArtifact(fragment, newFileRoot());
    if (!result.isTreeArtifact()) {
      throw new EvalException(
          null,
          String.format(
              "'%s' has already been declared as a regular file, not directory.", filename));
    }
    return result;
  }

  @Override
  public Artifact declareSymlink(String filename, Object sibling) throws EvalException {
    context.checkMutable("actions.declare_symlink");

    if (!ruleContext.getConfiguration().allowUnresolvedSymlinks()) {
      throw Starlark.errorf(
          "actions.declare_symlink() is not allowed; "
              + "use the --experimental_allow_unresolved_symlinks command line option");
    }

    Artifact result;
    PathFragment rootRelativePath;
    if (Starlark.NONE.equals(sibling)) {
      rootRelativePath = ruleContext.getPackageDirectory().getRelative(filename);
    } else {
      PathFragment original = ((Artifact) sibling).getRootRelativePath();
      rootRelativePath = original.replaceName(filename);
    }

    result =
        ruleContext.getAnalysisEnvironment().getSymlinkArtifact(rootRelativePath, newFileRoot());

    if (!result.isSymlink()) {
      throw Starlark.errorf(
          "'%s' has already been declared as something other than a symlink.", filename);
    }

    return result;
  }

  @Override
  public void doNothing(String mnemonic, Object inputs) throws EvalException {
    context.checkMutable("actions.do_nothing");
    NestedSet<Artifact> inputSet =
        inputs instanceof Depset
            ? Depset.cast(inputs, Artifact.class, "inputs")
            : NestedSetBuilder.<Artifact>compileOrder()
                .addAll(Sequence.cast(inputs, Artifact.class, "inputs"))
                .build();
    Action action =
        new PseudoAction<>(
            UUID.nameUUIDFromBytes(
                String.format("empty action %s", ruleContext.getLabel())
                    .getBytes(StandardCharsets.UTF_8)),
            ruleContext.getActionOwner(),
            inputSet,
            ImmutableList.of(PseudoAction.getDummyOutput(ruleContext)),
            mnemonic,
            SPAWN_INFO,
            SpawnInfo.newBuilder().build());
    registerAction(action);
  }

  @AutoCodec @AutoCodec.VisibleForSerialization
  static final GeneratedMessage.GeneratedExtension<ExtraActionInfo, SpawnInfo> SPAWN_INFO =
      SpawnInfo.spawnInfo;

  @Override
  public void symlink(
      FileApi output,
      Object /* Artifact or None */ targetFile,
      Object /* String or None */ targetPath,
      Boolean isExecutable,
      Object /* String or None */ progressMessageUnchecked)
      throws EvalException {
    context.checkMutable("actions.symlink");

    if ((targetFile == Starlark.NONE) == (targetPath == Starlark.NONE)) {
      throw Starlark.errorf("Exactly one of \"target_file\" and \"target_path\" is required");
    }

    Artifact outputArtifact = (Artifact) output;
    String progressMessage =
        (progressMessageUnchecked != Starlark.NONE)
            ? (String) progressMessageUnchecked
            : "Creating symlink " + outputArtifact.getRootRelativePathString();

    SymlinkAction action;
    if (targetFile != Starlark.NONE) {
      if (outputArtifact.isSymlink()) {
        throw Starlark.errorf(
            "symlink() with \"target_file\" param requires that \"output\" be declared as a "
                + "regular file, not a symlink (did you mean to use declare_file() instead of "
                + "declare_symlink()?)");
      }

      if (isExecutable) {
        action =
            SymlinkAction.toExecutable(
                ruleContext.getActionOwner(),
                (Artifact) targetFile,
                outputArtifact,
                progressMessage);
      } else {
        action =
            SymlinkAction.toArtifact(
                ruleContext.getActionOwner(),
                (Artifact) targetFile,
                outputArtifact,
                progressMessage);
      }
    } else {
      if (!ruleContext.getConfiguration().allowUnresolvedSymlinks()) {
        throw Starlark.errorf(
            "actions.symlink() to unresolved symlink is not allowed; "
                + "use the --experimental_allow_unresolved_symlinks command line option");
      }

      if (!outputArtifact.isSymlink()) {
        throw Starlark.errorf(
            "symlink() with \"target_path\" param requires that \"output\" be declared as a "
                + "symlink, not a regular file (did you mean to use declare_symlink() instead of "
                + "declare_file()?)");
      }

      if (isExecutable) {
        throw Starlark.errorf("\"is_executable\" cannot be True when using \"target_path\"");
      }

      action =
          SymlinkAction.createUnresolved(
              ruleContext.getActionOwner(),
              outputArtifact,
              PathFragment.create((String) targetPath),
              progressMessage);
    }
    registerAction(action);
  }

  @Override
  public void write(FileApi output, Object content, Boolean isExecutable) throws EvalException {
    context.checkMutable("actions.write");
    final Action action;
    if (content instanceof String) {
      action =
          FileWriteAction.create(ruleContext, (Artifact) output, (String) content, isExecutable);
    } else if (content instanceof Args) {
      Args args = (Args) content;
      action =
          new ParameterFileWriteAction(
              ruleContext.getActionOwner(),
              NestedSetBuilder.wrap(Order.STABLE_ORDER, args.getDirectoryArtifacts()),
              (Artifact) output,
              args.build(),
              args.getParameterFileType());
    } else {
      throw new AssertionError("Unexpected type: " + content.getClass().getSimpleName());
    }
    registerAction(action);
  }

  @Override
  public void run(
      Sequence<?> outputs,
      Object inputs,
      Object unusedInputsList,
      Object executableUnchecked,
      Object toolsUnchecked,
      Object arguments,
      Object mnemonicUnchecked,
      Object progressMessage,
      Boolean useDefaultShellEnv,
      Object envUnchecked,
      Object executionRequirementsUnchecked,
      Object inputManifestsUnchecked,
      Object execGroupUnchecked)
      throws EvalException {
    context.checkMutable("actions.run");
    StarlarkAction.Builder builder = new StarlarkAction.Builder();

    Sequence<?> argumentsList = ((Sequence) arguments);
    buildCommandLine(builder, argumentsList);
    if (executableUnchecked instanceof Artifact) {
      Artifact executable = (Artifact) executableUnchecked;
      FilesToRunProvider provider = context.getExecutableRunfiles(executable);
      if (provider == null) {
        builder.setExecutable(executable);
      } else {
        builder.setExecutable(provider);
      }
    } else if (executableUnchecked instanceof String) {
      builder.setExecutable(PathFragment.create((String) executableUnchecked));
    } else if (executableUnchecked instanceof FilesToRunProvider) {
      builder.setExecutable((FilesToRunProvider) executableUnchecked);
    } else {
      // Should have been verified by Starlark before this function is called
      throw new IllegalStateException();
    }
    registerStarlarkAction(
        outputs,
        inputs,
        unusedInputsList,
        toolsUnchecked,
        mnemonicUnchecked,
        progressMessage,
        useDefaultShellEnv,
        envUnchecked,
        executionRequirementsUnchecked,
        inputManifestsUnchecked,
        execGroupUnchecked,
        builder);
  }

  private void validateActionCreation() throws EvalException {
    if (ruleContext.getRule().isAnalysisTest()) {
      throw Starlark.errorf(
          "implementation function of a rule with "
              + "analysis_test=true may not register actions. Analysis test rules may only return "
              + "success/failure information via AnalysisTestResultInfo.");
    }
  }

  /**
   * Registers actions in the context of this {@link StarlarkActionFactory}.
   *
   * <p>Use {@link #getActionConstructionContext()} to obtain the context required to create those
   * actions.
   */
  public void registerAction(ActionAnalysisMetadata... actions) throws EvalException {
    validateActionCreation();
    ruleContext.registerAction(actions);
  }

  /**
   * Returns information needed to construct actions that can be registered with {@link
   * #registerAction(ActionAnalysisMetadata...)}.
   */
  public ActionConstructionContext getActionConstructionContext() {
    return ruleContext;
  }

  public RuleContext getRuleContext() {
    return ruleContext;
  }

  @Override
  public void runShell(
      Sequence<?> outputs,
      Object inputs,
      Object toolsUnchecked,
      Object arguments,
      Object mnemonicUnchecked,
      Object commandUnchecked,
      Object progressMessage,
      Boolean useDefaultShellEnv,
      Object envUnchecked,
      Object executionRequirementsUnchecked,
      Object inputManifestsUnchecked,
      Object execGroupUnchecked,
      StarlarkThread thread)
      throws EvalException {
    context.checkMutable("actions.run_shell");

    Sequence<?> argumentList = (Sequence) arguments;
    StarlarkAction.Builder builder = new StarlarkAction.Builder();
    buildCommandLine(builder, argumentList);

    if (commandUnchecked instanceof String) {
      Map<String, String> executionInfo =
          ImmutableMap.copyOf(TargetUtils.getExecutionInfo(ruleContext.getRule()));
      String helperScriptSuffix = String.format(".run_shell_%d.sh", runShellOutputCounter++);
      String command = (String) commandUnchecked;
      PathFragment shExecutable = ShToolchain.getPathOrError(ruleContext);
      BashCommandConstructor constructor =
          CommandHelper.buildBashCommandConstructor(
              executionInfo, shExecutable, helperScriptSuffix);
      Artifact helperScript =
          CommandHelper.commandHelperScriptMaybe(ruleContext, command, constructor);
      if (helperScript == null) {
        builder.setShellCommand(shExecutable, command);
      } else {
        builder.setShellCommand(shExecutable, helperScript.getExecPathString());
        builder.addInput(helperScript);
        FilesToRunProvider provider = context.getExecutableRunfiles(helperScript);
        if (provider != null) {
          builder.addTool(provider);
        }
      }
    } else if (commandUnchecked instanceof Sequence) {
      if (thread.getSemantics().incompatibleRunShellCommandString()) {
        throw Starlark.errorf(
            "'command' must be of type string. passing a sequence of strings as 'command'"
                + " is deprecated. To temporarily disable this check,"
                + " set --incompatible_objc_framework_cleanup=false.");
      }
      Sequence<?> commandList = (Sequence) commandUnchecked;
      if (argumentList.size() > 0) {
        throw Starlark.errorf("'arguments' must be empty if 'command' is a sequence of strings");
      }
      List<String> command = Sequence.cast(commandList, String.class, "command");
      builder.setShellCommand(command);
    } else {
      throw new EvalException(
          null,
          "expected string or list of strings for command instead of "
              + Starlark.type(commandUnchecked));
    }
    if (argumentList.size() > 0) {
      // When we use a shell command, add an empty argument before other arguments.
      //   e.g.  bash -c "cmd" '' 'arg1' 'arg2'
      // bash will use the empty argument as the value of $0 (which we don't care about).
      // arg1 and arg2 will be $1 and $2, as a user expects.
      builder.addExecutableArguments("");
    }
    registerStarlarkAction(
        outputs,
        inputs,
        /*unusedInputsList=*/ Starlark.NONE,
        toolsUnchecked,
        mnemonicUnchecked,
        progressMessage,
        useDefaultShellEnv,
        envUnchecked,
        executionRequirementsUnchecked,
        inputManifestsUnchecked,
        execGroupUnchecked,
        builder);
  }

  private static void buildCommandLine(SpawnAction.Builder builder, Sequence<?> argumentsList)
      throws EvalException {
    List<String> stringArgs = new ArrayList<>();
    for (Object value : argumentsList) {
      if (value instanceof String) {
        stringArgs.add((String) value);
      } else if (value instanceof Args) {
        if (!stringArgs.isEmpty()) {
          builder.addCommandLine(CommandLine.of(stringArgs));
          stringArgs = new ArrayList<>();
        }
        Args args = (Args) value;
        ParamFileInfo paramFileInfo = args.getParamFileInfo();
        builder.addCommandLine(args.build(), paramFileInfo);
      } else {
        throw new EvalException(
            null,
            "expected list of strings or ctx.actions.args() for arguments instead of "
                + Starlark.type(value));
      }
    }
    if (!stringArgs.isEmpty()) {
      builder.addCommandLine(CommandLine.of(stringArgs));
    }
  }

  /**
   * Setup for spawn actions common between {@link #run} and {@link #runShell}.
   *
   * <p>{@code builder} should have either executable or a command set.
   */
  private void registerStarlarkAction(
      Sequence<?> outputs,
      Object inputs,
      Object unusedInputsList,
      Object toolsUnchecked,
      Object mnemonicUnchecked,
      Object progressMessage,
      Boolean useDefaultShellEnv,
      Object envUnchecked,
      Object executionRequirementsUnchecked,
      Object inputManifestsUnchecked,
      Object execGroupUnchecked,
      StarlarkAction.Builder builder)
      throws EvalException {
    Iterable<Artifact> inputArtifacts;
    if (inputs instanceof Sequence) {
      inputArtifacts = Sequence.cast(inputs, Artifact.class, "inputs");
      builder.addInputs(inputArtifacts);
    } else {
      NestedSet<Artifact> inputSet = Depset.cast(inputs, Artifact.class, "inputs");
      builder.addTransitiveInputs(inputSet);
      inputArtifacts = inputSet.toList();
    }

    List<Artifact> outputArtifacts = Sequence.cast(outputs, Artifact.class, "outputs");
    if (outputArtifacts.isEmpty()) {
      throw Starlark.errorf("param 'outputs' may not be empty");
    }
    builder.addOutputs(outputArtifacts);

    if (unusedInputsList != Starlark.NONE) {
      if (!starlarkSemantics.experimentalStarlarkUnusedInputsList()) {
        throw Starlark.errorf(
            "'unused_inputs_list' attribute is experimental and disabled by default. "
                + "This API is in development and subject to change at any time. "
                + "Use --experimental_starlark_unused_inputs_list to use this experimental API.");
      }
      if (unusedInputsList instanceof Artifact) {
        builder.setUnusedInputsList(Optional.of((Artifact) unusedInputsList));
      } else {
        throw Starlark.errorf(
            "expected value of type 'File' for a member of parameter 'unused_inputs_list' but got"
                + " %s instead",
            Starlark.type(unusedInputsList));
      }
    }

    if (toolsUnchecked != Starlark.UNBOUND) {
      List<?> tools =
          toolsUnchecked instanceof Sequence
              ? Sequence.cast(toolsUnchecked, Object.class, "tools")
              : Depset.cast(toolsUnchecked, Object.class, "tools").toList();

      for (Object toolUnchecked : tools) {
        if (toolUnchecked instanceof Artifact) {
          Artifact artifact = (Artifact) toolUnchecked;
          builder.addInput(artifact);
          FilesToRunProvider provider = context.getExecutableRunfiles(artifact);
          if (provider != null) {
            builder.addTool(provider);
          }
        } else if (toolUnchecked instanceof FilesToRunProvider) {
          builder.addTool((FilesToRunProvider) toolUnchecked);
        } else {
          throw new EvalException(
              null,
              "expected value of type 'File or FilesToRunProvider' for "
                  + "a member of parameter 'tools' but got "
                  + Starlark.type(toolUnchecked)
                  + " instead");
        }
      }
    } else {
      // Users didn't pass 'tools', kick in compatibility modes
      if (starlarkSemantics.incompatibleNoSupportToolsInActionInputs()) {
        // In this mode we error out if we find any tools among the inputs
        List<Artifact> tools = null;
        for (Artifact artifact : inputArtifacts) {
          FilesToRunProvider provider = context.getExecutableRunfiles(artifact);
          if (provider != null) {
            tools = tools != null ? tools : new ArrayList<>(1);
            tools.add(artifact);
          }
        }
        if (tools != null) {
          String toolsAsString =
              Joiner.on(", ")
                  .join(
                      tools
                          .stream()
                          .map(Artifact::getExecPathString)
                          .map(s -> "'" + s + "'")
                          .collect(toList()));
          throw Starlark.errorf(
              "Found tool(s) %s in inputs. "
                  + "A tool is an input with executable=True set. "
                  + "All tools should be passed using the 'tools' "
                  + "argument instead of 'inputs' in order to make their runfiles available "
                  + "to the action. This safety check will not be performed once the action "
                  + "is modified to take a 'tools' argument. "
                  + "To temporarily disable this check, "
                  + "set --incompatible_no_support_tools_in_action_inputs=false.",
              toolsAsString);
        }
      } else {
        // Full legacy support -- add tools from inputs
        for (Artifact artifact : inputArtifacts) {
          FilesToRunProvider provider = context.getExecutableRunfiles(artifact);
          if (provider != null) {
            builder.addTool(provider);
          }
        }
      }
    }

    String mnemonic = getMnemonic(mnemonicUnchecked);
    builder.setMnemonic(mnemonic);
    if (envUnchecked != Starlark.NONE) {
      builder.setEnvironment(
          ImmutableMap.copyOf(Dict.cast(envUnchecked, String.class, String.class, "env")));
    }
    if (progressMessage != Starlark.NONE) {
      builder.setProgressMessageNonLazy((String) progressMessage);
    }
    if (Starlark.truth(useDefaultShellEnv)) {
      builder.useDefaultShellEnvironment();
    }

    ImmutableMap<String, String> executionInfo =
        TargetUtils.getFilteredExecutionInfo(
            executionRequirementsUnchecked,
            ruleContext.getRule(),
            starlarkSemantics.experimentalAllowTagsPropagation());
    builder.setExecutionInfo(executionInfo);

    if (inputManifestsUnchecked != Starlark.NONE) {
      for (RunfilesSupplier supplier :
          Sequence.cast(inputManifestsUnchecked, RunfilesSupplier.class, "runfiles suppliers")) {
        builder.addRunfilesSupplier(supplier);
      }
    }

    if (execGroupUnchecked != Starlark.NONE) {
      String execGroup = (String) execGroupUnchecked;
      if (!ExecGroupCollection.isValidGroupName(execGroup)
          || !ruleContext.hasToolchainContext(execGroup)) {
        throw Starlark.errorf("Action declared for non-existent exec group '%s'.", execGroup);
      }
      builder.setExecGroup(execGroup);
    }

    // Always register the action
    registerAction(builder.build(ruleContext));
  }

  private String getMnemonic(Object mnemonicUnchecked) {
    String mnemonic = mnemonicUnchecked == Starlark.NONE ? "Action" : (String) mnemonicUnchecked;
    if (ruleContext.getConfiguration().getReservedActionMnemonics().contains(mnemonic)) {
      mnemonic = mangleMnemonic(mnemonic);
    }
    return mnemonic;
  }

  private static String mangleMnemonic(String mnemonic) {
    return mnemonic + "FromStarlark";
  }

  @Override
  public void expandTemplate(
      FileApi template, FileApi output, Dict<?, ?> substitutionsUnchecked, Boolean executable)
      throws EvalException {
    context.checkMutable("actions.expand_template");
    ImmutableList.Builder<Substitution> substitutionsBuilder = ImmutableList.builder();
    for (Map.Entry<String, String> substitution :
        Dict.cast(substitutionsUnchecked, String.class, String.class, "substitutions").entrySet()) {
      // ParserInput.create(Path) uses Latin1 when reading BUILD files, which might
      // contain UTF-8 encoded symbols as part of template substitution.
      // As a quick fix, the substitution values are corrected before being passed on.
      // In the long term, fixing ParserInput.create(Path) would be a better approach.
      substitutionsBuilder.add(
          Substitution.of(substitution.getKey(), convertLatin1ToUtf8(substitution.getValue())));
    }
    TemplateExpansionAction action =
        new TemplateExpansionAction(
            ruleContext.getActionOwner(),
            (Artifact) template,
            (Artifact) output,
            substitutionsBuilder.build(),
            executable);
    registerAction(action);
  }

  /**
   * Returns the proper UTF-8 representation of a String that was erroneously read using Latin1.
   *
   * @param latin1 Input string
   * @return The input string, UTF8 encoded
   */
  private static String convertLatin1ToUtf8(String latin1) {
    return new String(latin1.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
  }

  @Override
  public Args args(StarlarkThread thread) {
    return Args.newArgs(thread.mutability(), thread.getSemantics());
  }

  @Override
  public boolean isImmutable() {
    return context.isImmutable();
  }

  @Override
  public void repr(Printer printer) {
    printer.append("actions for");
    context.repr(printer);
  }

  void nullify() {
    ruleContext = null;
  }
}
