diff options
Diffstat (limited to 'tools/libclang/CIndexer.cpp')
-rw-r--r-- | tools/libclang/CIndexer.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/tools/libclang/CIndexer.cpp b/tools/libclang/CIndexer.cpp index 694ed606306cf..62ea881720699 100644 --- a/tools/libclang/CIndexer.cpp +++ b/tools/libclang/CIndexer.cpp @@ -12,10 +12,14 @@ //===----------------------------------------------------------------------===// #include "CIndexer.h" +#include "CXString.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/Version.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Support/MD5.h" +#include "llvm/Support/MutexGuard.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include <cstdio> @@ -76,3 +80,83 @@ const std::string &CIndexer::getClangResourcesPath() { ResourcesPath = LibClangPath.str(); 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 << 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 << '"' << I.value() << '"'; + } + if (!InvocationArgs.empty()) { + OS << R"(],"invocation-args":[)"; + for (const auto &I : llvm::enumerate(InvocationArgs)) { + if (I.index()) + OS << ','; + OS << '"' << 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); +} |