1 | //===--- IncludeSpellerTest.cpp--------------------------------------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
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" |
19 | #include <assert.h> |
20 | #include <string> |
21 | namespace clang::include_cleaner { |
22 | namespace { |
23 | |
24 | const char *testRoot() { |
25 | #ifdef _WIN32 |
26 | return "C:\\include-cleaner-test" ; |
27 | #else |
28 | return "/include-cleaner-test" ; |
29 | #endif |
30 | } |
31 | |
32 | std::string testPath(llvm::StringRef File) { |
33 | assert(llvm::sys::path::is_relative(File) && "FileName should be relative" ); |
34 | |
35 | llvm::SmallString<32> NativeFile = File; |
36 | llvm::sys::path::native(path&: NativeFile, style: llvm::sys::path::Style::native); |
37 | llvm::SmallString<32> Path; |
38 | llvm::sys::path::append(path&: Path, style: llvm::sys::path::Style::native, a: testRoot(), |
39 | b: NativeFile); |
40 | return std::string(Path.str()); |
41 | } |
42 | |
43 | class DummyIncludeSpeller : public IncludeSpeller { |
44 | public: |
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) |
49 | return "" ; |
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(Prefix: llvm::StringRef{RootWithSeparator})) |
55 | return "" ; |
56 | return "\"" + AbsolutePath.str() + "\"" ; |
57 | } |
58 | }; |
59 | |
60 | TEST(IncludeSpeller, IsRelativeToTestRoot) { |
61 | TestInputs Inputs; |
62 | |
63 | Inputs.ExtraArgs.push_back(x: "-isystemdir" ); |
64 | |
65 | Inputs.ExtraFiles[testPath(File: "foo.h" )] = "" ; |
66 | Inputs.ExtraFiles["dir/header.h" ] = "" ; |
67 | TestAST AST{Inputs}; |
68 | |
69 | auto &FM = AST.fileManager(); |
70 | auto &HS = AST.preprocessor().getHeaderSearchInfo(); |
71 | const auto *MainFile = AST.sourceManager().getFileEntryForID( |
72 | FID: AST.sourceManager().getMainFileID()); |
73 | |
74 | EXPECT_EQ("\"foo.h\"" , |
75 | spellHeader({Header{*FM.getOptionalFileRef(testPath("foo.h" ))}, HS, |
76 | MainFile})); |
77 | EXPECT_EQ("<header.h>" , |
78 | spellHeader({Header{*FM.getOptionalFileRef("dir/header.h" )}, HS, |
79 | MainFile})); |
80 | } |
81 | |
82 | TEST(IncludeSpeller, CanOverrideSystemHeaders) { |
83 | TestAST AST("" ); |
84 | auto &HS = AST.preprocessor().getHeaderSearchInfo(); |
85 | const auto *MainFile = AST.sourceManager().getFileEntryForID( |
86 | FID: AST.sourceManager().getMainFileID()); |
87 | EXPECT_EQ("<bits/stdc++.h>" , |
88 | spellHeader({Header{*tooling::stdlib::Header::named("<vector>" )}, |
89 | HS, MainFile})); |
90 | } |
91 | |
92 | IncludeSpellingStrategy::Add<DummyIncludeSpeller> |
93 | Speller("dummy" , "Dummy Include Speller" ); |
94 | |
95 | } // namespace |
96 | } // namespace clang::include_cleaner |
97 | |