diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -506,6 +506,9 @@ } applyConfiguration(Params.initializationOptions.ConfigSettings); + ClangdServerOpts.AlwaysIncomplete = + Params.initializationOptions.AlwaysIncomplete; + CCOpts.EnableSnippets = Params.capabilities.CompletionSnippets; CCOpts.IncludeFixIts = Params.capabilities.CompletionFixes; if (!CCOpts.BundleOverloads.hasValue()) @@ -976,7 +979,11 @@ if (!List) return Reply(List.takeError()); CompletionList LSPList; - LSPList.isIncomplete = List->HasMore; + // Set isIncomplete to true regardless of the actual + // results if the corresponding flag was added to + // Clangd invocation. + LSPList.isIncomplete = + ClangdServerOpts.AlwaysIncomplete || List->HasMore; for (const auto &R : List->Completions) { CompletionItem C = R.render(CCOpts); C.kind = adjustKindToCapability( diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h --- a/clang-tools-extra/clangd/ClangdServer.h +++ b/clang-tools-extra/clangd/ClangdServer.h @@ -145,6 +145,9 @@ /// Enable cross-file rename feature. bool CrossFileRename = false; + /// Always set isIncomplete to true when returning CompletionList. + bool AlwaysIncomplete = false; + /// Returns true if the tweak should be enabled. std::function TweakFilter = [](const Tweak &T) { return !T.hidden(); // only enable non-hidden tweaks. @@ -295,7 +298,7 @@ /// Get all document links in a file. void documentLinks(PathRef File, Callback> CB); - + /// Returns estimated memory usage for each of the currently open files. /// The order of results is unspecified. /// Overall memory usage of clangd may be significantly more than reported diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -474,6 +474,10 @@ /// Clients supports show file status for textDocument/clangd.fileStatus. bool FileStatus = false; + + /// Always sets code completion list's isIncomplete to true. This helps to + /// utilize Clangd code completion ranking to a higher degree. + bool AlwaysIncomplete = false; }; bool fromJSON(const llvm::json::Value &, InitializationOptions &); diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -993,6 +993,7 @@ O.map("compilationDatabasePath", Opts.compilationDatabasePath); O.map("fallbackFlags", Opts.fallbackFlags); O.map("clangdFileStatus", Opts.FileStatus); + O.map("alwaysIncomplete", Opts.AlwaysIncomplete); return true; } diff --git a/clang-tools-extra/clangd/test/always-incomplete.test b/clang-tools-extra/clangd/test/always-incomplete.test new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clangd/test/always-incomplete.test @@ -0,0 +1,39 @@ +# RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"initializationOptions":{"alwaysIncomplete": true},"trace":"off"}} +--- +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct S { int a; };\nint main() {\nS().\n}"}}} +--- +{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":4}}} +# CHECK: "id": 1 +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "isIncomplete": true, +# CHECK-NEXT: "items": [ +# CHECK-NEXT: { +# CHECK-NEXT: "detail": "int", +# CHECK-NEXT: "filterText": "a", +# CHECK-NEXT: "insertText": "a", +# CHECK-NEXT: "insertTextFormat": 1, +# CHECK-NEXT: "kind": 5, +# CHECK-NEXT: "label": " a", +# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}}, +# CHECK-NEXT: "sortText": "{{.*}}a" +# CHECK-NEXT: "textEdit": { +# CHECK-NEXT: "newText": "a", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 4, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: } +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 4, +# CHECK-NEXT: "line": 2 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ] +--- +{"jsonrpc":"2.0","id":4,"method":"shutdown"} +--- +{"jsonrpc":"2.0","method":"exit"}