This revision was automatically updated to reflect the committed changes.
Closed by commit rL318287: [clangd] Support returning a limited number of 
completion results. (authored by sammccall).

Changed prior to commit:
  https://reviews.llvm.org/D39852?vs=122342&id=122987#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D39852

Files:
  clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
  clang-tools-extra/trunk/clangd/ClangdServer.cpp
  clang-tools-extra/trunk/clangd/ClangdServer.h
  clang-tools-extra/trunk/clangd/ClangdUnit.cpp
  clang-tools-extra/trunk/clangd/ClangdUnit.h
  clang-tools-extra/trunk/clangd/Protocol.cpp
  clang-tools-extra/trunk/clangd/Protocol.h
  clang-tools-extra/trunk/test/clangd/authority-less-uri.test
  clang-tools-extra/trunk/test/clangd/completion-items-kinds.test
  clang-tools-extra/trunk/test/clangd/completion-priorities.test
  clang-tools-extra/trunk/test/clangd/completion-qualifiers.test
  clang-tools-extra/trunk/test/clangd/completion-snippet.test
  clang-tools-extra/trunk/test/clangd/completion.test
  clang-tools-extra/trunk/test/clangd/protocol.test
  clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp

Index: clang-tools-extra/trunk/test/clangd/protocol.test
===================================================================
--- clang-tools-extra/trunk/test/clangd/protocol.test
+++ clang-tools-extra/trunk/test/clangd/protocol.test
@@ -31,14 +31,17 @@
 #
 #      CHECK:  "id": 1,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
-#      CHECK:      "filterText": "fake",
-# CHECK-NEXT:      "insertText": "fake",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 7,
-# CHECK-NEXT:      "label": "fake::",
-# CHECK-NEXT:      "sortText": "000075fake"
-#      CHECK:  ]
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+#      CHECK:        "filterText": "fake",
+# CHECK-NEXT:        "insertText": "fake",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 7,
+# CHECK-NEXT:        "label": "fake::",
+# CHECK-NEXT:        "sortText": "000075fake"
+#      CHECK:    ]
+# CHECK-NEXT:  }
 
 X-Test: Testing
 Content-Type: application/vscode-jsonrpc; charset-utf-8
@@ -57,14 +60,17 @@
 #
 #      CHECK:  "id": 3,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
-#      CHECK:      "filterText": "fake",
-# CHECK-NEXT:      "insertText": "fake",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 7,
-# CHECK-NEXT:      "label": "fake::",
-# CHECK-NEXT:      "sortText": "000075fake"
-#      CHECK:  ]
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+#      CHECK:        "filterText": "fake",
+# CHECK-NEXT:        "insertText": "fake",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 7,
+# CHECK-NEXT:        "label": "fake::",
+# CHECK-NEXT:        "sortText": "000075fake"
+#      CHECK:    ]
+# CHECK-NEXT:  }
 # STDERR: Warning: Duplicate Content-Length header received. The previous value for this message (10) was ignored.
 
 Content-Type: application/vscode-jsonrpc; charset-utf-8
@@ -83,14 +89,17 @@
 #
 #      CHECK:  "id": 5,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
-#      CHECK:      "filterText": "fake",
-# CHECK-NEXT:      "insertText": "fake",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 7,
-# CHECK-NEXT:      "label": "fake::",
-# CHECK-NEXT:      "sortText": "000075fake"
-#      CHECK:  ]
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+#      CHECK:        "filterText": "fake",
+# CHECK-NEXT:        "insertText": "fake",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 7,
+# CHECK-NEXT:        "label": "fake::",
+# CHECK-NEXT:        "sortText": "000075fake"
+#      CHECK:    ]
+# CHECK-NEXT:  }
 Content-Length: 1024
 
 {"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:/main.cpp"},"position":{"line":3,"character":5}}}
Index: clang-tools-extra/trunk/test/clangd/completion-priorities.test
===================================================================
--- clang-tools-extra/trunk/test/clangd/completion-priorities.test
+++ clang-tools-extra/trunk/test/clangd/completion-priorities.test
@@ -15,69 +15,74 @@
 {"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":12,"character":8}}}
 #      CHECK:  "id": 2,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "void",
-# CHECK-NEXT:      "filterText": "priv",
-# CHECK-NEXT:      "insertText": "priv",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "priv()",
-# CHECK-NEXT:      "sortText": "000034priv"
-# CHECK-NEXT:    },
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "void",
-# CHECK-NEXT:      "filterText": "prot",
-# CHECK-NEXT:      "insertText": "prot",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "prot()",
-# CHECK-NEXT:      "sortText": "000034prot"
-# CHECK-NEXT:    },
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "void",
-# CHECK-NEXT:      "filterText": "pub",
-# CHECK-NEXT:      "insertText": "pub",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "pub()",
-# CHECK-NEXT:      "sortText": "000034pub"
-# CHECK-NEXT:    },
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "void",
+# CHECK-NEXT:        "filterText": "priv",
+# CHECK-NEXT:        "insertText": "priv",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "priv()",
+# CHECK-NEXT:        "sortText": "000034priv"
+# CHECK-NEXT:      },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "void",
+# CHECK-NEXT:        "filterText": "prot",
+# CHECK-NEXT:        "insertText": "prot",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "prot()",
+# CHECK-NEXT:        "sortText": "000034prot"
+# CHECK-NEXT:      },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "void",
+# CHECK-NEXT:        "filterText": "pub",
+# CHECK-NEXT:        "insertText": "pub",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "pub()",
+# CHECK-NEXT:        "sortText": "000034pub"
+# CHECK-NEXT:      },
 Content-Length: 151
 
 {"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":17,"character":4}}}
 #      CHECK:  "id": 3,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "void",
-# CHECK-NEXT:      "filterText": "pub",
-# CHECK-NEXT:      "insertText": "pub",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "pub()",
-# CHECK-NEXT:      "sortText": "000034pub"
-# CHECK-NEXT:    },
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "void",
+# CHECK-NEXT:        "filterText": "pub",
+# CHECK-NEXT:        "insertText": "pub",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "pub()",
+# CHECK-NEXT:        "sortText": "000034pub"
+# CHECK-NEXT:      },
 # priv() and prot() are at the end of the list
-# CHECK-NEXT:    {
-#      CHECK:      "detail": "void",
-#      CHECK:      "filterText": "priv",
-# CHECK-NEXT:      "insertText": "priv",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "priv()",
-# CHECK-NEXT:      "sortText": "200034priv"
-# CHECK-NEXT:    },
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "void",
-# CHECK-NEXT:      "filterText": "prot",
-# CHECK-NEXT:      "insertText": "prot",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "prot()",
-# CHECK-NEXT:      "sortText": "200034prot"
-# CHECK-NEXT:    }
-# CHECK-NEXT:  ]
+# CHECK-NEXT:      {
+#      CHECK:        "detail": "void",
+#      CHECK:        "filterText": "priv",
+# CHECK-NEXT:        "insertText": "priv",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "priv()",
+# CHECK-NEXT:        "sortText": "200034priv"
+# CHECK-NEXT:      },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "void",
+# CHECK-NEXT:        "filterText": "prot",
+# CHECK-NEXT:        "insertText": "prot",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "prot()",
+# CHECK-NEXT:        "sortText": "200034prot"
+# CHECK-NEXT:      }
+# CHECK-NEXT:    ]
+# CHECK-NEXT:  }
 Content-Length: 58
 
 {"jsonrpc":"2.0","id":4,"method":"shutdown","params":null}
Index: clang-tools-extra/trunk/test/clangd/completion-items-kinds.test
===================================================================
--- clang-tools-extra/trunk/test/clangd/completion-items-kinds.test
+++ clang-tools-extra/trunk/test/clangd/completion-items-kinds.test
@@ -11,7 +11,7 @@
 
 {"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":7}}}
 Content-Length: 58
-# CHECK: {"id":1,"jsonrpc":"2.0","result":[
+# CHECK: {"id":1,"jsonrpc":"2.0","result":{"isIncomplete":false,"items":
 #
 # Keyword
 # CHECK-DAG: {"filterText":"int","insertText":"int","insertTextFormat":1,"kind":14,"label":"int","sortText":"000050int"}
@@ -31,6 +31,6 @@
 # Function
 # CHECK-DAG: {"detail":"int","filterText":"function","insertText":"function()","insertTextFormat":1,"kind":3,"label":"function()","sortText":"000012function"}
 #
-# CHECK-SAME: ]}
+# CHECK-SAME: ]}}
 
 {"jsonrpc":"2.0","id":3,"method":"shutdown","params":null}
Index: clang-tools-extra/trunk/test/clangd/completion-snippet.test
===================================================================
--- clang-tools-extra/trunk/test/clangd/completion-snippet.test
+++ clang-tools-extra/trunk/test/clangd/completion-snippet.test
@@ -14,71 +14,74 @@
 {"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}
 #      CHECK:  "id": 1,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
-# 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:      "sortText": "000035a"
-# CHECK-NEXT:    },
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "int",
-# CHECK-NEXT:      "filterText": "bb",
-# CHECK-NEXT:      "insertText": "bb",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 5,
-# CHECK-NEXT:      "label": "bb",
-# CHECK-NEXT:      "sortText": "000035bb"
-# CHECK-NEXT:    },
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "int",
-# CHECK-NEXT:      "filterText": "ccc",
-# CHECK-NEXT:      "insertText": "ccc",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 5,
-# CHECK-NEXT:      "label": "ccc",
-# CHECK-NEXT:      "sortText": "000035ccc"
-# CHECK-NEXT:    },
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "int",
-# CHECK-NEXT:      "filterText": "f",
-# CHECK-NEXT:      "insertText": "f(${1:int i}, ${2:const float f})",
-# CHECK-NEXT:      "insertTextFormat": 2,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "f(int i, const float f) const",
-# CHECK-NEXT:      "sortText": "000035f"
-# CHECK-NEXT:    },
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "filterText": "fake",
-# CHECK-NEXT:      "insertText": "fake::",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 7,
-# CHECK-NEXT:      "label": "fake::",
-# CHECK-NEXT:      "sortText": "000075fake"
-# CHECK-NEXT:    },
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "fake &",
-# CHECK-NEXT:      "filterText": "operator=",
-# CHECK-NEXT:      "insertText": "operator=(${1:const fake &})",
-# CHECK-NEXT:      "insertTextFormat": 2,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "operator=(const fake &)",
-# CHECK-NEXT:      "sortText": "000079operator="
-# CHECK-NEXT:    },
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# 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:        "sortText": "000035a"
+# CHECK-NEXT:      },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "int",
+# CHECK-NEXT:        "filterText": "bb",
+# CHECK-NEXT:        "insertText": "bb",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 5,
+# CHECK-NEXT:        "label": "bb",
+# CHECK-NEXT:        "sortText": "000035bb"
+# CHECK-NEXT:      },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "int",
+# CHECK-NEXT:        "filterText": "ccc",
+# CHECK-NEXT:        "insertText": "ccc",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 5,
+# CHECK-NEXT:        "label": "ccc",
+# CHECK-NEXT:        "sortText": "000035ccc"
+# CHECK-NEXT:      },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "int",
+# CHECK-NEXT:        "filterText": "f",
+# CHECK-NEXT:        "insertText": "f(${1:int i}, ${2:const float f})",
+# CHECK-NEXT:        "insertTextFormat": 2,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "f(int i, const float f) const",
+# CHECK-NEXT:        "sortText": "000035f"
+# CHECK-NEXT:      },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "filterText": "fake",
+# CHECK-NEXT:        "insertText": "fake::",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 7,
+# CHECK-NEXT:        "label": "fake::",
+# CHECK-NEXT:        "sortText": "000075fake"
+# CHECK-NEXT:      },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "fake &",
+# CHECK-NEXT:        "filterText": "operator=",
+# CHECK-NEXT:        "insertText": "operator=(${1:const fake &})",
+# CHECK-NEXT:        "insertTextFormat": 2,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "operator=(const fake &)",
+# CHECK-NEXT:        "sortText": "000079operator="
+# CHECK-NEXT:      },
 # FIXME: Why do some buildbots show an extra operator==(fake&&) here?
-#      CHECK:    {
-#      CHECK:      "detail": "void",
-# CHECK-NEXT:      "filterText": "~fake",
-# CHECK-NEXT:      "insertText": "~fake()",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 4,
-# CHECK-NEXT:      "label": "~fake()",
-# CHECK-NEXT:      "sortText": "000079~fake"
-# CHECK-NEXT:    }
-# CHECK-NEXT:  ]
+#      CHECK:      {
+#      CHECK:        "detail": "void",
+# CHECK-NEXT:        "filterText": "~fake",
+# CHECK-NEXT:        "insertText": "~fake()",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 4,
+# CHECK-NEXT:        "label": "~fake()",
+# CHECK-NEXT:        "sortText": "000079~fake"
+# CHECK-NEXT:      }
+# CHECK-NEXT:    ]
+# CHECK-NEXT:  }
 # Update the source file and check for completions again.
 Content-Length: 226
 
@@ -89,16 +92,18 @@
 {"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}
 #      CHECK:  "id": 3,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "int (*)(int, int)",
-# CHECK-NEXT:      "filterText": "func",
-# CHECK-NEXT:      "insertText": "func()",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "func()",
-# CHECK-NEXT:      "sortText": "000034func"
-# CHECK-NEXT:    },
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "int (*)(int, int)",
+# CHECK-NEXT:        "filterText": "func",
+# CHECK-NEXT:        "insertText": "func()",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "func()",
+# CHECK-NEXT:        "sortText": "000034func"
+# CHECK-NEXT:      },
 Content-Length: 44
 
 {"jsonrpc":"2.0","id":4,"method":"shutdown"}
Index: clang-tools-extra/trunk/test/clangd/authority-less-uri.test
===================================================================
--- clang-tools-extra/trunk/test/clangd/authority-less-uri.test
+++ clang-tools-extra/trunk/test/clangd/authority-less-uri.test
@@ -17,29 +17,35 @@
 #
 #      CHECK:  "id": 1,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
-#      CHECK:      "filterText": "fake",
-# CHECK-NEXT:      "insertText": "fake",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 7,
-# CHECK-NEXT:      "label": "fake::",
-# CHECK-NEXT:      "sortText": "000075fake"
-#      CHECK:  ]
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+#      CHECK:        "filterText": "fake",
+# CHECK-NEXT:        "insertText": "fake",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 7,
+# CHECK-NEXT:        "label": "fake::",
+# CHECK-NEXT:        "sortText": "000075fake"
+#      CHECK:    ]
+# CHECK-NEXT:  }
 Content-Length: 172
 
 {"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"uri":"file:///main.cpp","position":{"line":3,"character":5}}}
 # Test params parsing in the presence of a 1.x-compatible client (inlined "uri")
 #
 #      CHECK:  "id": 2,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
-#      CHECK:      "filterText": "fake",
-# CHECK-NEXT:      "insertText": "fake",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 7,
-# CHECK-NEXT:      "label": "fake::",
-# CHECK-NEXT:      "sortText": "000075fake"
-#      CHECK:  ]
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
+#      CHECK:        "filterText": "fake",
+# CHECK-NEXT:        "insertText": "fake",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 7,
+# CHECK-NEXT:        "label": "fake::",
+# CHECK-NEXT:        "sortText": "000075fake"
+#      CHECK:    ]
+# CHECK-NEXT:  }
 Content-Length: 44
 
 {"jsonrpc":"2.0","id":3,"method":"shutdown"}
Index: clang-tools-extra/trunk/test/clangd/completion-qualifiers.test
===================================================================
--- clang-tools-extra/trunk/test/clangd/completion-qualifiers.test
+++ clang-tools-extra/trunk/test/clangd/completion-qualifiers.test
@@ -10,37 +10,40 @@
 {"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":11,"character":8}}}
 #      CHECK:  "id": 2,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
 # Eligible const functions are at the top of the list.
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "int",
-# CHECK-NEXT:      "filterText": "bar",
-# CHECK-NEXT:      "insertText": "bar",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "bar() const",
-# CHECK-NEXT:      "sortText": "000037bar"
-# CHECK-NEXT:    },
-# CHECK-NEXT:    {
-# CHECK-NEXT:      "detail": "int",
-# CHECK-NEXT:      "filterText": "foo",
-# CHECK-NEXT:      "insertText": "foo",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "Foo::foo() const",
-# CHECK-NEXT:      "sortText": "000037foo"
-# CHECK-NEXT:    },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "int",
+# CHECK-NEXT:        "filterText": "bar",
+# CHECK-NEXT:        "insertText": "bar",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "bar() const",
+# CHECK-NEXT:        "sortText": "000037bar"
+# CHECK-NEXT:      },
+# CHECK-NEXT:      {
+# CHECK-NEXT:        "detail": "int",
+# CHECK-NEXT:        "filterText": "foo",
+# CHECK-NEXT:        "insertText": "foo",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "Foo::foo() const",
+# CHECK-NEXT:        "sortText": "000037foo"
+# CHECK-NEXT:      },
 # Ineligible non-const function is at the bottom of the list.
-# CHECK-NEXT:    {
-#      CHECK:      "detail": "int",
-#      CHECK:      "filterText": "foo",
-# CHECK-NEXT:      "insertText": "foo",
-# CHECK-NEXT:      "insertTextFormat": 1,
-# CHECK-NEXT:      "kind": 2,
-# CHECK-NEXT:      "label": "foo() const",
-# CHECK-NEXT:      "sortText": "200035foo"
-# CHECK-NEXT:    }
-# CHECK-NEXT:  ]
+# CHECK-NEXT:      {
+#      CHECK:        "detail": "int",
+#      CHECK:        "filterText": "foo",
+# CHECK-NEXT:        "insertText": "foo",
+# CHECK-NEXT:        "insertTextFormat": 1,
+# CHECK-NEXT:        "kind": 2,
+# CHECK-NEXT:        "label": "foo() const",
+# CHECK-NEXT:        "sortText": "200035foo"
+# CHECK-NEXT:      }
+# CHECK-NEXT:    ]
+# CHECK-NEXT:  }
 Content-Length: 44
 
 {"jsonrpc":"2.0","id":4,"method":"shutdown"}
Index: clang-tools-extra/trunk/test/clangd/completion.test
===================================================================
--- clang-tools-extra/trunk/test/clangd/completion.test
+++ clang-tools-extra/trunk/test/clangd/completion.test
@@ -14,7 +14,9 @@
 {"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}
 #      CHECK:  "id": 1
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "int",
 # CHECK-NEXT:      "filterText": "a",
@@ -84,7 +86,9 @@
 {"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}
 #      CHECK:  "id": 2
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "int",
 # CHECK-NEXT:      "filterText": "a",
@@ -158,7 +162,9 @@
 {"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":5}}}
 #      CHECK:    "id": 3,
 # CHECK-NEXT:  "jsonrpc": "2.0",
-# CHECK-NEXT:  "result": [
+# CHECK-NEXT:  "result": {
+# CHECK-NEXT:    "isIncomplete": false,
+# CHECK-NEXT:    "items": [
 # CHECK-NEXT:    {
 # CHECK-NEXT:      "detail": "int (*)(int, int)",
 # CHECK-NEXT:      "filterText": "func",
Index: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
===================================================================
--- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
+++ clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
@@ -619,16 +619,15 @@
 class ClangdCompletionTest : public ClangdVFSTest {
 protected:
   template <class Predicate>
-  bool ContainsItemPred(std::vector<CompletionItem> const &Items,
-                        Predicate Pred) {
-    for (const auto &Item : Items) {
+  bool ContainsItemPred(CompletionList const &Items, Predicate Pred) {
+    for (const auto &Item : Items.items) {
       if (Pred(Item))
         return true;
     }
     return false;
   }
 
-  bool ContainsItem(std::vector<CompletionItem> const &Items, StringRef Name) {
+  bool ContainsItem(CompletionList const &Items, StringRef Name) {
     return ContainsItemPred(Items, [Name](clangd::CompletionItem Item) {
       return Item.insertText == Name;
     });
@@ -694,6 +693,44 @@
   }
 }
 
+TEST_F(ClangdCompletionTest, Limit) {
+  MockFSProvider FS;
+  MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
+  CDB.ExtraClangFlags.push_back("-xc++");
+  ErrorCheckingDiagConsumer DiagConsumer;
+  clangd::CodeCompleteOptions Opts;
+  Opts.Limit = 2;
+  ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+                      Opts, EmptyLogger::getInstance());
+
+  auto FooCpp = getVirtualTestFilePath("foo.cpp");
+  FS.Files[FooCpp] = "";
+  FS.ExpectedFile = FooCpp;
+  StringWithPos Completion = parseTextMarker(R"cpp(
+struct ClassWithMembers {
+  int AAA();
+  int BBB();
+  int CCC();
+}
+int main() { ClassWithMembers().{complete} }
+      )cpp",
+                                             "complete");
+  Server.addDocument(FooCpp, Completion.Text);
+
+  /// For after-dot completion we must always get consistent results.
+  auto Results = Server
+                     .codeComplete(FooCpp, Completion.MarkerPos,
+                                   StringRef(Completion.Text))
+                     .get()
+                     .Value;
+
+  EXPECT_TRUE(Results.isIncomplete);
+  EXPECT_EQ(Opts.Limit, Results.items.size());
+  EXPECT_TRUE(ContainsItem(Results, "AAA"));
+  EXPECT_TRUE(ContainsItem(Results, "BBB"));
+  EXPECT_FALSE(ContainsItem(Results, "CCC"));
+}
+
 TEST_F(ClangdCompletionTest, CompletionOptions) {
   MockFSProvider FS;
   ErrorCheckingDiagConsumer DiagConsumer;
Index: clang-tools-extra/trunk/clangd/Protocol.h
===================================================================
--- clang-tools-extra/trunk/clangd/Protocol.h
+++ clang-tools-extra/trunk/clangd/Protocol.h
@@ -547,6 +547,18 @@
 
 bool operator<(const CompletionItem &, const CompletionItem &);
 
+/// Represents a collection of completion items to be presented in the editor.
+struct CompletionList {
+  /// The list is not complete. Further typing should result in recomputing the
+  /// list.
+  bool isIncomplete = false;
+
+  /// The completion items.
+  std::vector<CompletionItem> items;
+
+  static json::Expr unparse(const CompletionList &);
+};
+
 /// A single parameter of a particular signature.
 struct ParameterInformation {
 
Index: clang-tools-extra/trunk/clangd/Protocol.cpp
===================================================================
--- clang-tools-extra/trunk/clangd/Protocol.cpp
+++ clang-tools-extra/trunk/clangd/Protocol.cpp
@@ -1043,6 +1043,13 @@
          (R.sortText.empty() ? R.label : R.sortText);
 }
 
+json::Expr CompletionList::unparse(const CompletionList &L) {
+  return json::obj{
+      {"isIncomplete", L.isIncomplete},
+      {"items", json::ary(L.items)},
+  };
+}
+
 json::Expr ParameterInformation::unparse(const ParameterInformation &PI) {
   assert(!PI.label.empty() && "parameter information label is required");
   json::obj Result{{"label", PI.label}};
Index: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
===================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
@@ -195,15 +195,15 @@
 }
 
 void ClangdLSPServer::onCompletion(Ctx C, TextDocumentPositionParams &Params) {
-  auto Items = Server
-                   .codeComplete(Params.textDocument.uri.file,
-                                 Position{Params.position.line,
-                                          Params.position.character})
-                   .get() // FIXME(ibiryukov): This could be made async if we
-                          // had an API that would allow to attach callbacks to
-                          // futures returned by ClangdServer.
-                   .Value;
-  C.reply(json::ary(Items));
+  auto List = Server
+                  .codeComplete(
+                      Params.textDocument.uri.file,
+                      Position{Params.position.line, Params.position.character})
+                  .get() // FIXME(ibiryukov): This could be made async if we
+                         // had an API that would allow to attach callbacks to
+                         // futures returned by ClangdServer.
+                  .Value;
+  C.reply(List);
 }
 
 void ClangdLSPServer::onSignatureHelp(Ctx C,
Index: clang-tools-extra/trunk/clangd/ClangdUnit.h
===================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.h
+++ clang-tools-extra/trunk/clangd/ClangdUnit.h
@@ -263,7 +263,7 @@
                       bool IncludeBriefComments);
 
   /// Returns options that can be passed to clang's completion engine.
-  clang::CodeCompleteOptions getClangCompleteOpts();
+  clang::CodeCompleteOptions getClangCompleteOpts() const;
 
   /// When true, completion items will contain expandable code snippets in
   /// completion (e.g.  `return ${1:expression}` or `foo(${1:int a}, ${2:int
@@ -285,10 +285,14 @@
   /// FIXME(ibiryukov): it looks like turning this option on significantly slows
   /// down completion, investigate if it can be made faster.
   bool IncludeBriefComments = true;
+
+  /// Limit the number of results returned (0 means no limit).
+  /// If more results are available, we set CompletionList.isIncomplete.
+  size_t Limit = 0;
 };
 
 /// Get code completions at a specified \p Pos in \p FileName.
-std::vector<CompletionItem>
+CompletionList
 codeComplete(PathRef FileName, const tooling::CompileCommand &Command,
              PrecompiledPreamble const *Preamble, StringRef Contents,
              Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
Index: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
===================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp
+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp
@@ -368,97 +368,124 @@
   return Result;
 }
 
+/// A scored code completion result.
+/// It may be promoted to a CompletionItem if it's among the top-ranked results.
+struct CompletionCandidate {
+  CompletionCandidate(CodeCompletionResult &Result)
+      : Result(&Result), Score(score(Result)) {}
+
+  CodeCompletionResult *Result;
+  // Higher score is worse. FIXME: use a more natural scale!
+  int Score;
+
+  // Comparison reflects rank: better candidates are smaller.
+  bool operator<(const CompletionCandidate &C) const {
+    if (Score != C.Score)
+      return Score < C.Score;
+    return *Result < *C.Result;
+  }
+
+  std::string sortText() const {
+    // Fill in the sortText of the CompletionItem.
+    assert(Score <= 999999 && "Expecting score to have at most 6-digits");
+    std::string S, NameStorage;
+    StringRef Name = Result->getOrderedName(NameStorage);
+    llvm::raw_string_ostream(S)
+        << llvm::format("%06d%.*s", Score, Name.size(), Name.data());
+    return S;
+  }
+
+private:
+  static int score(const CodeCompletionResult &Result) {
+    int Score = Result.Priority;
+    // Fill in the sortText of the CompletionItem.
+    assert(Score <= 99999 && "Expecting code completion result "
+                             "priority to have at most 5-digits");
+
+    const int Penalty = 100000;
+    switch (static_cast<CXAvailabilityKind>(Result.Availability)) {
+    case CXAvailability_Available:
+      // No penalty.
+      break;
+    case CXAvailability_Deprecated:
+      Score += Penalty;
+      break;
+    case CXAvailability_NotAccessible:
+      Score += 2 * Penalty;
+      break;
+    case CXAvailability_NotAvailable:
+      Score += 3 * Penalty;
+      break;
+    }
+    return Score;
+  }
+};
+
 class CompletionItemsCollector : public CodeCompleteConsumer {
 public:
-  CompletionItemsCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
-                           std::vector<CompletionItem> &Items)
-      : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
-        Items(Items),
+  CompletionItemsCollector(const clangd::CodeCompleteOptions &CodeCompleteOpts,
+                           CompletionList &Items)
+      : CodeCompleteConsumer(CodeCompleteOpts.getClangCompleteOpts(),
+                             /*OutputIsBinary=*/false),
+        ClangdOpts(CodeCompleteOpts), Items(Items),
         Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
         CCTUInfo(Allocator) {}
 
   void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
                                   CodeCompletionResult *Results,
                                   unsigned NumResults) override final {
-    Items.reserve(NumResults);
+    std::priority_queue<CompletionCandidate> Candidates;
     for (unsigned I = 0; I < NumResults; ++I) {
-      auto &Result = Results[I];
-      const auto *CCS = Result.CreateCodeCompletionString(
+      Candidates.emplace(Results[I]);
+      if (ClangdOpts.Limit && Candidates.size() > ClangdOpts.Limit) {
+        Candidates.pop();
+        Items.isIncomplete = true;
+      }
+    }
+    while (!Candidates.empty()) {
+      auto &Candidate = Candidates.top();
+      const auto *CCS = Candidate.Result->CreateCodeCompletionString(
           S, Context, *Allocator, CCTUInfo,
           CodeCompleteOpts.IncludeBriefComments);
       assert(CCS && "Expected the CodeCompletionString to be non-null");
-      Items.push_back(ProcessCodeCompleteResult(Result, *CCS));
+      Items.items.push_back(ProcessCodeCompleteResult(Candidate, *CCS));
+      Candidates.pop();
     }
-    std::sort(Items.begin(), Items.end());
+    std::reverse(Items.items.begin(), Items.items.end());
   }
 
   GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
 
   CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
 
 private:
   CompletionItem
-  ProcessCodeCompleteResult(const CodeCompletionResult &Result,
+  ProcessCodeCompleteResult(const CompletionCandidate &Candidate,
                             const CodeCompletionString &CCS) const {
 
     // Adjust this to InsertTextFormat::Snippet iff we encounter a
     // CK_Placeholder chunk in SnippetCompletionItemsCollector.
     CompletionItem Item;
     Item.insertTextFormat = InsertTextFormat::PlainText;
 
     Item.documentation = getDocumentation(CCS);
+    Item.sortText = Candidate.sortText();
 
     // Fill in the label, detail, insertText and filterText fields of the
     // CompletionItem.
     ProcessChunks(CCS, Item);
 
     // Fill in the kind field of the CompletionItem.
-    Item.kind = getKind(Result.Kind, Result.CursorKind);
-
-    FillSortText(CCS, Item);
+    Item.kind = getKind(Candidate.Result->Kind, Candidate.Result->CursorKind);
 
     return Item;
   }
 
   virtual void ProcessChunks(const CodeCompletionString &CCS,
                              CompletionItem &Item) const = 0;
 
-  static int GetSortPriority(const CodeCompletionString &CCS) {
-    int Score = CCS.getPriority();
-    // Fill in the sortText of the CompletionItem.
-    assert(Score <= 99999 && "Expecting code completion result "
-                             "priority to have at most 5-digits");
-
-    const int Penalty = 100000;
-    switch (static_cast<CXAvailabilityKind>(CCS.getAvailability())) {
-    case CXAvailability_Available:
-      // No penalty.
-      break;
-    case CXAvailability_Deprecated:
-      Score += Penalty;
-      break;
-    case CXAvailability_NotAccessible:
-      Score += 2 * Penalty;
-      break;
-    case CXAvailability_NotAvailable:
-      Score += 3 * Penalty;
-      break;
-    }
-
-    return Score;
-  }
-
-  static void FillSortText(const CodeCompletionString &CCS,
-                           CompletionItem &Item) {
-    int Priority = GetSortPriority(CCS);
-    // Fill in the sortText of the CompletionItem.
-    assert(Priority <= 999999 &&
-           "Expecting sort priority to have at most 6-digits");
-    llvm::raw_string_ostream(Item.sortText)
-        << llvm::format("%06d%s", Priority, Item.filterText.c_str());
-  }
-
-  std::vector<CompletionItem> &Items;
+  clangd::CodeCompleteOptions ClangdOpts;
+  CompletionList &Items;
   std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
   CodeCompletionTUInfo CCTUInfo;
 
@@ -474,8 +501,8 @@
 
 public:
   PlainTextCompletionItemsCollector(
-      const clang::CodeCompleteOptions &CodeCompleteOpts,
-      std::vector<CompletionItem> &Items)
+      const clangd::CodeCompleteOptions &CodeCompleteOpts,
+      CompletionList &Items)
       : CompletionItemsCollector(CodeCompleteOpts, Items) {}
 
 private:
@@ -511,8 +538,8 @@
 
 public:
   SnippetCompletionItemsCollector(
-      const clang::CodeCompleteOptions &CodeCompleteOpts,
-      std::vector<CompletionItem> &Items)
+      const clangd::CodeCompleteOptions &CodeCompleteOpts,
+      CompletionList &Items)
       : CompletionItemsCollector(CodeCompleteOpts, Items) {}
 
 private:
@@ -795,7 +822,8 @@
       IncludeMacros(IncludeMacros), IncludeGlobals(IncludeGlobals),
       IncludeBriefComments(IncludeBriefComments) {}
 
-clang::CodeCompleteOptions clangd::CodeCompleteOptions::getClangCompleteOpts() {
+clang::CodeCompleteOptions
+clangd::CodeCompleteOptions::getClangCompleteOpts() const {
   clang::CodeCompleteOptions Result;
   Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;
   Result.IncludeMacros = IncludeMacros;
@@ -805,25 +833,24 @@
   return Result;
 }
 
-std::vector<CompletionItem>
+CompletionList
 clangd::codeComplete(PathRef FileName, const tooling::CompileCommand &Command,
                      PrecompiledPreamble const *Preamble, StringRef Contents,
                      Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
                      std::shared_ptr<PCHContainerOperations> PCHs,
                      clangd::CodeCompleteOptions Opts, clangd::Logger &Logger) {
-  std::vector<CompletionItem> Results;
+  CompletionList Results;
   std::unique_ptr<CodeCompleteConsumer> Consumer;
-  clang::CodeCompleteOptions ClangCompleteOpts = Opts.getClangCompleteOpts();
   if (Opts.EnableSnippets) {
-    Consumer = llvm::make_unique<SnippetCompletionItemsCollector>(
-        ClangCompleteOpts, Results);
+    Consumer =
+        llvm::make_unique<SnippetCompletionItemsCollector>(Opts, Results);
   } else {
-    Consumer = llvm::make_unique<PlainTextCompletionItemsCollector>(
-        ClangCompleteOpts, Results);
+    Consumer =
+        llvm::make_unique<PlainTextCompletionItemsCollector>(Opts, Results);
   }
-  invokeCodeComplete(std::move(Consumer), ClangCompleteOpts, FileName, Command,
-                     Preamble, Contents, Pos, std::move(VFS), std::move(PCHs),
-                     Logger);
+  invokeCodeComplete(std::move(Consumer), Opts.getClangCompleteOpts(), FileName,
+                     Command, Preamble, Contents, Pos, std::move(VFS),
+                     std::move(PCHs), Logger);
   return Results;
 }
 
Index: clang-tools-extra/trunk/clangd/ClangdServer.h
===================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.h
+++ clang-tools-extra/trunk/clangd/ClangdServer.h
@@ -251,18 +251,17 @@
   /// This method should only be called for currently tracked files. However, it
   /// is safe to call removeDocument for \p File after this method returns, even
   /// while returned future is not yet ready.
-  std::future<Tagged<std::vector<CompletionItem>>>
+  std::future<Tagged<CompletionList>>
   codeComplete(PathRef File, Position Pos,
                llvm::Optional<StringRef> OverridenContents = llvm::None,
                IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
 
   /// A version of `codeComplete` that runs \p Callback on the processing thread
   /// when codeComplete results become available.
-  void codeComplete(
-      UniqueFunction<void(Tagged<std::vector<CompletionItem>>)> Callback,
-      PathRef File, Position Pos,
-      llvm::Optional<StringRef> OverridenContents = llvm::None,
-      IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
+  void codeComplete(UniqueFunction<void(Tagged<CompletionList>)> Callback,
+                    PathRef File, Position Pos,
+                    llvm::Optional<StringRef> OverridenContents = llvm::None,
+                    IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS = nullptr);
 
   /// Provide signature help for \p File at \p Pos. If \p OverridenContents is
   /// not None, they will used only for signature help, i.e. no diagnostics
Index: clang-tools-extra/trunk/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp
@@ -222,11 +222,11 @@
                                  std::move(TaggedFS));
 }
 
-std::future<Tagged<std::vector<CompletionItem>>>
+std::future<Tagged<CompletionList>>
 ClangdServer::codeComplete(PathRef File, Position Pos,
                            llvm::Optional<StringRef> OverridenContents,
                            IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
-  using ResultType = Tagged<std::vector<CompletionItem>>;
+  using ResultType = Tagged<CompletionList>;
 
   std::promise<ResultType> ResultPromise;
 
@@ -242,11 +242,10 @@
 }
 
 void ClangdServer::codeComplete(
-    UniqueFunction<void(Tagged<std::vector<CompletionItem>>)> Callback,
-    PathRef File, Position Pos, llvm::Optional<StringRef> OverridenContents,
+    UniqueFunction<void(Tagged<CompletionList>)> Callback, PathRef File,
+    Position Pos, llvm::Optional<StringRef> OverridenContents,
     IntrusiveRefCntPtr<vfs::FileSystem> *UsedFS) {
-  using CallbackType =
-      UniqueFunction<void(Tagged<std::vector<CompletionItem>>)>;
+  using CallbackType = UniqueFunction<void(Tagged<CompletionList>)>;
 
   std::string Contents;
   if (OverridenContents) {
@@ -283,7 +282,7 @@
         // FIXME(ibiryukov): even if Preamble is non-null, we may want to check
         // both the old and the new version in case only one of them matches.
 
-        std::vector<CompletionItem> Result = clangd::codeComplete(
+        CompletionList Result = clangd::codeComplete(
             File, Resources->getCompileCommand(),
             Preamble ? &Preamble->Preamble : nullptr, Contents, Pos,
             TaggedFS.Value, PCHs, CodeCompleteOpts, Logger);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to