// Copyright 2018 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/compile_commands_writer.h"

#include <sstream>

#include "base/json/string_escape.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "gn/builder.h"
#include "gn/c_substitution_type.h"
#include "gn/c_tool.h"
#include "gn/config_values_extractors.h"
#include "gn/deps_iterator.h"
#include "gn/escape.h"
#include "gn/ninja_module_writer_util.h"
#include "gn/ninja_target_command_util.h"
#include "gn/path_output.h"
#include "gn/resolved_target_data.h"
#include "gn/string_output_buffer.h"
#include "gn/substitution_list.h"
#include "gn/substitution_writer.h"
#include "gn/unique_vector.h"

// Structure of JSON output file
// [
//   {
//      "directory": "The build directory."
//      "file": "The main source file processed by this compilation step.
//               Must be absolute or relative to the above build directory."
//      "command": "The compile command executed."
//   }
//   ...
// ]

namespace {

#if defined(OS_WIN)
const char kPrettyPrintLineEnding[] = "\r\n";
#else
const char kPrettyPrintLineEnding[] = "\n";
#endif

struct CompileFlags {
  std::string includes;
  std::string defines;
  std::string cflags;
  std::string cflags_c;
  std::string cflags_cc;
  std::string cflags_objc;
  std::string cflags_objcc;
  std::string framework_dirs;
  std::string frameworks;
  std::string clang_module_deps;
  std::string clang_module_deps_no_self;
};

// Helper template function to call RecursiveTargetConfigToStream<std::string>
// and return the JSON-escaped resulting string.
//
// NOTE: The Windows compiler cannot properly deduce the first parameter type
// so pass it at each call site to ensure proper builds for this platform.
template <typename T, typename Writer>
std::string FlagsGetter(RecursiveWriterConfig config,
                        const Target* target,
                        const std::vector<T>& (ConfigValues::*getter)() const,
                        const Writer& writer) {
  std::string result;
  std::ostringstream out;
  RecursiveTargetConfigToStream<T>(config, target, getter, writer, out);
  base::EscapeJSONString(out.str(), false, &result);
  return result;
}

void SetupCompileFlags(const Target* target,
                       PathOutput& path_output,
                       EscapeOptions opts,
                       const ResolvedTargetData& resolved,
                       CompileFlags& flags) {
  bool has_precompiled_headers =
      target->config_values().has_precompiled_headers();

  flags.defines = FlagsGetter<std::string>(
      kRecursiveWriterSkipDuplicates, target, &ConfigValues::defines,
      DefineWriter(ESCAPE_COMPILATION_DATABASE));

  flags.framework_dirs = FlagsGetter<SourceDir>(
      kRecursiveWriterSkipDuplicates, target, &ConfigValues::framework_dirs,
      FrameworkDirsWriter(path_output, "-F"));

  flags.frameworks = FlagsGetter<std::string>(
      kRecursiveWriterSkipDuplicates, target, &ConfigValues::frameworks,
      FrameworksWriter(ESCAPE_COMPILATION_DATABASE, "-framework"));
  flags.frameworks += FlagsGetter<std::string>(
      kRecursiveWriterSkipDuplicates, target, &ConfigValues::weak_frameworks,
      FrameworksWriter(ESCAPE_COMPILATION_DATABASE, "-weak_framework"));

  flags.includes = FlagsGetter<SourceDir>(kRecursiveWriterSkipDuplicates,
                                          target, &ConfigValues::include_dirs,
                                          IncludeWriter(path_output));

  std::vector<ClangModuleDep> module_dep_info =
      GetModuleDepsInformation(target, resolved);
  if (!module_dep_info.empty()) {
    std::ostringstream module_deps_out;
    for (const auto& module_dep : module_dep_info) {
      module_deps_out << " -fmodule-file=" << module_dep.module_name << "=";
      path_output.WriteFile(module_deps_out, module_dep.pcm);
    }
    base::EscapeJSONString(module_deps_out.str(), false,
                           &flags.clang_module_deps);

    std::ostringstream module_deps_no_self_out;
    for (const auto& module_dep : module_dep_info) {
      if (!module_dep.is_self) {
        if (module_dep.modulemap) {
          module_deps_no_self_out << " -fmodule-map-file=";
          path_output.WriteFile(module_deps_no_self_out, *module_dep.modulemap);
        }
        module_deps_no_self_out << " -fmodule-file=" << module_dep.module_name
                                << "=";
        path_output.WriteFile(module_deps_no_self_out, module_dep.pcm);
      }
    }
    base::EscapeJSONString(module_deps_no_self_out.str(), false,
                           &flags.clang_module_deps_no_self);
  }

  // Helper lambda to call WriteOneFlag() and return the resulting
  // escaped JSON string.
  auto one_flag = [&](RecursiveWriterConfig config,
                      const Substitution* substitution,
                      bool has_precompiled_headers, const char* tool_name,
                      const std::vector<std::string>& (ConfigValues::*getter)()
                          const) -> std::string {
    std::string result;
    std::ostringstream out;
    WriteOneFlag(config, target, substitution, has_precompiled_headers,
                 tool_name, getter, opts, path_output, out,
                 /*write_substitution=*/false, /*indent=*/false);
    base::EscapeJSONString(out.str(), false, &result);
    return result;
  };

  flags.cflags = one_flag(kRecursiveWriterKeepDuplicates, &CSubstitutionCFlags,
                          false, Tool::kToolNone, &ConfigValues::cflags);

  flags.cflags_c = one_flag(kRecursiveWriterKeepDuplicates,
                            &CSubstitutionCFlagsC, has_precompiled_headers,
                            CTool::kCToolCc, &ConfigValues::cflags_c);

  flags.cflags_cc = one_flag(kRecursiveWriterKeepDuplicates,
                             &CSubstitutionCFlagsCc, has_precompiled_headers,
                             CTool::kCToolCxx, &ConfigValues::cflags_cc);

  flags.cflags_objc = one_flag(
      kRecursiveWriterKeepDuplicates, &CSubstitutionCFlagsObjC,
      has_precompiled_headers, CTool::kCToolObjC, &ConfigValues::cflags_objc);

  flags.cflags_objcc =
      one_flag(kRecursiveWriterKeepDuplicates, &CSubstitutionCFlagsObjCc,
               has_precompiled_headers, CTool::kCToolObjCxx,
               &ConfigValues::cflags_objcc);
}

void WriteFile(const SourceFile& source,
               PathOutput& path_output,
               std::ostream& out) {
  std::ostringstream rel_source_path;
  out << "    \"file\": \"";
  path_output.WriteFile(out, source);
}

void WriteDirectory(std::string build_dir, std::ostream& out) {
  out << "\",";
  out << kPrettyPrintLineEnding;
  out << "    \"directory\": \"";
  out << build_dir;
  out << "\",";
}

void WriteCommand(const Target* target,
                  const SourceFile& source,
                  const CompileFlags& flags,
                  std::vector<OutputFile>& tool_outputs,
                  PathOutput& path_output,
                  SourceFile::Type source_type,
                  const char* tool_name,
                  EscapeOptions opts,
                  std::ostream& out) {
  EscapeOptions no_quoting(opts);
  no_quoting.inhibit_quoting = true;
  const Tool* tool = target->toolchain()->GetTool(tool_name);

  out << kPrettyPrintLineEnding;
  out << "    \"command\": \"";

  for (const auto& range : tool->command().ranges()) {
    // TODO: this is emitting a bonus space prior to each substitution.
    if (range.type == &SubstitutionLiteral) {
      EscapeJSONStringToStream(out, range.literal, no_quoting);
    } else if (range.type == &SubstitutionOutput) {
      path_output.WriteFiles(out, tool_outputs);
    } else if (range.type == &CSubstitutionDefines) {
      out << flags.defines;
    } else if (range.type == &CSubstitutionFrameworkDirs) {
      out << flags.framework_dirs;
    } else if (range.type == &CSubstitutionFrameworks) {
      out << flags.frameworks;
    } else if (range.type == &CSubstitutionIncludeDirs) {
      out << flags.includes;
    } else if (range.type == &CSubstitutionModuleDeps) {
      out << flags.clang_module_deps;
    } else if (range.type == &CSubstitutionModuleDepsNoSelf) {
      out << flags.clang_module_deps_no_self;
    } else if (range.type == &CSubstitutionCFlags) {
      out << flags.cflags;
    } else if (range.type == &CSubstitutionCFlagsC) {
      if (source_type == SourceFile::SOURCE_C)
        out << flags.cflags_c;
    } else if (range.type == &CSubstitutionCFlagsCc) {
      if (source_type == SourceFile::SOURCE_CPP)
        out << flags.cflags_cc;
    } else if (range.type == &CSubstitutionCFlagsObjC) {
      if (source_type == SourceFile::SOURCE_M)
        out << flags.cflags_objc;
    } else if (range.type == &CSubstitutionCFlagsObjCc) {
      if (source_type == SourceFile::SOURCE_MM)
        out << flags.cflags_objcc;
    } else if (range.type == &CSubstitutionModuleName) {
      EscapeStringToStream(out, target->module_name(), opts);
    } else if (range.type == &SubstitutionLabel ||
               range.type == &SubstitutionLabelName ||
               range.type == &SubstitutionLabelNoToolchain ||
               range.type == &SubstitutionRootGenDir ||
               range.type == &SubstitutionRootOutDir ||
               range.type == &SubstitutionTargetGenDir ||
               range.type == &SubstitutionTargetOutDir ||
               range.type == &SubstitutionTargetOutputName ||
               range.type == &SubstitutionSource ||
               range.type == &SubstitutionSourceNamePart ||
               range.type == &SubstitutionSourceFilePart ||
               range.type == &SubstitutionSourceDir ||
               range.type == &SubstitutionSourceRootRelativeDir ||
               range.type == &SubstitutionSourceGenDir ||
               range.type == &SubstitutionSourceOutDir ||
               range.type == &SubstitutionSourceTargetRelative) {
      EscapeStringToStream(out,
                           SubstitutionWriter::GetCompilerSubstitution(
                               target, source, range.type),
                           opts);
    } else {
      // Other flags shouldn't be relevant to compiling C/C++/ObjC/ObjC++
      // source files.
      NOTREACHED() << "Unsupported substitution for this type of target : "
                   << range.type->name;
      continue;
    }
  }
}

void OutputJSON(const BuildSettings* build_settings,
                std::vector<const Target*>& all_targets,
                std::ostream& out) {
  out << '[';
  out << kPrettyPrintLineEnding;
  bool first = true;
  auto build_dir = build_settings->GetFullPath(build_settings->build_dir())
                       .StripTrailingSeparators();
  std::vector<OutputFile> tool_outputs;  // Prevent reallocation in loop.

  EscapeOptions opts;
  opts.mode = ESCAPE_NINJA_PREFORMATTED_COMMAND;
  ResolvedTargetData resolved;

  for (const auto* target : all_targets) {
    if (!target->IsBinary())
      continue;

    // Precompute values that are the same for all sources in a target to avoid
    // computing for every source.

    PathOutput path_output(
        target->settings()->build_settings()->build_dir(),
        target->settings()->build_settings()->root_path_utf8(),
        ESCAPE_NINJA_COMMAND);

    CompileFlags flags;
    SetupCompileFlags(target, path_output, opts, resolved, flags);

    for (const auto& source : target->sources()) {
      // If this source is not a C/C++/ObjC/ObjC++ source (not header) file,
      // continue as it does not belong in the compilation database.
      const SourceFile::Type source_type = source.GetType();
      if (source_type != SourceFile::SOURCE_CPP &&
          source_type != SourceFile::SOURCE_C &&
          source_type != SourceFile::SOURCE_M &&
          source_type != SourceFile::SOURCE_MM &&
          source_type != SourceFile::SOURCE_MODULEMAP)
        continue;

      const char* tool_name = Tool::kToolNone;
      if (!target->GetOutputFilesForSource(source, &tool_name, &tool_outputs))
        continue;

      if (!first) {
        out << ',';
        out << kPrettyPrintLineEnding;
      }
      first = false;
      out << "  {";
      out << kPrettyPrintLineEnding;

      WriteFile(source, path_output, out);
      WriteDirectory(base::StringPrintf("%" PRIsFP, PATH_CSTR(build_dir)), out);
      WriteCommand(target, source, flags, tool_outputs, path_output,
                   source_type, tool_name, opts, out);
      out << "\"";
      out << kPrettyPrintLineEnding;
      out << "  }";
    }
  }

  out << kPrettyPrintLineEnding;
  out << "]";
  out << kPrettyPrintLineEnding;
}

}  // namespace

std::string CompileCommandsWriter::RenderJSON(
    const BuildSettings* build_settings,
    std::vector<const Target*>& all_targets) {
  StringOutputBuffer json;
  std::ostream out(&json);
  OutputJSON(build_settings, all_targets, out);
  return json.str();
}

bool CompileCommandsWriter::RunAndWriteFiles(
    const BuildSettings* build_settings,
    const std::vector<const Target*>& all_targets,
    const std::vector<LabelPattern>& patterns,
    const std::optional<std::string>& legacy_target_filters,
    const base::FilePath& output_path,
    Err* err) {
  std::vector<const Target*> to_write = CollectTargets(
      build_settings, all_targets, patterns, legacy_target_filters, err);
  if (err->has_error())
    return false;

  StringOutputBuffer json;
  std::ostream output_to_json(&json);
  OutputJSON(build_settings, to_write, output_to_json);

  return json.WriteToFileIfChanged(output_path, err);
}

std::vector<const Target*> CompileCommandsWriter::CollectTargets(
    const BuildSettings* build_setting,
    const std::vector<const Target*>& all_targets,
    const std::vector<LabelPattern>& patterns,
    const std::optional<std::string>& legacy_target_filters,
    Err* err) {
  if (legacy_target_filters && legacy_target_filters->empty()) {
    // The legacy filter was specified but has no parameter. This matches
    // everything and we can skip any other kinds of matching.
    return all_targets;
  }

  // Collect the first level of target matches. These are the ones that the
  // patterns match directly.
  std::vector<const Target*> input_targets;
  for (const Target* target : all_targets) {
    if (LabelPattern::VectorMatches(patterns, target->label()))
      input_targets.push_back(target);
  }

  // Add in any legacy filter matches.
  if (legacy_target_filters) {
    std::vector<const Target*> legacy_matches =
        FilterLegacyTargets(all_targets, *legacy_target_filters);

    // This can produce some duplicates with the patterns but the "collect
    // deps" phase will eliminate them.
    input_targets.insert(input_targets.end(), legacy_matches.begin(),
                         legacy_matches.end());
  }

  return CollectDepsOfMatches(input_targets);
}

std::vector<const Target*> CompileCommandsWriter::CollectDepsOfMatches(
    const std::vector<const Target*>& input_targets) {
  // The current set of matched targets.
  TargetSet collected;

  // Represents the next layer of the breadth-first seach. These are all targets
  // that we haven't checked so far.
  std::vector<const Target*> frontier;

  // Collect the first level of target matches specified in the input. There may
  // be duplicates so we still need to do the set checking.
  // patterns match directly.
  for (const Target* target : input_targets) {
    if (!collected.contains(target)) {
      collected.add(target);
      frontier.push_back(target);
    }
  }

  // Collects the dependencies for the next level of iteration. This could be
  // inside the loop but is kept outside to avoid reallocating in every
  // iteration.
  std::vector<const Target*> next_frontier;

  // Loop for each level of the search.
  while (!frontier.empty()) {
    for (const Target* target : frontier) {
      // Check the target's dependencies.
      for (const auto& pair : target->GetDeps(Target::DEPS_ALL)) {
        if (!collected.contains(pair.ptr)) {
          // New dependency found.
          collected.add(pair.ptr);
          next_frontier.push_back(pair.ptr);
        }
      }
    }

    // Swap to the new level and clear out the next one without deallocating the
    // buffer (in most STL implementations, clear() doesn't free the existing
    // buffer).
    std::swap(frontier, next_frontier);
    next_frontier.clear();
  }

  // Convert to vector for output.
  std::vector<const Target*> output;
  output.reserve(collected.size());
  for (const Target* target : collected) {
    output.push_back(target);
  }
  return output;
}

std::vector<const Target*> CompileCommandsWriter::FilterLegacyTargets(
    const std::vector<const Target*>& all_targets,
    const std::string& target_filter_string) {
  std::vector<std::string> target_filters =
      base::SplitString(target_filter_string, ",", base::TRIM_WHITESPACE,
                        base::SPLIT_WANT_NONEMPTY);
  UniqueVector<std::string> target_filters_set;
  target_filters_set.reserve(target_filters.size());
  target_filters_set.Append(std::move(target_filters));

  std::vector<const Target*> result;
  result.reserve(all_targets.size());
  for (auto& target : all_targets) {
    if (target_filters_set.Contains(target->label().name()))
      result.push_back(target);
  }

  return result;
}
