clang: lib/Tooling/RefactoringCallbacks.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
15
16using llvm::StringError;
17using llvm::make_error;
18
21
26
28 std::map<std::string, Replacements> &FileToReplaces)
29 : FileToReplaces(FileToReplaces) {}
30
32 const ast_matchers::internal::DynTypedMatcher &Matcher,
34 MatchFinder.addDynamicMatcher(Matcher, Callback);
35 Callbacks.push_back(Callback);
36}
37
39public:
41 : Refactoring(Refactoring) {}
42
44
45
46 for (const auto &Callback : Refactoring.Callbacks) {
47 Callback->getReplacements().clear();
48 }
49 Refactoring.MatchFinder.matchAST(Context);
50 for (const auto &Callback : Refactoring.Callbacks) {
51 for (const auto &Replacement : Callback->getReplacements()) {
52 llvm::Error Err =
55 if (Err) {
57 << " due to this error:\n"
58 << toString(std::move(Err)) << "\n";
59 }
60 }
61 }
62 }
63
64private:
66};
67
69 return std::make_unique(*this);
70}
71
78 const Stmt &To) {
80 Sources, From,
83}
84
86 : FromId(std::string(FromId)), ToText(std::string(ToText)) {}
87
90 if (const Stmt *FromMatch = Result.Nodes.getNodeAs<Stmt>(FromId)) {
92 *Result.SourceManager,
94
95
96 if (Err) {
97 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
98 assert(false);
99 }
100 }
101}
102
104 : FromId(std::string(FromId)), ToId(std::string(ToId)) {}
105
108 const Stmt *FromMatch = Result.Nodes.getNodeAs<Stmt>(FromId);
109 const Stmt *ToMatch = Result.Nodes.getNodeAs<Stmt>(ToId);
110 if (FromMatch && ToMatch) {
113
114
115 if (Err) {
116 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
117 assert(false);
118 }
119 }
120}
121
123 bool PickTrueBranch)
124 : Id(std::string(Id)), PickTrueBranch(PickTrueBranch) {}
125
129 const Stmt *Body = PickTrueBranch ? Node->getThen() : Node->getElse();
130 if (Body) {
131 auto Err =
133
134
135 if (Err) {
136 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
137 assert(false);
138 }
139 } else if (!PickTrueBranch) {
140
141
142 auto Err =
144
145
146 if (Err) {
147 llvm::errs() << llvm::toString(std::move(Err)) << "\n";
148 assert(false);
149 }
150 }
151 }
152}
153
154ReplaceNodeWithTemplate::ReplaceNodeWithTemplate(
155 llvm::StringRef FromId, std::vector Template)
157
160 std::vector ParsedTemplate;
161 for (size_t Index = 0; Index < ToTemplate.size();) {
162 if (ToTemplate[Index] == '$') {
163 if (ToTemplate.substr(Index, 2) == "$$") {
164 Index += 2;
165 ParsedTemplate.push_back(
166 TemplateElement{TemplateElement::Literal, "$"});
167 } else if (ToTemplate.substr(Index, 2) == "${") {
168 size_t EndOfIdentifier = ToTemplate.find("}", Index);
169 if (EndOfIdentifier == std:🧵:npos) {
170 return make_error(
171 "Unterminated ${...} in replacement template near " +
172 ToTemplate.substr(Index),
173 llvm::inconvertibleErrorCode());
174 }
175 std::string SourceNodeName = std::string(
176 ToTemplate.substr(Index + 2, EndOfIdentifier - Index - 2));
177 ParsedTemplate.push_back(
178 TemplateElement{TemplateElement::Identifier, SourceNodeName});
179 Index = EndOfIdentifier + 1;
180 } else {
181 return make_error(
182 "Invalid $ in replacement template near " +
183 ToTemplate.substr(Index),
184 llvm::inconvertibleErrorCode());
185 }
186 } else {
187 size_t NextIndex = ToTemplate.find('$', Index + 1);
188 ParsedTemplate.push_back(TemplateElement{
189 TemplateElement::Literal,
190 std::string(ToTemplate.substr(Index, NextIndex - Index))});
191 Index = NextIndex;
192 }
193 }
194 return std::unique_ptr(
195 new ReplaceNodeWithTemplate(FromId, std::move(ParsedTemplate)));
196}
197
200 const auto &NodeMap = Result.Nodes.getMap();
201
202 std::string ToText;
203 for (const auto &Element : Template) {
204 switch (Element.Type) {
205 case TemplateElement::Literal:
206 ToText += Element.Value;
207 break;
208 case TemplateElement::Identifier: {
209 auto NodeIter = NodeMap.find(Element.Value);
210 if (NodeIter == NodeMap.end()) {
211 llvm::errs() << "Node " << Element.Value
212 << " used in replacement template not bound in Matcher \n";
213 llvm::report_fatal_error("Unbound node in replacement template.");
214 }
218 Result.Context->getLangOpts());
219 break;
220 }
221 }
222 }
223 auto It = NodeMap.find(FromId);
224 if (It == NodeMap.end()) {
225 llvm::errs() << "Node to be replaced " << FromId
226 << " not bound in query.\n";
227 llvm::report_fatal_error("FromId node not bound in MatchResult");
228 }
231 Result.Context->getLangOpts());
233 if (Err) {
235 << "! " << llvm::toString(std::move(Err)) << "\n";
236 llvm::report_fatal_error("Replacement failed");
237 }
238}
239
240}
241}
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Defines the clang::SourceLocation class and associated facilities.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Represents a character-granular source range.
static CharSourceRange getTokenRange(SourceRange R)
IfStmt - This represents an if/then/else.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
This class handles loading and caching of source files into memory.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
ReplaceIfStmtWithItsBody(StringRef Id, bool PickTrueBranch)
Definition RefactoringCallbacks.cpp:122
void run(const ast_matchers::MatchFinder::MatchResult &Result) override
Called on every match by the MatchFinder.
Definition RefactoringCallbacks.cpp:126
ReplaceStmtWithText(StringRef FromId, StringRef ToText)
Definition RefactoringCallbacks.cpp:85
void run(const ast_matchers::MatchFinder::MatchResult &Result) override
Called on every match by the MatchFinder.
Definition RefactoringCallbacks.cpp:88
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
@ Template
We are parsing a template declaration.
Contains all information for a given match.