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>
21namespace clang::include_cleaner {
22namespace {
23
24const char *testRoot() {
25#ifdef _WIN32
26 return "C:\\include-cleaner-test";
27#else
28 return "/include-cleaner-test";
29#endif
30}
31
32std::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
43class DummyIncludeSpeller : public IncludeSpeller {
44public:
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
60TEST(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
82TEST(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
92IncludeSpellingStrategy::Add<DummyIncludeSpeller>
93 Speller("dummy", "Dummy Include Speller");
94
95} // namespace
96} // namespace clang::include_cleaner
97

source code of clang-tools-extra/include-cleaner/unittests/IncludeSpellerTest.cpp