1dd46a080SHaojian Wu //===- unittest/Tooling/HeaderAnalysisTest.cpp ----------------------------===//
2dd46a080SHaojian Wu //
3dd46a080SHaojian Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4dd46a080SHaojian Wu // See https://llvm.org/LICENSE.txt for license information.
5dd46a080SHaojian Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dd46a080SHaojian Wu //
7dd46a080SHaojian Wu //===----------------------------------------------------------------------===//
8dd46a080SHaojian Wu
9dd46a080SHaojian Wu #include "clang/Tooling/Inclusions/HeaderAnalysis.h"
10dd46a080SHaojian Wu #include "clang/Lex/Preprocessor.h"
11dd46a080SHaojian Wu #include "clang/Testing/TestAST.h"
1258c9467fSHaojian Wu #include "gmock/gmock.h"
13dd46a080SHaojian Wu #include "gtest/gtest.h"
14dd46a080SHaojian Wu
15dd46a080SHaojian Wu namespace clang {
16dd46a080SHaojian Wu namespace tooling {
17dd46a080SHaojian Wu namespace {
1899b5ec1fSSam McCall using testing::Eq;
19dd46a080SHaojian Wu
TEST(HeaderAnalysisTest,IsSelfContained)20dd46a080SHaojian Wu TEST(HeaderAnalysisTest, IsSelfContained) {
21dd46a080SHaojian Wu TestInputs Inputs;
22dd46a080SHaojian Wu Inputs.Code = R"cpp(
23dd46a080SHaojian Wu #include "headerguard.h"
24dd46a080SHaojian Wu #include "pragmaonce.h"
25dd46a080SHaojian Wu #import "imported.h"
26dd46a080SHaojian Wu
27dd46a080SHaojian Wu #include "bad.h"
28dd46a080SHaojian Wu #include "unguarded.h"
29dd46a080SHaojian Wu )cpp";
30dd46a080SHaojian Wu
31dd46a080SHaojian Wu Inputs.ExtraFiles["headerguard.h"] = R"cpp(
32dd46a080SHaojian Wu #ifndef HEADER_H
33dd46a080SHaojian Wu #define HEADER_H
34dd46a080SHaojian Wu
35dd46a080SHaojian Wu #endif HEADER_H
36dd46a080SHaojian Wu )cpp";
37dd46a080SHaojian Wu Inputs.ExtraFiles["pragmaonce.h"] = R"cpp(
38dd46a080SHaojian Wu #pragma once
39dd46a080SHaojian Wu )cpp";
40dd46a080SHaojian Wu Inputs.ExtraFiles["imported.h"] = "";
41dd46a080SHaojian Wu
42dd46a080SHaojian Wu Inputs.ExtraFiles["unguarded.h"] = "";
43dd46a080SHaojian Wu Inputs.ExtraFiles["bad.h"] = R"cpp(
44dd46a080SHaojian Wu #pragma once
45dd46a080SHaojian Wu
46dd46a080SHaojian Wu #if defined(INSIDE_H)
47dd46a080SHaojian Wu #error "Only ... can be included directly"
48dd46a080SHaojian Wu #endif
49dd46a080SHaojian Wu )cpp";
50dd46a080SHaojian Wu
51dd46a080SHaojian Wu TestAST AST(Inputs);
52dd46a080SHaojian Wu const auto &SM = AST.sourceManager();
53dd46a080SHaojian Wu auto &FM = SM.getFileManager();
54dd46a080SHaojian Wu auto &HI = AST.preprocessor().getHeaderSearchInfo();
5551f1ae52SDavid Goldman EXPECT_TRUE(
56*b0abc9ddSJan Svoboda isSelfContainedHeader(*FM.getOptionalFileRef("headerguard.h"), SM, HI));
57*b0abc9ddSJan Svoboda EXPECT_TRUE(
58*b0abc9ddSJan Svoboda isSelfContainedHeader(*FM.getOptionalFileRef("pragmaonce.h"), SM, HI));
59*b0abc9ddSJan Svoboda EXPECT_TRUE(
60*b0abc9ddSJan Svoboda isSelfContainedHeader(*FM.getOptionalFileRef("imported.h"), SM, HI));
61*b0abc9ddSJan Svoboda EXPECT_TRUE(isSelfContainedHeader(
62*b0abc9ddSJan Svoboda *SM.getFileEntryRefForID(SM.getMainFileID()), SM, HI));
63dd46a080SHaojian Wu
64*b0abc9ddSJan Svoboda EXPECT_FALSE(
65*b0abc9ddSJan Svoboda isSelfContainedHeader(*FM.getOptionalFileRef("unguarded.h"), SM, HI));
66*b0abc9ddSJan Svoboda EXPECT_FALSE(isSelfContainedHeader(*FM.getOptionalFileRef("bad.h"), SM, HI));
67dd46a080SHaojian Wu }
68dd46a080SHaojian Wu
TEST(HeaderAnalysisTest,CodeContainsImports)6951f1ae52SDavid Goldman TEST(HeaderAnalysisTest, CodeContainsImports) {
7051f1ae52SDavid Goldman EXPECT_TRUE(codeContainsImports(R"cpp(
7151f1ae52SDavid Goldman #include "foo.h"
7251f1ae52SDavid Goldman #import "NSFoo.h"
7351f1ae52SDavid Goldman
7451f1ae52SDavid Goldman int main() {
7551f1ae52SDavid Goldman foo();
7651f1ae52SDavid Goldman }
7751f1ae52SDavid Goldman )cpp"));
7851f1ae52SDavid Goldman
7951f1ae52SDavid Goldman EXPECT_TRUE(codeContainsImports(R"cpp(
8051f1ae52SDavid Goldman #include "foo.h"
8151f1ae52SDavid Goldman
8251f1ae52SDavid Goldman int main() {
8351f1ae52SDavid Goldman foo();
8451f1ae52SDavid Goldman }
8551f1ae52SDavid Goldman
8651f1ae52SDavid Goldman #import "NSFoo.h"
8751f1ae52SDavid Goldman )cpp"));
8851f1ae52SDavid Goldman
8951f1ae52SDavid Goldman EXPECT_FALSE(codeContainsImports(R"cpp(
9051f1ae52SDavid Goldman #include "foo.h"
9151f1ae52SDavid Goldman
9251f1ae52SDavid Goldman int main() {
9351f1ae52SDavid Goldman foo();
9451f1ae52SDavid Goldman }
9551f1ae52SDavid Goldman )cpp"));
9651f1ae52SDavid Goldman }
9751f1ae52SDavid Goldman
TEST(HeaderAnalysisTest,ParseIWYUPragma)9899b5ec1fSSam McCall TEST(HeaderAnalysisTest, ParseIWYUPragma) {
9958c9467fSHaojian Wu EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep"), Eq("keep"));
10099b5ec1fSSam McCall EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep me\netc"),
10158c9467fSHaojian Wu Eq("keep me"));
10258c9467fSHaojian Wu EXPECT_THAT(parseIWYUPragma("/* IWYU pragma: keep */"), Eq("keep"));
103a41fbb1fSKazu Hirata EXPECT_EQ(parseIWYUPragma("// IWYU pragma: keep"), std::nullopt)
10499b5ec1fSSam McCall << "Prefix is sensitive to whitespace";
105a41fbb1fSKazu Hirata EXPECT_EQ(parseIWYUPragma("// IWYU pragma:keep"), std::nullopt)
10699b5ec1fSSam McCall << "Prefix is sensitive to whitespace";
107a41fbb1fSKazu Hirata EXPECT_EQ(parseIWYUPragma("/\n* IWYU pragma: keep */"), std::nullopt)
10899b5ec1fSSam McCall << "Must start with /* or //";
10999b5ec1fSSam McCall }
11099b5ec1fSSam McCall
111dd46a080SHaojian Wu } // namespace
112dd46a080SHaojian Wu } // namespace tooling
113dd46a080SHaojian Wu } // namespace clang
114