#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
#include "clang/ASTMatchers/Dynamic/Diagnostics.h"
+#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
///
/// All the arguments passed here have already been processed.
///
- /// \param MatcherName The matcher name found by the parser.
+ /// \param Ctor A matcher constructor looked up by lookupMatcherCtor.
///
/// \param NameRange The location of the name in the matcher source.
/// Useful for error reporting.
/// \return The matcher objects constructed by the processor, or a null
/// matcher if an error occurred. In that case, \c Error will contain a
/// description of the error.
- virtual VariantMatcher actOnMatcherExpression(StringRef MatcherName,
+ virtual VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
const SourceRange &NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) = 0;
+
+ /// \brief Look up a matcher by name.
+ ///
+ /// \param MatcherName The matcher name found by the parser.
+ ///
+ /// \param NameRange The location of the name in the matcher source.
+ /// Useful for error reporting.
+ ///
+ /// \return The matcher constructor, or Optional<MatcherCtor>() if an error
+ /// occurred. In that case, \c Error will contain a description of the
+ /// error.
+ virtual llvm::Optional<MatcherCtor>
+ lookupMatcherCtor(StringRef MatcherName, const SourceRange &NameRange,
+ Diagnostics *Error) = 0;
};
/// \brief Parse a matcher expression, creating matchers from the registry.
#include "clang/ASTMatchers/Dynamic/VariantValue.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
namespace ast_matchers {
namespace dynamic {
+namespace internal {
+class MatcherCreateCallback;
+}
+
+typedef const internal::MatcherCreateCallback *MatcherCtor;
+
class Registry {
public:
- /// \brief Construct a matcher from the registry by name.
+ /// \brief Look up a matcher in the registry by name,
///
- /// Consult the registry of known matchers and construct the appropriate
- /// matcher by name.
+ /// \return An opaque value which may be used to refer to the matcher
+ /// constructor, or Optional<MatcherCtor>() if not found. In that case
+ /// \c Error will contain the description of the error.
+ static llvm::Optional<MatcherCtor>
+ lookupMatcherCtor(StringRef MatcherName, const SourceRange &NameRange,
+ Diagnostics *Error);
+
+ /// \brief Construct a matcher from the registry.
///
- /// \param MatcherName The name of the matcher to instantiate.
+ /// \param Ctor The matcher constructor to instantiate.
///
/// \param NameRange The location of the name in the matcher source.
/// Useful for error reporting.
/// will return an error.
///
/// \return The matcher object constructed if no error was found.
- /// A null matcher if the matcher is not found, or if the number of
- /// arguments or argument types do not match the signature.
- /// In that case \c Error will contain the description of the error.
- static VariantMatcher constructMatcher(StringRef MatcherName,
+ /// A null matcher if the number of arguments or argument types do not match
+ /// the signature. In that case \c Error will contain the description of
+ /// the error.
+ static VariantMatcher constructMatcher(MatcherCtor Ctor,
const SourceRange &NameRange,
ArrayRef<ParserValue> Args,
Diagnostics *Error);
/// matcher to the specified \c BindID.
/// If the matcher is not bindable, it sets an error in \c Error and returns
/// a null matcher.
- static VariantMatcher constructBoundMatcher(StringRef MatcherName,
+ static VariantMatcher constructBoundMatcher(MatcherCtor Ctor,
const SourceRange &NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
#include "clang/ASTMatchers/Dynamic/Parser.h"
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "clang/Basic/CharInfo.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/Twine.h"
namespace clang {
return false;
}
+ llvm::Optional<MatcherCtor> Ctor =
+ S->lookupMatcherCtor(NameToken.Text, NameToken.Range, Error);
+
std::vector<ParserValue> Args;
TokenInfo EndToken;
while (Tokenizer->nextTokenKind() != TokenInfo::TK_Eof) {
BindID = IDToken.Value.getString();
}
+ if (!Ctor)
+ return false;
+
// Merge the start and end infos.
Diagnostics::Context Ctx(Diagnostics::Context::ConstructMatcher, Error,
NameToken.Text, NameToken.Range);
SourceRange MatcherRange = NameToken.Range;
MatcherRange.End = EndToken.Range.End;
VariantMatcher Result = S->actOnMatcherExpression(
- NameToken.Text, MatcherRange, BindID, Args, Error);
+ *Ctor, MatcherRange, BindID, Args, Error);
if (Result.isNull()) return false;
*Value = Result;
class RegistrySema : public Parser::Sema {
public:
virtual ~RegistrySema() {}
- VariantMatcher actOnMatcherExpression(StringRef MatcherName,
+ llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
+ const SourceRange &NameRange,
+ Diagnostics *Error) {
+ return Registry::lookupMatcherCtor(MatcherName, NameRange, Error);
+ }
+ VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
const SourceRange &NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
if (BindID.empty()) {
- return Registry::constructMatcher(MatcherName, NameRange, Args, Error);
+ return Registry::constructMatcher(Ctor, NameRange, Args, Error);
} else {
- return Registry::constructBoundMatcher(MatcherName, NameRange, BindID,
- Args, Error);
+ return Registry::constructBoundMatcher(Ctor, NameRange, BindID, Args,
+ Error);
}
}
};
} // anonymous namespace
// static
-VariantMatcher Registry::constructMatcher(StringRef MatcherName,
- const SourceRange &NameRange,
- ArrayRef<ParserValue> Args,
- Diagnostics *Error) {
+llvm::Optional<MatcherCtor>
+Registry::lookupMatcherCtor(StringRef MatcherName, const SourceRange &NameRange,
+ Diagnostics *Error) {
ConstructorMap::const_iterator it =
RegistryData->constructors().find(MatcherName);
if (it == RegistryData->constructors().end()) {
Error->addError(NameRange, Error->ET_RegistryNotFound) << MatcherName;
- return VariantMatcher();
+ return llvm::Optional<MatcherCtor>();
}
- return it->second->run(NameRange, Args, Error);
+ return it->second;
+}
+
+// static
+VariantMatcher Registry::constructMatcher(MatcherCtor Ctor,
+ const SourceRange &NameRange,
+ ArrayRef<ParserValue> Args,
+ Diagnostics *Error) {
+ return Ctor->run(NameRange, Args, Error);
}
// static
-VariantMatcher Registry::constructBoundMatcher(StringRef MatcherName,
+VariantMatcher Registry::constructBoundMatcher(MatcherCtor Ctor,
const SourceRange &NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
- VariantMatcher Out = constructMatcher(MatcherName, NameRange, Args, Error);
+ VariantMatcher Out = constructMatcher(Ctor, NameRange, Args, Error);
if (Out.isNull()) return Out;
llvm::Optional<DynTypedMatcher> Result = Out.getSingleMatcher();
#include "clang/ASTMatchers/Dynamic/Parser.h"
#include "clang/ASTMatchers/Dynamic/Registry.h"
#include "gtest/gtest.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
namespace clang {
Errors.push_back(Error.toStringFull());
}
- VariantMatcher actOnMatcherExpression(StringRef MatcherName,
+ llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
+ const SourceRange &NameRange,
+ Diagnostics *Error) {
+ const ExpectedMatchersTy::value_type *Matcher =
+ &*ExpectedMatchers.find(MatcherName);
+ return reinterpret_cast<MatcherCtor>(Matcher);
+ }
+
+ VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
const SourceRange &NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) {
- MatcherInfo ToStore = { MatcherName, NameRange, Args, BindID };
+ const ExpectedMatchersTy::value_type *Matcher =
+ reinterpret_cast<const ExpectedMatchersTy::value_type *>(Ctor);
+ MatcherInfo ToStore = { Matcher->first, NameRange, Args, BindID };
Matchers.push_back(ToStore);
- return VariantMatcher::SingleMatcher(
- ExpectedMatchers.find(MatcherName)->second);
+ return VariantMatcher::SingleMatcher(Matcher->second);
}
struct MatcherInfo {
std::vector<std::string> Errors;
std::vector<VariantValue> Values;
std::vector<MatcherInfo> Matchers;
- std::map<std::string, ast_matchers::internal::Matcher<Stmt> >
- ExpectedMatchers;
+ typedef std::map<std::string, ast_matchers::internal::Matcher<Stmt> >
+ ExpectedMatchersTy;
+ ExpectedMatchersTy ExpectedMatchers;
};
TEST(ParserTest, ParseUnsigned) {
"1:5: Error parsing matcher. Found token <123> while looking for '('.",
ParseWithError("Foo 123"));
EXPECT_EQ(
+ "1:1: Matcher not found: Foo\n"
"1:9: Error parsing matcher. Found token <123> while looking for ','.",
ParseWithError("Foo(\"A\" 123)"));
EXPECT_EQ(
+ "1:1: Matcher not found: Foo\n"
"1:4: Error parsing matcher. Found end-of-code while looking for ')'.",
ParseWithError("Foo("));
EXPECT_EQ("1:1: End of code found while looking for token.",
ParseWithError(""));
EXPECT_EQ("Input value is not a matcher expression.",
ParseMatcherWithError("\"A\""));
- EXPECT_EQ("1:1: Error parsing argument 1 for matcher Foo.\n"
+ EXPECT_EQ("1:1: Matcher not found: Foo\n"
+ "1:1: Error parsing argument 1 for matcher Foo.\n"
"1:5: Invalid token <(> found when looking for a value.",
ParseWithError("Foo(("));
EXPECT_EQ("1:7: Expected end of code.", ParseWithError("expr()a"));
return Out;
}
+ llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName,
+ Diagnostics *Error = 0) {
+ Diagnostics DummyError;
+ if (!Error) Error = &DummyError;
+ llvm::Optional<MatcherCtor> Ctor =
+ Registry::lookupMatcherCtor(MatcherName, SourceRange(), Error);
+ EXPECT_EQ("", DummyError.toStringFull());
+ return Ctor;
+ }
+
VariantMatcher constructMatcher(StringRef MatcherName,
Diagnostics *Error = NULL) {
Diagnostics DummyError;
if (!Error) Error = &DummyError;
- const VariantMatcher Out =
- Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error);
+ llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
+ VariantMatcher Out;
+ if (Ctor)
+ Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(), Error);
EXPECT_EQ("", DummyError.toStringFull());
return Out;
}
Diagnostics *Error = NULL) {
Diagnostics DummyError;
if (!Error) Error = &DummyError;
- const VariantMatcher Out = Registry::constructMatcher(
- MatcherName, SourceRange(), Args(Arg1), Error);
+ llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
+ VariantMatcher Out;
+ if (Ctor)
+ Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
EXPECT_EQ("", DummyError.toStringFull());
return Out;
}
Diagnostics *Error = NULL) {
Diagnostics DummyError;
if (!Error) Error = &DummyError;
- const VariantMatcher Out = Registry::constructMatcher(
- MatcherName, SourceRange(), Args(Arg1, Arg2), Error);
+ llvm::Optional<MatcherCtor> Ctor = lookupMatcherCtor(MatcherName, Error);
+ VariantMatcher Out;
+ if (Ctor)
+ Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1, Arg2),
+ Error);
EXPECT_EQ("", DummyError.toStringFull());
return Out;
}