// 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 "tools/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 "tools/gn/builder.h"
#include "tools/gn/c_substitution_type.h"
#include "tools/gn/c_tool.h"
#include "tools/gn/config_values_extractors.h"
#include "tools/gn/deps_iterator.h"
#include "tools/gn/escape.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/ninja_target_command_util.h"
#include "tools/gn/path_output.h"
#include "tools/gn/substitution_writer.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;
};

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

  std::ostringstream defines_out;
  RecursiveTargetConfigToStream<std::string>(
      target, &ConfigValues::defines,
      DefineWriter(ESCAPE_NINJA_PREFORMATTED_COMMAND, true), defines_out);
  base::EscapeJSONString(defines_out.str(), false, &flags.defines);

  std::ostringstream includes_out;
  RecursiveTargetConfigToStream<SourceDir>(target, &ConfigValues::include_dirs,
                                           IncludeWriter(path_output),
                                           includes_out);
  base::EscapeJSONString(includes_out.str(), false, &flags.includes);

  std::ostringstream cflags_out;
  WriteOneFlag(target, &CSubstitutionCFlags, false, Tool::kToolNone,
               &ConfigValues::cflags, opts, path_output, cflags_out,
               /*write_substitution=*/false);
  base::EscapeJSONString(cflags_out.str(), false, &flags.cflags);

  std::ostringstream cflags_c_out;
  WriteOneFlag(target, &CSubstitutionCFlagsC, has_precompiled_headers,
               CTool::kCToolCc, &ConfigValues::cflags_c, opts, path_output,
               cflags_c_out, /*write_substitution=*/false);
  base::EscapeJSONString(cflags_c_out.str(), false, &flags.cflags_c);

  std::ostringstream cflags_cc_out;
  WriteOneFlag(target, &CSubstitutionCFlagsCc, has_precompiled_headers,
               CTool::kCToolCxx, &ConfigValues::cflags_cc, opts, path_output,
               cflags_cc_out, /*write_substitution=*/false);
  base::EscapeJSONString(cflags_cc_out.str(), false, &flags.cflags_cc);

  std::ostringstream cflags_objc_out;
  WriteOneFlag(target, &CSubstitutionCFlagsObjC, has_precompiled_headers,
               CTool::kCToolObjC, &ConfigValues::cflags_objc, opts, path_output,
               cflags_objc_out,
               /*write_substitution=*/false);
  base::EscapeJSONString(cflags_objc_out.str(), false, &flags.cflags_objc);

  std::ostringstream cflags_objcc_out;
  WriteOneFlag(target, &CSubstitutionCFlagsObjCc, has_precompiled_headers,
               CTool::kCToolObjCxx, &ConfigValues::cflags_objcc, opts,
               path_output, cflags_objcc_out, /*write_substitution=*/false);
  base::EscapeJSONString(cflags_objcc_out.str(), false, &flags.cflags_objcc);
}

void WriteFile(const SourceFile& source,
               PathOutput& path_output,
               std::string* compile_commands) {
  std::ostringstream rel_source_path;
  path_output.WriteFile(rel_source_path, source);
  compile_commands->append("    \"file\": \"");
  compile_commands->append(rel_source_path.str());
}

void WriteDirectory(std::string build_dir, std::string* compile_commands) {
  compile_commands->append("\",");
  compile_commands->append(kPrettyPrintLineEnding);
  compile_commands->append("    \"directory\": \"");
  compile_commands->append(build_dir);
  compile_commands->append("\",");
}

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

  for (const auto& range : tool->command().ranges()) {
    // TODO: this is emitting a bonus space prior to each substitution.
    if (range.type == &SubstitutionLiteral) {
      EscapeStringToStream(command_out, range.literal, no_quoting);
    } else if (range.type == &SubstitutionOutput) {
      path_output.WriteFiles(command_out, tool_outputs);
    } else if (range.type == &CSubstitutionDefines) {
      command_out << flags.defines;
    } else if (range.type == &CSubstitutionIncludeDirs) {
      command_out << flags.includes;
    } else if (range.type == &CSubstitutionCFlags) {
      command_out << flags.cflags;
    } else if (range.type == &CSubstitutionCFlagsC) {
      if (source_type == SOURCE_C)
        command_out << flags.cflags_c;
    } else if (range.type == &CSubstitutionCFlagsCc) {
      if (source_type == SOURCE_CPP)
        command_out << flags.cflags_cc;
    } else if (range.type == &CSubstitutionCFlagsObjC) {
      if (source_type == SOURCE_M)
        command_out << flags.cflags_objc;
    } else if (range.type == &CSubstitutionCFlagsObjCc) {
      if (source_type == SOURCE_MM)
        command_out << flags.cflags_objcc;
    } else if (range.type == &SubstitutionLabel ||
               range.type == &SubstitutionLabelName ||
               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(command_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;
    }
  }
  compile_commands->append(kPrettyPrintLineEnding);
  compile_commands->append("    \"command\": \"");
  compile_commands->append(command_out.str());
}

}  // namespace

void CompileCommandsWriter::RenderJSON(const BuildSettings* build_settings,
                                       std::vector<const Target*>& all_targets,
                                       std::string* compile_commands) {
  // TODO: Determine out an appropriate size to reserve.
  compile_commands->reserve(all_targets.size() * 100);
  compile_commands->append("[");
  compile_commands->append(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;

  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, 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.
      SourceFileType source_type = GetSourceFileType(source);
      if (source_type != SOURCE_CPP && source_type != SOURCE_C &&
          source_type != SOURCE_M && source_type != SOURCE_MM)
        continue;

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

      if (!first) {
        compile_commands->append(",");
        compile_commands->append(kPrettyPrintLineEnding);
      }
      first = false;
      compile_commands->append("  {");
      compile_commands->append(kPrettyPrintLineEnding);

      WriteFile(source, path_output, compile_commands);
      WriteDirectory(base::StringPrintf("%" PRIsFP, build_dir.value().c_str()),
                     compile_commands);
      WriteCommand(target, source, flags, tool_outputs, path_output,
                   source_type, tool_name, opts, compile_commands);
      compile_commands->append("\"");
      compile_commands->append(kPrettyPrintLineEnding);
      compile_commands->append("  }");
    }
  }

  compile_commands->append(kPrettyPrintLineEnding);
  compile_commands->append("]");
  compile_commands->append(kPrettyPrintLineEnding);
}

bool CompileCommandsWriter::RunAndWriteFiles(
    const BuildSettings* build_settings,
    const Builder& builder,
    const std::string& file_name,
    const std::string& target_filters,
    bool quiet,
    Err* err) {
  SourceFile output_file = build_settings->build_dir().ResolveRelativeFile(
      Value(nullptr, file_name), err);
  if (output_file.is_null())
    return false;

  base::FilePath output_path = build_settings->GetFullPath(output_file);

  std::vector<const Target*> all_targets = builder.GetAllResolvedTargets();

  std::set<std::string> target_filters_set;
  for (auto& target :
       base::SplitString(target_filters, ",", base::TRIM_WHITESPACE,
                         base::SPLIT_WANT_NONEMPTY)) {
    target_filters_set.insert(target);
  }
  std::string json;
  if (target_filters_set.empty()) {
    RenderJSON(build_settings, all_targets, &json);
  } else {
    std::vector<const Target*> preserved_targets =
        FilterTargets(all_targets, target_filters_set);
    RenderJSON(build_settings, preserved_targets, &json);
  }

  if (!WriteFileIfChanged(output_path, json, err))
    return false;
  return true;
}

std::vector<const Target*> CompileCommandsWriter::FilterTargets(
    const std::vector<const Target*>& all_targets,
    const std::set<std::string>& target_filters_set) {
  std::vector<const Target*> preserved_targets;

  std::set<const Target*> visited;
  for (auto& target : all_targets) {
    if (target_filters_set.count(target->label().name())) {
      VisitDeps(target, &visited);
    }
  }

  preserved_targets.reserve(visited.size());
  // Preserve the original ordering of all_targets
  // to allow easier debugging and testing.
  for (auto& target : all_targets) {
    if (visited.count(target)) {
      preserved_targets.push_back(target);
    }
  }
  return preserved_targets;
}

void CompileCommandsWriter::VisitDeps(const Target* target,
                                      std::set<const Target*>* visited) {
  if (!visited->count(target)) {
    visited->insert(target);
    for (const auto& pair : target->GetDeps(Target::DEPS_ALL)) {
      VisitDeps(pair.ptr, visited);
    }
  }
}