Refactor Matcher code to reduce per-Matcher boilerplate (#615)

This is in part to eliminate the "sm" and "lang_opts" variables that received comment, but also cuts back on the use of auto.
This commit is contained in:
Jon Meow
2021-07-08 12:42:24 -07:00
committed by GitHub
parent db2efeafeb
commit 4f1b2198ff
13 changed files with 252 additions and 162 deletions
+68 -9
View File
@@ -6,28 +6,87 @@
#define MIGRATE_CPP_CPP_REFACTORING_MATCHER_H_
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/Core/Replacement.h"
namespace Carbon {
// This is an abstract class with helpers to make it easier to write matchers.
class Matcher : public clang::ast_matchers::MatchFinder::MatchCallback {
// Note a MatcherFactory (below) is also typically required.
class Matcher {
public:
// Alias these to elide the namespaces in subclass headers.
using MatchFinder = clang::ast_matchers::MatchFinder;
using Replacements = clang::tooling::Replacements;
using ReplacementMap = std::map<std::string, clang::tooling::Replacements>;
explicit Matcher(std::map<std::string, Replacements>& in_replacements)
: replacements(&in_replacements) {}
Matcher(const clang::ast_matchers::MatchFinder::MatchResult* in_match_result,
ReplacementMap* in_replacements)
: match_result(in_match_result), replacements(in_replacements) {}
virtual ~Matcher() = default;
// Performs main execution of the matcher when a result is found.
virtual void Run() = 0;
protected:
// Replaces the given range with the specified text.
void AddReplacement(const clang::SourceManager& sm,
clang::CharSourceRange range,
void AddReplacement(clang::CharSourceRange range,
llvm::StringRef replacement_text);
// Returns a matched node by ID, exiting if not present.
template <typename NodeType>
auto GetNodeAsOrDie(llvm::StringRef id) -> const NodeType& {
auto* node = match_result->Nodes.getNodeAs<NodeType>(id);
if (!node) {
llvm::report_fatal_error(std::string("getNodeAs failed for ") + id);
}
return *node;
}
// Returns the language options.
auto GetLangOpts() -> const clang::LangOptions& {
return match_result->Context->getLangOpts();
}
// Returns the full source manager.
auto GetSourceManager() -> const clang::SourceManager& {
return *match_result->SourceManager;
}
// Returns the source text for a given range.
auto GetSourceText(clang::CharSourceRange range) -> llvm::StringRef {
return clang::Lexer::getSourceText(range, GetSourceManager(),
GetLangOpts());
}
private:
std::map<std::string, Replacements>* const replacements;
const clang::ast_matchers::MatchFinder::MatchResult* const match_result;
ReplacementMap* const replacements;
};
// A factory used to instantiate per-MatchResult Matchers, to be registered with
// the MatcherManager.
class MatcherFactory {
public:
virtual ~MatcherFactory() = default;
virtual auto CreateMatcher(
const clang::ast_matchers::MatchFinder::MatchResult* match_result,
Matcher::ReplacementMap* replacements) -> std::unique_ptr<Matcher> = 0;
// Returns the AST matcher which determines when the Matcher is instantiated
// and run.
virtual auto GetAstMatcher() -> clang::ast_matchers::DeclarationMatcher = 0;
};
// A convenience factory that implements CreateMatcher for Matchers that have a
// standard constructor.
template <typename MatcherType>
class MatcherFactoryBase : public MatcherFactory {
public:
auto CreateMatcher(
const clang::ast_matchers::MatchFinder::MatchResult* match_result,
Matcher::ReplacementMap* replacements)
-> std::unique_ptr<Matcher> override {
return std::make_unique<MatcherType>(match_result, replacements);
}
};
} // namespace Carbon