summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2018-08-30 23:11:09 +0000
committerStephen Kelly <steveire@gmail.com>2018-08-30 23:11:09 +0000
commite6e8fef281d155094fae889cd0c9b7a5830f496b (patch)
tree59e8d7e78ead81d383d62b09c4bdcca4e6c1ee82
parent6cc61e5fd444350aa376e6c9d6e55bffa819d652 (diff)
Allow binding to NamedValue resulting from let expression
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
-rw-r--r--lib/ASTMatchers/Dynamic/Parser.cpp23
-rw-r--r--unittests/ASTMatchers/Dynamic/ParserTest.cpp38
2 files changed, 59 insertions, 2 deletions
diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp
index 1288b0897f..96362cd4bc 100644
--- a/lib/ASTMatchers/Dynamic/Parser.cpp
+++ b/lib/ASTMatchers/Dynamic/Parser.cpp
@@ -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.
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
index d670e3129b..fd7bbdde4a 100644
--- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -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