blob: 357a371e1e9ac6da0d20255be5ae0dad67518f9b [file] [log] [blame]
Manuel Klimekf7f295f2013-05-14 09:13:00 +00001//===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===-----------------------------------------------------------------------===//
9
10#include <vector>
11
12#include "../ASTMatchersTest.h"
13#include "clang/ASTMatchers/Dynamic/Registry.h"
14#include "gtest/gtest.h"
15
16namespace clang {
17namespace ast_matchers {
18namespace dynamic {
19namespace {
20
21using ast_matchers::internal::Matcher;
22
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000023class RegistryTest : public ::testing::Test {
24public:
25 std::vector<ParserValue> Args() { return std::vector<ParserValue>(); }
26 std::vector<ParserValue> Args(const VariantValue &Arg1) {
27 std::vector<ParserValue> Out(1);
28 Out[0].Value = Arg1;
29 return Out;
30 }
31 std::vector<ParserValue> Args(const VariantValue &Arg1,
32 const VariantValue &Arg2) {
33 std::vector<ParserValue> Out(2);
34 Out[0].Value = Arg1;
35 Out[1].Value = Arg2;
36 return Out;
37 }
Manuel Klimekf7f295f2013-05-14 09:13:00 +000038
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000039 template <class T>
40 Matcher<T> constructMatcher(StringRef MatcherName, Diagnostics *Error) {
Samuel Benzaquenef7eb022013-06-21 15:51:31 +000041 return Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error)
42 .getTypedMatcher<T>();
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000043 }
Manuel Klimekf7f295f2013-05-14 09:13:00 +000044
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000045 template <class T>
46 Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
47 Diagnostics *Error) {
Samuel Benzaquenef7eb022013-06-21 15:51:31 +000048 return Registry::constructMatcher(MatcherName, SourceRange(), Args(Arg1),
49 Error).getTypedMatcher<T>();
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000050 }
Manuel Klimekf7f295f2013-05-14 09:13:00 +000051
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000052 template <class T>
53 Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
54 const VariantValue &Arg2, Diagnostics *Error) {
Samuel Benzaquenef7eb022013-06-21 15:51:31 +000055 return Registry::constructMatcher(MatcherName, SourceRange(),
56 Args(Arg1, Arg2), Error)
57 .getTypedMatcher<T>();
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000058 }
59};
60
61TEST_F(RegistryTest, CanConstructNoArgs) {
62 Matcher<Stmt> IsArrowValue = constructMatcher<Stmt>(
63 "memberExpr", constructMatcher<MemberExpr>("isArrow", NULL), NULL);
64 Matcher<Stmt> BoolValue = constructMatcher<Stmt>("boolLiteral", NULL);
Manuel Klimekf7f295f2013-05-14 09:13:00 +000065
66 const std::string ClassSnippet = "struct Foo { int x; };\n"
67 "Foo *foo = new Foo;\n"
68 "int i = foo->x;\n";
69 const std::string BoolSnippet = "bool Foo = true;\n";
70
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000071 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
72 EXPECT_TRUE(matches(BoolSnippet, BoolValue));
73 EXPECT_FALSE(matches(ClassSnippet, BoolValue));
74 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
Manuel Klimekf7f295f2013-05-14 09:13:00 +000075}
76
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000077TEST_F(RegistryTest, ConstructWithSimpleArgs) {
78 Matcher<Decl> Value = constructMatcher<Decl>(
79 "namedDecl",
80 constructMatcher<NamedDecl>("hasName", std::string("X"), NULL), NULL);
81 EXPECT_TRUE(matches("class X {};", Value));
82 EXPECT_FALSE(matches("int x;", Value));
Samuel Benzaquen7a337af2013-06-04 15:46:22 +000083
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000084 Value =
85 functionDecl(constructMatcher<FunctionDecl>("parameterCountIs", 2, NULL));
86 EXPECT_TRUE(matches("void foo(int,int);", Value));
87 EXPECT_FALSE(matches("void foo(int);", Value));
Manuel Klimekf7f295f2013-05-14 09:13:00 +000088}
89
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000090TEST_F(RegistryTest, ConstructWithMatcherArgs) {
91 Matcher<Decl> HasInitializerSimple = constructMatcher<Decl>(
92 "varDecl", constructMatcher<VarDecl>("hasInitializer", stmt(), NULL),
93 NULL);
94 Matcher<Decl> HasInitializerComplex = constructMatcher<Decl>(
95 "varDecl", constructMatcher<VarDecl>("hasInitializer", callExpr(), NULL),
96 NULL);
Manuel Klimekf7f295f2013-05-14 09:13:00 +000097
98 std::string code = "int i;";
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000099 EXPECT_FALSE(matches(code, HasInitializerSimple));
100 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000101
102 code = "int i = 1;";
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000103 EXPECT_TRUE(matches(code, HasInitializerSimple));
104 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000105
106 code = "int y(); int i = y();";
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000107 EXPECT_TRUE(matches(code, HasInitializerSimple));
108 EXPECT_TRUE(matches(code, HasInitializerComplex));
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000109
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000110 Matcher<Decl> HasParameter = functionDecl(
111 constructMatcher<FunctionDecl>("hasParameter", 1, hasName("x"), NULL));
112 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
113 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000114}
115
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000116TEST_F(RegistryTest, PolymorphicMatchers) {
117 const MatcherList IsDefinition =
118 Registry::constructMatcher("isDefinition", SourceRange(), Args(), NULL);
119 Matcher<Decl> Var = constructMatcher<Decl>("varDecl", IsDefinition, NULL);
120 Matcher<Decl> Class =
121 constructMatcher<Decl>("recordDecl", IsDefinition, NULL);
122 Matcher<Decl> Func =
123 constructMatcher<Decl>("functionDecl", IsDefinition, NULL);
124 EXPECT_TRUE(matches("int a;", Var));
125 EXPECT_FALSE(matches("extern int a;", Var));
126 EXPECT_TRUE(matches("class A {};", Class));
127 EXPECT_FALSE(matches("class A;", Class));
128 EXPECT_TRUE(matches("void f(){};", Func));
129 EXPECT_FALSE(matches("void f();", Func));
130
131 Matcher<Decl> Anything = constructMatcher<Decl>("anything", NULL);
132 Matcher<Decl> RecordDecl =
133 constructMatcher<Decl>("recordDecl", Anything, NULL);
134
135 EXPECT_TRUE(matches("int a;", Anything));
136 EXPECT_TRUE(matches("class A {};", Anything));
137 EXPECT_TRUE(matches("void f(){};", Anything));
138 EXPECT_FALSE(matches("int a;", RecordDecl));
139 EXPECT_TRUE(matches("class A {};", RecordDecl));
140 EXPECT_FALSE(matches("void f(){};", RecordDecl));
141}
142
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000143TEST_F(RegistryTest, Errors) {
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000144 // Incorrect argument count.
145 OwningPtr<Diagnostics> Error(new Diagnostics());
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000146 EXPECT_TRUE(Registry::constructMatcher("hasInitializer", SourceRange(),
147 Args(), Error.get()).empty());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000148 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
149 Error->ToString());
150 Error.reset(new Diagnostics());
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000151 EXPECT_TRUE(Registry::constructMatcher(
152 "isArrow", SourceRange(), Args(std::string()), Error.get()).empty());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000153 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
154 Error->ToString());
155
156 // Bad argument type
157 Error.reset(new Diagnostics());
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000158 EXPECT_TRUE(Registry::constructMatcher(
159 "ofClass", SourceRange(), Args(std::string()), Error.get()).empty());
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000160 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
161 "(Actual = String)",
162 Error->ToString());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000163 Error.reset(new Diagnostics());
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000164 EXPECT_TRUE(Registry::constructMatcher(
165 "recordDecl", SourceRange(), Args(recordDecl(), parameterCountIs(3)),
166 Error.get()).empty());
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000167 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
168 "(Actual = Matcher<FunctionDecl>)",
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000169 Error->ToString());
170}
171
172} // end anonymous namespace
173} // end namespace dynamic
174} // end namespace ast_matchers
175} // end namespace clang