16 #include "../RenamingAction.h"
17 #include "../USRFindingAction.h"
18 #include "clang/Basic/Diagnostic.h"
19 #include "clang/Basic/DiagnosticOptions.h"
20 #include "clang/Basic/FileManager.h"
21 #include "clang/Basic/IdentifierTable.h"
22 #include "clang/Basic/LangOptions.h"
23 #include "clang/Basic/SourceManager.h"
24 #include "clang/Basic/TokenKinds.h"
25 #include "clang/Frontend/TextDiagnosticPrinter.h"
26 #include "clang/Rewrite/Core/Rewriter.h"
27 #include "clang/Tooling/CommonOptionsParser.h"
28 #include "clang/Tooling/Refactoring.h"
29 #include "clang/Tooling/ReplacementsYaml.h"
30 #include "clang/Tooling/Tooling.h"
31 #include "llvm/ADT/IntrusiveRefCntPtr.h"
32 #include "llvm/Support/CommandLine.h"
33 #include "llvm/Support/FileSystem.h"
34 #include "llvm/Support/YAMLTraits.h"
35 #include "llvm/Support/raw_ostream.h"
38 #include <system_error>
41 using namespace clang;
59 IO.mapOptional(
"Offset", Info.
Offset);
61 IO.mapRequired(
"NewName", Info.
NewName);
72 cl::desc(
"Locates the symbol by offset as opposed to <line>:<column>."),
74 static cl::opt<bool>
Inplace(
"i", cl::desc(
"Overwrite edited <file>s."),
76 static cl::list<std::string>
78 cl::desc(
"The fully qualified name of the symbol."),
81 static cl::list<std::string>
82 NewNames(
"new-name", cl::desc(
"The new name to change the symbol to."),
86 cl::desc(
"Print the found symbol's name prior to renaming to stderr."),
89 "pl", cl::desc(
"Print the locations affected by renaming to stderr."),
91 static cl::opt<std::string>
93 cl::desc(
"YAML file to store suggested fixes in."),
95 static cl::opt<std::string>
96 Input(
"input", cl::desc(
"YAML file to load oldname-newname pairs from."),
99 int main(
int argc,
const char **argv) {
102 if (!
Input.empty()) {
104 ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
105 llvm::MemoryBuffer::getFile(
Input);
107 errs() <<
"clang-rename: failed to read " <<
Input <<
": "
108 << Buffer.getError().message() <<
"\n";
112 std::vector<RenameAllInfo> Infos;
115 for (
const auto &Info : Infos) {
116 if (!Info.QualifiedName.empty())
126 errs() <<
"clang-rename: -new-name must be specified.\n\n";
131 errs() <<
"clang-rename: -offset and -qualified-name can't be present at "
138 Options.CPlusPlus =
true;
139 Options.CPlusPlus1z =
true;
140 IdentifierTable Table(Options);
141 for (
const auto &NewName :
NewNames) {
142 auto NewNameTokKind = Table.get(NewName).getTokenID();
143 if (!tok::isAnyIdentifier(NewNameTokKind)) {
144 errs() <<
"ERROR: new name is not a valid identifier in C++17.\n\n";
150 errs() <<
"clang-rename: number of symbol offsets(" <<
SymbolOffsets.size()
152 <<
") must be equal to number of new names(" << NewNames.size()
154 cl::PrintHelpMessage();
158 auto Files = OP.getSourcePathList();
159 tooling::RefactoringTool Tool(OP.getCompilations(),
Files);
161 Tool.run(tooling::newFrontendActionFactory(&FindingAction).
get());
162 const std::vector<std::vector<std::string>> &USRList =
163 FindingAction.getUSRList();
164 const std::vector<std::string> &PrevNames = FindingAction.getUSRSpellings();
166 for (
const auto &
PrevName : PrevNames) {
167 outs() <<
"clang-rename found name: " <<
PrevName <<
'\n';
171 if (FindingAction.errorOccurred()) {
179 std::unique_ptr<tooling::FrontendActionFactory> Factory =
180 tooling::newFrontendActionFactory(&RenameAction);
184 ExitCode = Tool.runAndSave(Factory.get());
186 ExitCode = Tool.run(Factory.get());
190 llvm::raw_fd_ostream OS(
ExportFixes, EC, llvm::sys::fs::F_None);
192 llvm::errs() <<
"Error opening output file: " << EC.message() <<
'\n';
197 tooling::TranslationUnitReplacements TUR;
198 const auto &FileToReplacements = Tool.getReplacements();
199 for (
const auto &
Entry : FileToReplacements)
200 TUR.Replacements.insert(TUR.Replacements.end(),
Entry.second.begin(),
203 yaml::Output YAML(OS);
212 LangOptions DefaultLangOptions;
213 IntrusiveRefCntPtr<DiagnosticOptions>
DiagOpts =
new DiagnosticOptions();
214 TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);
215 DiagnosticsEngine Diagnostics(
216 IntrusiveRefCntPtr<DiagnosticIDs>(
new DiagnosticIDs()), &*DiagOpts,
217 &DiagnosticPrinter,
false);
218 auto &FileMgr = Tool.getFiles();
219 SourceManager Sources(Diagnostics, FileMgr);
220 Rewriter Rewrite(Sources, DefaultLangOptions);
222 Tool.applyAllReplacements(Rewrite);
224 const auto *
Entry = FileMgr.getFile(
File);
225 const auto ID = Sources.getOrCreateFileID(
Entry, SrcMgr::C_User);
226 Rewrite.getEditBuffer(ID).write(outs());
static cl::opt< bool > PrintLocations("pl", cl::desc("Print the locations affected by renaming to stderr."), cl::cat(ClangRenameOptions))
int main(int argc, const char **argv)
static cl::opt< bool > Inplace("i", cl::desc("Overwrite edited <file>s."), cl::cat(ClangRenameOptions))
static cl::list< std::string > NewNames("new-name", cl::desc("The new name to change the symbol to."), cl::ZeroOrMore, cl::cat(ClangRenameOptions))
static void mapping(IO &IO, RenameAllInfo &Info)
const std::string PrevName
static cl::opt< std::string > Input("input", cl::desc("YAML file to load oldname-newname pairs from."), cl::Optional, cl::cat(ClangRenameOptions))
static cl::list< std::string > QualifiedNames("qualified-name", cl::desc("The fully qualified name of the symbol."), cl::ZeroOrMore, cl::cat(ClangRenameOptions))
An oldname -> newname rename.
static cl::opt< std::string > ExportFixes("export-fixes", cl::desc("YAML file to store suggested fixes in."), cl::value_desc("filename"), cl::cat(ClangRenameOptions))
static cl::list< unsigned > SymbolOffsets("offset", cl::desc("Locates the symbol by offset as opposed to <line>:<column>."), cl::ZeroOrMore, cl::cat(ClangRenameOptions))
static cl::OptionCategory ClangRenameOptions("clang-rename common options")
IntrusiveRefCntPtr< DiagnosticOptions > DiagOpts
static cl::opt< bool > PrintName("pn", cl::desc("Print the found symbol's name prior to renaming to stderr."), cl::cat(ClangRenameOptions))
std::string QualifiedName