diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 89eee392837a..f0c8dbe3d4be 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -350,8 +350,7 @@ struct CodeCompletionBuilder { CodeCompletionContext::Kind ContextKind, const CodeCompleteOptions &Opts, bool IsUsingDeclaration, tok::TokenKind NextTokenKind) - : ASTCtx(ASTCtx), - EnableFunctionArgSnippets(Opts.EnableFunctionArgSnippets), + : ASTCtx(ASTCtx), PlaceholderType(Opts.PlaceholderType), IsUsingDeclaration(IsUsingDeclaration), NextTokenKind(NextTokenKind) { Completion.Deprecated = true; // cleared by any non-deprecated overload. add(C, SemaCCS, ContextKind); @@ -568,7 +567,9 @@ private: // 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)"; + return PlaceholderType == CodeCompleteOptions::PlaceholderOption::None + ? "" + : "($0)"; if (Snippet->empty()) return ""; @@ -607,7 +608,8 @@ private: return ""; } } - if (EnableFunctionArgSnippets) + if (PlaceholderType == + CodeCompleteOptions::PlaceholderOption::FullPlaceholders) return *Snippet; // Replace argument snippets with a simplified pattern. @@ -622,9 +624,13 @@ private: bool EmptyArgs = llvm::StringRef(*Snippet).ends_with("()"); if (Snippet->front() == '<') - return EmptyArgs ? "<$1>()$0" : "<$1>($0)"; + return PlaceholderType == CodeCompleteOptions::PlaceholderOption::None + ? "" + : (EmptyArgs ? "<$1>()$0" : "<$1>($0)"); if (Snippet->front() == '(') - return EmptyArgs ? "()" : "($0)"; + return PlaceholderType == CodeCompleteOptions::PlaceholderOption::None + ? "" + : (EmptyArgs ? "()" : "($0)"); return *Snippet; // Not an arg snippet? } // 'CompletionItemKind::Interface' matches template type aliases. @@ -638,7 +644,9 @@ private: // e.g. Foo<${1:class}>. if (llvm::StringRef(*Snippet).ends_with("<>")) return "<>"; // can happen with defaulted template arguments. - return "<$0>"; + return PlaceholderType == CodeCompleteOptions::PlaceholderOption::None + ? "" + : "<$0>"; } return *Snippet; } @@ -654,7 +662,7 @@ private: ASTContext *ASTCtx; CodeCompletion Completion; llvm::SmallVector Bundled; - bool EnableFunctionArgSnippets; + CodeCompleteOptions::PlaceholderOption PlaceholderType; // No snippets will be generated for using declarations and when the function // arguments are already present. bool IsUsingDeclaration; @@ -797,8 +805,8 @@ SpecifiedScope getQueryScopes(CodeCompletionContext &CCContext, llvm::StringRef SpelledSpecifier = Lexer::getSourceText( CharSourceRange::getCharRange(SemaSpecifier->getRange()), CCSema.SourceMgr, clang::LangOptions()); - if (SpelledSpecifier.consume_front("::")) - Scopes.QueryScopes = {""}; + if (SpelledSpecifier.consume_front("::")) + Scopes.QueryScopes = {""}; Scopes.UnresolvedQualifier = std::string(SpelledSpecifier); // Sema excludes the trailing "::". if (!Scopes.UnresolvedQualifier->empty()) @@ -1591,7 +1599,7 @@ class CodeCompleteFlow { CompletionPrefix HeuristicPrefix; std::optional Filter; // Initialized once Sema runs. Range ReplacedRange; - std::vector QueryScopes; // Initialized once Sema runs. + std::vector QueryScopes; // Initialized once Sema runs. std::vector AccessibleScopes; // Initialized once Sema runs. // Initialized once QueryScopes is initialized, if there are scopes. std::optional ScopeProximity; @@ -2387,8 +2395,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CodeCompletion &C) { llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const CodeCompleteResult &R) { OS << "CodeCompleteResult: " << R.Completions.size() << (R.HasMore ? "+" : "") - << " (" << getCompletionKindString(R.Context) << ")" - << " items:\n"; + << " (" << getCompletionKindString(R.Context) << ")" << " items:\n"; for (const auto &C : R.Completions) OS << C << "\n"; return OS; diff --git a/clang-tools-extra/clangd/CodeComplete.h b/clang-tools-extra/clangd/CodeComplete.h index a7c1ae95dcbf..53ba9688f894 100644 --- a/clang-tools-extra/clangd/CodeComplete.h +++ b/clang-tools-extra/clangd/CodeComplete.h @@ -96,9 +96,21 @@ struct CodeCompleteOptions { /// '->' on member access etc. bool IncludeFixIts = false; - /// Whether to generate snippets for function arguments on code-completion. - /// Needs snippets to be enabled as well. - bool EnableFunctionArgSnippets = true; + // requested by community in favour of 'EnableFunctionArgSnippets', + // see here for more info: + // https://github.com/llvm/llvm-project/issues/63565#issuecomment-1975065771 + /// Controls how the delimter/argument-list for callables: "()" + /// and for generics: "<>" are handled + enum PlaceholderOption { + /// empty pair of delimiters (or [legacy] alias 0) + Delimiters = 0, + /// full name of both type and variable (or [legacy] alias 1) + FullPlaceholders, + /// variable names only + NamePlaceholders, + /// nothing, no argument list and also NO Delimiters "()" or "<>" + None, + } PlaceholderType = PlaceholderOption::FullPlaceholders; /// Whether to include index symbols that are not defined in the scopes /// visible from the code completion point. This applies in contexts without diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index 3a5449ac8c79..ab24ee06cacc 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -242,13 +242,32 @@ opt FallbackStyle{ init(clang::format::DefaultFallbackStyle), }; -opt EnableFunctionArgSnippets{ - "function-arg-placeholders", - cat(Features), - desc("When disabled, completions contain only parentheses for " - "function calls. When enabled, completions also contain " - "placeholders for method parameters"), - init(CodeCompleteOptions().EnableFunctionArgSnippets), +// PlaceholderOption, deprecates: 'EnableFunctionArgSnippets' in favour of +// having more options, values "0" and "1" are the legacy options marked as +// deprecated. requested by comunity: +// https://github.com/llvm/llvm-project/issues/63565#issuecomment-1975065771 +opt PlaceholderOption{ + "function-arg-placeholders", cat(Features), + desc("Set the way placeholders and delimiters are implemented."), + init(CodeCompleteOptions().PlaceholderType), + values(clEnumValN(CodeCompleteOptions::PlaceholderOption::Delimiters, + "Delimiters", + "Only insert delimiters \"()\" and \"<>\", no values or " + "types: void foo()"), + clEnumValN(CodeCompleteOptions::PlaceholderOption::FullPlaceholders, + "FullPlaceholders", + "Use full type names and value names: void foo(int x)"), + clEnumValN(CodeCompleteOptions::PlaceholderOption::NamePlaceholders, + "NamePlaceholders", + "only use value names, not type names: void foo(x)"), + clEnumValN(CodeCompleteOptions::PlaceholderOption::None, "None", + "insert nothing, not even the delimiters \"()\" and " + "\"<>\": void foo"), + clEnumValN(CodeCompleteOptions::PlaceholderOption::Delimiters, "0", + "[deprecated] use: Delimiters instead"), + clEnumValN(CodeCompleteOptions::PlaceholderOption::FullPlaceholders, + "1", "[deprecated] use: FullPlaceholders instead")) + }; opt HeaderInsertion{ @@ -916,7 +935,7 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var Opts.CodeComplete.IncludeIndicator.Insert.clear(); Opts.CodeComplete.IncludeIndicator.NoInsert.clear(); } - Opts.CodeComplete.EnableFunctionArgSnippets = EnableFunctionArgSnippets; + Opts.CodeComplete.PlaceholderType = PlaceholderOption; Opts.CodeComplete.RunParser = CodeCompletionParse; Opts.CodeComplete.RankingModel = RankingModel;