summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/CodeComplete.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clangd/CodeComplete.cpp')
-rw-r--r--clang-tools-extra/clangd/CodeComplete.cpp42
1 files changed, 36 insertions, 6 deletions
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index ca083964e9c..2328fc601d0 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -482,13 +482,43 @@ private:
auto *Snippet = onlyValue<&BundledEntry::SnippetSuffix>();
if (!Snippet)
// All bundles are function calls.
+ // FIXME(ibiryukov): sometimes add template arguments to a snippet, e.g.
+ // we need to complete 'forward<$1>($0)'.
return "($0)";
- if (!Snippet->empty() && !EnableFunctionArgSnippets &&
- ((Completion.Kind == CompletionItemKind::Function) ||
- (Completion.Kind == CompletionItemKind::Method)) &&
- (Snippet->front() == '(') && (Snippet->back() == ')'))
- // Check whether function has any parameters or not.
- return Snippet->size() > 2 ? "($0)" : "()";
+ if (EnableFunctionArgSnippets)
+ return *Snippet;
+
+ // Replace argument snippets with a simplified pattern.
+ if (Snippet->empty())
+ return "";
+ if (Completion.Kind == CompletionItemKind::Function ||
+ Completion.Kind == CompletionItemKind::Method) {
+ // Functions snippets can be of 2 types:
+ // - containing only function arguments, e.g.
+ // foo(${1:int p1}, ${2:int p2});
+ // We transform this pattern to '($0)' or '()'.
+ // - template arguments and function arguments, e.g.
+ // foo<${1:class}>(${2:int p1}).
+ // We transform this pattern to '<$1>()$0' or '<$0>()'.
+
+ bool EmptyArgs = llvm::StringRef(*Snippet).endswith("()");
+ if (Snippet->front() == '<')
+ return EmptyArgs ? "<$1>()$0" : "<$1>($0)";
+ if (Snippet->front() == '(')
+ return EmptyArgs ? "()" : "($0)";
+ return *Snippet; // Not an arg snippet?
+ }
+ if (Completion.Kind == CompletionItemKind::Reference ||
+ Completion.Kind == CompletionItemKind::Class) {
+ if (Snippet->front() != '<')
+ return *Snippet; // Not an arg snippet?
+
+ // Classes and template using aliases can only have template arguments,
+ // e.g. Foo<${1:class}>.
+ if (llvm::StringRef(*Snippet).endswith("<>"))
+ return "<>"; // can happen with defaulted template arguments.
+ return "<$0>";
+ }
return *Snippet;
}
OpenPOWER on IntegriCloud