https://github.com/Noustaa updated 
https://github.com/llvm/llvm-project/pull/137613

>From 7e715447d242d7e409e02059d2948fb3417fb00f Mon Sep 17 00:00:00 2001
From: Noustaa <nous...@gmail.com>
Date: Mon, 28 Apr 2025 12:38:36 +0200
Subject: [PATCH] [clangd] Add CodePatterns config option under Completion

Allows enabling/disabling code patterns & snippets suggestion from
completion.
This can be done either with YAML config or CLI with --code-patterns
---
 clang-tools-extra/clangd/ClangdServer.cpp     |  1 +
 clang-tools-extra/clangd/CodeComplete.cpp     |  7 ++++++-
 clang-tools-extra/clangd/CodeComplete.h       |  3 +++
 clang-tools-extra/clangd/Config.h             |  7 +++++++
 clang-tools-extra/clangd/ConfigCompile.cpp    | 11 +++++++++++
 clang-tools-extra/clangd/ConfigFragment.h     |  6 ++++++
 clang-tools-extra/clangd/ConfigYAML.cpp       |  4 ++++
 clang-tools-extra/clangd/tool/ClangdMain.cpp  | 19 +++++++++++++++++++
 .../clangd/unittests/CodeCompleteTests.cpp    | 18 ++++++++++++++++++
 .../clangd/unittests/ConfigYAMLTests.cpp      | 13 +++++++++++++
 10 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clangd/ClangdServer.cpp 
b/clang-tools-extra/clangd/ClangdServer.cpp
index 52844129834c3..b499683621f53 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -457,6 +457,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
     CodeCompleteOpts.ArgumentLists = 
Config::current().Completion.ArgumentLists;
     CodeCompleteOpts.InsertIncludes =
         Config::current().Completion.HeaderInsertion;
+    CodeCompleteOpts.CodePatterns = Config::current().Completion.CodePatterns;
     // 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.
     CodeCompleteResult Result = clangd::codeComplete(
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp 
b/clang-tools-extra/clangd/CodeComplete.cpp
index 0eb196fbad46a..171690b6e78b4 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -950,6 +950,10 @@ struct CompletionRecorder : public CodeCompleteConsumer {
     // Retain the results we might want.
     for (unsigned I = 0; I < NumResults; ++I) {
       auto &Result = InResults[I];
+      if (Config::current().Completion.CodePatterns ==
+              Config::CodePatternsPolicy::None &&
+          Result.Kind == CodeCompletionResult::RK_Pattern)
+        continue;
       // Class members that are shadowed by subclasses are usually noise.
       if (Result.Hidden && Result.Declaration &&
           Result.Declaration->isCXXClassMember())
@@ -2153,7 +2157,8 @@ class CodeCompleteFlow {
 
 clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
   clang::CodeCompleteOptions Result;
-  Result.IncludeCodePatterns = EnableSnippets;
+  Result.IncludeCodePatterns =
+      EnableSnippets && (CodePatterns != Config::CodePatternsPolicy::None);
   Result.IncludeMacros = true;
   Result.IncludeGlobals = true;
   // We choose to include full comments and not do doxygen parsing in
diff --git a/clang-tools-extra/clangd/CodeComplete.h 
b/clang-tools-extra/clangd/CodeComplete.h
index 83d347054119e..1cf3b41119043 100644
--- a/clang-tools-extra/clangd/CodeComplete.h
+++ b/clang-tools-extra/clangd/CodeComplete.h
@@ -111,6 +111,9 @@ struct CodeCompleteOptions {
   Config::ArgumentListsPolicy ArgumentLists =
       Config::ArgumentListsPolicy::FullPlaceholders;
 
+  /// Whether to suggest code patterns & snippets or not in completion
+  Config::CodePatternsPolicy CodePatterns = Config::CodePatternsPolicy::All;
+
   /// Whether to use the clang parser, or fallback to text-based completion
   /// (using identifiers in the current file and symbol indexes).
   enum CodeCompletionParse {
diff --git a/clang-tools-extra/clangd/Config.h 
b/clang-tools-extra/clangd/Config.h
index 2891a6d1e77b0..83e0fce847271 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -152,6 +152,11 @@ struct Config {
     NeverInsert // Never insert headers as part of code completion
   };
 
+  enum class CodePatternsPolicy {
+    All, // Suggest all code patterns and snippets
+    None // Suggest none of the code patterns and snippets
+  };
+
   /// Configures code completion feature.
   struct {
     /// Whether code completion includes results that are not visible in 
current
@@ -161,6 +166,8 @@ struct Config {
     ArgumentListsPolicy ArgumentLists = ArgumentListsPolicy::FullPlaceholders;
     /// Controls if headers should be inserted when completions are accepted
     HeaderInsertionPolicy HeaderInsertion = HeaderInsertionPolicy::IWYU;
+    /// Enables code patterns & snippets suggestions
+    CodePatternsPolicy CodePatterns = CodePatternsPolicy::All;
   } Completion;
 
   /// Configures hover feature.
diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp 
b/clang-tools-extra/clangd/ConfigCompile.cpp
index 13c2405e76df7..35d35f747a868 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -707,6 +707,17 @@ struct FragmentCompiler {
           C.Completion.HeaderInsertion = *Val;
         });
     }
+
+    if (F.CodePatterns) {
+      if (auto Val = compileEnum<Config::CodePatternsPolicy>("CodePatterns",
+                                                             *F.CodePatterns)
+                         .map("All", Config::CodePatternsPolicy::All)
+                         .map("None", Config::CodePatternsPolicy::None)
+                         .value())
+        Out.Apply.push_back([Val](const Params &, Config &C) {
+          C.Completion.CodePatterns = *Val;
+        });
+    }
   }
 
   void compile(Fragment::HoverBlock &&F) {
diff --git a/clang-tools-extra/clangd/ConfigFragment.h 
b/clang-tools-extra/clangd/ConfigFragment.h
index 2363b483ab96d..c5d95ef125dee 100644
--- a/clang-tools-extra/clangd/ConfigFragment.h
+++ b/clang-tools-extra/clangd/ConfigFragment.h
@@ -349,6 +349,12 @@ struct Fragment {
     ///     symbol is forward-declared
     ///   "Never": Never insert headers
     std::optional<Located<std::string>> HeaderInsertion;
+    /// Will suggest code patterns & snippets.
+    /// CLI option available '--code-patterns':
+    /// Values are Config::CodePatternsPolicy:
+    ///   all  => enable all code patterns and snippets suggestion
+    ///   none => disable all code patterns and snippets suggestion
+    std::optional<Located<std::string>> CodePatterns;
   };
   CompletionBlock Completion;
 
diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp 
b/clang-tools-extra/clangd/ConfigYAML.cpp
index 47c6e1cd0f7e7..ff457d8701307 100644
--- a/clang-tools-extra/clangd/ConfigYAML.cpp
+++ b/clang-tools-extra/clangd/ConfigYAML.cpp
@@ -249,6 +249,10 @@ class Parser {
       if (auto HeaderInsertion = scalarValue(N, "HeaderInsertion"))
         F.HeaderInsertion = *HeaderInsertion;
     });
+    Dict.handle("CodePatterns", [&](Node &N) {
+      if (auto CodePatterns = scalarValue(N, "CodePatterns"))
+        F.CodePatterns = *CodePatterns;
+    });
     Dict.parse(N);
   }
 
diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp 
b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index 4bd256d6be22b..688b4d4fee17b 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -267,6 +267,17 @@ opt<Config::HeaderInsertionPolicy> HeaderInsertion{
             "Never insert #include directives as part of code completion")),
 };
 
+opt<Config::CodePatternsPolicy> CodePatterns{
+    "code-patterns",
+    cat(Features),
+    desc("Code completion menu will suggest code patterns and snippets."),
+    init(CodeCompleteOptions().CodePatterns),
+    values(clEnumValN(Config::CodePatternsPolicy::All, "all",
+                      "Enable all code patterns and snippets."),
+           clEnumValN(Config::CodePatternsPolicy::None, "none",
+                      "Disable all code patterns and snippets.")),
+};
+
 opt<bool> ImportInsertions{
     "import-insertions",
     cat(Features),
@@ -669,6 +680,7 @@ class FlagsConfigProvider : public config::Provider {
     std::optional<Config::BackgroundPolicy> BGPolicy;
     std::optional<Config::ArgumentListsPolicy> ArgumentLists;
     std::optional<Config::HeaderInsertionPolicy> HeaderInsertionPolicy;
+    std::optional<Config::CodePatternsPolicy> CodePatternsPolicy;
 
     // If --compile-commands-dir arg was invoked, check value and override
     // default path.
@@ -723,6 +735,10 @@ class FlagsConfigProvider : public config::Provider {
                               : Config::ArgumentListsPolicy::Delimiters;
     }
 
+    if (CodePatterns == Config::CodePatternsPolicy::None) {
+      CodePatternsPolicy = Config::CodePatternsPolicy::None;
+    }
+
     Frag = [=](const config::Params &, Config &C) {
       if (CDBSearch)
         C.CompileFlags.CDBSearch = *CDBSearch;
@@ -736,6 +752,8 @@ class FlagsConfigProvider : public config::Provider {
         C.Completion.HeaderInsertion = *HeaderInsertionPolicy;
       if (AllScopesCompletion.getNumOccurrences())
         C.Completion.AllScopes = AllScopesCompletion;
+      if (CodePatternsPolicy)
+        C.Completion.CodePatterns = *CodePatternsPolicy;
 
       if (Test)
         C.Index.StandardLibrary = false;
@@ -949,6 +967,7 @@ clangd accepts flags on the commandline, and in the 
CLANGD_FLAGS environment var
     Opts.CodeComplete.BundleOverloads = CompletionStyle != Detailed;
   Opts.CodeComplete.ShowOrigins = ShowOrigins;
   Opts.CodeComplete.InsertIncludes = HeaderInsertion;
+  Opts.CodeComplete.CodePatterns = CodePatterns;
   Opts.CodeComplete.ImportInsertions = ImportInsertions;
   if (!HeaderInsertionDecorators) {
     Opts.CodeComplete.IncludeIndicator.Insert.clear();
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp 
b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 718bee2e40b11..8387a847f706a 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3326,6 +3326,24 @@ TEST(CompletionTest, AllScopesCompletion) {
                                  kind(CompletionItemKind::EnumMember))));
 }
 
+TEST(CompletionTest, NoCodePatternsIfDisabled) {
+  clangd::CodeCompleteOptions Opts = {};
+  Opts.EnableSnippets = true;
+  Opts.CodePatterns = Config::CodePatternsPolicy::None;
+
+  auto Results = completions(R"cpp(
+    void function() {
+      /// Trying to trigger "for (init-statement; condition; inc-expression)
+      /// {statements}~" code pattern
+      for^
+    }
+  )cpp",
+                             {}, Opts);
+
+  EXPECT_THAT(Results.Completions,
+              Not(Contains(kind(CompletionItemKind::Snippet))));
+}
+
 TEST(CompletionTest, NoQualifierIfShadowed) {
   clangd::CodeCompleteOptions Opts = {};
   Opts.AllScopes = true;
diff --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp 
b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
index 979d725461fd0..d71b8d5f9302a 100644
--- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
@@ -217,6 +217,19 @@ TEST(ParseYAML, AllScopesWarn) {
   EXPECT_THAT(Results[0].Completion.AllScopes, testing::Eq(std::nullopt));
 }
 
+TEST(ParseYAML, CodePatterns) {
+  CapturedDiags Diags;
+  Annotations YAML(R"yaml(
+    Completion:
+      CodePatterns: None
+  )yaml");
+  auto Results =
+      Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
+  ASSERT_THAT(Diags.Diagnostics, IsEmpty());
+  ASSERT_EQ(Results.size(), 1u);
+  EXPECT_THAT(Results[0].Completion.CodePatterns, llvm::ValueIs(val("None")));
+}
+
 TEST(ParseYAML, ShowAKA) {
   CapturedDiags Diags;
   Annotations YAML(R"yaml(

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to