blob: b7e29ed0cbb218a220a0fcb65b6d48571ed5606d [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 Benzaquen3f84bb32013-07-15 19:25:06 +000039 MatcherList constructMatcher(StringRef MatcherName,
40 Diagnostics *Error = NULL) {
41 Diagnostics DummyError;
42 if (!Error) Error = &DummyError;
43 const MatcherList Out =
44 Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error);
45 EXPECT_EQ("", DummyError.ToStringFull());
46 return Out;
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000047 }
Manuel Klimekf7f295f2013-05-14 09:13:00 +000048
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +000049 MatcherList constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
50 Diagnostics *Error = NULL) {
51 Diagnostics DummyError;
52 if (!Error) Error = &DummyError;
53 const MatcherList Out = Registry::constructMatcher(
54 MatcherName, SourceRange(), Args(Arg1), Error);
55 EXPECT_EQ("", DummyError.ToStringFull());
56 return Out;
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000057 }
Manuel Klimekf7f295f2013-05-14 09:13:00 +000058
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +000059 MatcherList constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
60 const VariantValue &Arg2,
61 Diagnostics *Error = NULL) {
62 Diagnostics DummyError;
63 if (!Error) Error = &DummyError;
64 const MatcherList Out = Registry::constructMatcher(
65 MatcherName, SourceRange(), Args(Arg1, Arg2), Error);
66 EXPECT_EQ("", DummyError.ToStringFull());
67 return Out;
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000068 }
69};
70
71TEST_F(RegistryTest, CanConstructNoArgs) {
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +000072 Matcher<Stmt> IsArrowValue = constructMatcher(
73 "memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
74 Matcher<Stmt> BoolValue =
75 constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
Manuel Klimekf7f295f2013-05-14 09:13:00 +000076
77 const std::string ClassSnippet = "struct Foo { int x; };\n"
78 "Foo *foo = new Foo;\n"
79 "int i = foo->x;\n";
80 const std::string BoolSnippet = "bool Foo = true;\n";
81
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000082 EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
83 EXPECT_TRUE(matches(BoolSnippet, BoolValue));
84 EXPECT_FALSE(matches(ClassSnippet, BoolValue));
85 EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
Manuel Klimekf7f295f2013-05-14 09:13:00 +000086}
87
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000088TEST_F(RegistryTest, ConstructWithSimpleArgs) {
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +000089 Matcher<Decl> Value = constructMatcher(
90 "namedDecl", constructMatcher("hasName", std::string("X")))
91 .getTypedMatcher<Decl>();
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000092 EXPECT_TRUE(matches("class X {};", Value));
93 EXPECT_FALSE(matches("int x;", Value));
Samuel Benzaquen7a337af2013-06-04 15:46:22 +000094
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +000095 Value = functionDecl(constructMatcher("parameterCountIs", 2)
96 .getTypedMatcher<FunctionDecl>());
Samuel Benzaquen76c2f922013-06-20 14:28:32 +000097 EXPECT_TRUE(matches("void foo(int,int);", Value));
98 EXPECT_FALSE(matches("void foo(int);", Value));
Manuel Klimekf7f295f2013-05-14 09:13:00 +000099}
100
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000101TEST_F(RegistryTest, ConstructWithMatcherArgs) {
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000102 Matcher<Decl> HasInitializerSimple =
103 constructMatcher("varDecl", constructMatcher("hasInitializer", stmt()))
104 .getTypedMatcher<Decl>();
105 Matcher<Decl> HasInitializerComplex = constructMatcher(
106 "varDecl", constructMatcher("hasInitializer", callExpr()))
107 .getTypedMatcher<Decl>();
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000108
109 std::string code = "int i;";
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000110 EXPECT_FALSE(matches(code, HasInitializerSimple));
111 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000112
113 code = "int i = 1;";
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000114 EXPECT_TRUE(matches(code, HasInitializerSimple));
115 EXPECT_FALSE(matches(code, HasInitializerComplex));
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000116
117 code = "int y(); int i = y();";
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000118 EXPECT_TRUE(matches(code, HasInitializerSimple));
119 EXPECT_TRUE(matches(code, HasInitializerComplex));
Samuel Benzaquen7a337af2013-06-04 15:46:22 +0000120
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000121 Matcher<Decl> HasParameter = functionDecl(constructMatcher(
122 "hasParameter", 1, hasName("x")).getTypedMatcher<FunctionDecl>());
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000123 EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
124 EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000125}
126
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000127TEST_F(RegistryTest, PolymorphicMatchers) {
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000128 const MatcherList IsDefinition = constructMatcher("isDefinition");
129 Matcher<Decl> Var =
130 constructMatcher("varDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000131 Matcher<Decl> Class =
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000132 constructMatcher("recordDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000133 Matcher<Decl> Func =
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000134 constructMatcher("functionDecl", IsDefinition).getTypedMatcher<Decl>();
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000135 EXPECT_TRUE(matches("int a;", Var));
136 EXPECT_FALSE(matches("extern int a;", Var));
137 EXPECT_TRUE(matches("class A {};", Class));
138 EXPECT_FALSE(matches("class A;", Class));
139 EXPECT_TRUE(matches("void f(){};", Func));
140 EXPECT_FALSE(matches("void f();", Func));
141
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000142 Matcher<Decl> Anything = constructMatcher("anything").getTypedMatcher<Decl>();
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000143 Matcher<Decl> RecordDecl =
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000144 constructMatcher("recordDecl", Anything).getTypedMatcher<Decl>();
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000145
146 EXPECT_TRUE(matches("int a;", Anything));
147 EXPECT_TRUE(matches("class A {};", Anything));
148 EXPECT_TRUE(matches("void f(){};", Anything));
NAKAMURA Takumie0548192013-06-24 13:19:26 +0000149 // FIXME: A couple of tests have been suppressed.
150 // I know it'd be bad with _MSC_VER here, though.
151#if !defined(_MSC_VER)
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000152 EXPECT_FALSE(matches("int a;", RecordDecl));
NAKAMURA Takumie0548192013-06-24 13:19:26 +0000153#endif
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000154 EXPECT_TRUE(matches("class A {};", RecordDecl));
NAKAMURA Takumie0548192013-06-24 13:19:26 +0000155#if !defined(_MSC_VER)
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000156 EXPECT_FALSE(matches("void f(){};", RecordDecl));
NAKAMURA Takumie0548192013-06-24 13:19:26 +0000157#endif
Samuel Benzaquenef7eb022013-06-21 15:51:31 +0000158}
159
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000160TEST_F(RegistryTest, TypeTraversal) {
161 Matcher<Type> M = constructMatcher(
162 "pointerType",
163 constructMatcher("pointee", constructMatcher("isConstQualified"),
164 constructMatcher("isInteger"))).getTypedMatcher<Type>();
165 EXPECT_FALSE(matches("int *a;", M));
166 EXPECT_TRUE(matches("int const *b;", M));
167
168 M = constructMatcher(
169 "arrayType",
170 constructMatcher("hasElementType", constructMatcher("builtinType")))
171 .getTypedMatcher<Type>();
172 EXPECT_FALSE(matches("struct A{}; A a[7];;", M));
173 EXPECT_TRUE(matches("int b[7];", M));
174}
175
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000176TEST_F(RegistryTest, Errors) {
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000177 // Incorrect argument count.
178 OwningPtr<Diagnostics> Error(new Diagnostics());
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000179 EXPECT_TRUE(constructMatcher("hasInitializer", Error.get()).empty());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000180 EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
181 Error->ToString());
182 Error.reset(new Diagnostics());
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000183 EXPECT_TRUE(constructMatcher("isArrow", std::string(), Error.get()).empty());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000184 EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
185 Error->ToString());
186
187 // Bad argument type
188 Error.reset(new Diagnostics());
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000189 EXPECT_TRUE(constructMatcher("ofClass", std::string(), Error.get()).empty());
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000190 EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
191 "(Actual = String)",
192 Error->ToString());
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000193 Error.reset(new Diagnostics());
Samuel Benzaquen3f84bb32013-07-15 19:25:06 +0000194 EXPECT_TRUE(constructMatcher("recordDecl", recordDecl(), parameterCountIs(3),
195 Error.get()).empty());
Samuel Benzaquen76c2f922013-06-20 14:28:32 +0000196 EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
197 "(Actual = Matcher<FunctionDecl>)",
Manuel Klimekf7f295f2013-05-14 09:13:00 +0000198 Error->ToString());
199}
200
201} // end anonymous namespace
202} // end namespace dynamic
203} // end namespace ast_matchers
204} // end namespace clang