1//===- unittest/ASTMatchers/Dynamic/ParserTest.cpp - Parser unit tests -===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===-------------------------------------------------------------------===//
8
9#include "../ASTMatchersTest.h"
10#include "clang/ASTMatchers/Dynamic/Parser.h"
11#include "clang/ASTMatchers/Dynamic/Registry.h"
12#include "gtest/gtest.h"
13#include <optional>
14#include <string>
15#include <vector>
16
17namespace clang {
18namespace ast_matchers {
19namespace dynamic {
20namespace {
21
22class MockSema : public Parser::Sema {
23public:
24 ~MockSema() override {}
25
26 uint64_t expectMatcher(StringRef MatcherName) {
27 // Optimizations on the matcher framework make simple matchers like
28 // 'stmt()' to be all the same matcher.
29 // Use a more complex expression to prevent that.
30 ast_matchers::internal::Matcher<Stmt> M = stmt(stmt(), stmt());
31 ExpectedMatchers.insert(x: std::make_pair(x: std::string(MatcherName), y&: M));
32 return M.getID().second;
33 }
34
35 bool isBuilderMatcher(MatcherCtor) const override { return false; }
36
37 ASTNodeKind nodeMatcherType(MatcherCtor) const override { return {}; }
38
39 internal::MatcherDescriptorPtr
40 buildMatcherCtor(MatcherCtor, SourceRange NameRange,
41 ArrayRef<ParserValue> Args,
42 Diagnostics *Error) const override {
43 return internal::MatcherDescriptorPtr{nullptr};
44 }
45
46 void parse(StringRef Code) {
47 Diagnostics Error;
48 VariantValue Value;
49 Parser::parseExpression(Code, S: this, Value: &Value, Error: &Error);
50 Values.push_back(x: Value);
51 Errors.push_back(x: Error.toStringFull());
52 }
53
54 std::optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) override {
55 const ExpectedMatchersTy::value_type *Matcher =
56 &*ExpectedMatchers.find(x: std::string(MatcherName));
57 return reinterpret_cast<MatcherCtor>(Matcher);
58 }
59
60 VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
61 SourceRange NameRange,
62 StringRef BindID,
63 ArrayRef<ParserValue> Args,
64 Diagnostics *Error) override {
65 const ExpectedMatchersTy::value_type *Matcher =
66 reinterpret_cast<const ExpectedMatchersTy::value_type *>(Ctor);
67 MatcherInfo ToStore = {.MatcherName: Matcher->first, .NameRange: NameRange, .Args: Args,
68 .BoundID: std::string(BindID)};
69 Matchers.push_back(x: ToStore);
70 return VariantMatcher::SingleMatcher(Matcher: Matcher->second);
71 }
72
73 struct MatcherInfo {
74 StringRef MatcherName;
75 SourceRange NameRange;
76 std::vector<ParserValue> Args;
77 std::string BoundID;
78 };
79
80 std::vector<std::string> Errors;
81 std::vector<VariantValue> Values;
82 std::vector<MatcherInfo> Matchers;
83 typedef std::map<std::string, ast_matchers::internal::Matcher<Stmt> >
84 ExpectedMatchersTy;
85 ExpectedMatchersTy ExpectedMatchers;
86};
87
88TEST(ParserTest, ParseBoolean) {
89 MockSema Sema;
90 Sema.parse(Code: "true");
91 Sema.parse(Code: "false");
92 EXPECT_EQ(2U, Sema.Values.size());
93 EXPECT_TRUE(Sema.Values[0].getBoolean());
94 EXPECT_FALSE(Sema.Values[1].getBoolean());
95}
96
97TEST(ParserTest, ParseDouble) {
98 MockSema Sema;
99 Sema.parse(Code: "1.0");
100 Sema.parse(Code: "2.0f");
101 Sema.parse(Code: "34.56e-78");
102 Sema.parse(Code: "4.E+6");
103 Sema.parse(Code: "1");
104 EXPECT_EQ(5U, Sema.Values.size());
105 EXPECT_EQ(1.0, Sema.Values[0].getDouble());
106 EXPECT_EQ("1:1: Error parsing numeric literal: <2.0f>", Sema.Errors[1]);
107 EXPECT_EQ(34.56e-78, Sema.Values[2].getDouble());
108 EXPECT_EQ(4e+6, Sema.Values[3].getDouble());
109 EXPECT_FALSE(Sema.Values[4].isDouble());
110}
111
112TEST(ParserTest, ParseUnsigned) {
113 MockSema Sema;
114 Sema.parse(Code: "0");
115 Sema.parse(Code: "123");
116 Sema.parse(Code: "0x1f");
117 Sema.parse(Code: "12345678901");
118 Sema.parse(Code: "1a1");
119 EXPECT_EQ(5U, Sema.Values.size());
120 EXPECT_EQ(0U, Sema.Values[0].getUnsigned());
121 EXPECT_EQ(123U, Sema.Values[1].getUnsigned());
122 EXPECT_EQ(31U, Sema.Values[2].getUnsigned());
123 EXPECT_EQ("1:1: Error parsing numeric literal: <12345678901>", Sema.Errors[3]);
124 EXPECT_EQ("1:1: Error parsing numeric literal: <1a1>", Sema.Errors[4]);
125}
126
127TEST(ParserTest, ParseString) {
128 MockSema Sema;
129 Sema.parse(Code: "\"Foo\"");
130 Sema.parse(Code: "\"\"");
131 Sema.parse(Code: "\"Baz");
132 EXPECT_EQ(3ULL, Sema.Values.size());
133 EXPECT_EQ("Foo", Sema.Values[0].getString());
134 EXPECT_EQ("", Sema.Values[1].getString());
135 EXPECT_EQ("1:1: Error parsing string token: <\"Baz>", Sema.Errors[2]);
136}
137
138bool matchesRange(SourceRange Range, unsigned StartLine,
139 unsigned EndLine, unsigned StartColumn, unsigned EndColumn) {
140 EXPECT_EQ(StartLine, Range.Start.Line);
141 EXPECT_EQ(EndLine, Range.End.Line);
142 EXPECT_EQ(StartColumn, Range.Start.Column);
143 EXPECT_EQ(EndColumn, Range.End.Column);
144 return Range.Start.Line == StartLine && Range.End.Line == EndLine &&
145 Range.Start.Column == StartColumn && Range.End.Column == EndColumn;
146}
147
148std::optional<DynTypedMatcher> getSingleMatcher(const VariantValue &Value) {
149 std::optional<DynTypedMatcher> Result = Value.getMatcher().getSingleMatcher();
150 EXPECT_TRUE(Result);
151 return Result;
152}
153
154TEST(ParserTest, ParseMatcher) {
155 MockSema Sema;
156 const uint64_t ExpectedFoo = Sema.expectMatcher(MatcherName: "Foo");
157 const uint64_t ExpectedBar = Sema.expectMatcher(MatcherName: "Bar");
158 const uint64_t ExpectedBaz = Sema.expectMatcher(MatcherName: "Baz");
159 Sema.parse(Code: " Foo ( Bar ( 17), Baz( \n \"B A,Z\") ) .bind( \"Yo!\") ");
160 for (const auto &E : Sema.Errors) {
161 EXPECT_EQ("", E);
162 }
163
164 EXPECT_NE(ExpectedFoo, ExpectedBar);
165 EXPECT_NE(ExpectedFoo, ExpectedBaz);
166 EXPECT_NE(ExpectedBar, ExpectedBaz);
167
168 EXPECT_EQ(1ULL, Sema.Values.size());
169 EXPECT_EQ(ExpectedFoo, getSingleMatcher(Sema.Values[0])->getID().second);
170
171 EXPECT_EQ(3ULL, Sema.Matchers.size());
172 const MockSema::MatcherInfo Bar = Sema.Matchers[0];
173 EXPECT_EQ("Bar", Bar.MatcherName);
174 EXPECT_TRUE(matchesRange(Bar.NameRange, 1, 1, 8, 17));
175 EXPECT_EQ(1ULL, Bar.Args.size());
176 EXPECT_EQ(17U, Bar.Args[0].Value.getUnsigned());
177
178 const MockSema::MatcherInfo Baz = Sema.Matchers[1];
179 EXPECT_EQ("Baz", Baz.MatcherName);
180 EXPECT_TRUE(matchesRange(Baz.NameRange, 1, 2, 19, 10));
181 EXPECT_EQ(1ULL, Baz.Args.size());
182 EXPECT_EQ("B A,Z", Baz.Args[0].Value.getString());
183
184 const MockSema::MatcherInfo Foo = Sema.Matchers[2];
185 EXPECT_EQ("Foo", Foo.MatcherName);
186 EXPECT_TRUE(matchesRange(Foo.NameRange, 1, 2, 2, 12));
187 EXPECT_EQ(2ULL, Foo.Args.size());
188 EXPECT_EQ(ExpectedBar, getSingleMatcher(Foo.Args[0].Value)->getID().second);
189 EXPECT_EQ(ExpectedBaz, getSingleMatcher(Foo.Args[1].Value)->getID().second);
190 EXPECT_EQ("Yo!", Foo.BoundID);
191}
192
193TEST(ParserTest, ParseComment) {
194 MockSema Sema;
195 Sema.expectMatcher(MatcherName: "Foo");
196 Sema.parse(Code: " Foo() # Bar() ");
197 for (const auto &E : Sema.Errors) {
198 EXPECT_EQ("", E);
199 }
200
201 EXPECT_EQ(1ULL, Sema.Matchers.size());
202
203 Sema.parse(Code: "Foo(#) ");
204
205 EXPECT_EQ("1:4: Error parsing matcher. Found end-of-code while looking for ')'.", Sema.Errors[1]);
206}
207
208using ast_matchers::internal::Matcher;
209
210Parser::NamedValueMap getTestNamedValues() {
211 Parser::NamedValueMap Values;
212 Values["nameX"] = llvm::StringRef("x");
213 Values["hasParamA"] = VariantMatcher::SingleMatcher(
214 Matcher: functionDecl(hasParameter(N: 0, InnerMatcher: hasName(Name: "a"))));
215 return Values;
216}
217
218TEST(ParserTest, FullParserTest) {
219 Diagnostics Error;
220
221 StringRef Code =
222 "varDecl(hasInitializer(binaryOperator(hasLHS(integerLiteral()),"
223 " hasOperatorName(\"+\"))))";
224 std::optional<DynTypedMatcher> VarDecl(
225 Parser::parseMatcherExpression(MatcherCode&: Code, Error: &Error));
226 EXPECT_EQ("", Error.toStringFull());
227 Matcher<Decl> M = VarDecl->unconditionalConvertTo<Decl>();
228 EXPECT_TRUE(matches("int x = 1 + false;", M));
229 EXPECT_FALSE(matches("int x = true + 1;", M));
230 EXPECT_FALSE(matches("int x = 1 - false;", M));
231 EXPECT_FALSE(matches("int x = true - 1;", M));
232
233 Code = "implicitCastExpr(hasCastKind(\"CK_IntegralToBoolean\"))";
234 std::optional<DynTypedMatcher> implicitIntBooleanCast(
235 Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: nullptr, Error: &Error));
236 EXPECT_EQ("", Error.toStringFull());
237 Matcher<Stmt> MCastStmt =
238 traverse(TK: TK_AsIs, InnerMatcher: implicitIntBooleanCast->unconditionalConvertTo<Stmt>());
239 EXPECT_TRUE(matches("bool X = 1;", MCastStmt));
240 EXPECT_FALSE(matches("bool X = true;", MCastStmt));
241
242 Code = "functionDecl(hasParameter(1, hasName(\"x\")))";
243 std::optional<DynTypedMatcher> HasParameter(
244 Parser::parseMatcherExpression(MatcherCode&: Code, Error: &Error));
245 EXPECT_EQ("", Error.toStringFull());
246 M = HasParameter->unconditionalConvertTo<Decl>();
247
248 EXPECT_TRUE(matches("void f(int a, int x);", M));
249 EXPECT_FALSE(matches("void f(int x, int a);", M));
250
251 // Test named values.
252 auto NamedValues = getTestNamedValues();
253
254 Code = "functionDecl(hasParamA, hasParameter(1, hasName(nameX)))";
255 std::optional<DynTypedMatcher> HasParameterWithNamedValues(
256 Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: &NamedValues, Error: &Error));
257 EXPECT_EQ("", Error.toStringFull());
258 M = HasParameterWithNamedValues->unconditionalConvertTo<Decl>();
259
260 EXPECT_TRUE(matches("void f(int a, int x);", M));
261 EXPECT_FALSE(matches("void f(int x, int a);", M));
262
263 Code = "unaryExprOrTypeTraitExpr(ofKind(\"UETT_SizeOf\"))";
264 std::optional<DynTypedMatcher> UnaryExprSizeOf(
265 Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: nullptr, Error: &Error));
266 EXPECT_EQ("", Error.toStringFull());
267 Matcher<Stmt> MStmt = UnaryExprSizeOf->unconditionalConvertTo<Stmt>();
268 EXPECT_TRUE(matches("unsigned X = sizeof(int);", MStmt));
269 EXPECT_FALSE(matches("unsigned X = alignof(int);", MStmt));
270
271 Code =
272 R"query(namedDecl(matchesName("^::[ABC]*$", "IgnoreCase | BasicRegex")))query";
273 std::optional<DynTypedMatcher> MatchesName(
274 Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: nullptr, Error: &Error));
275 EXPECT_EQ("", Error.toStringFull());
276 M = MatchesName->unconditionalConvertTo<Decl>();
277 EXPECT_TRUE(matches("unsigned AAACCBB;", M));
278 EXPECT_TRUE(matches("unsigned aaaccbb;", M));
279
280 Code = "hasInitializer(\n binaryOperator(hasLHS(\"A\")))";
281 EXPECT_TRUE(!Parser::parseMatcherExpression(Code, &Error));
282 EXPECT_EQ("1:1: Error parsing argument 1 for matcher hasInitializer.\n"
283 "2:5: Error parsing argument 1 for matcher binaryOperator.\n"
284 "2:20: Error building matcher hasLHS.\n"
285 "2:27: Incorrect type for arg 1. "
286 "(Expected = Matcher<Expr>) != (Actual = String)",
287 Error.toStringFull());
288}
289
290TEST(ParserTest, VariadicMatchTest) {
291 Diagnostics Error;
292
293 StringRef Code =
294 "stmt(objcMessageExpr(hasAnySelector(\"methodA\", \"methodB:\")))";
295 std::optional<DynTypedMatcher> OM(
296 Parser::parseMatcherExpression(MatcherCode&: Code, Error: &Error));
297 EXPECT_EQ("", Error.toStringFull());
298 auto M = OM->unconditionalConvertTo<Stmt>();
299 EXPECT_TRUE(matchesObjC("@interface I @end "
300 "void foo(I* i) { [i methodA]; }", M));
301}
302
303std::string ParseWithError(StringRef Code) {
304 Diagnostics Error;
305 VariantValue Value;
306 Parser::parseExpression(Code, Value: &Value, Error: &Error);
307 return Error.toStringFull();
308}
309
310std::string ParseMatcherWithError(StringRef Code) {
311 Diagnostics Error;
312 Parser::parseMatcherExpression(MatcherCode&: Code, Error: &Error);
313 return Error.toStringFull();
314}
315
316TEST(ParserTest, Errors) {
317 EXPECT_EQ(
318 "1:5: Error parsing matcher. Found token <123> while looking for '('.",
319 ParseWithError("Foo 123"));
320 EXPECT_EQ(
321 "1:1: Matcher not found: Foo\n"
322 "1:9: Error parsing matcher. Found token <123> while looking for ','.",
323 ParseWithError("Foo(\"A\" 123)"));
324 EXPECT_EQ(
325 "1:1: Error parsing argument 1 for matcher stmt.\n"
326 "1:6: Value not found: someValue",
327 ParseWithError("stmt(someValue)"));
328 EXPECT_EQ(
329 "1:1: Matcher not found: Foo\n"
330 "1:4: Error parsing matcher. Found end-of-code while looking for ')'.",
331 ParseWithError("Foo("));
332 EXPECT_EQ("1:1: End of code found while looking for token.",
333 ParseWithError(""));
334 EXPECT_EQ("Input value is not a matcher expression.",
335 ParseMatcherWithError("\"A\""));
336 EXPECT_EQ("1:1: Matcher not found: Foo\n"
337 "1:1: Error parsing argument 1 for matcher Foo.\n"
338 "1:5: Invalid token <(> found when looking for a value.",
339 ParseWithError("Foo(("));
340 EXPECT_EQ("1:7: Expected end of code.", ParseWithError("expr()a"));
341 EXPECT_EQ("1:11: Period not followed by valid chained call.",
342 ParseWithError("isArrow().biind"));
343 EXPECT_EQ("1:15: Malformed bind() expression.",
344 ParseWithError("isArrow().bind"));
345 EXPECT_EQ("1:16: Malformed bind() expression.",
346 ParseWithError("isArrow().bind(foo"));
347 EXPECT_EQ("1:21: Malformed bind() expression.",
348 ParseWithError("isArrow().bind(\"foo\""));
349 EXPECT_EQ("1:1: Error building matcher isArrow.\n"
350 "1:1: Matcher does not support binding.",
351 ParseWithError("isArrow().bind(\"foo\")"));
352 EXPECT_EQ("1:1: Error building matcher isArrow.\n"
353 "1:11: Matcher does not support with call.",
354 ParseWithError("isArrow().with"));
355 EXPECT_EQ(
356 "1:22: Error parsing matcher. Found token <EOF> while looking for '('.",
357 ParseWithError("mapAnyOf(ifStmt).with"));
358 EXPECT_EQ(
359 "1:22: Error parsing matcher. Found end-of-code while looking for ')'.",
360 ParseWithError("mapAnyOf(ifStmt).with("));
361 EXPECT_EQ("1:1: Failed to build matcher: mapAnyOf.",
362 ParseWithError("mapAnyOf()"));
363 EXPECT_EQ("1:1: Error parsing argument 1 for matcher mapAnyOf.\n1:1: Failed "
364 "to build matcher: mapAnyOf.",
365 ParseWithError("mapAnyOf(\"foo\")"));
366 EXPECT_EQ("Input value has unresolved overloaded type: "
367 "Matcher<DoStmt|ForStmt|WhileStmt|CXXForRangeStmt|FunctionDecl|"
368 "CoroutineBodyStmt>",
369 ParseMatcherWithError("hasBody(stmt())"));
370 EXPECT_EQ(
371 "1:1: Error parsing argument 1 for matcher decl.\n"
372 "1:6: Error building matcher hasAttr.\n"
373 "1:14: Unknown value 'attr::Fnal' for arg 1; did you mean 'attr::Final'",
374 ParseMatcherWithError(R"query(decl(hasAttr("attr::Fnal")))query"));
375 EXPECT_EQ("1:1: Error parsing argument 1 for matcher decl.\n"
376 "1:6: Error building matcher hasAttr.\n"
377 "1:14: Unknown value 'Final' for arg 1; did you mean 'attr::Final'",
378 ParseMatcherWithError(R"query(decl(hasAttr("Final")))query"));
379 EXPECT_EQ("1:1: Error parsing argument 1 for matcher decl.\n"
380 "1:6: Error building matcher hasAttr.\n"
381 "1:14: Value not found: unrelated",
382 ParseMatcherWithError(R"query(decl(hasAttr("unrelated")))query"));
383 EXPECT_EQ(
384 "1:1: Error parsing argument 1 for matcher namedDecl.\n"
385 "1:11: Error building matcher matchesName.\n"
386 "1:33: Unknown value 'Ignorecase' for arg 2; did you mean 'IgnoreCase'",
387 ParseMatcherWithError(
388 R"query(namedDecl(matchesName("[ABC]*", "Ignorecase")))query"));
389 EXPECT_EQ(
390 "1:1: Error parsing argument 1 for matcher namedDecl.\n"
391 "1:11: Error building matcher matchesName.\n"
392 "1:33: Value not found: IgnoreCase & BasicRegex",
393 ParseMatcherWithError(
394 R"query(namedDecl(matchesName("[ABC]*", "IgnoreCase & BasicRegex")))query"));
395 EXPECT_EQ(
396 "1:1: Error parsing argument 1 for matcher namedDecl.\n"
397 "1:11: Error building matcher matchesName.\n"
398 "1:33: Unknown value 'IgnoreCase | Basicregex' for arg 2; did you mean "
399 "'IgnoreCase | BasicRegex'",
400 ParseMatcherWithError(
401 R"query(namedDecl(matchesName("[ABC]*", "IgnoreCase | Basicregex")))query"));
402}
403
404TEST(ParserTest, OverloadErrors) {
405 EXPECT_EQ("1:1: Error building matcher callee.\n"
406 "1:8: Candidate 1: Incorrect type for arg 1. "
407 "(Expected = Matcher<Stmt>) != (Actual = String)\n"
408 "1:8: Candidate 2: Incorrect type for arg 1. "
409 "(Expected = Matcher<Decl>) != (Actual = String)",
410 ParseWithError("callee(\"A\")"));
411}
412
413TEST(ParserTest, ParseMultiline) {
414 StringRef Code;
415
416 std::optional<DynTypedMatcher> M;
417 {
418 Code = R"matcher(varDecl(
419 hasName("foo")
420 )
421)matcher";
422 Diagnostics Error;
423 EXPECT_TRUE(Parser::parseMatcherExpression(Code, &Error));
424 }
425
426 {
427 Code = R"matcher(varDecl(
428 # Internal comment
429 hasName("foo") # Internal comment
430# Internal comment
431 )
432)matcher";
433 Diagnostics Error;
434 EXPECT_TRUE(Parser::parseMatcherExpression(Code, &Error));
435 }
436
437 {
438 Code = R"matcher(decl().bind(
439 "paramName")
440)matcher";
441 Diagnostics Error;
442 EXPECT_TRUE(Parser::parseMatcherExpression(Code, &Error));
443 }
444
445 {
446 Code = R"matcher(decl().bind(
447 "paramName"
448 )
449)matcher";
450 Diagnostics Error;
451 EXPECT_TRUE(Parser::parseMatcherExpression(Code, &Error).has_value());
452 }
453
454 {
455 Code = R"matcher(decl(decl()
456, decl()))matcher";
457 Diagnostics Error;
458 EXPECT_TRUE(Parser::parseMatcherExpression(Code, &Error).has_value());
459 }
460
461 {
462 Code = R"matcher(decl(decl(),
463decl()))matcher";
464 Diagnostics Error;
465 EXPECT_TRUE(Parser::parseMatcherExpression(Code, &Error).has_value());
466 }
467
468 {
469 Code = "namedDecl(hasName(\"n\"\n))";
470 Diagnostics Error;
471 EXPECT_TRUE(Parser::parseMatcherExpression(Code, &Error).has_value());
472 }
473
474 {
475 Diagnostics Error;
476
477 auto NamedValues = getTestNamedValues();
478
479 Code = R"matcher(hasParamA.bind
480 ("paramName")
481)matcher";
482 M = Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: &NamedValues, Error: &Error);
483 EXPECT_FALSE(M);
484 EXPECT_EQ("1:15: Malformed bind() expression.", Error.toStringFull());
485 }
486
487 {
488 Diagnostics Error;
489
490 auto NamedValues = getTestNamedValues();
491
492 Code = R"matcher(hasParamA.
493 bind("paramName")
494)matcher";
495 M = Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: &NamedValues, Error: &Error);
496 EXPECT_FALSE(M);
497 EXPECT_EQ("1:11: Period not followed by valid chained call.",
498 Error.toStringFull());
499 }
500
501 {
502 Diagnostics Error;
503
504 Code = R"matcher(varDecl
505()
506)matcher";
507 M = Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: nullptr, Error: &Error);
508 EXPECT_FALSE(M);
509 EXPECT_EQ("1:8: Error parsing matcher. Found token "
510 "<NewLine> while looking for '('.",
511 Error.toStringFull());
512 }
513
514 // Correct line/column numbers
515 {
516 Diagnostics Error;
517
518 Code = R"matcher(varDecl(
519 doesNotExist()
520 )
521)matcher";
522 M = Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: nullptr, Error: &Error);
523 EXPECT_FALSE(M);
524 StringRef Expected = R"error(1:1: Error parsing argument 1 for matcher varDecl.
5252:3: Matcher not found: doesNotExist)error";
526 EXPECT_EQ(Expected, Error.toStringFull());
527 }
528}
529
530TEST(ParserTest, CompletionRegistry) {
531 StringRef Code = "while";
532 std::vector<MatcherCompletion> Comps = Parser::completeExpression(Code, CompletionOffset: 5);
533 ASSERT_EQ(1u, Comps.size());
534 EXPECT_EQ("Stmt(", Comps[0].TypedText);
535 EXPECT_EQ("Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)",
536 Comps[0].MatcherDecl);
537
538 Code = "whileStmt().";
539 Comps = Parser::completeExpression(Code, CompletionOffset: 12);
540 ASSERT_EQ(1u, Comps.size());
541 EXPECT_EQ("bind(\"", Comps[0].TypedText);
542 EXPECT_EQ("bind", Comps[0].MatcherDecl);
543
544 Code = "mapAny";
545 Comps = Parser::completeExpression(Code, CompletionOffset: 6);
546 ASSERT_EQ(1u, Comps.size());
547 EXPECT_EQ("Of(", Comps[0].TypedText);
548 EXPECT_EQ("Matcher<NestedNameSpecifierLoc|QualType|TypeLoc|...> "
549 "mapAnyOf(NestedNameSpecifierLoc|QualType|TypeLoc|"
550 "NestedNameSpecifier|Decl|Stmt|Type...)",
551 Comps[0].MatcherDecl);
552
553 Code = "mapAnyOf(ifStmt).";
554 Comps = Parser::completeExpression(Code, CompletionOffset: 17);
555 ASSERT_EQ(2u, Comps.size());
556 EXPECT_EQ("bind(\"", Comps[0].TypedText);
557 EXPECT_EQ("bind", Comps[0].MatcherDecl);
558 EXPECT_EQ("with(", Comps[1].TypedText);
559 EXPECT_EQ("with", Comps[1].MatcherDecl);
560
561 Code = "mapAnyOf(ifS";
562 Comps = Parser::completeExpression(Code, CompletionOffset: 12);
563 ASSERT_EQ(1u, Comps.size());
564 EXPECT_EQ("tmt", Comps[0].TypedText);
565 EXPECT_EQ("ifStmt", Comps[0].MatcherDecl);
566}
567
568TEST(ParserTest, CompletionNamedValues) {
569 // Can complete non-matcher types.
570 auto NamedValues = getTestNamedValues();
571 StringRef Code = "functionDecl(hasName(";
572 std::vector<MatcherCompletion> Comps =
573 Parser::completeExpression(Code, CompletionOffset: Code.size(), S: nullptr, NamedValues: &NamedValues);
574 ASSERT_EQ(1u, Comps.size());
575 EXPECT_EQ("nameX", Comps[0].TypedText);
576 EXPECT_EQ("String nameX", Comps[0].MatcherDecl);
577
578 // Can complete if there are names in the expression.
579 Code = "cxxMethodDecl(hasName(nameX), ";
580 Comps = Parser::completeExpression(Code, CompletionOffset: Code.size(), S: nullptr, NamedValues: &NamedValues);
581 EXPECT_LT(0u, Comps.size());
582
583 // Can complete names and registry together.
584 Code = "functionDecl(hasP";
585 Comps = Parser::completeExpression(Code, CompletionOffset: Code.size(), S: nullptr, NamedValues: &NamedValues);
586 ASSERT_EQ(3u, Comps.size());
587
588 EXPECT_EQ("arameter(", Comps[0].TypedText);
589 EXPECT_EQ(
590 "Matcher<FunctionDecl> hasParameter(unsigned, Matcher<ParmVarDecl>)",
591 Comps[0].MatcherDecl);
592
593 EXPECT_EQ("aramA", Comps[1].TypedText);
594 EXPECT_EQ("Matcher<Decl> hasParamA", Comps[1].MatcherDecl);
595
596 EXPECT_EQ("arent(", Comps[2].TypedText);
597 EXPECT_EQ(
598 "Matcher<Decl> "
599 "hasParent(Matcher<NestedNameSpecifierLoc|TypeLoc|Decl|...>)",
600 Comps[2].MatcherDecl);
601}
602
603TEST(ParserTest, ParseBindOnLet) {
604
605 auto NamedValues = getTestNamedValues();
606
607 Diagnostics Error;
608
609 {
610 StringRef Code = "hasParamA.bind(\"parmABinding\")";
611 std::optional<DynTypedMatcher> TopLevelLetBinding(
612 Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: &NamedValues, Error: &Error));
613 EXPECT_EQ("", Error.toStringFull());
614 auto M = TopLevelLetBinding->unconditionalConvertTo<Decl>();
615
616 EXPECT_TRUE(matchAndVerifyResultTrue(
617 "void foo(int a);", M,
618 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
619 EXPECT_TRUE(matchAndVerifyResultFalse(
620 "void foo(int b);", M,
621 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
622 }
623
624 {
625 StringRef Code = "functionDecl(hasParamA.bind(\"parmABinding\"))";
626 std::optional<DynTypedMatcher> NestedLetBinding(
627 Parser::parseMatcherExpression(MatcherCode&: Code, S: nullptr, NamedValues: &NamedValues, Error: &Error));
628 EXPECT_EQ("", Error.toStringFull());
629 auto M = NestedLetBinding->unconditionalConvertTo<Decl>();
630
631 EXPECT_TRUE(matchAndVerifyResultTrue(
632 "void foo(int a);", M,
633 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
634 EXPECT_TRUE(matchAndVerifyResultFalse(
635 "void foo(int b);", M,
636 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
637 }
638}
639
640} // end anonymous namespace
641} // end namespace dynamic
642} // end namespace ast_matchers
643} // end namespace clang
644

source code of clang/unittests/ASTMatchers/Dynamic/ParserTest.cpp