MatchConsumer.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- MatchConsumer.h - MatchConsumer abstraction ------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file This file defines the *MatchConsumer* abstraction: a computation over
  15. /// match results, specifically the `ast_matchers::MatchFinder::MatchResult`
  16. /// class.
  17. ///
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_CLANG_TOOLING_TRANSFORMER_MATCHCONSUMER_H
  20. #define LLVM_CLANG_TOOLING_TRANSFORMER_MATCHCONSUMER_H
  21. #include "clang/AST/ASTTypeTraits.h"
  22. #include "clang/ASTMatchers/ASTMatchFinder.h"
  23. #include "llvm/ADT/StringRef.h"
  24. #include "llvm/Support/Errc.h"
  25. #include "llvm/Support/Error.h"
  26. namespace clang {
  27. namespace transformer {
  28. /// A failable computation over nodes bound by AST matchers.
  29. ///
  30. /// The computation should report any errors though its return value (rather
  31. /// than terminating the program) to enable usage in interactive scenarios like
  32. /// clang-query.
  33. ///
  34. /// This is a central abstraction of the Transformer framework.
  35. template <typename T>
  36. using MatchConsumer =
  37. std::function<Expected<T>(const ast_matchers::MatchFinder::MatchResult &)>;
  38. /// Creates an error that signals that a `MatchConsumer` expected a certain node
  39. /// to be bound by AST matchers, but it was not actually bound.
  40. inline llvm::Error notBoundError(llvm::StringRef Id) {
  41. return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument,
  42. "Id not bound: " + Id);
  43. }
  44. /// Chooses between the two consumers, based on whether \p ID is bound in the
  45. /// match.
  46. template <typename T>
  47. MatchConsumer<T> ifBound(std::string ID, MatchConsumer<T> TrueC,
  48. MatchConsumer<T> FalseC) {
  49. return [=](const ast_matchers::MatchFinder::MatchResult &Result) {
  50. auto &Map = Result.Nodes.getMap();
  51. return (Map.find(ID) != Map.end() ? TrueC : FalseC)(Result);
  52. };
  53. }
  54. /// A failable computation over nodes bound by AST matchers, with (limited)
  55. /// reflection via the `toString` method.
  56. ///
  57. /// The computation should report any errors though its return value (rather
  58. /// than terminating the program) to enable usage in interactive scenarios like
  59. /// clang-query.
  60. ///
  61. /// This is a central abstraction of the Transformer framework. It is a
  62. /// generalization of `MatchConsumer` and intended to replace it.
  63. template <typename T> class MatchComputation {
  64. public:
  65. virtual ~MatchComputation() = default;
  66. /// Evaluates the computation and (potentially) updates the accumulator \c
  67. /// Result. \c Result is undefined in the case of an error. `Result` is an
  68. /// out parameter to optimize case where the computation involves composing
  69. /// the result of sub-computation evaluations.
  70. virtual llvm::Error eval(const ast_matchers::MatchFinder::MatchResult &Match,
  71. T *Result) const = 0;
  72. /// Convenience version of `eval`, for the case where the computation is being
  73. /// evaluated on its own.
  74. llvm::Expected<T> eval(const ast_matchers::MatchFinder::MatchResult &R) const;
  75. /// Constructs a string representation of the computation, for informational
  76. /// purposes. The representation must be deterministic, but is not required to
  77. /// be unique.
  78. virtual std::string toString() const = 0;
  79. protected:
  80. MatchComputation() = default;
  81. // Since this is an abstract class, copying/assigning only make sense for
  82. // derived classes implementing `clone()`.
  83. MatchComputation(const MatchComputation &) = default;
  84. MatchComputation &operator=(const MatchComputation &) = default;
  85. };
  86. template <typename T>
  87. llvm::Expected<T> MatchComputation<T>::eval(
  88. const ast_matchers::MatchFinder::MatchResult &R) const {
  89. T Output;
  90. if (auto Err = eval(R, &Output))
  91. return std::move(Err);
  92. return Output;
  93. }
  94. } // namespace transformer
  95. } // namespace clang
  96. #endif // LLVM_CLANG_TOOLING_TRANSFORMER_MATCHCONSUMER_H
  97. #ifdef __GNUC__
  98. #pragma GCC diagnostic pop
  99. #endif