diff options
Diffstat (limited to 'include/clang/ASTMatchers/Dynamic')
-rw-r--r-- | include/clang/ASTMatchers/Dynamic/Diagnostics.h | 4 | ||||
-rw-r--r-- | include/clang/ASTMatchers/Dynamic/Parser.h | 130 | ||||
-rw-r--r-- | include/clang/ASTMatchers/Dynamic/Registry.h | 51 | ||||
-rw-r--r-- | include/clang/ASTMatchers/Dynamic/VariantValue.h | 184 |
4 files changed, 247 insertions, 122 deletions
diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h index 82a14f1929bec..ef93ac54508d7 100644 --- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h +++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H -#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H +#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H +#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H #include "clang/ASTMatchers/Dynamic/VariantValue.h" #include "clang/Basic/LLVM.h" diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h index 4045f57d1b364..bd006b6e1290e 100644 --- a/include/clang/ASTMatchers/Dynamic/Parser.h +++ b/include/clang/ASTMatchers/Dynamic/Parser.h @@ -31,8 +31,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H -#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H +#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H +#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H #include "clang/ASTMatchers/Dynamic/Diagnostics.h" #include "clang/ASTMatchers/Dynamic/Registry.h" @@ -63,17 +63,6 @@ public: public: virtual ~Sema(); - /// \brief Lookup a value by name. - /// - /// This can be used in the Sema layer to declare known constants or to - /// allow to split an expression in pieces. - /// - /// \param Name The name of the value to lookup. - /// - /// \return The named value. It could be any type that VariantValue - /// supports. An empty value means that the name is not recognized. - virtual VariantValue getNamedValue(StringRef Name); - /// \brief Process a matcher expression. /// /// All the arguments passed here have already been processed. @@ -105,6 +94,29 @@ public: /// found. virtual llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) = 0; + + /// \brief Compute the list of completion types for \p Context. + /// + /// Each element of \p Context represents a matcher invocation, going from + /// outermost to innermost. Elements are pairs consisting of a reference to + /// the matcher constructor and the index of the next element in the + /// argument list of that matcher (or for the last element, the index of + /// the completion point in the argument list). An empty list requests + /// completion for the root matcher. + virtual std::vector<ArgKind> getAcceptedCompletionTypes( + llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context); + + /// \brief Compute the list of completions that match any of + /// \p AcceptedTypes. + /// + /// \param AcceptedTypes All types accepted for this completion. + /// + /// \return All completions for the specified types. + /// Completions should be valid when used in \c lookupMatcherCtor(). + /// The matcher constructed from the return of \c lookupMatcherCtor() + /// should be convertible to some type in \p AcceptedTypes. + virtual std::vector<MatcherCompletion> + getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes); }; /// \brief Sema implementation that uses the matcher registry to process the @@ -121,58 +133,91 @@ public: StringRef BindID, ArrayRef<ParserValue> Args, Diagnostics *Error) override; + + std::vector<ArgKind> getAcceptedCompletionTypes( + llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) override; + + std::vector<MatcherCompletion> + getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override; }; - /// \brief Parse a matcher expression, creating matchers from the registry. - /// - /// This overload creates matchers calling directly into the registry. If the - /// caller needs more control over how the matchers are created, then it can - /// use the overload below that takes a Sema. - /// - /// \param MatcherCode The matcher expression to parse. - /// - /// \return The matcher object constructed, or an empty Optional if an error - /// occurred. - /// In that case, \c Error will contain a description of the error. - /// The caller takes ownership of the DynTypedMatcher object returned. - static llvm::Optional<DynTypedMatcher> - parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error); + typedef llvm::StringMap<VariantValue> NamedValueMap; /// \brief Parse a matcher expression. /// /// \param MatcherCode The matcher expression to parse. /// /// \param S The Sema instance that will help the parser - /// construct the matchers. + /// construct the matchers. If null, it uses the default registry. + /// + /// \param NamedValues A map of precomputed named values. This provides + /// the dictionary for the <NamedValue> rule of the grammar. + /// If null, it is ignored. + /// /// \return The matcher object constructed by the processor, or an empty /// Optional if an error occurred. In that case, \c Error will contain a /// description of the error. /// The caller takes ownership of the DynTypedMatcher object returned. static llvm::Optional<DynTypedMatcher> - parseMatcherExpression(StringRef MatcherCode, Sema *S, Diagnostics *Error); - - /// \brief Parse an expression, creating matchers from the registry. - /// - /// Parses any expression supported by this parser. In general, the - /// \c parseMatcherExpression function is a better approach to get a matcher - /// object. - static bool parseExpression(StringRef Code, VariantValue *Value, - Diagnostics *Error); + parseMatcherExpression(StringRef MatcherCode, Sema *S, + const NamedValueMap *NamedValues, + Diagnostics *Error); + static llvm::Optional<DynTypedMatcher> + parseMatcherExpression(StringRef MatcherCode, Sema *S, + Diagnostics *Error) { + return parseMatcherExpression(MatcherCode, S, nullptr, Error); + } + static llvm::Optional<DynTypedMatcher> + parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error) { + return parseMatcherExpression(MatcherCode, nullptr, Error); + } /// \brief Parse an expression. /// /// Parses any expression supported by this parser. In general, the /// \c parseMatcherExpression function is a better approach to get a matcher /// object. + /// + /// \param S The Sema instance that will help the parser + /// construct the matchers. If null, it uses the default registry. + /// + /// \param NamedValues A map of precomputed named values. This provides + /// the dictionary for the <NamedValue> rule of the grammar. + /// If null, it is ignored. static bool parseExpression(StringRef Code, Sema *S, + const NamedValueMap *NamedValues, VariantValue *Value, Diagnostics *Error); + static bool parseExpression(StringRef Code, Sema *S, + VariantValue *Value, Diagnostics *Error) { + return parseExpression(Code, S, nullptr, Value, Error); + } + static bool parseExpression(StringRef Code, VariantValue *Value, + Diagnostics *Error) { + return parseExpression(Code, nullptr, Value, Error); + } /// \brief Complete an expression at the given offset. /// + /// \param S The Sema instance that will help the parser + /// construct the matchers. If null, it uses the default registry. + /// + /// \param NamedValues A map of precomputed named values. This provides + /// the dictionary for the <NamedValue> rule of the grammar. + /// If null, it is ignored. + /// /// \return The list of completions, which may be empty if there are no /// available completions or if an error occurred. static std::vector<MatcherCompletion> - completeExpression(StringRef Code, unsigned CompletionOffset); + completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S, + const NamedValueMap *NamedValues); + static std::vector<MatcherCompletion> + completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S) { + return completeExpression(Code, CompletionOffset, S, nullptr); + } + static std::vector<MatcherCompletion> + completeExpression(StringRef Code, unsigned CompletionOffset) { + return completeExpression(Code, CompletionOffset, nullptr); + } private: class CodeTokenizer; @@ -180,6 +225,7 @@ private: struct TokenInfo; Parser(CodeTokenizer *Tokenizer, Sema *S, + const NamedValueMap *NamedValues, Diagnostics *Error); bool parseExpressionImpl(VariantValue *Value); @@ -187,12 +233,16 @@ private: VariantValue *Value); bool parseIdentifierPrefixImpl(VariantValue *Value); - void addCompletion(const TokenInfo &CompToken, StringRef TypedText, - StringRef Decl); + void addCompletion(const TokenInfo &CompToken, + const MatcherCompletion &Completion); void addExpressionCompletions(); + std::vector<MatcherCompletion> + getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes); + CodeTokenizer *const Tokenizer; Sema *const S; + const NamedValueMap *const NamedValues; Diagnostics *const Error; typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy; diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h index faa9254bc2e7a..ad24a8d1b7947 100644 --- a/include/clang/ASTMatchers/Dynamic/Registry.h +++ b/include/clang/ASTMatchers/Dynamic/Registry.h @@ -14,8 +14,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H -#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H +#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H +#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H #include "clang/ASTMatchers/Dynamic/Diagnostics.h" #include "clang/ASTMatchers/Dynamic/VariantValue.h" @@ -36,8 +36,10 @@ typedef const internal::MatcherDescriptor *MatcherCtor; struct MatcherCompletion { MatcherCompletion() {} - MatcherCompletion(StringRef TypedText, StringRef MatcherDecl) - : TypedText(TypedText), MatcherDecl(MatcherDecl) {} + MatcherCompletion(StringRef TypedText, StringRef MatcherDecl, + unsigned Specificity) + : TypedText(TypedText), MatcherDecl(MatcherDecl), + Specificity(Specificity) {} /// \brief The text to type to select this matcher. std::string TypedText; @@ -45,6 +47,13 @@ struct MatcherCompletion { /// \brief The "declaration" of the matcher, with type information. std::string MatcherDecl; + /// \brief Value corresponding to the "specificity" of the converted matcher. + /// + /// Zero specificity indicates that this conversion would produce a trivial + /// matcher that will either always or never match. + /// Such matchers are excluded from code completion results. + unsigned Specificity; + bool operator==(const MatcherCompletion &Other) const { return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl; } @@ -58,28 +67,28 @@ public: /// constructor, or Optional<MatcherCtor>() if not found. static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName); - /// \brief Compute the list of completions for \p Context. + /// \brief Compute the list of completion types for \p Context. /// /// Each element of \p Context represents a matcher invocation, going from - /// outermost to innermost. Elements are pairs consisting of a reference to the - /// matcher constructor and the index of the next element in the argument list - /// of that matcher (or for the last element, the index of the completion - /// point in the argument list). An empty list requests completion for the - /// root matcher. + /// outermost to innermost. Elements are pairs consisting of a reference to + /// the matcher constructor and the index of the next element in the + /// argument list of that matcher (or for the last element, the index of + /// the completion point in the argument list). An empty list requests + /// completion for the root matcher. + static std::vector<ArgKind> getAcceptedCompletionTypes( + llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context); + + /// \brief Compute the list of completions that match any of + /// \p AcceptedTypes. /// - /// The completions are ordered first by decreasing relevance, then - /// alphabetically. Relevance is determined by how closely the matcher's - /// type matches that of the context. For example, if the innermost matcher - /// takes a FunctionDecl matcher, the FunctionDecl matchers are returned - /// first, followed by the ValueDecl matchers, then NamedDecl, then Decl, then - /// polymorphic matchers. + /// \param AcceptedTypes All types accepted for this completion. /// - /// Matchers which are technically convertible to the innermost context but - /// which would match either all or no nodes are excluded. For example, - /// namedDecl and varDecl are excluded in a FunctionDecl context, because - /// those matchers would match respectively all or no nodes in such a context. + /// \return All completions for the specified types. + /// Completions should be valid when used in \c lookupMatcherCtor(). + /// The matcher constructed from the return of \c lookupMatcherCtor() + /// should be convertible to some type in \p AcceptedTypes. static std::vector<MatcherCompletion> - getCompletions(ArrayRef<std::pair<MatcherCtor, unsigned> > Context); + getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes); /// \brief Construct a matcher from the registry. /// diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h index b25267b1c54b0..a9bd3d50115ad 100644 --- a/include/clang/ASTMatchers/Dynamic/VariantValue.h +++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h @@ -14,8 +14,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H -#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H +#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H +#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" @@ -29,6 +29,51 @@ namespace clang { namespace ast_matchers { namespace dynamic { +/// \brief Kind identifier. +/// +/// It supports all types that VariantValue can contain. +class ArgKind { + public: + enum Kind { + AK_Matcher, + AK_Unsigned, + AK_String + }; + /// \brief Constructor for non-matcher types. + ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); } + + /// \brief Constructor for matcher types. + ArgKind(ast_type_traits::ASTNodeKind MatcherKind) + : K(AK_Matcher), MatcherKind(MatcherKind) {} + + Kind getArgKind() const { return K; } + ast_type_traits::ASTNodeKind getMatcherKind() const { + assert(K == AK_Matcher); + return MatcherKind; + } + + /// \brief Determines if this type can be converted to \p To. + /// + /// \param To the requested destination type. + /// + /// \param Specificity value corresponding to the "specificity" of the + /// convertion. + bool isConvertibleTo(ArgKind To, unsigned *Specificity) const; + + bool operator<(const ArgKind &Other) const { + if (K == AK_Matcher && Other.K == AK_Matcher) + return MatcherKind < Other.MatcherKind; + return K < Other.K; + } + + /// \brief String representation of the type. + std::string asString() const; + +private: + Kind K; + ast_type_traits::ASTNodeKind MatcherKind; +}; + using ast_matchers::internal::DynTypedMatcher; /// \brief A variant matcher object. @@ -48,13 +93,28 @@ class VariantMatcher { /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher. class MatcherOps { public: - virtual ~MatcherOps(); - virtual bool canConstructFrom(const DynTypedMatcher &Matcher, - bool &IsExactMatch) const = 0; - virtual void constructFrom(const DynTypedMatcher &Matcher) = 0; - virtual void constructVariadicOperator( - ast_matchers::internal::VariadicOperatorFunction Func, - ArrayRef<VariantMatcher> InnerMatchers) = 0; + MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {} + + bool canConstructFrom(const DynTypedMatcher &Matcher, + bool &IsExactMatch) const; + + /// \brief Convert \p Matcher the destination type and return it as a new + /// DynTypedMatcher. + virtual DynTypedMatcher + convertMatcher(const DynTypedMatcher &Matcher) const = 0; + + /// \brief Constructs a variadic typed matcher from \p InnerMatchers. + /// Will try to convert each inner matcher to the destination type and + /// return llvm::None if it fails to do so. + llvm::Optional<DynTypedMatcher> + constructVariadicOperator(DynTypedMatcher::VariadicOperator Op, + ArrayRef<VariantMatcher> InnerMatchers) const; + + protected: + ~MatcherOps() {} + + private: + ast_type_traits::ASTNodeKind NodeKind; }; /// \brief Payload interface to be specialized by each matcher type. @@ -65,7 +125,10 @@ class VariantMatcher { virtual ~Payload(); virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0; virtual std::string getTypeAsString() const = 0; - virtual void makeTypedMatcher(MatcherOps &Ops) const = 0; + virtual llvm::Optional<DynTypedMatcher> + getTypedMatcher(const MatcherOps &Ops) const = 0; + virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, + unsigned *Specificity) const = 0; }; public: @@ -84,9 +147,9 @@ public: /// \brief Creates a 'variadic' operator matcher. /// /// It will bind to the appropriate type on getTypedMatcher<T>(). - static VariantMatcher VariadicOperatorMatcher( - ast_matchers::internal::VariadicOperatorFunction Func, - std::vector<VariantMatcher> Args); + static VariantMatcher + VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, + std::vector<VariantMatcher> Args); /// \brief Makes the matcher the "null" matcher. void reset(); @@ -111,9 +174,21 @@ public: /// that can, the result would be ambiguous and false is returned. template <class T> bool hasTypedMatcher() const { - TypedMatcherOps<T> Ops; - if (Value) Value->makeTypedMatcher(Ops); - return Ops.hasMatcher(); + if (!Value) return false; + return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue(); + } + + /// \brief Determines if the contained matcher can be converted to \p Kind. + /// + /// \param Kind the requested destination type. + /// + /// \param Specificity value corresponding to the "specificity" of the + /// convertion. + bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, + unsigned *Specificity) const { + if (Value) + return Value->isConvertibleTo(Kind, Specificity); + return false; } /// \brief Return this matcher as a \c Matcher<T>. @@ -122,10 +197,9 @@ public: /// Asserts that \c hasTypedMatcher<T>() is true. template <class T> ast_matchers::internal::Matcher<T> getTypedMatcher() const { - TypedMatcherOps<T> Ops; - Value->makeTypedMatcher(Ops); - assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false"); - return Ops.matcher(); + assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false"); + return Value->getTypedMatcher(TypedMatcherOps<T>()) + ->template convertTo<T>(); } /// \brief String representation of the type of the value. @@ -137,51 +211,25 @@ public: private: explicit VariantMatcher(Payload *Value) : Value(Value) {} + template <typename T> struct TypedMatcherOps; + class SinglePayload; class PolymorphicPayload; class VariadicOpPayload; - template <typename T> - class TypedMatcherOps : public MatcherOps { - public: - typedef ast_matchers::internal::Matcher<T> MatcherT; - - virtual bool canConstructFrom(const DynTypedMatcher &Matcher, - bool &IsExactMatch) const { - IsExactMatch = Matcher.getSupportedKind().isSame( - ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); - return Matcher.canConvertTo<T>(); - } - - virtual void constructFrom(const DynTypedMatcher& Matcher) { - Out.reset(new MatcherT(Matcher.convertTo<T>())); - } - - virtual void constructVariadicOperator( - ast_matchers::internal::VariadicOperatorFunction Func, - ArrayRef<VariantMatcher> InnerMatchers) { - std::vector<DynTypedMatcher> DynMatchers; - for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { - // Abort if any of the inner matchers can't be converted to - // Matcher<T>. - if (!InnerMatchers[i].hasTypedMatcher<T>()) { - return; - } - DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>()); - } - Out.reset(new MatcherT( - new ast_matchers::internal::VariadicOperatorMatcherInterface<T>( - Func, DynMatchers))); - } - - bool hasMatcher() const { return Out.get() != nullptr; } - const MatcherT &matcher() const { return *Out; } + IntrusiveRefCntPtr<const Payload> Value; +}; - private: - std::unique_ptr<MatcherT> Out; - }; +template <typename T> +struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps { + TypedMatcherOps() + : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {} + typedef ast_matchers::internal::Matcher<T> MatcherT; - IntrusiveRefCntPtr<const Payload> Value; + DynTypedMatcher + convertMatcher(const DynTypedMatcher &Matcher) const override { + return DynTypedMatcher(Matcher.convertTo<T>()); + } }; /// \brief Variant value class. @@ -228,6 +276,24 @@ public: const VariantMatcher &getMatcher() const; void setMatcher(const VariantMatcher &Matcher); + /// \brief Determines if the contained value can be converted to \p Kind. + /// + /// \param Kind the requested destination type. + /// + /// \param Specificity value corresponding to the "specificity" of the + /// convertion. + bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const; + + /// \brief Determines if the contained value can be converted to any kind + /// in \p Kinds. + /// + /// \param Kinds the requested destination types. + /// + /// \param Specificity value corresponding to the "specificity" of the + /// convertion. It is the maximum specificity of all the possible + /// conversions. + bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const; + /// \brief String representation of the type of the value. std::string getTypeAsString() const; |