]> granicus.if.org Git - clang/commitdiff
Allow binding to NamedValue resulting from let expression
authorStephen Kelly <steveire@gmail.com>
Thu, 30 Aug 2018 23:11:09 +0000 (23:11 +0000)
committerStephen Kelly <steveire@gmail.com>
Thu, 30 Aug 2018 23:11:09 +0000 (23:11 +0000)
Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D51259

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341142 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ASTMatchers/Dynamic/Parser.cpp
unittests/ASTMatchers/Dynamic/ParserTest.cpp

index 1288b0897fee10cafa608d18332b16ae6cc3a179..96362cd4bc61519f30412392a902b57c3b6ba0a5 100644 (file)
@@ -339,8 +339,27 @@ bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) {
     if (const VariantValue NamedValue =
             NamedValues ? NamedValues->lookup(NameToken.Text)
                         : VariantValue()) {
-      *Value = NamedValue;
-      return true;
+
+      if (Tokenizer->nextTokenKind() != TokenInfo::TK_Period) {
+        *Value = NamedValue;
+        return true;
+      }
+
+      std::string BindID;
+      if (!parseBindID(BindID))
+        return false;
+
+      assert(NamedValue.isMatcher());
+      llvm::Optional<DynTypedMatcher> Result =
+          NamedValue.getMatcher().getSingleMatcher();
+      if (Result.hasValue()) {
+        llvm::Optional<DynTypedMatcher> Bound = Result->tryBind(BindID);
+        if (Bound.hasValue()) {
+          *Value = VariantMatcher::SingleMatcher(*Bound);
+          return true;
+        }
+      }
+      return false;
     }
     // If the syntax is correct and the name is not a matcher either, report
     // unknown named value.
index d670e3129b80edb6966000bc21f12e2bce9a9152..fd7bbdde4a117895848b32e30e3901ddba571a30 100644 (file)
@@ -359,6 +359,44 @@ TEST(ParserTest, CompletionNamedValues) {
       Comps[2].MatcherDecl);
 }
 
+TEST(ParserTest, ParseBindOnLet) {
+
+  auto NamedValues = getTestNamedValues();
+
+  Diagnostics Error;
+
+  {
+    llvm::Optional<DynTypedMatcher> TopLevelLetBinding(
+        Parser::parseMatcherExpression("hasParamA.bind(\"parmABinding\")",
+                                       nullptr, &NamedValues, &Error));
+    EXPECT_EQ("", Error.toStringFull());
+    auto M = TopLevelLetBinding->unconditionalConvertTo<Decl>();
+
+    EXPECT_TRUE(matchAndVerifyResultTrue(
+        "void foo(int a);", M,
+        llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+    EXPECT_TRUE(matchAndVerifyResultFalse(
+        "void foo(int b);", M,
+        llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+  }
+
+  {
+    llvm::Optional<DynTypedMatcher> NestedLetBinding(
+        Parser::parseMatcherExpression(
+            "functionDecl(hasParamA.bind(\"parmABinding\"))", nullptr,
+            &NamedValues, &Error));
+    EXPECT_EQ("", Error.toStringFull());
+    auto M = NestedLetBinding->unconditionalConvertTo<Decl>();
+
+    EXPECT_TRUE(matchAndVerifyResultTrue(
+        "void foo(int a);", M,
+        llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+    EXPECT_TRUE(matchAndVerifyResultFalse(
+        "void foo(int b);", M,
+        llvm::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("parmABinding")));
+  }
+}
+
 }  // end anonymous namespace
 }  // end namespace dynamic
 }  // end namespace ast_matchers