[clangd] Enable snippet completion based on client capabilities.
Summary: And remove -enable-snippets flag. Reviewers: hokein, ioeric, sammccall Reviewed By: ioeric Subscribers: klimek, jkorous-apple, cfe-commits Differential Revision: https://reviews.llvm.org/D43229 llvm-svn: 325242
This commit is contained in:
parent
6353ecb08a
commit
23bc73b626
|
@ -87,6 +87,14 @@ std::vector<TextEdit> replacementsToEdits(StringRef Code,
|
|||
} // namespace
|
||||
|
||||
void ClangdLSPServer::onInitialize(InitializeParams &Params) {
|
||||
if (Params.rootUri && !Params.rootUri->file.empty())
|
||||
Server.setRootPath(Params.rootUri->file);
|
||||
else if (Params.rootPath && !Params.rootPath->empty())
|
||||
Server.setRootPath(*Params.rootPath);
|
||||
|
||||
CCOpts.EnableSnippets =
|
||||
Params.capabilities.textDocument.completion.completionItem.snippetSupport;
|
||||
|
||||
reply(json::obj{
|
||||
{{"capabilities",
|
||||
json::obj{
|
||||
|
@ -116,10 +124,6 @@ void ClangdLSPServer::onInitialize(InitializeParams &Params) {
|
|||
{"commands", {ExecuteCommandParams::CLANGD_APPLY_FIX_COMMAND}},
|
||||
}},
|
||||
}}}});
|
||||
if (Params.rootUri && !Params.rootUri->file.empty())
|
||||
Server.setRootPath(Params.rootUri->file);
|
||||
else if (Params.rootPath && !Params.rootPath->empty())
|
||||
Server.setRootPath(*Params.rootPath);
|
||||
}
|
||||
|
||||
void ClangdLSPServer::onShutdown(ShutdownParams &Params) {
|
||||
|
|
|
@ -150,6 +150,41 @@ bool fromJSON(const json::Expr &E, TraceLevel &Out) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool fromJSON(const json::Expr &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::Expr &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 json::Expr &Params, TextDocumentClientCapabilities &R) {
|
||||
json::ObjectMapper O(Params);
|
||||
if (!O)
|
||||
return false;
|
||||
O.map("completion", R.completion);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fromJSON(const json::Expr &Params, ClientCapabilities &R) {
|
||||
json::ObjectMapper O(Params);
|
||||
if (!O)
|
||||
return false;
|
||||
O.map("textDocument", R.textDocument);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fromJSON(const json::Expr &Params, InitializeParams &R) {
|
||||
json::ObjectMapper O(Params);
|
||||
if (!O)
|
||||
|
@ -159,6 +194,7 @@ bool fromJSON(const json::Expr &Params, InitializeParams &R) {
|
|||
O.map("processId", R.processId);
|
||||
O.map("rootUri", R.rootUri);
|
||||
O.map("rootPath", R.rootPath);
|
||||
O.map("capabilities", R.capabilities);
|
||||
O.map("trace", R.trace);
|
||||
// initializationOptions, capabilities unused
|
||||
return true;
|
||||
|
|
|
@ -179,6 +179,51 @@ inline bool fromJSON(const json::Expr &, NoParams &) { return true; }
|
|||
using ShutdownParams = NoParams;
|
||||
using ExitParams = NoParams;
|
||||
|
||||
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 json::Expr &, CompletionItemClientCapabilities &);
|
||||
|
||||
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 client supports to send additional context information for a
|
||||
/// `textDocument/completion` request.
|
||||
bool contextSupport = false;
|
||||
};
|
||||
bool fromJSON(const json::Expr &, CompletionClientCapabilities &);
|
||||
|
||||
// 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;
|
||||
};
|
||||
bool fromJSON(const json::Expr &, TextDocumentClientCapabilities &);
|
||||
|
||||
struct ClientCapabilities {
|
||||
// Workspace specific client capabilities.
|
||||
// NOTE: not used by clangd at the moment.
|
||||
// WorkspaceClientCapabilities workspace;
|
||||
|
||||
// Text document specific client capabilities.
|
||||
TextDocumentClientCapabilities textDocument;
|
||||
};
|
||||
|
||||
bool fromJSON(const json::Expr &, ClientCapabilities &);
|
||||
|
||||
struct InitializeParams {
|
||||
/// The process Id of the parent process that started
|
||||
/// the server. Is null if the process has not been started by another
|
||||
|
@ -201,8 +246,7 @@ struct InitializeParams {
|
|||
// initializationOptions?: any;
|
||||
|
||||
/// The capabilities provided by the client (editor or tool)
|
||||
/// Note: Not currently used by clangd
|
||||
// ClientCapabilities capabilities;
|
||||
ClientCapabilities capabilities;
|
||||
|
||||
/// The initial trace setting. If omitted trace is disabled ('off').
|
||||
llvm::Optional<TraceLevel> trace;
|
||||
|
|
|
@ -58,13 +58,6 @@ static llvm::cl::opt<unsigned>
|
|||
llvm::cl::desc("Number of async workers used by clangd"),
|
||||
llvm::cl::init(getDefaultAsyncThreadsCount()));
|
||||
|
||||
static llvm::cl::opt<bool> EnableSnippets(
|
||||
"enable-snippets",
|
||||
llvm::cl::desc(
|
||||
"Present snippet completions instead of plaintext completions. "
|
||||
"This also enables code pattern results." /* FIXME: should it? */),
|
||||
llvm::cl::init(clangd::CodeCompleteOptions().EnableSnippets));
|
||||
|
||||
// FIXME: Flags are the wrong mechanism for user preferences.
|
||||
// We should probably read a dotfile or similar.
|
||||
static llvm::cl::opt<bool> IncludeIneligibleResults(
|
||||
|
@ -237,7 +230,6 @@ int main(int argc, char *argv[]) {
|
|||
if (EnableIndexBasedCompletion && !YamlSymbolFile.empty())
|
||||
StaticIdx = BuildStaticIndex(YamlSymbolFile);
|
||||
clangd::CodeCompleteOptions CCOpts;
|
||||
CCOpts.EnableSnippets = EnableSnippets;
|
||||
CCOpts.IncludeIneligibleResults = IncludeIneligibleResults;
|
||||
CCOpts.Limit = LimitCompletionResult;
|
||||
// Initialize and run ClangdLSPServer.
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s
|
||||
# RUN: clangd -lit-test -pch-storage=memory < %s | FileCheck -strict-whitespace %s
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 0,
|
||||
"method": "initialize",
|
||||
"params": {
|
||||
"processId": 123,
|
||||
"rootPath": "clangd",
|
||||
"capabilities": {
|
||||
"textDocument": {
|
||||
"completion": {
|
||||
"completionItem": {
|
||||
"snippetSupport": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"trace": "off"
|
||||
}
|
||||
}
|
||||
---
|
||||
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int func_with_args(int a, int b);\nint main() {\nfunc_with\n}"}}}
|
||||
---
|
||||
{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":7}}}
|
||||
# CHECK: "id": 1
|
||||
# CHECK-NEXT: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK-NEXT: "isIncomplete": {{.*}}
|
||||
# CHECK-NEXT: "items": [
|
||||
# CHECK-NEXT: {
|
||||
# CHECK-NEXT: "detail": "int",
|
||||
# CHECK-NEXT: "filterText": "func_with_args",
|
||||
# CHECK-NEXT: "insertText": "func_with_args(${1:int a}, ${2:int b})",
|
||||
# CHECK-NEXT: "insertTextFormat": 2,
|
||||
# CHECK-NEXT: "kind": 3,
|
||||
# CHECK-NEXT: "label": "func_with_args(int a, int b)",
|
||||
# CHECK-NEXT: "sortText": "{{.*}}func_with_args"
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
# CHECK-NEXT: }
|
||||
---
|
||||
{"jsonrpc":"2.0","id":4,"method":"shutdown"}
|
Loading…
Reference in New Issue