1//===- unittest/ASTMatchers/Dynamic/ParserTest.cpp - Parser 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 "../ASTMatchersTest.h" 11#include "clang/ASTMatchers/Dynamic/Parser.h" 12#include "clang/ASTMatchers/Dynamic/Registry.h" 13#include "llvm/ADT/Optional.h" 14#include "llvm/ADT/StringMap.h" 15#include "gtest/gtest.h" 16#include <string> 17#include <vector> 18 19namespace clang { 20namespace ast_matchers { 21namespace dynamic { 22namespace { 23 24class MockSema : public Parser::Sema { 25public: 26 ~MockSema() override {} 27 28 uint64_t expectMatcher(StringRef MatcherName) { 29 // Optimizations on the matcher framework make simple matchers like 30 // 'stmt()' to be all the same matcher. 31 // Use a more complex expression to prevent that. 32 ast_matchers::internal::Matcher<Stmt> M = stmt(stmt(), stmt()); 33 ExpectedMatchers.insert(std::make_pair(MatcherName, M)); 34 return M.getID().second; 35 } 36 37 void parse(StringRef Code) { 38 Diagnostics Error; 39 VariantValue Value; 40 Parser::parseExpression(Code, this, &Value, &Error); 41 Values.push_back(Value); 42 Errors.push_back(Error.toStringFull()); 43 } 44 45 llvm::Optional<MatcherCtor> 46 lookupMatcherCtor(StringRef MatcherName) override { 47 const ExpectedMatchersTy::value_type *Matcher = 48 &*ExpectedMatchers.find(MatcherName); 49 return reinterpret_cast<MatcherCtor>(Matcher); 50 } 51 52 VariantMatcher actOnMatcherExpression(MatcherCtor Ctor, 53 SourceRange NameRange, 54 StringRef BindID, 55 ArrayRef<ParserValue> Args, 56 Diagnostics *Error) override { 57 const ExpectedMatchersTy::value_type *Matcher = 58 reinterpret_cast<const ExpectedMatchersTy::value_type *>(Ctor); 59 MatcherInfo ToStore = { Matcher->first, NameRange, Args, BindID }; 60 Matchers.push_back(ToStore); 61 return VariantMatcher::SingleMatcher(Matcher->second); 62 } 63 64 struct MatcherInfo { 65 StringRef MatcherName; 66 SourceRange NameRange; 67 std::vector<ParserValue> Args; 68 std::string BoundID; 69 }; 70 71 std::vector<std::string> Errors; 72 std::vector<VariantValue> Values; 73 std::vector<MatcherInfo> Matchers; 74 typedef std::map<std::string, ast_matchers::internal::Matcher<Stmt> > 75 ExpectedMatchersTy; 76 ExpectedMatchersTy ExpectedMatchers; 77}; 78 79TEST(ParserTest, ParseUnsigned) { 80 MockSema Sema; 81 Sema.parse("0"); 82 Sema.parse("123"); 83 Sema.parse("0x1f"); 84 Sema.parse("12345678901"); 85 Sema.parse("1a1"); 86 EXPECT_EQ(5U, Sema.Values.size()); 87 EXPECT_EQ(0U, Sema.Values[0].getUnsigned()); 88 EXPECT_EQ(123U, Sema.Values[1].getUnsigned()); 89 EXPECT_EQ(31U, Sema.Values[2].getUnsigned()); 90 EXPECT_EQ("1:1: Error parsing unsigned token: <12345678901>", Sema.Errors[3]); 91 EXPECT_EQ("1:1: Error parsing unsigned token: <1a1>", Sema.Errors[4]); 92} 93 94TEST(ParserTest, ParseString) { 95 MockSema Sema; 96 Sema.parse("\"Foo\""); 97 Sema.parse("\"\""); 98 Sema.parse("\"Baz"); 99 EXPECT_EQ(3ULL, Sema.Values.size()); 100 EXPECT_EQ("Foo", Sema.Values[0].getString()); 101 EXPECT_EQ("", Sema.Values[1].getString()); 102 EXPECT_EQ("1:1: Error parsing string token: <\"Baz>", Sema.Errors[2]); 103} 104 105bool matchesRange(SourceRange Range, unsigned StartLine, 106 unsigned EndLine, unsigned StartColumn, unsigned EndColumn) { 107 EXPECT_EQ(StartLine, Range.Start.Line); 108 EXPECT_EQ(EndLine, Range.End.Line); 109 EXPECT_EQ(StartColumn, Range.Start.Column); 110 EXPECT_EQ(EndColumn, Range.End.Column); 111 return Range.Start.Line == StartLine && Range.End.Line == EndLine && 112 Range.Start.Column == StartColumn && Range.End.Column == EndColumn; 113} 114 115llvm::Optional<DynTypedMatcher> getSingleMatcher(const VariantValue &Value) { 116 llvm::Optional<DynTypedMatcher> Result = 117 Value.getMatcher().getSingleMatcher(); 118 EXPECT_TRUE(Result.hasValue()); 119 return Result; 120} 121 122TEST(ParserTest, ParseMatcher) { 123 MockSema Sema; 124 const uint64_t ExpectedFoo = Sema.expectMatcher("Foo"); 125 const uint64_t ExpectedBar = Sema.expectMatcher("Bar"); 126 const uint64_t ExpectedBaz = Sema.expectMatcher("Baz"); 127 Sema.parse(" Foo ( Bar ( 17), Baz( \n \"B A,Z\") ) .bind( \"Yo!\") "); 128 for (size_t i = 0, e = Sema.Errors.size(); i != e; ++i) { 129 EXPECT_EQ("", Sema.Errors[i]); 130 } 131 132 EXPECT_NE(ExpectedFoo, ExpectedBar); 133 EXPECT_NE(ExpectedFoo, ExpectedBaz); 134 EXPECT_NE(ExpectedBar, ExpectedBaz); 135 136 EXPECT_EQ(1ULL, Sema.Values.size()); 137 EXPECT_EQ(ExpectedFoo, getSingleMatcher(Sema.Values[0])->getID().second); 138 139 EXPECT_EQ(3ULL, Sema.Matchers.size()); 140 const MockSema::MatcherInfo Bar = Sema.Matchers[0]; 141 EXPECT_EQ("Bar", Bar.MatcherName); 142 EXPECT_TRUE(matchesRange(Bar.NameRange, 1, 1, 8, 17)); 143 EXPECT_EQ(1ULL, Bar.Args.size()); 144 EXPECT_EQ(17U, Bar.Args[0].Value.getUnsigned()); 145 146 const MockSema::MatcherInfo Baz = Sema.Matchers[1]; 147 EXPECT_EQ("Baz", Baz.MatcherName); 148 EXPECT_TRUE(matchesRange(Baz.NameRange, 1, 2, 19, 10)); 149 EXPECT_EQ(1ULL, Baz.Args.size()); 150 EXPECT_EQ("B A,Z", Baz.Args[0].Value.getString()); 151 152 const MockSema::MatcherInfo Foo = Sema.Matchers[2]; 153 EXPECT_EQ("Foo", Foo.MatcherName); 154 EXPECT_TRUE(matchesRange(Foo.NameRange, 1, 2, 2, 12)); 155 EXPECT_EQ(2ULL, Foo.Args.size()); 156 EXPECT_EQ(ExpectedBar, getSingleMatcher(Foo.Args[0].Value)->getID().second); 157 EXPECT_EQ(ExpectedBaz, getSingleMatcher(Foo.Args[1].Value)->getID().second); 158 EXPECT_EQ("Yo!", Foo.BoundID); 159} 160 161using ast_matchers::internal::Matcher; 162 163Parser::NamedValueMap getTestNamedValues() { 164 Parser::NamedValueMap Values; 165 Values["nameX"] = llvm::StringRef("x"); 166 Values["hasParamA"] = 167 VariantMatcher::SingleMatcher(hasParameter(0, hasName("a"))); 168 return Values; 169} 170 171TEST(ParserTest, FullParserTest) { 172 Diagnostics Error; 173 llvm::Optional<DynTypedMatcher> VarDecl(Parser::parseMatcherExpression( 174 "varDecl(hasInitializer(binaryOperator(hasLHS(integerLiteral())," 175 " hasOperatorName(\"+\"))))", 176 &Error)); 177 EXPECT_EQ("", Error.toStringFull()); 178 Matcher<Decl> M = VarDecl->unconditionalConvertTo<Decl>(); 179 EXPECT_TRUE(matches("int x = 1 + false;", M)); 180 EXPECT_FALSE(matches("int x = true + 1;", M)); 181 EXPECT_FALSE(matches("int x = 1 - false;", M)); 182 EXPECT_FALSE(matches("int x = true - 1;", M)); 183 184 llvm::Optional<DynTypedMatcher> HasParameter(Parser::parseMatcherExpression( 185 "functionDecl(hasParameter(1, hasName(\"x\")))", &Error)); 186 EXPECT_EQ("", Error.toStringFull()); 187 M = HasParameter->unconditionalConvertTo<Decl>(); 188 189 EXPECT_TRUE(matches("void f(int a, int x);", M)); 190 EXPECT_FALSE(matches("void f(int x, int a);", M)); 191 192 // Test named values. 193 auto NamedValues = getTestNamedValues(); 194 llvm::Optional<DynTypedMatcher> HasParameterWithNamedValues( 195 Parser::parseMatcherExpression( 196 "functionDecl(hasParamA, hasParameter(1, hasName(nameX)))", 197 nullptr, &NamedValues, &Error)); 198 EXPECT_EQ("", Error.toStringFull()); 199 M = HasParameterWithNamedValues->unconditionalConvertTo<Decl>(); 200 201 EXPECT_TRUE(matches("void f(int a, int x);", M)); 202 EXPECT_FALSE(matches("void f(int x, int a);", M)); 203 204 205 EXPECT_TRUE(!Parser::parseMatcherExpression( 206 "hasInitializer(\n binaryOperator(hasLHS(\"A\")))", 207 &Error).hasValue()); 208 EXPECT_EQ("1:1: Error parsing argument 1 for matcher hasInitializer.\n" 209 "2:5: Error parsing argument 1 for matcher binaryOperator.\n" 210 "2:20: Error building matcher hasLHS.\n" 211 "2:27: Incorrect type for arg 1. " 212 "(Expected = Matcher<Expr>) != (Actual = String)", 213 Error.toStringFull()); 214} 215 216std::string ParseWithError(StringRef Code) { 217 Diagnostics Error; 218 VariantValue Value; 219 Parser::parseExpression(Code, &Value, &Error); 220 return Error.toStringFull(); 221} 222 223std::string ParseMatcherWithError(StringRef Code) { 224 Diagnostics Error; 225 Parser::parseMatcherExpression(Code, &Error); 226 return Error.toStringFull(); 227} 228 229TEST(ParserTest, Errors) { 230 EXPECT_EQ( 231 "1:5: Error parsing matcher. Found token <123> while looking for '('.", 232 ParseWithError("Foo 123")); 233 EXPECT_EQ( 234 "1:1: Matcher not found: Foo\n" 235 "1:9: Error parsing matcher. Found token <123> while looking for ','.", 236 ParseWithError("Foo(\"A\" 123)")); 237 EXPECT_EQ( 238 "1:1: Error parsing argument 1 for matcher stmt.\n" 239 "1:6: Value not found: someValue", 240 ParseWithError("stmt(someValue)")); 241 EXPECT_EQ( 242 "1:1: Matcher not found: Foo\n" 243 "1:4: Error parsing matcher. Found end-of-code while looking for ')'.", 244 ParseWithError("Foo(")); 245 EXPECT_EQ("1:1: End of code found while looking for token.", 246 ParseWithError("")); 247 EXPECT_EQ("Input value is not a matcher expression.", 248 ParseMatcherWithError("\"A\"")); 249 EXPECT_EQ("1:1: Matcher not found: Foo\n" 250 "1:1: Error parsing argument 1 for matcher Foo.\n" 251 "1:5: Invalid token <(> found when looking for a value.", 252 ParseWithError("Foo((")); 253 EXPECT_EQ("1:7: Expected end of code.", ParseWithError("expr()a")); 254 EXPECT_EQ("1:11: Malformed bind() expression.", 255 ParseWithError("isArrow().biind")); 256 EXPECT_EQ("1:15: Malformed bind() expression.", 257 ParseWithError("isArrow().bind")); 258 EXPECT_EQ("1:16: Malformed bind() expression.", 259 ParseWithError("isArrow().bind(foo")); 260 EXPECT_EQ("1:21: Malformed bind() expression.", 261 ParseWithError("isArrow().bind(\"foo\"")); 262 EXPECT_EQ("1:1: Error building matcher isArrow.\n" 263 "1:1: Matcher does not support binding.", 264 ParseWithError("isArrow().bind(\"foo\")")); 265 EXPECT_EQ("Input value has unresolved overloaded type: " 266 "Matcher<DoStmt|ForStmt|WhileStmt|CXXForRangeStmt>", 267 ParseMatcherWithError("hasBody(stmt())")); 268} 269 270TEST(ParserTest, OverloadErrors) { 271 EXPECT_EQ("1:1: Error building matcher callee.\n" 272 "1:8: Candidate 1: Incorrect type for arg 1. " 273 "(Expected = Matcher<Stmt>) != (Actual = String)\n" 274 "1:8: Candidate 2: Incorrect type for arg 1. " 275 "(Expected = Matcher<Decl>) != (Actual = String)", 276 ParseWithError("callee(\"A\")")); 277} 278 279TEST(ParserTest, CompletionRegistry) { 280 std::vector<MatcherCompletion> Comps = 281 Parser::completeExpression("while", 5); 282 ASSERT_EQ(1u, Comps.size()); 283 EXPECT_EQ("Stmt(", Comps[0].TypedText); 284 EXPECT_EQ("Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)", 285 Comps[0].MatcherDecl); 286 287 Comps = Parser::completeExpression("whileStmt().", 12); 288 ASSERT_EQ(1u, Comps.size()); 289 EXPECT_EQ("bind(\"", Comps[0].TypedText); 290 EXPECT_EQ("bind", Comps[0].MatcherDecl); 291} 292 293TEST(ParserTest, CompletionNamedValues) { 294 // Can complete non-matcher types. 295 auto NamedValues = getTestNamedValues(); 296 StringRef Code = "functionDecl(hasName("; 297 std::vector<MatcherCompletion> Comps = 298 Parser::completeExpression(Code, Code.size(), nullptr, &NamedValues); 299 ASSERT_EQ(1u, Comps.size()); 300 EXPECT_EQ("nameX", Comps[0].TypedText); 301 EXPECT_EQ("String nameX", Comps[0].MatcherDecl); 302 303 // Can complete if there are names in the expression. 304 Code = "cxxMethodDecl(hasName(nameX), "; 305 Comps = Parser::completeExpression(Code, Code.size(), nullptr, &NamedValues); 306 EXPECT_LT(0u, Comps.size()); 307 308 // Can complete names and registry together. 309 Code = "cxxMethodDecl(hasP"; 310 Comps = Parser::completeExpression(Code, Code.size(), nullptr, &NamedValues); 311 ASSERT_EQ(3u, Comps.size()); 312 EXPECT_EQ("aramA", Comps[0].TypedText); 313 EXPECT_EQ("Matcher<FunctionDecl> hasParamA", Comps[0].MatcherDecl); 314 315 EXPECT_EQ("arameter(", Comps[1].TypedText); 316 EXPECT_EQ( 317 "Matcher<FunctionDecl> hasParameter(unsigned, Matcher<ParmVarDecl>)", 318 Comps[1].MatcherDecl); 319 320 EXPECT_EQ("arent(", Comps[2].TypedText); 321 EXPECT_EQ( 322 "Matcher<Decl> " 323 "hasParent(Matcher<TemplateArgument|NestedNameSpecifierLoc|Decl|...>)", 324 Comps[2].MatcherDecl); 325} 326 327} // end anonymous namespace 328} // end namespace dynamic 329} // end namespace ast_matchers 330} // end namespace clang 331