// 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 "tools/gn/build_settings.h"
#include "tools/gn/err.h"
#include "tools/gn/filesystem_utils.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"

namespace {

// Returns true if the list of files looks like it might have a {{ }} pattern
// in it. Used for error checking.
bool FileListHasPattern(const Target::FileList& files) {
  for (size_t i = 0; i < files.size(); i++) {
    if (files[i].value().find("{{") != std::string::npos &&
        files[i].value().find("}}") != std::string::npos)
      return true;
  }
  return false;
}

}  // namespace

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() {
}

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

  FillSources();
  if (err_->has_error())
    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;
  }

  FillInputs();
  if (err_->has_error())
    return;

  FillScript();
  if (err_->has_error())
    return;

  FillScriptArgs();
  if (err_->has_error())
    return;

  FillOutputs();
  if (err_->has_error())
    return;

  FillDepfile();
  if (err_->has_error())
    return;

  CheckOutputs();
  if (err_->has_error())
    return;

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

void 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;
  }
  if (!value->VerifyTypeIs(Value::STRING, err_))
    return;

  SourceFile script_file =
      scope_->GetSourceDir().ResolveRelativeFile(value->string_value());
  if (script_file.value().empty()) {
    *err_ = Err(*value, "script name is empty");
    return;
  }
  target_->action_values().set_script(script_file);
}

void ActionTargetGenerator::FillScriptArgs() {
  const Value* value = scope_->GetValue(variables::kArgs, true);
  if (!value)
    return;

  std::vector<std::string> args;
  if (!ExtractListOfStringValues(*value, &args, err_))
    return;
  target_->action_values().swap_in_args(&args);
}

void ActionTargetGenerator::FillDepfile() {
  const Value* value = scope_->GetValue(variables::kDepfile, true);
  if (!value)
    return;
  target_->action_values().set_depfile(
      scope_->settings()->build_settings()->build_dir().ResolveRelativeFile(
          value->string_value()));
}

void ActionTargetGenerator::CheckOutputs() {
  const Target::FileList& outputs = target_->action_values().outputs();
  if (outputs.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;
  }

  if (output_type_ == Target::ACTION) {
    // Make sure the outputs for an action have no patterns in them.
    if (FileListHasPattern(outputs)) {
      *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;
    }
  } else if (output_type_ == Target::ACTION_FOREACH) {
    // A foreach target should always have a pattern in the outputs.
    if (!FileListHasPattern(outputs)) {
      *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;
    }
  }
}
