summaryrefslogtreecommitdiff
path: root/clang-tools-extra
diff options
context:
space:
mode:
authorKadir Cetinkaya <kadircet@google.com>2018-09-27 17:13:07 +0000
committerKadir Cetinkaya <kadircet@google.com>2018-09-27 17:13:07 +0000
commit3c5e1c821e2ba82bc98322c693dc2b3582368ac1 (patch)
tree985421d41163cc9ca0c99db26b4e11ac297f72f1 /clang-tools-extra
parent38caf2550c64982c18004e1971abf5794590c643 (diff)
Introduce completionItemKind capability support.
Reviewers: sammccall Reviewed By: sammccall Subscribers: ilya-biryukov, ioeric, jkorous, arphaman, cfe-commits Differential Revision: https://reviews.llvm.org/D52616
Diffstat (limited to 'clang-tools-extra')
-rw-r--r--clang-tools-extra/clangd/ClangdLSPServer.cpp26
-rw-r--r--clang-tools-extra/clangd/ClangdLSPServer.h2
-rw-r--r--clang-tools-extra/clangd/Protocol.cpp51
-rw-r--r--clang-tools-extra/clangd/Protocol.h87
4 files changed, 131 insertions, 35 deletions
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index a4ebf575d31..c6ce3ef9bf9 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -70,6 +70,14 @@ SymbolKindBitset defaultSymbolKinds() {
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) {
@@ -89,13 +97,20 @@ void ClangdLSPServer::onInitialize(InitializeParams &Params) {
Params.capabilities.textDocument.publishDiagnostics.categorySupport;
if (Params.capabilities.workspace && Params.capabilities.workspace->symbol &&
- Params.capabilities.workspace->symbol->symbolKind) {
+ Params.capabilities.workspace->symbol->symbolKind &&
+ Params.capabilities.workspace->symbol->symbolKind->valueSet) {
for (SymbolKind Kind :
*Params.capabilities.workspace->symbol->symbolKind->valueSet) {
SupportedSymbolKinds.set(static_cast<size_t>(Kind));
}
}
+ if (Params.capabilities.textDocument.completion.completionItemKind &&
+ Params.capabilities.textDocument.completion.completionItemKind->valueSet)
+ for (CompletionItemKind Kind : *Params.capabilities.textDocument.completion
+ .completionItemKind->valueSet)
+ SupportedCompletionItemKinds.set(static_cast<size_t>(Kind));
+
reply(json::Object{
{{"capabilities",
json::Object{
@@ -347,8 +362,12 @@ void ClangdLSPServer::onCompletion(TextDocumentPositionParams &Params) {
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 +478,7 @@ ClangdLSPServer::ClangdLSPServer(JSONOutput &Out,
: CompilationDB::makeDirectoryBased(
std::move(CompileCommandsDir))),
CCOpts(CCOpts), SupportedSymbolKinds(defaultSymbolKinds()),
+ SupportedCompletionItemKinds(defaultCompletionItemKinds()),
Server(new ClangdServer(CDB.getCDB(), FSProvider, /*DiagConsumer=*/*this,
Opts)) {}
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h
index f39fdb61c75..f77b24b9b69 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.h
+++ b/clang-tools-extra/clangd/ClangdLSPServer.h
@@ -164,6 +164,8 @@ private:
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;
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index e6ffe66a129..7a137eb6b8e 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -496,6 +496,57 @@ json::Value toJSON(const Hover &H) {
return std::move(Result);
}
+bool fromJSON(const json::Value &E, CompletionItemKind &Out) {
+ if (auto T = E.getAsInteger()) {
+ if (*T < static_cast<int>(CompletionItemKind::Text) ||
+ *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}};
diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h
index 5e77e8b6acf..22da2e3af6d 100644
--- a/clang-tools-extra/clangd/Protocol.h
+++ b/clang-tools-extra/clangd/Protocol.h
@@ -233,13 +233,65 @@ struct CompletionItemClientCapabilities {
};
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;
+};
+// Discards unknown CompletionItemKinds.
+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.
@@ -305,6 +357,7 @@ struct SymbolKindCapabilities {
/// value.
llvm::Optional<std::vector<SymbolKind>> valueSet;
};
+// Discards unknown SymbolKinds.
bool fromJSON(const llvm::json::Value &, std::vector<SymbolKind> &);
bool fromJSON(const llvm::json::Value &, SymbolKindCapabilities &);
SymbolKind adjustKindToCapability(SymbolKind Kind,
@@ -683,36 +736,6 @@ struct Hover {
};
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 {