117 lines · cpp
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("DiagWithNoLoc");15 }16 void registerMatchers(ast_matchers::MatchFinder *Finder) override {17 Finder->addMatcher(ast_matchers::varDecl().bind("var"), this);18 }19 void check(const ast_matchers::MatchFinder::MatchResult &Result) override {20 const auto *Var = Result.Nodes.getNodeAs<VarDecl>("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(ast_matchers::varDecl().bind("var"), this);33 }34 void check(const ast_matchers::MatchFinder::MatchResult &Result) override {35 const auto *Var = Result.Nodes.getNodeAs<VarDecl>("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(ast_matchers::varDecl().bind("var"), this);46 }47 void check(const ast_matchers::MatchFinder::MatchResult &Result) override {48 const auto *Var = Result.Nodes.getNodeAs<VarDecl>("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(ValidBeginLoc, "valid->valid")57 << SourceRange(ValidBeginLoc, ValidEndLoc);58 diag(ValidBeginLoc, "valid->invalid")59 << SourceRange(ValidBeginLoc, InvalidLoc);60 diag(ValidBeginLoc, "invalid->valid")61 << SourceRange(InvalidLoc, ValidEndLoc);62 diag(ValidBeginLoc, "invalid->invalid")63 << SourceRange(InvalidLoc, InvalidLoc);64 }65};66 67} // namespace68 69TEST(ClangTidyDiagnosticConsumer, SortsErrors) {70 std::vector<ClangTidyError> Errors;71 runCheckOnCode<TestCheck>("int a;", &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>("int abc;", &Errors);81 EXPECT_EQ(1ul, Errors.size());82 EXPECT_EQ("highlight range", Errors[0].Message.Message);83 84 // int abc;85 // ____^86 // 0123487 EXPECT_EQ(4ul, Errors[0].Message.FileOffset);88 89 // int abc90 // ~~~~~~~ -> 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>("int x;", &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 test115} // namespace tidy116} // namespace clang117