//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the Clang-C Source Indexing library.
//
//===----------------------------------------------------------------------===//

#include "CIndexer.h"
#include "CXString.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Driver.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/YAMLParser.h"
#include <cstdio>

#ifdef __CYGWIN__
#include <cygwin/version.h>
#include <sys/cygwin.h>
#define _WIN32 1
#endif

#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif

using namespace clang;

const std::string &CIndexer::getClangResourcesPath() {
  // Did we already compute the path?
  if (!ResourcesPath.empty())
    return ResourcesPath;

  SmallString<128> LibClangPath;

  // Find the location where this library lives (libclang.dylib).
#ifdef _WIN32
  MEMORY_BASIC_INFORMATION mbi;
  char path[MAX_PATH];
  VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi,
               sizeof(mbi));
  GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);

#ifdef __CYGWIN__
  char w32path[MAX_PATH];
  strcpy(w32path, path);
#if CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR >= 181
  cygwin_conv_path(CCP_WIN_A_TO_POSIX, w32path, path, MAX_PATH);
#else
  cygwin_conv_to_full_posix_path(w32path, path);
#endif
#endif

  LibClangPath += path;
#else
  // This silly cast below avoids a C++ warning.
  Dl_info info;
  if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0)
    llvm_unreachable("Call to dladdr() failed");

  // We now have the CIndex directory, locate clang relative to it.
  LibClangPath += info.dli_fname;
#endif

  // Cache our result.
  ResourcesPath = driver::Driver::GetResourcesPath(LibClangPath);
  return ResourcesPath;
}

StringRef CIndexer::getClangToolchainPath() {
  if (!ToolchainPath.empty())
    return ToolchainPath;
  StringRef ResourcePath = getClangResourcesPath();
  ToolchainPath = llvm::sys::path::parent_path(
      llvm::sys::path::parent_path(llvm::sys::path::parent_path(ResourcePath)));
  return ToolchainPath;
}

LibclangInvocationReporter::LibclangInvocationReporter(
    CIndexer &Idx, OperationKind Op, unsigned ParseOptions,
    llvm::ArrayRef<const char *> Args,
    llvm::ArrayRef<std::string> InvocationArgs,
    llvm::ArrayRef<CXUnsavedFile> UnsavedFiles) {
  StringRef Path = Idx.getInvocationEmissionPath();
  if (Path.empty())
    return;

  // Create a temporary file for the invocation log.
  SmallString<256> TempPath;
  TempPath = Path;
  llvm::sys::path::append(TempPath, "libclang-%%%%%%%%%%%%");
  int FD;
  if (llvm::sys::fs::createUniqueFile(TempPath, FD, TempPath))
    return;
  File = std::string(TempPath.begin(), TempPath.end());
  llvm::raw_fd_ostream OS(FD, /*ShouldClose=*/true);

  // Write out the information about the invocation to it.
  auto WriteStringKey = [&OS](StringRef Key, StringRef Value) {
    OS << R"(")" << Key << R"(":")";
    OS << llvm::yaml::escape(Value) << '"';
  };
  OS << '{';
  WriteStringKey("toolchain", Idx.getClangToolchainPath());
  OS << ',';
  WriteStringKey("libclang.operation",
                 Op == OperationKind::ParseOperation ? "parse" : "complete");
  OS << ',';
  OS << R"("libclang.opts":)" << ParseOptions;
  OS << ',';
  OS << R"("args":[)";
  for (const auto &I : llvm::enumerate(Args)) {
    if (I.index())
      OS << ',';
    OS << '"' << llvm::yaml::escape(I.value()) << '"';
  }
  if (!InvocationArgs.empty()) {
    OS << R"(],"invocation-args":[)";
    for (const auto &I : llvm::enumerate(InvocationArgs)) {
      if (I.index())
        OS << ',';
      OS << '"' << llvm::yaml::escape(I.value()) << '"';
    }
  }
  if (!UnsavedFiles.empty()) {
    OS << R"(],"unsaved_file_hashes":[)";
    for (const auto &UF : llvm::enumerate(UnsavedFiles)) {
      if (UF.index())
        OS << ',';
      OS << '{';
      WriteStringKey("name", UF.value().Filename);
      OS << ',';
      llvm::MD5 Hash;
      Hash.update(getContents(UF.value()));
      llvm::MD5::MD5Result Result;
      Hash.final(Result);
      SmallString<32> Digest = Result.digest();
      WriteStringKey("md5", Digest);
      OS << '}';
    }
  }
  OS << "]}";
}

LibclangInvocationReporter::~LibclangInvocationReporter() {
  if (!File.empty())
    llvm::sys::fs::remove(File);
}
