summaryrefslogtreecommitdiff
path: root/tools/libclang/CIndexer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libclang/CIndexer.cpp')
-rw-r--r--tools/libclang/CIndexer.cpp84
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);
+}