[clang-tools-extra] r344673 - [clangd] Simplify client capabilities parsing.
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 17 00:33:42 PDT 2018
Author: sammccall
Date: Wed Oct 17 00:33:42 2018
New Revision: 344673
URL: http://llvm.org/viewvc/llvm-project?rev=344673&view=rev
Log:
[clangd] Simplify client capabilities parsing.
Summary:
Instead of parsing into structs that mirror LSP, simply parse into a flat struct
that contains the info we need.
This is an exception to our strategy with Protocol.h, which seems justified:
- the structure here is very large and deeply nested
- we care about almost none of it
- we should never have to serialize client capabilities
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, cfe-commits
Differential Revision: https://reviews.llvm.org/D53266
Modified:
clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
clang-tools-extra/trunk/clangd/Protocol.cpp
clang-tools-extra/trunk/clangd/Protocol.h
Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=344673&r1=344672&r2=344673&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Wed Oct 17 00:33:42 2018
@@ -97,29 +97,14 @@ void ClangdLSPServer::onInitialize(Initi
else if (Params.rootPath && !Params.rootPath->empty())
Server->setRootPath(*Params.rootPath);
- CCOpts.EnableSnippets =
- Params.capabilities.textDocument.completion.completionItem.snippetSupport;
- DiagOpts.EmbedFixesInDiagnostics =
- Params.capabilities.textDocument.publishDiagnostics.clangdFixSupport;
- DiagOpts.SendDiagnosticCategory =
- Params.capabilities.textDocument.publishDiagnostics.categorySupport;
- SupportsCodeAction =
- Params.capabilities.textDocument.codeActionLiteralSupport;
-
- if (Params.capabilities.workspace && Params.capabilities.workspace->symbol &&
- 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));
+ CCOpts.EnableSnippets = Params.capabilities.CompletionSnippets;
+ DiagOpts.EmbedFixesInDiagnostics = Params.capabilities.DiagnosticFixes;
+ DiagOpts.SendDiagnosticCategory = Params.capabilities.DiagnosticCategory;
+ if (Params.capabilities.WorkspaceSymbolKinds)
+ SupportedSymbolKinds |= *Params.capabilities.WorkspaceSymbolKinds;
+ if (Params.capabilities.CompletionItemKinds)
+ SupportedCompletionItemKinds |= *Params.capabilities.CompletionItemKinds;
+ SupportsCodeAction = Params.capabilities.CodeActionStructure;
reply(json::Object{
{{"capabilities",
Modified: clang-tools-extra/trunk/clangd/Protocol.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=344673&r1=344672&r2=344673&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.cpp (original)
+++ clang-tools-extra/trunk/clangd/Protocol.cpp Wed Oct 17 00:33:42 2018
@@ -161,35 +161,6 @@ bool fromJSON(const json::Value &E, Trac
return false;
}
-bool fromJSON(const json::Value &Params, CompletionItemClientCapabilities &R) {
- json::ObjectMapper O(Params);
- if (!O)
- return false;
- O.map("snippetSupport", R.snippetSupport);
- O.map("commitCharacterSupport", R.commitCharacterSupport);
- return true;
-}
-
-bool fromJSON(const json::Value &Params, CompletionClientCapabilities &R) {
- json::ObjectMapper O(Params);
- if (!O)
- return false;
- O.map("dynamicRegistration", R.dynamicRegistration);
- O.map("completionItem", R.completionItem);
- O.map("contextSupport", R.contextSupport);
- return true;
-}
-
-bool fromJSON(const llvm::json::Value &Params,
- PublishDiagnosticsClientCapabilities &R) {
- json::ObjectMapper O(Params);
- if (!O)
- return false;
- O.map("clangdFixSupport", R.clangdFixSupport);
- O.map("categorySupport", R.categorySupport);
- return true;
-}
-
bool fromJSON(const json::Value &E, SymbolKind &Out) {
if (auto T = E.getAsInteger()) {
if (*T < static_cast<int>(SymbolKind::File) ||
@@ -201,24 +172,18 @@ bool fromJSON(const json::Value &E, Symb
return false;
}
-bool fromJSON(const json::Value &E, std::vector<SymbolKind> &Out) {
+bool fromJSON(const json::Value &E, SymbolKindBitset &Out) {
if (auto *A = E.getAsArray()) {
- Out.clear();
for (size_t I = 0; I < A->size(); ++I) {
SymbolKind KindOut;
if (fromJSON((*A)[I], KindOut))
- Out.push_back(KindOut);
+ Out.set(size_t(KindOut));
}
return true;
}
return false;
}
-bool fromJSON(const json::Value &Params, SymbolKindCapabilities &R) {
- json::ObjectMapper O(Params);
- return O && O.map("valueSet", R.valueSet);
-}
-
SymbolKind adjustKindToCapability(SymbolKind Kind,
SymbolKindBitset &SupportedSymbolKinds) {
auto KindVal = static_cast<size_t>(Kind);
@@ -237,34 +202,46 @@ SymbolKind adjustKindToCapability(Symbol
}
}
-bool fromJSON(const json::Value &Params, WorkspaceSymbolCapabilities &R) {
- json::ObjectMapper O(Params);
- return O && O.map("symbolKind", R.symbolKind);
-}
-
-bool fromJSON(const json::Value &Params, WorkspaceClientCapabilities &R) {
- json::ObjectMapper O(Params);
- return O && O.map("symbol", R.symbol);
-}
-
-bool fromJSON(const json::Value &Params, TextDocumentClientCapabilities &R) {
- json::ObjectMapper O(Params);
- if (!O)
- return false;
- O.map("completion", R.completion);
- O.map("publishDiagnostics", R.publishDiagnostics);
- if (auto *CodeAction = Params.getAsObject()->getObject("codeAction"))
- if (CodeAction->getObject("codeActionLiteralSupport"))
- R.codeActionLiteralSupport = true;
- return true;
-}
-
bool fromJSON(const json::Value &Params, ClientCapabilities &R) {
- json::ObjectMapper O(Params);
+ const json::Object *O = Params.getAsObject();
if (!O)
return false;
- O.map("textDocument", R.textDocument);
- O.map("workspace", R.workspace);
+ if (auto *TextDocument = O->getObject("textDocument")) {
+ if (auto *Diagnostics = TextDocument->getObject("publishDiagnostics")) {
+ if (auto CategorySupport = Diagnostics->getBoolean("categorySupport"))
+ R.DiagnosticCategory = *CategorySupport;
+ if (auto ClangdFixSupport = Diagnostics->getBoolean("clangdFixSupport"))
+ R.DiagnosticFixes = *ClangdFixSupport;
+ }
+ if (auto *Completion = TextDocument->getObject("completion")) {
+ if (auto *Item = Completion->getObject("completionItem")) {
+ if (auto SnippetSupport = Item->getBoolean("snippetSupport"))
+ R.CompletionSnippets = *SnippetSupport;
+ }
+ if (auto *ItemKind = Completion->getObject("completionItemKind")) {
+ if (auto *ValueSet = ItemKind->get("valueSet")) {
+ R.CompletionItemKinds.emplace();
+ if (!fromJSON(*ValueSet, *R.CompletionItemKinds))
+ return false;
+ }
+ }
+ }
+ if (auto *CodeAction = TextDocument->getObject("codeAction")) {
+ if (CodeAction->getObject("codeActionLiteralSupport"))
+ R.CodeActionStructure = true;
+ }
+ }
+ if (auto *Workspace = O->getObject("workspace")) {
+ if (auto *Symbol = Workspace->getObject("symbol")) {
+ if (auto *SymbolKind = Symbol->getObject("symbolKind")) {
+ if (auto *ValueSet = SymbolKind->get("valueSet")) {
+ R.WorkspaceSymbolKinds.emplace();
+ if (!fromJSON(*ValueSet, *R.WorkspaceSymbolKinds))
+ return false;
+ }
+ }
+ }
+ }
return true;
}
@@ -560,24 +537,18 @@ adjustKindToCapability(CompletionItemKin
}
}
-bool fromJSON(const json::Value &E, std::vector<CompletionItemKind> &Out) {
+bool fromJSON(const json::Value &E, CompletionItemKindBitset &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);
+ Out.set(size_t(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}};
Modified: clang-tools-extra/trunk/clangd/Protocol.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.h?rev=344673&r1=344672&r2=344673&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.h (original)
+++ clang-tools-extra/trunk/clangd/Protocol.h Wed Oct 17 00:33:42 2018
@@ -238,18 +238,6 @@ enum class TextDocumentSyncKind {
Incremental = 2,
};
-struct CompletionItemClientCapabilities {
- /// Client supports snippets as insert text.
- bool snippetSupport = false;
- /// Client supports commit characters on a completion item.
- bool commitCharacterSupport = false;
- // Client supports the follow content formats for the documentation property.
- // The order describes the preferred format of the client.
- // NOTE: not used by clangd at the moment.
- // std::vector<MarkupKind> documentationFormat;
-};
-bool fromJSON(const llvm::json::Value &, CompletionItemClientCapabilities &);
-
/// The kind of a completion entry.
enum class CompletionItemKind {
Missing = 0,
@@ -280,58 +268,16 @@ enum class CompletionItemKind {
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>;
+bool fromJSON(const llvm::json::Value &, CompletionItemKindBitset &);
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;
- /// 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.
- bool contextSupport = false;
-};
-bool fromJSON(const llvm::json::Value &, CompletionClientCapabilities &);
-
-struct PublishDiagnosticsClientCapabilities {
- // Whether the client accepts diagnostics with related information.
- // NOTE: not used by clangd at the moment.
- // bool relatedInformation;
-
- /// Whether the client accepts diagnostics with fixes attached using the
- /// "clangd_fixes" extension.
- bool clangdFixSupport = false;
-
- /// Whether the client accepts diagnostics with category attached to it
- /// using the "category" extension.
- bool categorySupport = false;
-};
-bool fromJSON(const llvm::json::Value &,
- PublishDiagnosticsClientCapabilities &);
-
/// A symbol kind.
enum class SymbolKind {
File = 1,
@@ -361,62 +307,44 @@ enum class SymbolKind {
Operator = 25,
TypeParameter = 26
};
-
+bool fromJSON(const llvm::json::Value &, SymbolKind &);
constexpr auto SymbolKindMin = static_cast<size_t>(SymbolKind::File);
constexpr auto SymbolKindMax = static_cast<size_t>(SymbolKind::TypeParameter);
using SymbolKindBitset = std::bitset<SymbolKindMax + 1>;
-
-bool fromJSON(const llvm::json::Value &, SymbolKind &);
-
-struct SymbolKindCapabilities {
- /// The SymbolKinds that the client supports. If not set, the client only
- /// supports <= SymbolKind::Array and will not fall back to a valid default
- /// 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 &);
+bool fromJSON(const llvm::json::Value &, SymbolKindBitset &);
SymbolKind adjustKindToCapability(SymbolKind Kind,
SymbolKindBitset &supportedSymbolKinds);
-struct WorkspaceSymbolCapabilities {
- /// Capabilities SymbolKind.
- llvm::Optional<SymbolKindCapabilities> symbolKind;
-};
-bool fromJSON(const llvm::json::Value &, WorkspaceSymbolCapabilities &);
+// This struct doesn't mirror LSP!
+// The protocol defines deeply nested structures for client capabilities.
+// Instead of mapping them all, this just parses out the bits we care about.
+struct ClientCapabilities {
+ /// The supported set of SymbolKinds for workspace/symbol.
+ /// workspace.symbol.symbolKind.valueSet
+ llvm::Optional<SymbolKindBitset> WorkspaceSymbolKinds;
-// FIXME: most of the capabilities are missing from this struct. Only the ones
-// used by clangd are currently there.
-struct WorkspaceClientCapabilities {
- /// Capabilities specific to `workspace/symbol`.
- llvm::Optional<WorkspaceSymbolCapabilities> symbol;
-};
-bool fromJSON(const llvm::json::Value &, WorkspaceClientCapabilities &);
+ /// Whether the client accepts diagnostics with fixes attached using the
+ /// "clangd_fixes" extension.
+ /// textDocument.publishDiagnostics.clangdFixSupport
+ bool DiagnosticFixes = false;
-// FIXME: most of the capabilities are missing from this struct. Only the ones
-// used by clangd are currently there.
-struct TextDocumentClientCapabilities {
- /// Capabilities specific to the `textDocument/completion`
- CompletionClientCapabilities completion;
-
- /// Capabilities specific to the 'textDocument/publishDiagnostics'
- PublishDiagnosticsClientCapabilities publishDiagnostics;
-
- /// Flattened from codeAction.codeActionLiteralSupport.
- // FIXME: flatten other properties in this way.
- bool codeActionLiteralSupport = false;
-};
-bool fromJSON(const llvm::json::Value &, TextDocumentClientCapabilities &);
+ /// Whether the client accepts diagnostics with category attached to it
+ /// using the "category" extension.
+ /// textDocument.publishDiagnostics.categorySupport
+ bool DiagnosticCategory = false;
-struct ClientCapabilities {
- // Workspace specific client capabilities.
- llvm::Optional<WorkspaceClientCapabilities> workspace;
+ /// Client supports snippets as insert text.
+ /// textDocument.completion.completionItem.snippetSupport
+ bool CompletionSnippets = false;
- // Text document specific client capabilities.
- TextDocumentClientCapabilities textDocument;
+ /// The supported set of CompletionItemKinds for textDocument/completion.
+ /// textDocument.completion.completionItemKind.valueSet
+ llvm::Optional<CompletionItemKindBitset> CompletionItemKinds;
+
+ /// Client supports CodeAction return value for textDocument/codeAction.
+ /// textDocument.codeAction.codeActionLiteralSupport.
+ bool CodeActionStructure = false;
};
-
bool fromJSON(const llvm::json::Value &, ClientCapabilities &);
/// Clangd extension that's used in the 'compilationDatabaseChanges' in
More information about the cfe-commits
mailing list