[clangd] Implement textDocument/hover

Summary: Implemention of textDocument/hover as described in LSP definition.

This patch adds a basic Hover implementation.  When hovering a variable,
function, method or namespace, clangd will return a text containing the
declaration's scope, as well as the declaration of the hovered entity.
For example, for a variable:

  Declared in class Foo::Bar

  int hello = 2

For macros, the macro definition is returned.

This patch doesn't include:

- markdown support (the client I use doesn't support it yet)
- range support (optional in the Hover response)
- comments associated to variables/functions/classes

They are kept as future work to keep this patch simpler.

I added tests in XRefsTests.cpp.  hover.test contains one simple
smoketest to make sure the feature works from a black box perspective.

Reviewers: malaperle, krasimir, bkramer, ilya-biryukov

Subscribers: sammccall, mgrang, klimek, rwols, ilya-biryukov, arphaman, cfe-commits

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

Signed-off-by: Simon Marchi <simon.marchi@ericsson.com>
Signed-off-by: William Enright <william.enright@polymtl.ca>
llvm-svn: 325395
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index 07b563a..fb3f05a 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -386,6 +386,35 @@
          O.map("position", R.position);
 }
 
+static StringRef toTextKind(MarkupKind Kind) {
+  switch (Kind) {
+  case MarkupKind::PlainText:
+    return "plaintext";
+  case MarkupKind::Markdown:
+    return "markdown";
+  }
+  llvm_unreachable("Invalid MarkupKind");
+}
+
+json::Expr toJSON(const MarkupContent &MC) {
+  if (MC.Value.empty())
+    return nullptr;
+
+  return json::obj{
+      {"kind", toTextKind(MC.Kind)},
+      {"value", MC.Value},
+  };
+}
+
+json::Expr toJSON(const Hover &H) {
+  json::obj Result{{"contents", toJSON(H.Contents)}};
+
+  if (H.Range.hasValue())
+    Result["range"] = toJSON(*H.Range);
+
+  return std::move(Result);
+}
+
 json::Expr toJSON(const CompletionItem &CI) {
   assert(!CI.label.empty() && "completion item label is required");
   json::obj Result{{"label", CI.label}};