brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.2 KiB · 88e1410 Raw
644 lines · cpp
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-exception6//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 like28    // '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(std::make_pair(std::string(MatcherName), 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::MatcherDescriptorPtr40  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, this, &Value, &Error);50    Values.push_back(Value);51    Errors.push_back(Error.toStringFull());52  }53 54  std::optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) override {55    const ExpectedMatchersTy::value_type *Matcher =56        &*ExpectedMatchers.find(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 = {Matcher->first, NameRange, Args,68                           std::string(BindID)};69    Matchers.push_back(ToStore);70    return VariantMatcher::SingleMatcher(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("true");91  Sema.parse("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("1.0");100  Sema.parse("2.0f");101  Sema.parse("34.56e-78");102  Sema.parse("4.E+6");103  Sema.parse("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("0");115  Sema.parse("123");116  Sema.parse("0x1f");117  Sema.parse("12345678901");118  Sema.parse("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("\"Foo\"");130  Sema.parse("\"\"");131  Sema.parse("\"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("Foo");157  const uint64_t ExpectedBar = Sema.expectMatcher("Bar");158  const uint64_t ExpectedBaz = Sema.expectMatcher("Baz");159  Sema.parse(" 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("Foo");196  Sema.parse(" 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("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      functionDecl(hasParameter(0, hasName("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(Code, &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(Code, nullptr, nullptr, &Error));236  EXPECT_EQ("", Error.toStringFull());237  Matcher<Stmt> MCastStmt =238      traverse(TK_AsIs, 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(Code, &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(Code, nullptr, &NamedValues, &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(Code, nullptr, nullptr, &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(Code, nullptr, nullptr, &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(Code, &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, &Error);307  return Error.toStringFull();308}309 310std::string ParseMatcherWithError(StringRef Code) {311  Diagnostics Error;312  Parser::parseMatcherExpression(Code, &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 comment429  hasName("foo") # Internal comment430# Internal comment431  )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.bind480  ("paramName")481)matcher";482    M = Parser::parseMatcherExpression(Code, nullptr, &NamedValues, &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(Code, nullptr, &NamedValues, &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(varDecl505()506)matcher";507    M = Parser::parseMatcherExpression(Code, nullptr, nullptr, &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 numbers515  {516    Diagnostics Error;517 518    Code = R"matcher(varDecl(519  doesNotExist()520  )521)matcher";522    M = Parser::parseMatcherExpression(Code, nullptr, nullptr, &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, 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, 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, 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, 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, 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, Code.size(), nullptr, &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, Code.size(), nullptr, &NamedValues);581  EXPECT_LT(0u, Comps.size());582 583  // Can complete names and registry together.584  Code = "functionDecl(hasP";585  Comps = Parser::completeExpression(Code, Code.size(), nullptr, &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(Code, nullptr, &NamedValues, &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(Code, nullptr, &NamedValues, &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 namespace641}  // end namespace dynamic642}  // end namespace ast_matchers643}  // end namespace clang644