diff options
| author | Ilya Biryukov <ibiryukov@google.com> | 2018-02-15 14:32:57 +0000 |
|---|---|---|
| committer | Ilya Biryukov <ibiryukov@google.com> | 2018-02-15 14:32:57 +0000 |
| commit | 23bc73b6263c77894785948c13e7a91416ec5783 (patch) | |
| tree | 619cf7e7279c9e32d80d6c84e38de1d466250c39 | |
| parent | 6353ecb08a60e96bb42f7c63b31c3139e2fd95ec (diff) | |
| download | bcm5719-llvm-23bc73b6263c77894785948c13e7a91416ec5783.tar.gz bcm5719-llvm-23bc73b6263c77894785948c13e7a91416ec5783.zip | |
[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
| -rw-r--r-- | clang-tools-extra/clangd/ClangdLSPServer.cpp | 12 | ||||
| -rw-r--r-- | clang-tools-extra/clangd/Protocol.cpp | 36 | ||||
| -rw-r--r-- | clang-tools-extra/clangd/Protocol.h | 48 | ||||
| -rw-r--r-- | clang-tools-extra/clangd/tool/ClangdMain.cpp | 8 | ||||
| -rw-r--r-- | clang-tools-extra/test/clangd/completion-snippets.test | 43 |
5 files changed, 133 insertions, 14 deletions
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index 9038cf73c6e..3e5f79231f5 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -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) { diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index a55b50f0c54..0c10540ff3b 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -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; diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index b30e78cdd98..7e1595727b1 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -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; diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index 310ddbcd7f2..43dc11ee114 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -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. diff --git a/clang-tools-extra/test/clangd/completion-snippets.test b/clang-tools-extra/test/clangd/completion-snippets.test new file mode 100644 index 00000000000..48d212f087f --- /dev/null +++ b/clang-tools-extra/test/clangd/completion-snippets.test @@ -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"} |

