Skip to content

Commit d61bf57

Browse files
committed
Add initialization option completion.placeholder; change client.snippetSupport: false to drop ( and <
* client.snippetSupport: false => `foo` * client.snippetSupport: true + completion.placeholder: false => `foo($1)$0` `bar<$1>()$0` + completion.placeholder: true => `foo(${1:int a}, ${2:int b})$0` `bar<${1:typename T}>()$0` Note, client.snippetSupport is always false if the client does not support snippets. Close #412
1 parent 4711fd3 commit d61bf57

File tree

3 files changed

+34
-8
lines changed

3 files changed

+34
-8
lines changed

src/config.hh

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ struct Config {
129129
bool hierarchicalDocumentSymbolSupport = true;
130130
// TextDocumentClientCapabilities.definition.linkSupport
131131
bool linkSupport = true;
132+
133+
// If false, disable snippets and complete just the identifier part.
132134
// TextDocumentClientCapabilities.completion.completionItem.snippetSupport
133135
bool snippetSupport = true;
134136
} client;
@@ -176,9 +178,6 @@ struct Config {
176178
// that implement their own filtering and sorting logic.
177179
bool filterAndSort = true;
178180

179-
// Maxmum number of results.
180-
int maxNum = 100;
181-
182181
struct Include {
183182
// Regex patterns to match include completion candidates against. They
184183
// receive the absolute file path.
@@ -200,6 +199,15 @@ struct Config {
200199

201200
std::vector<std::string> whitelist;
202201
} include;
202+
203+
// Maxmum number of results.
204+
int maxNum = 100;
205+
206+
// Add placeholder text. Effective only if client.snippetSupport is true.
207+
//
208+
// false: foo($1)$0
209+
// true: foo(${1:int a}, ${2:int b})$0
210+
bool placeholder = true;
203211
} completion;
204212

205213
struct Diagnostics {
@@ -343,7 +351,7 @@ REFLECT_STRUCT(Config::Completion::Include, blacklist, maxPathSize,
343351
suffixWhitelist, whitelist);
344352
REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel,
345353
dropOldRequests, duplicateOptional, filterAndSort, include,
346-
maxNum);
354+
maxNum, placeholder);
347355
REFLECT_STRUCT(Config::Diagnostics, blacklist, onChange, onOpen, onSave,
348356
spellChecking, whitelist)
349357
REFLECT_STRUCT(Config::Highlight, largeFileSize, lsRanges, blacklist, whitelist)

src/messages/initialize.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,9 @@ void do_initialize(MessageHandler *m, InitializeParam &param,
319319
didChangeWatchedFiles =
320320
capabilities.workspace.didChangeWatchedFiles.dynamicRegistration;
321321

322+
if (!g_config->client.snippetSupport)
323+
g_config->completion.duplicateOptional = false;
324+
322325
// Ensure there is a resource directory.
323326
if (g_config->clang.resourceDir.empty())
324327
g_config->clang.resourceDir = getDefaultResourceDirectory();

src/messages/textDocument_completion.cc

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ limitations under the License.
2323

2424
#include <clang/Sema/CodeCompleteConsumer.h>
2525
#include <clang/Sema/Sema.h>
26+
#include <llvm/ADT/Twine.h>
2627

2728
#if LLVM_VERSION_MAJOR < 8
2829
#include <regex>
@@ -382,7 +383,7 @@ void buildItem(const CodeCompletionResult &r, const CodeCompletionString &ccs,
382383
continue;
383384
}
384385
out[i].textEdit.newText +=
385-
"${" + std::to_string(out[i].parameters_.size()) + ":" + text + "}";
386+
("${" + Twine(out[i].parameters_.size()) + ":" + text + "}").str();
386387
out[i].insertTextFormat = InsertTextFormat::Snippet;
387388
} else if (kind != CodeCompletionString::CK_Informative) {
388389
out[i].textEdit.newText += text;
@@ -462,9 +463,23 @@ class CompletionConsumer : public CodeCompleteConsumer {
462463
buildItem(r, *ccs, ls_items);
463464

464465
for (size_t j = first_idx; j < ls_items.size(); j++) {
465-
if (g_config->client.snippetSupport &&
466-
ls_items[j].insertTextFormat == InsertTextFormat::Snippet)
467-
ls_items[j].textEdit.newText += "$0";
466+
std::string &s = ls_items[j].textEdit.newText;
467+
if (!g_config->client.snippetSupport) {
468+
if (s.size()) {
469+
// Delete non-identifier parts.
470+
if (s.back() == '(' || s.back() == '<')
471+
s.pop_back();
472+
else if (s.size() >= 2 && !s.compare(s.size() - 2, 2, "()"))
473+
s.resize(s.size() - 2);
474+
}
475+
} else if (ls_items[j].insertTextFormat == InsertTextFormat::Snippet) {
476+
if (!g_config->completion.placeholder) {
477+
// foo(${1:int a}, ${2:int b}) -> foo($1)$0
478+
auto p = s.find("${"), q = s.rfind('}');
479+
s.replace(p, q - p + 1, "$1");
480+
}
481+
s += "$0";
482+
}
468483
ls_items[j].priority_ = ccs->getPriority();
469484
if (!g_config->completion.detailedLabel) {
470485
ls_items[j].detail = ls_items[j].label;

0 commit comments

Comments
 (0)