18 #include "llvm/ADT/Optional.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/Support/Errc.h" 21 #include "llvm/Support/Error.h" 27 using namespace clang;
28 using namespace tooling;
31 using ast_matchers::internal::DynTypedMatcher;
35 using llvm::StringError;
70 Expected<SmallVector<tooling::detail::Transformation, 1>>
74 for (
const auto &Edit : Edits) {
77 return Range.takeError();
78 if (Range->isInvalid() ||
83 return Replacement.takeError();
87 Transformations.push_back(std::move(T));
89 return Transformations;
102 std::move(M), std::move(Edits), std::move(Explanation), {}}}};
107 for (
auto &Case : Rule.
Cases)
108 Case.AddedIncludes.emplace_back(Header.str(), Format);
114 static auto TypeKind = ASTNodeKind::getFromNodeKind<Type>();
115 static auto QualKind = ASTNodeKind::getFromNodeKind<QualType>();
126 assert(!Cases.empty() &&
"Rule must have at least one case.");
127 ASTNodeKind JoinKind = Cases[0].Matcher.getSupportedKind();
130 for (
const auto &Case : Cases) {
131 auto K = Case.Matcher.getSupportedKind();
136 if (K.isSame(JoinKind) ||
isBaseOf(K, JoinKind))
147 static std::vector<DynTypedMatcher>
150 std::vector<DynTypedMatcher> Matchers;
151 Matchers.reserve(Cases.size());
153 for (
const auto &Case : Cases) {
154 std::string Tag = (TagBase + Twine(count)).str();
156 auto M = Case.Matcher.tryBind(Tag);
157 assert(M &&
"RewriteRule matchers should be bindable.");
158 Matchers.push_back(*std::move(M));
168 for (
auto &Rule : Rules)
174 assert(!Rule.
Cases.empty() &&
"Rule must have at least one case.");
175 if (Rule.
Cases.size() == 1)
176 return Rule.
Cases[0].Matcher;
179 assert(!CommonKind.isNone() &&
"Cases must have compatible matchers.");
180 return DynTypedMatcher::constructVariadic(
186 M.setAllowBind(
true);
196 if (Rule.
Cases.size() == 1)
197 return Rule.
Cases[0];
199 auto &NodesMap = Result.Nodes.getMap();
200 for (
size_t i = 0, N = Rule.
Cases.size();
i < N; ++
i) {
201 std::string Tag = (
"Tag" + Twine(
i)).str();
202 if (NodesMap.find(Tag) != NodesMap.end())
205 llvm_unreachable(
"No tag found for this rule.");
215 if (Result.Context->getDiagnostics().hasErrorOccurred())
219 auto &NodesMap = Result.Nodes.getMap();
221 assert(Root != NodesMap.end() &&
"Transformation failed: missing root node.");
223 Root->second.getSourceRange().getBegin());
224 assert(RootLoc.isValid() &&
"Invalid location for Root node of match.");
228 if (!Transformations) {
229 Consumer(Transformations.takeError());
233 if (Transformations->empty()) {
235 RootLoc.print(llvm::errs() <<
"note: skipping match at loc ",
236 *Result.SourceManager);
237 llvm::errs() <<
"\n";
243 for (
const auto &T : *Transformations) {
244 if (
auto Err = AC.
replace(*Result.SourceManager, T.Range, T.Replacement)) {
245 Consumer(std::move(Err));
250 for (
const auto &I : Case.AddedIncludes) {
251 auto &Header = I.first;
257 AC.
addHeader((llvm::Twine(
"<") + Header +
">").str());
262 Consumer(std::move(AC));
A class to allow finding matches over the Clang AST.
bool isSame(ASTNodeKind Other) const
Returns true if this and Other represent the same kind.
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
Gets the location of the immediate macro caller, one level up the stack toward the initial macro type...
MatchFinder::MatchResult MatchResult
friend class SourceManager
Defines the Diagnostic-related interfaces.
bool isMacroBodyExpansion(SourceLocation Loc) const
Tests whether the given source location represents the expansion of a macro body. ...
Contains all information for a given match.
Encodes a location in the source.
bool isBaseOf(ASTNodeKind Other, unsigned *Distance=nullptr) const
Returns true if this is a base kind of (or same as) Other.
ast_type_traits::DynTypedNode DynTypedNode
Dataflow Directional Tag Classes.
Defines the clang::SourceLocation class and associated facilities.
This class handles loading and caching of source files into memory.
bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action)
Adds a matcher to execute when running over the AST.