clang: lib/Tooling/Refactoring/Rename/RenamingAction.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/Support/Errc.h"
25#include "llvm/Support/Error.h"
26#include
27#include
28
29using namespace llvm;
30
33
34namespace {
35
38 std::vectorstd::string USRs =
40 std::string PrevName = ND->getNameAsString();
43}
44
45}
46
49 "local-rename",
50 "Rename",
51 "Finds and renames symbols in code with no indexer support",
52 };
53 return Descriptor;
54}
55
58 SourceRange SelectionRange, std::string NewName) {
61 if (!ND)
62 return Context.createDiagnosticError(
63 SelectionRange.getBegin(), diag::err_refactor_selection_no_symbol);
65 std::move(NewName));
66}
67
69
73 if (!Occurrences)
74 return Occurrences.takeError();
75
78 *Occurrences, Context.getASTContext().getSourceManager(), Name);
79}
80
83 std::string OldQualifiedName,
84 std::string NewQualifiedName) {
86 getNamedDeclFor(Context.getASTContext(), OldQualifiedName);
87 if (!ND)
88 return llvm::make_errorllvm::StringError("Could not find symbol " +
89 OldQualifiedName,
90 llvm::errc::invalid_argument);
91 return QualifiedRenameRule(ND, std::move(NewQualifiedName));
92}
93
96 "local-qualified-rename",
97 "Qualified Rename",
98
99 R"(Finds and renames qualified symbols in code within a translation unit.
100It is used to move/rename a symbol to a new namespace/name:
101 * Supported symbols: classes, class members, functions, enums, and type alias.
102 * Renames all symbol occurrences from the old qualified name to the new
103 qualified name. All symbol references will be correctly qualified; For
104 symbol definitions, only name will be changed.
105For example, rename "A::Foo" to "B::Bar":
106 Old code:
107 namespace foo {
108 class A {};
109 }
110
111 namespace bar {
112 void f(foo::A a) {}
114
115 New code after rename:
116 namespace foo {
117 class B {};
118 }
119
120 namespace bar {
121 void f(B b) {}
122 })"
123 };
124 return Descriptor;
125}
126
128QualifiedRenameRule::createSourceReplacements(RefactoringRuleContext &Context) {
130 assert(!USRs.empty());
132 USRs, NewQualifiedName, Context.getASTContext().getTranslationUnitDecl());
133}
134
138
139 std::vector Changes;
140 for (const auto &Occurrence : Occurrences) {
142 assert(NewName.getNamePieces().size() == Ranges.size() &&
143 "Mismatching number of ranges and name pieces");
145 for (const auto &Range : llvm::enumerate(Ranges)) {
150 return std::move(Error);
152 Changes.push_back(std::move(Change));
154 return std::move(Changes);
155}
156
157
158
161 std::map<std::string, tooling::Replacements> *FileToReplaces) {
164 llvm::Error Err =
165 (*FileToReplaces)[std::string(Replace.getFilePath())].add(Replace);
166 if (Err) {
167 llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! "
168 << llvm::toString(std::move(Err)) << "\n";
169 }
170 }
171 }
173
175public:
177 const std::vectorstd::string &NewNames,
178 const std::vectorstd::string &PrevNames,
179 const std::vector<std::vectorstd::string> &USRList,
180 std::map<std::string, tooling::Replacements> &FileToReplaces,
181 bool PrintLocations)
182 : NewNames(NewNames), PrevNames(PrevNames), USRList(USRList),
183 FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
184
186 for (unsigned I = 0; I < NewNames.size(); ++I) {
187
188 if (PrevNames[I].empty())
189 continue;
190
191 HandleOneRename(Context, NewNames[I], PrevNames[I], USRList[I]);
192 }
193 }
194
195 void HandleOneRename(ASTContext &Context, const std::string &NewName,
196 const std::string &PrevName,
197 const std::vectorstd::string &USRs) {
199
202 if (PrintLocations) {
203 for (const auto &Occurrence : Occurrences) {
204 FullSourceLoc FullLoc(Occurrence.getNameRanges()[0].getBegin(),
205 SourceMgr);
206 errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(FullLoc)
207 << ":" << FullLoc.getSpellingLineNumber() << ":"
208 << FullLoc.getSpellingColumnNumber() << "\n";
209 }
210 }
211
216 if (!Change) {
217 llvm::errs() << "Failed to create renaming replacements for '" << PrevName
218 << "'! " << llvm::toString(Change.takeError()) << "\n";
219 return;
220 }
222 }
223
224private:
225 const std::vectorstd::string &NewNames, &PrevNames;
226 const std::vector<std::vectorstd::string> &USRList;
227 std::map<std::string, tooling::Replacements> &FileToReplaces;
228 bool PrintLocations;
229};
230
231
232
233
234
235class USRSymbolRenamer : public ASTConsumer {
236public:
238 const std::vector<std::vectorstd::string> &USRList,
239 std::map<std::string, tooling::Replacements> &FileToReplaces)
240 : NewNames(NewNames), USRList(USRList), FileToReplaces(FileToReplaces) {
241 assert(USRList.size() == NewNames.size());
245 for (unsigned I = 0; I < NewNames.size(); ++I) {
246
247
249 USRList[I], NewNames[I], Context.getTranslationUnitDecl());
251 }
252 }
253
254private:
255 const std::vectorstd::string &NewNames;
256 const std::vector<std::vectorstd::string> &USRList;
257 std::map<std::string, tooling::Replacements> &FileToReplaces;
258};
259
261 return std::make_unique(NewNames, PrevNames, USRList,
262 FileToReplaces, PrintLocations);
263}
264
266 return std::make_unique(NewNames, USRList, FileToReplaces);
267}
268
269}
270}
Defines the clang::ASTContext interface.
Provides an action to rename every symbol at a point.
Methods for determining the USR of a symbol at a location in source code.
Provides an action to find all relevant USRs at a point.
Provides functionality for finding all instances of a USR in a given AST.
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
static CharSourceRange getCharRange(SourceRange R)
ASTContext & getASTContext() const LLVM_READONLY
This represents a decl that may have a name.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
The refactoring rule context stores all of the inputs that might be needed by a refactoring action ru...
The JSON file list parser is used to communicate input to InstallAPI.
Diagnostic wrappers for TextAPI types for error reporting.