[clang-tools-extra] 3f9f146 - [clangd] Move completion signatures and labelDetails
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 5 09:08:57 PDT 2023
Author: Sam McCall
Date: 2023-06-05T18:05:18+02:00
New Revision: 3f9f1463719d7491768e9a224ac089c8f9baab68
URL: https://github.com/llvm/llvm-project/commit/3f9f1463719d7491768e9a224ac089c8f9baab68
DIFF: https://github.com/llvm/llvm-project/commit/3f9f1463719d7491768e9a224ac089c8f9baab68.diff
LOG: [clangd] Move completion signatures and labelDetails
(When clients support it, otherwise keep the existing rendering).
In VSCode this makes the signature darker.
Differential Revision: https://reviews.llvm.org/D151253
Added:
Modified:
clang-tools-extra/clangd/ClangdLSPServer.cpp
clang-tools-extra/clangd/ClangdLSPServer.h
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/Protocol.cpp
clang-tools-extra/clangd/Protocol.h
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 26e239fa7bed6..396b903a9a762 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -513,6 +513,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
SupportedSymbolKinds |= *Params.capabilities.WorkspaceSymbolKinds;
if (Params.capabilities.CompletionItemKinds)
SupportedCompletionItemKinds |= *Params.capabilities.CompletionItemKinds;
+ SupportsCompletionLabelDetails = Params.capabilities.CompletionLabelDetail;
SupportsCodeAction = Params.capabilities.CodeActionStructure;
SupportsHierarchicalDocumentSymbol =
Params.capabilities.HierarchicalDocumentSymbol;
@@ -1100,6 +1101,8 @@ void ClangdLSPServer::onCompletion(const CompletionParams &Params,
CompletionItem C = R.render(Opts);
C.kind = adjustKindToCapability(
C.kind, SupportedCompletionItemKinds);
+ if (!SupportsCompletionLabelDetails)
+ removeCompletionLabelDetails(C);
LSPList.items.push_back(std::move(C));
}
return Reply(std::move(LSPList));
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h
index 332ff680438ad..a483d1110f64c 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.h
+++ b/clang-tools-extra/clangd/ClangdLSPServer.h
@@ -260,6 +260,8 @@ class ClangdLSPServer : private ClangdServer::Callbacks,
SymbolKindBitset SupportedSymbolKinds;
/// The supported completion item kinds of the client.
CompletionItemKindBitset SupportedCompletionItemKinds;
+ // Whether the client supports CompletionItem.labelDetails.
+ bool SupportsCompletionLabelDetails = false;
/// Whether the client supports CodeAction response objects.
bool SupportsCodeAction = false;
/// From capabilities of textDocument/documentSymbol.
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 3da923c6dd929..f4f93a01ec90e 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -2219,11 +2219,15 @@ bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx) {
CompletionItem CodeCompletion::render(const CodeCompleteOptions &Opts) const {
CompletionItem LSP;
const auto *InsertInclude = Includes.empty() ? nullptr : &Includes[0];
+ // We could move our indicators from label into labelDetails->description.
+ // In VSCode there are rendering issues that prevent these being aligned.
LSP.label = ((InsertInclude && InsertInclude->Insertion)
? Opts.IncludeIndicator.Insert
: Opts.IncludeIndicator.NoInsert) +
(Opts.ShowOrigins ? "[" + llvm::to_string(Origin) + "]" : "") +
- RequiredQualifier + Name + Signature;
+ RequiredQualifier + Name;
+ LSP.labelDetails.emplace();
+ LSP.labelDetails->detail = Signature;
LSP.kind = Kind;
LSP.detail = BundleSize > 1
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index f613624cd25d8..269e77372ad3b 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -393,6 +393,8 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R,
if (auto *Item = Completion->getObject("completionItem")) {
if (auto SnippetSupport = Item->getBoolean("snippetSupport"))
R.CompletionSnippets = *SnippetSupport;
+ if (auto LabelDetailsSupport = Item->getBoolean("labelDetailsSupport"))
+ R.CompletionLabelDetail = *LabelDetailsSupport;
if (const auto *DocumentationFormat =
Item->getArray("documentationFormat")) {
for (const auto &Format : *DocumentationFormat) {
@@ -1069,6 +1071,25 @@ bool fromJSON(const llvm::json::Value &E, CompletionItemKindBitset &Out,
return false;
}
+llvm::json::Value toJSON(const CompletionItemLabelDetails &CD) {
+ llvm::json::Object Result;
+ if (!CD.detail.empty())
+ Result["detail"] = CD.detail;
+ if (!CD.description.empty())
+ Result["description"] = CD.description;
+ return Result;
+}
+
+void removeCompletionLabelDetails(CompletionItem &C) {
+ if (!C.labelDetails)
+ return;
+ if (!C.labelDetails->detail.empty())
+ C.label += C.labelDetails->detail;
+ if (!C.labelDetails->description.empty())
+ C.label = C.labelDetails->description + C.label;
+ C.labelDetails.reset();
+}
+
llvm::json::Value toJSON(const CompletionItem &CI) {
assert(!CI.label.empty() && "completion item label is required");
llvm::json::Object Result{{"label", CI.label}};
@@ -1076,6 +1097,8 @@ llvm::json::Value toJSON(const CompletionItem &CI) {
Result["kind"] = static_cast<int>(CI.kind);
if (!CI.detail.empty())
Result["detail"] = CI.detail;
+ if (CI.labelDetails)
+ Result["labelDetails"] = *CI.labelDetails;
if (CI.documentation)
Result["documentation"] = CI.documentation;
if (!CI.sortText.empty())
diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h
index 511eae1940c6e..cc2ad99451a2f 100644
--- a/clang-tools-extra/clangd/Protocol.h
+++ b/clang-tools-extra/clangd/Protocol.h
@@ -508,6 +508,10 @@ struct ClientCapabilities {
/// textDocument.completion.completionItem.documentationFormat
MarkupKind CompletionDocumentationFormat = MarkupKind::PlainText;
+ /// The client has support for completion item label details.
+ /// textDocument.completion.completionItem.labelDetailsSupport.
+ bool CompletionLabelDetail = false;
+
/// Client supports CodeAction return value for textDocument/codeAction.
/// textDocument.codeAction.codeActionLiteralSupport.
bool CodeActionStructure = false;
@@ -1277,11 +1281,28 @@ enum class InsertTextFormat {
Snippet = 2,
};
+/// Additional details for a completion item label.
+struct CompletionItemLabelDetails {
+ /// An optional string which is rendered less prominently directly after label
+ /// without any spacing. Should be used for function signatures or type
+ /// annotations.
+ std::string detail;
+
+ /// An optional string which is rendered less prominently after
+ /// CompletionItemLabelDetails.detail. Should be used for fully qualified
+ /// names or file path.
+ std::string description;
+};
+llvm::json::Value toJSON(const CompletionItemLabelDetails &);
+
struct CompletionItem {
/// The label of this completion item. By default also the text that is
/// inserted when selecting this completion.
std::string label;
+ /// Additional details for the label.
+ std::optional<CompletionItemLabelDetails> labelDetails;
+
/// The kind of this completion item. Based of the kind an icon is chosen by
/// the editor.
CompletionItemKind kind = CompletionItemKind::Missing;
@@ -1342,6 +1363,10 @@ struct CompletionItem {
llvm::json::Value toJSON(const CompletionItem &);
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const CompletionItem &);
+/// Remove the labelDetails field (for clients that don't support it).
+/// Places the information into other fields of the completion item.
+void removeCompletionLabelDetails(CompletionItem &);
+
bool operator<(const CompletionItem &, const CompletionItem &);
/// Represents a collection of completion items to be presented in the editor.
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 1975488fd035a..fc330a4b8fd3f 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -2093,7 +2093,8 @@ TEST(CompletionTest, Render) {
Opts.EnableSnippets = false;
auto R = C.render(Opts);
- EXPECT_EQ(R.label, "Foo::x(bool) const");
+ EXPECT_EQ(R.label, "Foo::x");
+ EXPECT_EQ(R.labelDetails->detail, "(bool) const");
EXPECT_EQ(R.insertText, "Foo::x");
EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);
EXPECT_EQ(R.filterText, "x");
@@ -2121,12 +2122,14 @@ TEST(CompletionTest, Render) {
Include.Insertion.emplace();
R = C.render(Opts);
- EXPECT_EQ(R.label, "^Foo::x(bool) const");
+ EXPECT_EQ(R.label, "^Foo::x");
+ EXPECT_EQ(R.labelDetails->detail, "(bool) const");
EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));
Opts.ShowOrigins = true;
R = C.render(Opts);
- EXPECT_EQ(R.label, "^[AS]Foo::x(bool) const");
+ EXPECT_EQ(R.label, "^[AS]Foo::x");
+ EXPECT_EQ(R.labelDetails->detail, "(bool) const");
C.BundleSize = 2;
R = C.render(Opts);
More information about the cfe-commits
mailing list