1#include "ClangTidy.h"
2#include "ClangTidyTest.h"
3#include "gtest/gtest.h"
4
5namespace clang {
6namespace tidy {
7namespace test {
8
9namespace {
10class TestCheck : public ClangTidyCheck {
11public:
12 TestCheck(StringRef Name, ClangTidyContext *Context)
13 : ClangTidyCheck(Name, Context) {
14 diag(Description: "DiagWithNoLoc");
15 }
16 void registerMatchers(ast_matchers::MatchFinder *Finder) override {
17 Finder->addMatcher(NodeMatch: ast_matchers::varDecl().bind(ID: "var"), Action: this);
18 }
19 void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
20 const auto *Var = Result.Nodes.getNodeAs<VarDecl>(ID: "var");
21 // Add diagnostics in the wrong order.
22 diag(Var->getLocation(), "variable");
23 diag(Var->getTypeSpecStartLoc(), "type specifier");
24 }
25};
26
27class HighlightTestCheck : public ClangTidyCheck {
28public:
29 HighlightTestCheck(StringRef Name, ClangTidyContext *Context)
30 : ClangTidyCheck(Name, Context) {}
31 void registerMatchers(ast_matchers::MatchFinder *Finder) override {
32 Finder->addMatcher(NodeMatch: ast_matchers::varDecl().bind(ID: "var"), Action: this);
33 }
34 void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
35 const auto *Var = Result.Nodes.getNodeAs<VarDecl>(ID: "var");
36 diag(Var->getLocation(), "highlight range") << Var->getSourceRange();
37 }
38};
39
40class InvalidRangeTestCheck : public ClangTidyCheck {
41public:
42 InvalidRangeTestCheck(StringRef Name, ClangTidyContext *Context)
43 : ClangTidyCheck(Name, Context) {}
44 void registerMatchers(ast_matchers::MatchFinder *Finder) override {
45 Finder->addMatcher(NodeMatch: ast_matchers::varDecl().bind(ID: "var"), Action: this);
46 }
47 void check(const ast_matchers::MatchFinder::MatchResult &Result) override {
48 const auto *Var = Result.Nodes.getNodeAs<VarDecl>(ID: "var");
49 SourceLocation ValidBeginLoc = Var->getBeginLoc();
50 SourceLocation ValidEndLoc = Var->getEndLoc();
51 SourceLocation InvalidLoc;
52 ASSERT_TRUE(ValidBeginLoc.isValid());
53 ASSERT_TRUE(ValidEndLoc.isValid());
54 ASSERT_TRUE(InvalidLoc.isInvalid());
55
56 diag(Loc: ValidBeginLoc, Description: "valid->valid")
57 << SourceRange(ValidBeginLoc, ValidEndLoc);
58 diag(Loc: ValidBeginLoc, Description: "valid->invalid")
59 << SourceRange(ValidBeginLoc, InvalidLoc);
60 diag(Loc: ValidBeginLoc, Description: "invalid->valid")
61 << SourceRange(InvalidLoc, ValidEndLoc);
62 diag(Loc: ValidBeginLoc, Description: "invalid->invalid")
63 << SourceRange(InvalidLoc, InvalidLoc);
64 }
65};
66
67} // namespace
68
69TEST(ClangTidyDiagnosticConsumer, SortsErrors) {
70 std::vector<ClangTidyError> Errors;
71 runCheckOnCode<TestCheck>(Code: "int a;", Errors: &Errors);
72 EXPECT_EQ(3ul, Errors.size());
73 EXPECT_EQ("DiagWithNoLoc", Errors[0].Message.Message);
74 EXPECT_EQ("type specifier", Errors[1].Message.Message);
75 EXPECT_EQ("variable", Errors[2].Message.Message);
76}
77
78TEST(ClangTidyDiagnosticConsumer, HandlesSourceRangeHighlight) {
79 std::vector<ClangTidyError> Errors;
80 runCheckOnCode<HighlightTestCheck>(Code: "int abc;", Errors: &Errors);
81 EXPECT_EQ(1ul, Errors.size());
82 EXPECT_EQ("highlight range", Errors[0].Message.Message);
83
84 // int abc;
85 // ____^
86 // 01234
87 EXPECT_EQ(4ul, Errors[0].Message.FileOffset);
88
89 // int abc
90 // ~~~~~~~ -> Length 7. (0-length highlights are nonsensical.)
91 EXPECT_EQ(1ul, Errors[0].Message.Ranges.size());
92 EXPECT_EQ(0ul, Errors[0].Message.Ranges[0].FileOffset);
93 EXPECT_EQ(7ul, Errors[0].Message.Ranges[0].Length);
94}
95
96TEST(ClangTidyDiagnosticConsumer, InvalidSourceLocationRangesIgnored) {
97 std::vector<ClangTidyError> Errors;
98 runCheckOnCode<InvalidRangeTestCheck>(Code: "int x;", Errors: &Errors);
99 EXPECT_EQ(4ul, Errors.size());
100
101 EXPECT_EQ("invalid->invalid", Errors[0].Message.Message);
102 EXPECT_TRUE(Errors[0].Message.Ranges.empty());
103
104 EXPECT_EQ("invalid->valid", Errors[1].Message.Message);
105 EXPECT_TRUE(Errors[1].Message.Ranges.empty());
106
107 EXPECT_EQ("valid->invalid", Errors[2].Message.Message);
108 EXPECT_TRUE(Errors[2].Message.Ranges.empty());
109
110 EXPECT_EQ("valid->valid", Errors[3].Message.Message);
111 EXPECT_EQ(1ul, Errors[3].Message.Ranges.size());
112}
113
114} // namespace test
115} // namespace tidy
116} // namespace clang
117

source code of clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp