[clangd] Add support for hierarchical documentSymbol

Reviewers: ioeric, sammccall, simark

Reviewed By: sammccall

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

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

llvm-svn: 347498
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index d8369f3..bf32a96 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -18,6 +18,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/JSON.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -222,6 +223,11 @@
       if (CodeAction->getObject("codeActionLiteralSupport"))
         R.CodeActionStructure = true;
     }
+    if (auto *DocumentSymbol = TextDocument->getObject("documentSymbol")) {
+      if (auto HierarchicalSupport =
+              DocumentSymbol->getBoolean("hierarchicalDocumentSymbolSupport"))
+        R.HierarchicalDocumentSymbol = *HierarchicalSupport;
+    }
   }
   if (auto *Workspace = O->getObject("workspace")) {
     if (auto *Symbol = Workspace->getObject("symbol")) {
@@ -449,6 +455,25 @@
   return std::move(CodeAction);
 }
 
+llvm::raw_ostream &operator<<(llvm::raw_ostream &O, const DocumentSymbol &S) {
+  return O << S.name << " - " << toJSON(S);
+}
+
+llvm::json::Value toJSON(const DocumentSymbol &S) {
+  json::Object Result{{"name", S.name},
+                      {"kind", static_cast<int>(S.kind)},
+                      {"range", S.range},
+                      {"selectionRange", S.selectionRange}};
+
+  if (!S.detail.empty())
+    Result["detail"] = S.detail;
+  if (!S.children.empty())
+    Result["children"] = S.children;
+  if (S.deprecated)
+    Result["deprecated"] = true;
+  return Result;
+}
+
 json::Value toJSON(const WorkspaceEdit &WE) {
   if (!WE.changes)
     return json::Object{};