kadircet created this revision.
kadircet added a reviewer: sammccall.
Herald added subscribers: cfe-commits, arphaman, jkorous, ioeric, ilya-biryukov.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D52616

Files:
  clangd/ClangdLSPServer.cpp
  clangd/ClangdLSPServer.h
  clangd/Protocol.cpp
  clangd/Protocol.h

Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -233,13 +233,65 @@
 };
 bool fromJSON(const llvm::json::Value &, CompletionItemClientCapabilities &);
 
+/// The kind of a completion entry.
+enum class CompletionItemKind {
+  Missing = 0,
+  Text = 1,
+  Method = 2,
+  Function = 3,
+  Constructor = 4,
+  Field = 5,
+  Variable = 6,
+  Class = 7,
+  Interface = 8,
+  Module = 9,
+  Property = 10,
+  Unit = 11,
+  Value = 12,
+  Enum = 13,
+  Keyword = 14,
+  Snippet = 15,
+  Color = 16,
+  File = 17,
+  Reference = 18,
+  Folder = 19,
+  EnumMember = 20,
+  Constant = 21,
+  Struct = 22,
+  Event = 23,
+  Operator = 24,
+  TypeParameter = 25,
+};
+
+bool fromJSON(const llvm::json::Value &, CompletionItemKind &);
+
+struct CompletionItemKindCapabilities {
+  /// The CompletionItemKinds that the client supports. If not set, the client
+  /// only supports <= CompletionItemKind::Reference and will not fall back to a
+  /// valid default value.
+  llvm::Optional<std::vector<CompletionItemKind>> valueSet;
+};
+bool fromJSON(const llvm::json::Value &, std::vector<CompletionItemKind> &);
+bool fromJSON(const llvm::json::Value &, CompletionItemKindCapabilities &);
+
+constexpr auto CompletionItemKindMin =
+    static_cast<size_t>(CompletionItemKind::Text);
+constexpr auto CompletionItemKindMax =
+    static_cast<size_t>(CompletionItemKind::TypeParameter);
+using CompletionItemKindBitset = std::bitset<CompletionItemKindMax + 1>;
+CompletionItemKind
+adjustKindToCapability(CompletionItemKind Kind,
+                       CompletionItemKindBitset &supportedCompletionItemKinds);
+
 struct CompletionClientCapabilities {
   /// Whether completion supports dynamic registration.
   bool dynamicRegistration = false;
   /// The client supports the following `CompletionItem` specific capabilities.
   CompletionItemClientCapabilities completionItem;
-  // NOTE: not used by clangd at the moment.
-  // llvm::Optional<CompletionItemKindCapabilities> completionItemKind;
+  /// The CompletionItemKinds that the client supports. If not set, the client
+  /// only supports <= CompletionItemKind::Reference and will not fall back to a
+  /// valid default value.
+  llvm::Optional<CompletionItemKindCapabilities> completionItemKind;
 
   /// The client supports to send additional context information for a
   /// `textDocument/completion` request.
@@ -683,36 +735,6 @@
 };
 llvm::json::Value toJSON(const Hover &H);
 
-/// The kind of a completion entry.
-enum class CompletionItemKind {
-  Missing = 0,
-  Text = 1,
-  Method = 2,
-  Function = 3,
-  Constructor = 4,
-  Field = 5,
-  Variable = 6,
-  Class = 7,
-  Interface = 8,
-  Module = 9,
-  Property = 10,
-  Unit = 11,
-  Value = 12,
-  Enum = 13,
-  Keyword = 14,
-  Snippet = 15,
-  Color = 16,
-  File = 17,
-  Reference = 18,
-  Folder = 19,
-  EnumMember = 20,
-  Constant = 21,
-  Struct = 22,
-  Event = 23,
-  Operator = 24,
-  TypeParameter = 25,
-};
-
 /// Defines whether the insert text in a completion item should be interpreted
 /// as plain text or a snippet.
 enum class InsertTextFormat {
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -496,6 +496,57 @@
   return std::move(Result);
 }
 
+bool fromJSON(const json::Value &E, CompletionItemKind &Out) {
+  if (auto T = E.getAsInteger()) {
+    if (*T < static_cast<int>(CompletionItemKind::File) ||
+        *T > static_cast<int>(CompletionItemKind::TypeParameter))
+      return false;
+    Out = static_cast<CompletionItemKind>(*T);
+    return true;
+  }
+  return false;
+}
+
+CompletionItemKind
+adjustKindToCapability(CompletionItemKind Kind,
+                       CompletionItemKindBitset &supportedCompletionItemKinds) {
+  auto KindVal = static_cast<size_t>(Kind);
+  if (KindVal >= CompletionItemKindMin &&
+      KindVal <= supportedCompletionItemKinds.size() &&
+      supportedCompletionItemKinds[KindVal])
+    return Kind;
+
+  switch (Kind) {
+  // Provide some fall backs for common kinds that are close enough.
+  case CompletionItemKind::Folder:
+    return CompletionItemKind::File;
+  case CompletionItemKind::EnumMember:
+    return CompletionItemKind::Enum;
+  case CompletionItemKind::Struct:
+    return CompletionItemKind::Class;
+  default:
+    return CompletionItemKind::Text;
+  }
+}
+
+bool fromJSON(const json::Value &E, std::vector<CompletionItemKind> &Out) {
+  if (auto *A = E.getAsArray()) {
+    Out.clear();
+    for (size_t I = 0; I < A->size(); ++I) {
+      CompletionItemKind KindOut;
+      if (fromJSON((*A)[I], KindOut))
+        Out.push_back(KindOut);
+    }
+    return true;
+  }
+  return false;
+}
+
+bool fromJSON(const json::Value &Params, CompletionItemKindCapabilities &R) {
+  json::ObjectMapper O(Params);
+  return O && O.map("valueSet", R.valueSet);
+}
+
 json::Value toJSON(const CompletionItem &CI) {
   assert(!CI.label.empty() && "completion item label is required");
   json::Object Result{{"label", CI.label}};
Index: clangd/ClangdLSPServer.h
===================================================================
--- clangd/ClangdLSPServer.h
+++ clangd/ClangdLSPServer.h
@@ -164,6 +164,8 @@
   ClangdDiagnosticOptions DiagOpts;
   /// The supported kinds of the client.
   SymbolKindBitset SupportedSymbolKinds;
+  /// The supported completion item kinds of the client.
+  CompletionItemKindBitset SupportedCompletionItemKinds;
 
   // Store of the current versions of the open documents.
   DraftStore DraftMgr;
Index: clangd/ClangdLSPServer.cpp
===================================================================
--- clangd/ClangdLSPServer.cpp
+++ clangd/ClangdLSPServer.cpp
@@ -70,6 +70,14 @@
   return Defaults;
 }
 
+CompletionItemKindBitset defaultCompletionItemKinds() {
+  CompletionItemKindBitset Defaults;
+  for (size_t I = CompletionItemKindMin;
+       I <= static_cast<size_t>(CompletionItemKind::Reference); ++I)
+    Defaults.set(I);
+  return Defaults;
+}
+
 } // namespace
 
 void ClangdLSPServer::onInitialize(InitializeParams &Params) {
@@ -96,6 +104,11 @@
     }
   }
 
+  if (Params.capabilities.textDocument.completion.completionItemKind)
+    for (CompletionItemKind Kind : *Params.capabilities.textDocument.completion
+                                        .completionItemKind->valueSet)
+      SupportedCompletionItemKinds.set(static_cast<size_t>(Kind));
+
   reply(json::Object{
       {{"capabilities",
         json::Object{
@@ -347,8 +360,12 @@
                            return replyError(List.takeError());
                          CompletionList LSPList;
                          LSPList.isIncomplete = List->HasMore;
-                         for (const auto &R : List->Completions)
-                           LSPList.items.push_back(R.render(CCOpts));
+                         for (const auto &R : List->Completions) {
+                           CompletionItem C = R.render(CCOpts);
+                           C.kind = adjustKindToCapability(
+                               C.kind, SupportedCompletionItemKinds);
+                           LSPList.items.push_back(std::move(C));
+                         }
                          return reply(std::move(LSPList));
                        });
 }
@@ -459,6 +476,7 @@
                                          : CompilationDB::makeDirectoryBased(
                                                std::move(CompileCommandsDir))),
       CCOpts(CCOpts), SupportedSymbolKinds(defaultSymbolKinds()),
+      SupportedCompletionItemKinds(defaultCompletionItemKinds()),
       Server(new ClangdServer(CDB.getCDB(), FSProvider, /*DiagConsumer=*/*this,
                               Opts)) {}
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to