Skip to content

Commit 328025e

Browse files
committed
Use QuotedHeaders filter in determining inclusion style
1 parent e8e828c commit 328025e

File tree

4 files changed

+43
-12
lines changed

4 files changed

+43
-12
lines changed

clang-tools-extra/clangd/IncludeCleaner.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ bool mayConsiderUnused(const Inclusion &Inc, ParsedAST &AST,
118118
std::vector<Diag> generateMissingIncludeDiagnostics(
119119
ParsedAST &AST, llvm::ArrayRef<MissingIncludeDiagInfo> MissingIncludes,
120120
llvm::StringRef Code, HeaderFilter IgnoreHeaders,
121-
HeaderFilter AngledHeaders, const ThreadsafeFS &TFS) {
121+
HeaderFilter AngledHeaders, HeaderFilter QuotedHeaders,
122+
const ThreadsafeFS &TFS) {
122123
std::vector<Diag> Result;
123124
const SourceManager &SM = AST.getSourceManager();
124125
const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID());
@@ -142,24 +143,37 @@ std::vector<Diag> generateMissingIncludeDiagnostics(
142143
AST.getPreprocessor().getHeaderSearchInfo(), MainFile});
143144

144145
llvm::StringRef HeaderRef{Spelling};
145-
bool Angled = HeaderRef.starts_with("<");
146+
147+
bool IsAngled = false;
146148
for (auto &Filter : AngledHeaders) {
147149
if (Filter(HeaderRef)) {
148-
Angled = true;
150+
IsAngled = true;
151+
break;
152+
}
153+
}
154+
bool IsQuoted = false;
155+
for (auto &Filter : QuotedHeaders) {
156+
if (Filter(HeaderRef)) {
157+
IsQuoted = true;
149158
break;
150159
}
151160
}
161+
if (IsAngled == IsQuoted) {
162+
IsAngled = HeaderRef.starts_with("<");
163+
} else if (!IsAngled && IsQuoted) {
164+
IsAngled = false;
165+
}
152166

153167
// We might suggest insertion of an existing include in edge cases, e.g.,
154168
// include is present in a PP-disabled region, or spelling of the header
155169
// turns out to be the same as one of the unresolved includes in the
156170
// main file.
157171
std::optional<tooling::Replacement> Replacement = HeaderIncludes.insert(
158-
HeaderRef.trim("\"<>"), Angled, tooling::IncludeDirective::Include);
172+
HeaderRef.trim("\"<>"), IsAngled, tooling::IncludeDirective::Include);
159173
if (!Replacement.has_value())
160174
continue;
161175

162-
if (Angled && Spelling.front() == '\"') {
176+
if (IsAngled && Spelling.front() == '\"') {
163177
Spelling.front() = '<';
164178
Spelling.back() = '>';
165179
}
@@ -497,14 +511,16 @@ bool isPreferredProvider(const Inclusion &Inc,
497511
std::vector<Diag> issueIncludeCleanerDiagnostics(
498512
ParsedAST &AST, llvm::StringRef Code,
499513
const IncludeCleanerFindings &Findings, const ThreadsafeFS &TFS,
500-
HeaderFilter IgnoreHeaders, HeaderFilter AngledHeaders) {
514+
HeaderFilter IgnoreHeaders, HeaderFilter AngledHeaders,
515+
HeaderFilter QuotedHeaders) {
501516
trace::Span Tracer("IncludeCleaner::issueIncludeCleanerDiagnostics");
502517
std::vector<Diag> UnusedIncludes = generateUnusedIncludeDiagnostics(
503518
AST.tuPath(), Findings.UnusedIncludes, Code, IgnoreHeaders);
504519
std::optional<Fix> RemoveAllUnused = removeAllUnusedIncludes(UnusedIncludes);
505520

506521
std::vector<Diag> MissingIncludeDiags = generateMissingIncludeDiagnostics(
507-
AST, Findings.MissingIncludes, Code, IgnoreHeaders, AngledHeaders, TFS);
522+
AST, Findings.MissingIncludes, Code, IgnoreHeaders, AngledHeaders,
523+
QuotedHeaders, TFS);
508524
std::optional<Fix> AddAllMissing = addAllMissingIncludes(MissingIncludeDiags);
509525

510526
std::optional<Fix> FixAll;

clang-tools-extra/clangd/IncludeCleaner.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ computeIncludeCleanerFindings(ParsedAST &AST,
6060
std::vector<Diag> issueIncludeCleanerDiagnostics(
6161
ParsedAST &AST, llvm::StringRef Code,
6262
const IncludeCleanerFindings &Findings, const ThreadsafeFS &TFS,
63-
HeaderFilter IgnoreHeader = {}, HeaderFilter AngledHeaders = {});
63+
HeaderFilter IgnoreHeader = {}, HeaderFilter AngledHeaders = {},
64+
HeaderFilter QuotedHeaders = {});
6465

6566
/// Converts the clangd include representation to include-cleaner
6667
/// include representation.

clang-tools-extra/clangd/ParsedAST.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,9 +381,9 @@ std::vector<Diag> getIncludeCleanerDiags(ParsedAST &AST, llvm::StringRef Code,
381381
Findings.MissingIncludes.clear();
382382
if (SuppressUnused)
383383
Findings.UnusedIncludes.clear();
384-
return issueIncludeCleanerDiagnostics(AST, Code, Findings, TFS,
385-
Cfg.Diagnostics.Includes.IgnoreHeader,
386-
Cfg.Style.AngledHeaders);
384+
return issueIncludeCleanerDiagnostics(
385+
AST, Code, Findings, TFS, Cfg.Diagnostics.Includes.IgnoreHeader,
386+
Cfg.Style.AngledHeaders, Cfg.Style.QuotedHeaders);
387387
}
388388

389389
tidy::ClangTidyCheckFactories

clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
226226
#include "dir/c.h"
227227
$insert_d[[]]$insert_foo[[]]#include "fuzz.h"
228228
#include "header.h"
229-
$insert_foobar[[]]$insert_angled[[]]#include <e.h>
229+
$insert_foobar[[]]$insert_quoted[[]]#include "quoted_wrapper.h"
230+
$insert_angled[[]]#include <e.h>
230231
$insert_f[[]]$insert_vector[[]]
231232
232233
#define DEF(X) const Foo *X;
@@ -239,6 +240,7 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
239240
void foo() {
240241
$b[[b]]();
241242
$angled[[angled]]();
243+
$quoted[[quoted]]();
242244
243245
ns::$bar[[Bar]] bar;
244246
bar.d();
@@ -269,6 +271,9 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
269271
TU.AdditionalFiles["angled.h"] = guard("void angled();");
270272
TU.ExtraArgs.push_back("-I" + testPath("."));
271273

274+
TU.AdditionalFiles["quoted_wrapper.h"] = guard("#include \"quoted.h\"");
275+
TU.AdditionalFiles["quoted.h"] = guard("void quoted();");
276+
272277
TU.AdditionalFiles["dir/c.h"] = guard("#include \"d.h\"");
273278
TU.AdditionalFiles["dir/d.h"] =
274279
guard("namespace ns { struct Bar { void d(); }; }");
@@ -308,6 +313,9 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
308313
}},
309314
/*AngledHeaders=*/{[](llvm::StringRef Header) {
310315
return Header.contains("angled.h");
316+
}},
317+
/*QuotedHeaders=*/{[](llvm::StringRef Header) {
318+
return Header.contains("quoted.h");
311319
}});
312320
EXPECT_THAT(
313321
Diags,
@@ -322,6 +330,12 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) {
322330
withFix({Fix(MainFile.range("insert_angled"),
323331
"#include <angled.h>\n", "#include <angled.h>"),
324332
FixMessage("add all missing includes")})),
333+
AllOf(
334+
Diag(MainFile.range("quoted"),
335+
"No header providing \"quoted\" is directly included"),
336+
withFix({Fix(MainFile.range("insert_quoted"),
337+
"#include \"quoted.h\"\n", "#include \"quoted.h\""),
338+
FixMessage("add all missing includes")})),
325339
AllOf(Diag(MainFile.range("bar"),
326340
"No header providing \"ns::Bar\" is directly included"),
327341
withFix({Fix(MainFile.range("insert_d"),

0 commit comments

Comments
 (0)