[clangd] textDocument/SymbolInfo extension

New method returning symbol info for given source position.

Differential Revision: https://reviews.llvm.org/D54799

rdar://problem/46050281

llvm-svn: 347675
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index b7053ed..1cc6b16 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -14,7 +14,9 @@
 #include "Protocol.h"
 #include "Logger.h"
 #include "URI.h"
+#include "index/Index.h"
 #include "clang/Basic/LLVM.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -428,6 +430,44 @@
   return O;
 }
 
+bool operator==(const SymbolDetails &LHS, const SymbolDetails &RHS) {
+  return LHS.name == RHS.name && LHS.containerName == RHS.containerName &&
+         LHS.USR == RHS.USR && LHS.ID == RHS.ID;
+}
+
+llvm::json::Value toJSON(const SymbolDetails &P) {
+  json::Object result{{"name", llvm::json::Value(nullptr)},
+                      {"containerName", llvm::json::Value(nullptr)},
+                      {"usr", llvm::json::Value(nullptr)},
+                      {"id", llvm::json::Value(nullptr)}};
+
+  if (!P.name.empty())
+    result["name"] = P.name;
+
+  if (!P.containerName.empty())
+    result["containerName"] = P.containerName;
+
+  if (!P.USR.empty())
+    result["usr"] = P.USR;
+
+  if (P.ID.hasValue())
+    result["id"] = P.ID.getValue().str();
+
+  return result;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const SymbolDetails &S) {
+  if (!S.containerName.empty()) {
+    O << S.containerName;
+    StringRef ContNameRef;
+    if (!ContNameRef.endswith("::")) {
+      O << " ";
+    }
+  }
+  O << S.name << " - " << toJSON(S);
+  return O;
+}
+
 bool fromJSON(const json::Value &Params, WorkspaceSymbolParams &R) {
   json::ObjectMapper O(Params);
   return O && O.map("query", R.query);