https://github.com/Harald-R updated 
https://github.com/llvm/llvm-project/pull/140594

>From 322468b6354c45c0c81aa3ae28b900262d795a8e Mon Sep 17 00:00:00 2001
From: Harald-R <rotuna.raz...@gmail.com>
Date: Sun, 18 May 2025 19:07:59 +0300
Subject: [PATCH 1/7] Follow style configuration in clangd include cleaner

---
 clang-tools-extra/clangd/IncludeCleaner.cpp   | 21 ++++++++++++-------
 clang-tools-extra/clangd/IncludeCleaner.h     |  9 ++++----
 clang-tools-extra/clangd/ParsedAST.cpp        |  3 ++-
 .../clangd/unittests/IncludeCleanerTests.cpp  | 15 +++++++++++--
 4 files changed, 33 insertions(+), 15 deletions(-)

diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp 
b/clang-tools-extra/clangd/IncludeCleaner.cpp
index dc4c8fc498b1f..ce16d060a1f06 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.cpp
+++ b/clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -117,7 +117,8 @@ bool mayConsiderUnused(const Inclusion &Inc, ParsedAST &AST,
 
 std::vector<Diag> generateMissingIncludeDiagnostics(
     ParsedAST &AST, llvm::ArrayRef<MissingIncludeDiagInfo> MissingIncludes,
-    llvm::StringRef Code, HeaderFilter IgnoreHeaders, const ThreadsafeFS &TFS) 
{
+    llvm::StringRef Code, HeaderFilter IgnoreHeaders,
+    HeaderFilter AngledHeaders, const ThreadsafeFS &TFS) {
   std::vector<Diag> Result;
   const SourceManager &SM = AST.getSourceManager();
   const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID());
@@ -142,6 +143,13 @@ std::vector<Diag> generateMissingIncludeDiagnostics(
 
     llvm::StringRef HeaderRef{Spelling};
     bool Angled = HeaderRef.starts_with("<");
+    for (auto Filter : AngledHeaders) {
+      if (Filter(HeaderRef)) {
+        Angled = true;
+        break;
+      }
+    }
+
     // We might suggest insertion of an existing include in edge cases, e.g.,
     // include is present in a PP-disabled region, or spelling of the header
     // turns out to be the same as one of the unresolved includes in the
@@ -481,18 +489,17 @@ bool isPreferredProvider(const Inclusion &Inc,
   return false; // no header provides the symbol
 }
 
-std::vector<Diag>
-issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code,
-                               const IncludeCleanerFindings &Findings,
-                               const ThreadsafeFS &TFS,
-                               HeaderFilter IgnoreHeaders) {
+std::vector<Diag> issueIncludeCleanerDiagnostics(
+    ParsedAST &AST, llvm::StringRef Code,
+    const IncludeCleanerFindings &Findings, const ThreadsafeFS &TFS,
+    HeaderFilter IgnoreHeaders, HeaderFilter AngledHeaders) {
   trace::Span Tracer("IncludeCleaner::issueIncludeCleanerDiagnostics");
   std::vector<Diag> UnusedIncludes = generateUnusedIncludeDiagnostics(
       AST.tuPath(), Findings.UnusedIncludes, Code, IgnoreHeaders);
   std::optional<Fix> RemoveAllUnused = removeAllUnusedIncludes(UnusedIncludes);
 
   std::vector<Diag> MissingIncludeDiags = generateMissingIncludeDiagnostics(
-      AST, Findings.MissingIncludes, Code, IgnoreHeaders, TFS);
+      AST, Findings.MissingIncludes, Code, IgnoreHeaders, AngledHeaders, TFS);
   std::optional<Fix> AddAllMissing = 
addAllMissingIncludes(MissingIncludeDiags);
 
   std::optional<Fix> FixAll;
diff --git a/clang-tools-extra/clangd/IncludeCleaner.h 
b/clang-tools-extra/clangd/IncludeCleaner.h
index 3f6e3b2fd45b6..884feb69488d5 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.h
+++ b/clang-tools-extra/clangd/IncludeCleaner.h
@@ -57,11 +57,10 @@ IncludeCleanerFindings
 computeIncludeCleanerFindings(ParsedAST &AST,
                               bool AnalyzeAngledIncludes = false);
 
-std::vector<Diag>
-issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code,
-                               const IncludeCleanerFindings &Findings,
-                               const ThreadsafeFS &TFS,
-                               HeaderFilter IgnoreHeader = {});
+std::vector<Diag> issueIncludeCleanerDiagnostics(
+    ParsedAST &AST, llvm::StringRef Code,
+    const IncludeCleanerFindings &Findings, const ThreadsafeFS &TFS,
+    HeaderFilter IgnoreHeader = {}, HeaderFilter AngledHeaders = {});
 
 /// Converts the clangd include representation to include-cleaner
 /// include representation.
diff --git a/clang-tools-extra/clangd/ParsedAST.cpp 
b/clang-tools-extra/clangd/ParsedAST.cpp
index 9e1f6bb977226..4fedea35334f6 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -382,7 +382,8 @@ std::vector<Diag> getIncludeCleanerDiags(ParsedAST &AST, 
llvm::StringRef Code,
   if (SuppressUnused)
     Findings.UnusedIncludes.clear();
   return issueIncludeCleanerDiagnostics(AST, Code, Findings, TFS,
-                                        Cfg.Diagnostics.Includes.IgnoreHeader);
+                                        Cfg.Diagnostics.Includes.IgnoreHeader,
+                                        Cfg.Style.AngledHeaders);
 }
 
 tidy::ClangTidyCheckFactories
diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp 
b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
index 0ee748c1ed2d0..fda1b3b1835ae 100644
--- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -220,12 +220,13 @@ TEST(IncludeCleaner, ComputeMissingHeaders) {
 TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
   Annotations MainFile(R"cpp(
 #include "a.h"
+#include "a_angled.h"
 #include "all.h"
 $insert_b[[]]#include "baz.h"
 #include "dir/c.h"
 $insert_d[[]]$insert_foo[[]]#include "fuzz.h"
 #include "header.h"
-$insert_foobar[[]]#include <e.h>
+$insert_foobar[[]]$insert_b_angled[[]]#include <e.h>
 $insert_f[[]]$insert_vector[[]]
 
 #define DEF(X) const Foo *X;
@@ -237,6 +238,7 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
 
   void foo() {
     $b[[b]]();
+    $b_angled[[b_angled]]();
 
     ns::$bar[[Bar]] bar;
     bar.d();
@@ -262,6 +264,8 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
   TU.Filename = "main.cpp";
   TU.AdditionalFiles["a.h"] = guard("#include \"b.h\"");
   TU.AdditionalFiles["b.h"] = guard("void b();");
+  TU.AdditionalFiles["a_angled.h"] = guard("#include \"b_angled.h\"");
+  TU.AdditionalFiles["b_angled.h"] = guard("void b_angled();");
 
   TU.AdditionalFiles["dir/c.h"] = guard("#include \"d.h\"");
   TU.AdditionalFiles["dir/d.h"] =
@@ -297,7 +301,8 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
   Findings.UnusedIncludes.clear();
   std::vector<clangd::Diag> Diags = issueIncludeCleanerDiagnostics(
       AST, TU.Code, Findings, MockFS(),
-      {[](llvm::StringRef Header) { return Header.ends_with("buzz.h"); }});
+      {[](llvm::StringRef Header) { return Header.ends_with("buzz.h"); }},
+      {[](llvm::StringRef Header) { return Header.contains("b_angled.h"); }});
   EXPECT_THAT(
       Diags,
       UnorderedElementsAre(
@@ -306,6 +311,12 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
                 withFix({Fix(MainFile.range("insert_b"), "#include \"b.h\"\n",
                              "#include \"b.h\""),
                          FixMessage("add all missing includes")})),
+          AllOf(Diag(MainFile.range("b_angled"),
+                     "No header providing \"b_angled\" is directly included"),
+                withFix(
+                    {Fix(MainFile.range("insert_b_angled"),
+                         "#include <b_angled.h>\n", "#include \"b_angled.h\""),
+                     FixMessage("add all missing includes")})),
           AllOf(Diag(MainFile.range("bar"),
                      "No header providing \"ns::Bar\" is directly included"),
                 withFix({Fix(MainFile.range("insert_d"),

>From b2eb302792edab51a0e4a5a8b8146b6532262ffa Mon Sep 17 00:00:00 2001
From: Harald-R <rotuna.raz...@gmail.com>
Date: Sat, 24 May 2025 15:56:58 +0300
Subject: [PATCH 2/7] Use auto& for iteration

---
 clang-tools-extra/clangd/IncludeCleaner.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp 
b/clang-tools-extra/clangd/IncludeCleaner.cpp
index ce16d060a1f06..a8fcc6c7dd027 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.cpp
+++ b/clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -143,7 +143,7 @@ std::vector<Diag> generateMissingIncludeDiagnostics(
 
     llvm::StringRef HeaderRef{Spelling};
     bool Angled = HeaderRef.starts_with("<");
-    for (auto Filter : AngledHeaders) {
+    for (auto &Filter : AngledHeaders) {
       if (Filter(HeaderRef)) {
         Angled = true;
         break;

>From e43d2394a77aeea1ad834b81b286a5c25926dc26 Mon Sep 17 00:00:00 2001
From: Harald-R <rotuna.raz...@gmail.com>
Date: Sat, 24 May 2025 16:19:36 +0300
Subject: [PATCH 3/7] Add helper comment to test arguments

---
 .../clangd/unittests/IncludeCleanerTests.cpp              | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp 
b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
index fda1b3b1835ae..a27c340c37923 100644
--- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -301,8 +301,12 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
   Findings.UnusedIncludes.clear();
   std::vector<clangd::Diag> Diags = issueIncludeCleanerDiagnostics(
       AST, TU.Code, Findings, MockFS(),
-      {[](llvm::StringRef Header) { return Header.ends_with("buzz.h"); }},
-      {[](llvm::StringRef Header) { return Header.contains("b_angled.h"); }});
+      /*IgnoreHeaders=*/{[](llvm::StringRef Header) {
+        return Header.ends_with("buzz.h");
+      }},
+      /*AngledHeaders=*/{[](llvm::StringRef Header) {
+        return Header.contains("b_angled.h");
+      }});
   EXPECT_THAT(
       Diags,
       UnorderedElementsAre(

>From 775faf906b15f91891c3087572f1796d9c6fec25 Mon Sep 17 00:00:00 2001
From: Harald-R <rotuna.raz...@gmail.com>
Date: Sat, 24 May 2025 16:26:48 +0300
Subject: [PATCH 4/7] Ensure the message field is also angled

---
 clang-tools-extra/clangd/IncludeCleaner.cpp          |  5 +++++
 .../clangd/unittests/IncludeCleanerTests.cpp         | 12 ++++++------
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp 
b/clang-tools-extra/clangd/IncludeCleaner.cpp
index a8fcc6c7dd027..92c2ddf250420 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.cpp
+++ b/clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -159,6 +159,11 @@ std::vector<Diag> generateMissingIncludeDiagnostics(
     if (!Replacement.has_value())
       continue;
 
+    if (Angled && Spelling.front() == '\"') {
+      Spelling.front() = '<';
+      Spelling.back() = '>';
+    }
+
     Diag &D = Result.emplace_back();
     D.Message =
         llvm::formatv("No header providing \"{0}\" is directly included",
diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp 
b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
index a27c340c37923..bf1540280d5b5 100644
--- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -315,12 +315,12 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
                 withFix({Fix(MainFile.range("insert_b"), "#include \"b.h\"\n",
                              "#include \"b.h\""),
                          FixMessage("add all missing includes")})),
-          AllOf(Diag(MainFile.range("b_angled"),
-                     "No header providing \"b_angled\" is directly included"),
-                withFix(
-                    {Fix(MainFile.range("insert_b_angled"),
-                         "#include <b_angled.h>\n", "#include \"b_angled.h\""),
-                     FixMessage("add all missing includes")})),
+          AllOf(
+              Diag(MainFile.range("b_angled"),
+                   "No header providing \"b_angled\" is directly included"),
+              withFix({Fix(MainFile.range("insert_b_angled"),
+                           "#include <b_angled.h>\n", "#include <b_angled.h>"),
+                       FixMessage("add all missing includes")})),
           AllOf(Diag(MainFile.range("bar"),
                      "No header providing \"ns::Bar\" is directly included"),
                 withFix({Fix(MainFile.range("insert_d"),

>From 81fdbf7ec5dcf91c01d34822a959bec01105b276 Mon Sep 17 00:00:00 2001
From: Harald-R <rotuna.raz...@gmail.com>
Date: Mon, 26 May 2025 18:50:59 +0300
Subject: [PATCH 5/7] Rename test headers

---
 .../clangd/unittests/IncludeCleanerTests.cpp  | 25 ++++++++++---------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp 
b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
index bf1540280d5b5..f51e6e7896f39 100644
--- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -220,13 +220,13 @@ TEST(IncludeCleaner, ComputeMissingHeaders) {
 TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
   Annotations MainFile(R"cpp(
 #include "a.h"
-#include "a_angled.h"
+#include "angled_wrapper.h"
 #include "all.h"
 $insert_b[[]]#include "baz.h"
 #include "dir/c.h"
 $insert_d[[]]$insert_foo[[]]#include "fuzz.h"
 #include "header.h"
-$insert_foobar[[]]$insert_b_angled[[]]#include <e.h>
+$insert_foobar[[]]$insert_angled[[]]#include <e.h>
 $insert_f[[]]$insert_vector[[]]
 
 #define DEF(X) const Foo *X;
@@ -238,7 +238,7 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
 
   void foo() {
     $b[[b]]();
-    $b_angled[[b_angled]]();
+    $angled[[angled]]();
 
     ns::$bar[[Bar]] bar;
     bar.d();
@@ -264,8 +264,10 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
   TU.Filename = "main.cpp";
   TU.AdditionalFiles["a.h"] = guard("#include \"b.h\"");
   TU.AdditionalFiles["b.h"] = guard("void b();");
-  TU.AdditionalFiles["a_angled.h"] = guard("#include \"b_angled.h\"");
-  TU.AdditionalFiles["b_angled.h"] = guard("void b_angled();");
+
+  TU.AdditionalFiles["angled_wrapper.h"] = guard("#include <angled.h>");
+  TU.AdditionalFiles["angled.h"] = guard("void angled();");
+  TU.ExtraArgs.push_back("-I" + testPath("."));
 
   TU.AdditionalFiles["dir/c.h"] = guard("#include \"d.h\"");
   TU.AdditionalFiles["dir/d.h"] =
@@ -305,7 +307,7 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
         return Header.ends_with("buzz.h");
       }},
       /*AngledHeaders=*/{[](llvm::StringRef Header) {
-        return Header.contains("b_angled.h");
+        return Header.contains("angled.h");
       }});
   EXPECT_THAT(
       Diags,
@@ -315,12 +317,11 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
                 withFix({Fix(MainFile.range("insert_b"), "#include \"b.h\"\n",
                              "#include \"b.h\""),
                          FixMessage("add all missing includes")})),
-          AllOf(
-              Diag(MainFile.range("b_angled"),
-                   "No header providing \"b_angled\" is directly included"),
-              withFix({Fix(MainFile.range("insert_b_angled"),
-                           "#include <b_angled.h>\n", "#include <b_angled.h>"),
-                       FixMessage("add all missing includes")})),
+          AllOf(Diag(MainFile.range("angled"),
+                     "No header providing \"angled\" is directly included"),
+                withFix({Fix(MainFile.range("insert_angled"),
+                             "#include <angled.h>\n", "#include <angled.h>"),
+                         FixMessage("add all missing includes")})),
           AllOf(Diag(MainFile.range("bar"),
                      "No header providing \"ns::Bar\" is directly included"),
                 withFix({Fix(MainFile.range("insert_d"),

>From 6b50b8052269248a5f26c03a14ea31d7060da2cf Mon Sep 17 00:00:00 2001
From: Harald-R <rotuna.raz...@gmail.com>
Date: Mon, 26 May 2025 20:38:17 +0300
Subject: [PATCH 6/7] Use QuotedHeaders filter in determining inclusion style

---
 clang-tools-extra/clangd/IncludeCleaner.cpp   | 30 ++++++++++++++-----
 clang-tools-extra/clangd/IncludeCleaner.h     |  3 +-
 clang-tools-extra/clangd/ParsedAST.cpp        |  6 ++--
 .../clangd/unittests/IncludeCleanerTests.cpp  | 16 +++++++++-
 4 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp 
b/clang-tools-extra/clangd/IncludeCleaner.cpp
index 92c2ddf250420..d62003a6a19ee 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.cpp
+++ b/clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -118,7 +118,8 @@ bool mayConsiderUnused(const Inclusion &Inc, ParsedAST &AST,
 std::vector<Diag> generateMissingIncludeDiagnostics(
     ParsedAST &AST, llvm::ArrayRef<MissingIncludeDiagInfo> MissingIncludes,
     llvm::StringRef Code, HeaderFilter IgnoreHeaders,
-    HeaderFilter AngledHeaders, const ThreadsafeFS &TFS) {
+    HeaderFilter AngledHeaders, HeaderFilter QuotedHeaders,
+    const ThreadsafeFS &TFS) {
   std::vector<Diag> Result;
   const SourceManager &SM = AST.getSourceManager();
   const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID());
@@ -142,24 +143,37 @@ std::vector<Diag> generateMissingIncludeDiagnostics(
          AST.getPreprocessor().getHeaderSearchInfo(), MainFile});
 
     llvm::StringRef HeaderRef{Spelling};
-    bool Angled = HeaderRef.starts_with("<");
+
+    bool IsAngled = false;
     for (auto &Filter : AngledHeaders) {
       if (Filter(HeaderRef)) {
-        Angled = true;
+        IsAngled = true;
+        break;
+      }
+    }
+    bool IsQuoted = false;
+    for (auto &Filter : QuotedHeaders) {
+      if (Filter(HeaderRef)) {
+        IsQuoted = true;
         break;
       }
     }
+    if (IsAngled == IsQuoted) {
+      IsAngled = HeaderRef.starts_with("<");
+    } else if (!IsAngled && IsQuoted) {
+      IsAngled = false;
+    }
 
     // We might suggest insertion of an existing include in edge cases, e.g.,
     // include is present in a PP-disabled region, or spelling of the header
     // turns out to be the same as one of the unresolved includes in the
     // main file.
     std::optional<tooling::Replacement> Replacement = HeaderIncludes.insert(
-        HeaderRef.trim("\"<>"), Angled, tooling::IncludeDirective::Include);
+        HeaderRef.trim("\"<>"), IsAngled, tooling::IncludeDirective::Include);
     if (!Replacement.has_value())
       continue;
 
-    if (Angled && Spelling.front() == '\"') {
+    if (IsAngled && Spelling.front() == '\"') {
       Spelling.front() = '<';
       Spelling.back() = '>';
     }
@@ -497,14 +511,16 @@ bool isPreferredProvider(const Inclusion &Inc,
 std::vector<Diag> issueIncludeCleanerDiagnostics(
     ParsedAST &AST, llvm::StringRef Code,
     const IncludeCleanerFindings &Findings, const ThreadsafeFS &TFS,
-    HeaderFilter IgnoreHeaders, HeaderFilter AngledHeaders) {
+    HeaderFilter IgnoreHeaders, HeaderFilter AngledHeaders,
+    HeaderFilter QuotedHeaders) {
   trace::Span Tracer("IncludeCleaner::issueIncludeCleanerDiagnostics");
   std::vector<Diag> UnusedIncludes = generateUnusedIncludeDiagnostics(
       AST.tuPath(), Findings.UnusedIncludes, Code, IgnoreHeaders);
   std::optional<Fix> RemoveAllUnused = removeAllUnusedIncludes(UnusedIncludes);
 
   std::vector<Diag> MissingIncludeDiags = generateMissingIncludeDiagnostics(
-      AST, Findings.MissingIncludes, Code, IgnoreHeaders, AngledHeaders, TFS);
+      AST, Findings.MissingIncludes, Code, IgnoreHeaders, AngledHeaders,
+      QuotedHeaders, TFS);
   std::optional<Fix> AddAllMissing = 
addAllMissingIncludes(MissingIncludeDiags);
 
   std::optional<Fix> FixAll;
diff --git a/clang-tools-extra/clangd/IncludeCleaner.h 
b/clang-tools-extra/clangd/IncludeCleaner.h
index 884feb69488d5..9439eeed6a3e4 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.h
+++ b/clang-tools-extra/clangd/IncludeCleaner.h
@@ -60,7 +60,8 @@ computeIncludeCleanerFindings(ParsedAST &AST,
 std::vector<Diag> issueIncludeCleanerDiagnostics(
     ParsedAST &AST, llvm::StringRef Code,
     const IncludeCleanerFindings &Findings, const ThreadsafeFS &TFS,
-    HeaderFilter IgnoreHeader = {}, HeaderFilter AngledHeaders = {});
+    HeaderFilter IgnoreHeader = {}, HeaderFilter AngledHeaders = {},
+    HeaderFilter QuotedHeaders = {});
 
 /// Converts the clangd include representation to include-cleaner
 /// include representation.
diff --git a/clang-tools-extra/clangd/ParsedAST.cpp 
b/clang-tools-extra/clangd/ParsedAST.cpp
index 4fedea35334f6..48896e5f4ff87 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -381,9 +381,9 @@ std::vector<Diag> getIncludeCleanerDiags(ParsedAST &AST, 
llvm::StringRef Code,
     Findings.MissingIncludes.clear();
   if (SuppressUnused)
     Findings.UnusedIncludes.clear();
-  return issueIncludeCleanerDiagnostics(AST, Code, Findings, TFS,
-                                        Cfg.Diagnostics.Includes.IgnoreHeader,
-                                        Cfg.Style.AngledHeaders);
+  return issueIncludeCleanerDiagnostics(
+      AST, Code, Findings, TFS, Cfg.Diagnostics.Includes.IgnoreHeader,
+      Cfg.Style.AngledHeaders, Cfg.Style.QuotedHeaders);
 }
 
 tidy::ClangTidyCheckFactories
diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp 
b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
index f51e6e7896f39..9a37247c8799a 100644
--- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -226,7 +226,8 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
 #include "dir/c.h"
 $insert_d[[]]$insert_foo[[]]#include "fuzz.h"
 #include "header.h"
-$insert_foobar[[]]$insert_angled[[]]#include <e.h>
+$insert_foobar[[]]$insert_quoted[[]]#include "quoted_wrapper.h"
+$insert_angled[[]]#include <e.h>
 $insert_f[[]]$insert_vector[[]]
 
 #define DEF(X) const Foo *X;
@@ -239,6 +240,7 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
   void foo() {
     $b[[b]]();
     $angled[[angled]]();
+    $quoted[[quoted]]();
 
     ns::$bar[[Bar]] bar;
     bar.d();
@@ -269,6 +271,9 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
   TU.AdditionalFiles["angled.h"] = guard("void angled();");
   TU.ExtraArgs.push_back("-I" + testPath("."));
 
+  TU.AdditionalFiles["quoted_wrapper.h"] = guard("#include \"quoted.h\"");
+  TU.AdditionalFiles["quoted.h"] = guard("void quoted();");
+
   TU.AdditionalFiles["dir/c.h"] = guard("#include \"d.h\"");
   TU.AdditionalFiles["dir/d.h"] =
       guard("namespace ns { struct Bar { void d(); }; }");
@@ -308,6 +313,9 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
       }},
       /*AngledHeaders=*/{[](llvm::StringRef Header) {
         return Header.contains("angled.h");
+      }},
+      /*QuotedHeaders=*/{[](llvm::StringRef Header) {
+        return Header.contains("quoted.h");
       }});
   EXPECT_THAT(
       Diags,
@@ -322,6 +330,12 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
                 withFix({Fix(MainFile.range("insert_angled"),
                              "#include <angled.h>\n", "#include <angled.h>"),
                          FixMessage("add all missing includes")})),
+          AllOf(
+              Diag(MainFile.range("quoted"),
+                   "No header providing \"quoted\" is directly included"),
+              withFix({Fix(MainFile.range("insert_quoted"),
+                           "#include \"quoted.h\"\n", "#include \"quoted.h\""),
+                       FixMessage("add all missing includes")})),
           AllOf(Diag(MainFile.range("bar"),
                      "No header providing \"ns::Bar\" is directly included"),
                 withFix({Fix(MainFile.range("insert_d"),

>From 6739bd8ec96fe0d47e7566e459a9c2d1b433e0a8 Mon Sep 17 00:00:00 2001
From: Harald-R <rotuna.raz...@gmail.com>
Date: Tue, 27 May 2025 21:30:47 +0300
Subject: [PATCH 7/7] Use resolved path for filter

---
 clang-tools-extra/clangd/IncludeCleaner.cpp | 29 +++++++--------------
 1 file changed, 10 insertions(+), 19 deletions(-)

diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp 
b/clang-tools-extra/clangd/IncludeCleaner.cpp
index d62003a6a19ee..0195d0ce9b709 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.cpp
+++ b/clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -144,36 +144,27 @@ std::vector<Diag> generateMissingIncludeDiagnostics(
 
     llvm::StringRef HeaderRef{Spelling};
 
-    bool IsAngled = false;
-    for (auto &Filter : AngledHeaders) {
-      if (Filter(HeaderRef)) {
-        IsAngled = true;
-        break;
-      }
-    }
-    bool IsQuoted = false;
-    for (auto &Filter : QuotedHeaders) {
-      if (Filter(HeaderRef)) {
-        IsQuoted = true;
-        break;
+    bool Angled = HeaderRef.starts_with("<");
+    if (SymbolWithMissingInclude.Providers.front().kind() ==
+        include_cleaner::Header::Kind::Physical) {
+      for (auto &Filter : Angled ? QuotedHeaders : AngledHeaders) {
+        if (Filter(ResolvedPath)) {
+          Angled = !Angled;
+          break;
+        }
       }
     }
-    if (IsAngled == IsQuoted) {
-      IsAngled = HeaderRef.starts_with("<");
-    } else if (!IsAngled && IsQuoted) {
-      IsAngled = false;
-    }
 
     // We might suggest insertion of an existing include in edge cases, e.g.,
     // include is present in a PP-disabled region, or spelling of the header
     // turns out to be the same as one of the unresolved includes in the
     // main file.
     std::optional<tooling::Replacement> Replacement = HeaderIncludes.insert(
-        HeaderRef.trim("\"<>"), IsAngled, tooling::IncludeDirective::Include);
+        HeaderRef.trim("\"<>"), Angled, tooling::IncludeDirective::Include);
     if (!Replacement.has_value())
       continue;
 
-    if (IsAngled && Spelling.front() == '\"') {
+    if (Angled && Spelling.front() == '\"') {
       Spelling.front() = '<';
       Spelling.back() = '>';
     }

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

Reply via email to