// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "tools/gn/action_target_generator.h"

#include "base/stl_util.h"
#include "tools/gn/build_settings.h"
#include "tools/gn/err.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/functions.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/scope.h"
#include "tools/gn/value.h"
#include "tools/gn/value_extractors.h"
#include "tools/gn/variables.h"

ActionTargetGenerator::ActionTargetGenerator(
    Target* target,
    Scope* scope,
    const FunctionCallNode* function_call,
    Target::OutputType type,
    Err* err)
    : TargetGenerator(target, scope, function_call, err), output_type_(type) {}

ActionTargetGenerator::~ActionTargetGenerator() = default;

void ActionTargetGenerator::DoRun() {
  target_->set_output_type(output_type_);

  if (!FillSources())
    return;
  if (output_type_ == Target::ACTION_FOREACH && target_->sources().empty()) {
    // Foreach rules must always have some sources to have an effect.
    *err_ =
        Err(function_call_, "action_foreach target has no sources.",
            "If you don't specify any sources, there is nothing to run your\n"
            "script over.");
    return;
  }

  if (!FillInputs())
    return;

  if (!FillScript())
    return;

  if (!FillScriptArgs())
    return;

  if (!FillResponseFileContents())
    return;

  if (!FillOutputs(output_type_ == Target::ACTION_FOREACH))
    return;

  if (!FillDepfile())
    return;

  if (!FillPool())
    return;

  if (!FillCheckIncludes())
    return;

  if (!CheckOutputs())
    return;

  // Action outputs don't depend on the current toolchain so we can skip adding
  // that dependency.

  // response_file_contents and {{response_file_name}} in the args must go
  // together.
  const auto& required_args_substitutions =
      target_->action_values().args().required_types();
  bool has_rsp_file_name = base::ContainsValue(required_args_substitutions,
                                               SUBSTITUTION_RSP_FILE_NAME);
  if (target_->action_values().uses_rsp_file() && !has_rsp_file_name) {
    *err_ = Err(
        function_call_, "Missing {{response_file_name}} in args.",
        "This target defines response_file_contents but doesn't use\n"
        "{{response_file_name}} in the args, which means the response file\n"
        "will be unused.");
    return;
  }
  if (!target_->action_values().uses_rsp_file() && has_rsp_file_name) {
    *err_ = Err(
        function_call_, "Missing response_file_contents definition.",
        "This target uses {{response_file_name}} in the args, but does not\n"
        "define response_file_contents which means the response file\n"
        "will be empty.");
    return;
  }
}

bool ActionTargetGenerator::FillScript() {
  // If this gets called, the target type requires a script, so error out
  // if it doesn't have one.
  const Value* value = scope_->GetValue(variables::kScript, true);
  if (!value) {
    *err_ = Err(function_call_, "This target type requires a \"script\".");
    return false;
  }
  if (!value->VerifyTypeIs(Value::STRING, err_))
    return false;

  SourceFile script_file = scope_->GetSourceDir().ResolveRelativeFile(
      *value, err_, scope_->settings()->build_settings()->root_path_utf8());
  if (err_->has_error())
    return false;
  target_->action_values().set_script(script_file);
  return true;
}

bool ActionTargetGenerator::FillScriptArgs() {
  const Value* value = scope_->GetValue(variables::kArgs, true);
  if (!value)
    return true;  // Nothing to do.

  if (!target_->action_values().args().Parse(*value, err_))
    return false;
  if (!EnsureValidSubstitutions(
          target_->action_values().args().required_types(),
          &IsValidScriptArgsSubstitution, value->origin(), err_))
    return false;

  return true;
}

bool ActionTargetGenerator::FillResponseFileContents() {
  const Value* value = scope_->GetValue(variables::kResponseFileContents, true);
  if (!value)
    return true;  // Nothing to do.

  if (!target_->action_values().rsp_file_contents().Parse(*value, err_))
    return false;
  if (!EnsureValidSubstitutions(
          target_->action_values().rsp_file_contents().required_types(),
          &IsValidSourceSubstitution, value->origin(), err_))
    return false;

  return true;
}

bool ActionTargetGenerator::FillDepfile() {
  const Value* value = scope_->GetValue(variables::kDepfile, true);
  if (!value)
    return true;

  SubstitutionPattern depfile;
  if (!depfile.Parse(*value, err_))
    return false;
  if (!EnsureSubstitutionIsInOutputDir(depfile, *value))
    return false;

  target_->action_values().set_depfile(depfile);
  return true;
}

bool ActionTargetGenerator::FillPool() {
  const Value* value = scope_->GetValue(variables::kPool, true);
  if (!value)
    return true;

  Label label = Label::Resolve(scope_->GetSourceDir(),
                               ToolchainLabelForScope(scope_), *value, err_);
  if (err_->has_error())
    return false;

  LabelPtrPair<Pool> pair(label);
  pair.origin = target_->defined_from();

  target_->action_values().set_pool(std::move(pair));
  return true;
}

bool ActionTargetGenerator::CheckOutputs() {
  const SubstitutionList& outputs = target_->action_values().outputs();
  if (outputs.list().empty()) {
    *err_ =
        Err(function_call_, "Action has no outputs.",
            "If you have no outputs, the build system can not tell when your\n"
            "script needs to be run.");
    return false;
  }

  if (output_type_ == Target::ACTION) {
    if (!outputs.required_types().empty()) {
      *err_ = Err(
          function_call_, "Action has patterns in the output.",
          "An action target should have the outputs completely specified. If\n"
          "you want to provide a mapping from source to output, use an\n"
          "\"action_foreach\" target.");
      return false;
    }
  } else if (output_type_ == Target::ACTION_FOREACH) {
    // A foreach target should always have a pattern in the outputs.
    if (outputs.required_types().empty()) {
      *err_ = Err(
          function_call_, "action_foreach should have a pattern in the output.",
          "An action_foreach target should have a source expansion pattern in\n"
          "it to map source file to unique output file name. Otherwise, the\n"
          "build system can't determine when your script needs to be run.");
      return false;
    }
  }
  return true;
}

bool ActionTargetGenerator::FillInputs() {
  const Value* value = scope_->GetValue(variables::kInputs, true);
  if (!value)
    return true;

  Target::FileList dest_inputs;
  if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
                                  scope_->GetSourceDir(), &dest_inputs, err_))
    return false;
  target_->config_values().inputs().swap(dest_inputs);
  return true;
}
