// 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 "gn/config_values_generator.h"

#include "base/strings/string_util.h"
#include "gn/build_settings.h"
#include "gn/config_values.h"
#include "gn/filesystem_utils.h"
#include "gn/frameworks_utils.h"
#include "gn/scope.h"
#include "gn/settings.h"
#include "gn/value.h"
#include "gn/value_extractors.h"
#include "gn/variables.h"

namespace {

void GetStringList(Scope* scope,
                   const char* var_name,
                   ConfigValues* config_values,
                   std::vector<std::string>& (ConfigValues::*accessor)(),
                   Err* err) {
  const Value* value = scope->GetValue(var_name, true);
  if (!value)
    return;  // No value, empty input and succeed.

  ExtractListOfStringValues(*value, &(config_values->*accessor)(), err);
  if (err->has_error())
    return;

  const auto& strings = (config_values->*accessor)();
  for (size_t i = 0; i < strings.size(); i++) {
    if (strings[i].find('\n') != std::string::npos) {
      *err = Err(value->list_value()[i],
                 "Newlines in " + std::string(var_name) + " values are not "
                 "supported.",
                 "The value `" + strings[i] + "` contains a newline.");
      return;
    }
  }
}

void GetDirList(Scope* scope,
                const char* var_name,
                ConfigValues* config_values,
                const SourceDir input_dir,
                std::vector<SourceDir>& (ConfigValues::*accessor)(),
                Err* err) {
  const Value* value = scope->GetValue(var_name, true);
  if (!value)
    return;  // No value, empty input and succeed.

  std::vector<SourceDir> result;
  ExtractListOfRelativeDirs(scope->settings()->build_settings(), *value,
                            input_dir, &result, err);
  (config_values->*accessor)().swap(result);
}

void GetFrameworksList(Scope* scope,
                       const char* var_name,
                       ConfigValues* config_values,
                       std::vector<std::string>& (ConfigValues::*accessor)(),
                       Err* err) {
  const Value* value = scope->GetValue(var_name, true);
  if (!value)
    return;

  std::vector<std::string> frameworks;
  if (!ExtractListOfStringValues(*value, &frameworks, err))
    return;

  // All strings must end with ".frameworks".
  for (const std::string& framework : frameworks) {
    std::string_view framework_name = GetFrameworkName(framework);
    if (framework_name.empty()) {
      *err = Err(*value,
                 "This frameworks value is wrong. "
                 "All listed frameworks names must not include any\n"
                 "path component and have \".framework\" extension.");
      return;
    }
  }

  (config_values->*accessor)().swap(frameworks);
}

void GetWeakLibrariesList(Scope* scope,
                          const char* var_name,
                          ConfigValues* config_values,
                          std::vector<std::string>& (ConfigValues::*accessor)(),
                          Err* err) {
  const Value* value = scope->GetValue(var_name, true);
  if (!value)
    return;

  std::vector<std::string> weak_libraries;
  if (!ExtractListOfStringValues(*value, &weak_libraries, err))
    return;

  // All strings must end with ".dylib".
  for (const std::string& weak_library : weak_libraries) {
    std::string_view extension = FindExtension(&weak_library);
    if (extension != "dylib") {
      *err = Err(
          *value,
          "This weak_libraries value is wrong. "
          "All listed weak_libraries files must have \".dylib\" extension.");
      return;
    }
  }

  (config_values->*accessor)().swap(weak_libraries);
}

}  // namespace

ConfigValuesGenerator::ConfigValuesGenerator(ConfigValues* dest_values,
                                             Scope* scope,
                                             const SourceDir& input_dir,
                                             Err* err)
    : config_values_(dest_values),
      scope_(scope),
      input_dir_(input_dir),
      err_(err) {}

ConfigValuesGenerator::~ConfigValuesGenerator() = default;

void ConfigValuesGenerator::Run() {
#define FILL_STRING_CONFIG_VALUE(name) \
  GetStringList(scope_, #name, config_values_, &ConfigValues::name, err_);
#define FILL_DIR_CONFIG_VALUE(name)                                          \
  GetDirList(scope_, #name, config_values_, input_dir_, &ConfigValues::name, \
             err_);

  FILL_STRING_CONFIG_VALUE(arflags)
  FILL_STRING_CONFIG_VALUE(asmflags)
  FILL_STRING_CONFIG_VALUE(cflags)
  FILL_STRING_CONFIG_VALUE(cflags_c)
  FILL_STRING_CONFIG_VALUE(cflags_cc)
  FILL_STRING_CONFIG_VALUE(cflags_objc)
  FILL_STRING_CONFIG_VALUE(cflags_objcc)
  FILL_STRING_CONFIG_VALUE(defines)
  FILL_DIR_CONFIG_VALUE(framework_dirs)
  FILL_DIR_CONFIG_VALUE(include_dirs)
  FILL_STRING_CONFIG_VALUE(ldflags)
  FILL_DIR_CONFIG_VALUE(lib_dirs)
  FILL_STRING_CONFIG_VALUE(rustflags)
  FILL_STRING_CONFIG_VALUE(rustenv)
  FILL_STRING_CONFIG_VALUE(swiftflags)

#undef FILL_STRING_CONFIG_VALUE
#undef FILL_DIR_CONFIG_VALUE

  // Inputs
  const Value* inputs_value = scope_->GetValue(variables::kInputs, true);
  if (inputs_value) {
    ExtractListOfRelativeFiles(scope_->settings()->build_settings(),
                               *inputs_value, input_dir_,
                               &config_values_->inputs(), err_);
  }

  // Libs
  const Value* libs_value = scope_->GetValue(variables::kLibs, true);
  if (libs_value) {
    ExtractListOfLibs(scope_->settings()->build_settings(), *libs_value,
                      input_dir_, &config_values_->libs(), err_);
  }

  // Externs
  const Value* externs_value = scope_->GetValue(variables::kExterns, true);
  if (externs_value) {
    ExtractListOfExterns(scope_->settings()->build_settings(), *externs_value,
                         input_dir_, &config_values_->externs(), err_);
  }

  // Frameworks
  GetFrameworksList(scope_, variables::kFrameworks, config_values_,
                    &ConfigValues::frameworks, err_);
  GetFrameworksList(scope_, variables::kWeakFrameworks, config_values_,
                    &ConfigValues::weak_frameworks, err_);
  GetWeakLibrariesList(scope_, variables::kWeakLibraries, config_values_,
                       &ConfigValues::weak_libraries, err_);

  // Precompiled headers.
  const Value* precompiled_header_value =
      scope_->GetValue(variables::kPrecompiledHeader, true);
  if (precompiled_header_value) {
    if (!precompiled_header_value->VerifyTypeIs(Value::STRING, err_))
      return;

    // Check for common errors. This is a string and not a file.
    const std::string& pch_string = precompiled_header_value->string_value();
    if (pch_string.starts_with("//")) {
      *err_ = Err(
          *precompiled_header_value, "This precompiled_header value is wrong. ",
          "You need to specify a string that the compiler will match against\n"
          "the #include lines rather than a GN-style file name.\n");
      return;
    }
    config_values_->set_precompiled_header(pch_string);
  }

  const Value* precompiled_source_value =
      scope_->GetValue(variables::kPrecompiledSource, true);
  if (precompiled_source_value) {
    config_values_->set_precompiled_source(input_dir_.ResolveRelativeFile(
        *precompiled_source_value, err_,
        scope_->settings()->build_settings()->root_path_utf8()));
    if (err_->has_error())
      return;
  }
}
