1 //===--- IncludeSpellerTest.cpp--------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "clang-include-cleaner/IncludeSpeller.h"
10 #include "clang-include-cleaner/Analysis.h"
11 #include "clang-include-cleaner/Types.h"
12 #include "clang/Lex/Preprocessor.h"
13 #include "clang/Testing/TestAST.h"
14 #include "clang/Tooling/Inclusions/StandardLibrary.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Path.h"
18 #include "gtest/gtest.h"
21 namespace clang::include_cleaner
{
24 const char *testRoot() {
26 return "C:\\include-cleaner-test";
28 return "/include-cleaner-test";
32 std::string
testPath(llvm::StringRef File
) {
33 assert(llvm::sys::path::is_relative(File
) && "FileName should be relative");
35 llvm::SmallString
<32> NativeFile
= File
;
36 llvm::sys::path::native(NativeFile
, llvm::sys::path::Style::native
);
37 llvm::SmallString
<32> Path
;
38 llvm::sys::path::append(Path
, llvm::sys::path::Style::native
, testRoot(),
40 return std::string(Path
.str());
43 class DummyIncludeSpeller
: public IncludeSpeller
{
45 std::string
operator()(const IncludeSpeller::Input
&Input
) const override
{
46 if (Input
.H
.kind() == Header::Standard
)
47 return "<bits/stdc++.h>";
48 if (Input
.H
.kind() != Header::Physical
)
50 llvm::StringRef AbsolutePath
=
51 Input
.H
.physical().getFileEntry().tryGetRealPathName();
52 std::string RootWithSeparator
{testRoot()};
53 RootWithSeparator
+= llvm::sys::path::get_separator();
54 if (!AbsolutePath
.consume_front(llvm::StringRef
{RootWithSeparator
}))
56 return "\"" + AbsolutePath
.str() + "\"";
60 TEST(IncludeSpeller
, IsRelativeToTestRoot
) {
63 Inputs
.ExtraArgs
.push_back("-isystemdir");
65 Inputs
.ExtraFiles
[testPath("foo.h")] = "";
66 Inputs
.ExtraFiles
["dir/header.h"] = "";
69 auto &FM
= AST
.fileManager();
70 auto &HS
= AST
.preprocessor().getHeaderSearchInfo();
71 const auto *MainFile
= AST
.sourceManager().getFileEntryForID(
72 AST
.sourceManager().getMainFileID());
74 EXPECT_EQ("\"foo.h\"",
75 spellHeader({Header
{*FM
.getOptionalFileRef(testPath("foo.h"))}, HS
,
77 EXPECT_EQ("<header.h>",
78 spellHeader({Header
{*FM
.getOptionalFileRef("dir/header.h")}, HS
,
82 TEST(IncludeSpeller
, CanOverrideSystemHeaders
) {
84 auto &HS
= AST
.preprocessor().getHeaderSearchInfo();
85 const auto *MainFile
= AST
.sourceManager().getFileEntryForID(
86 AST
.sourceManager().getMainFileID());
87 EXPECT_EQ("<bits/stdc++.h>",
88 spellHeader({Header
{*tooling::stdlib::Header::named("<vector>")},
92 IncludeSpellingStrategy::Add
<DummyIncludeSpeller
>
93 Speller("dummy", "Dummy Include Speller");
96 } // namespace clang::include_cleaner