forked from OSchip/llvm-project
152 lines
4.8 KiB
C++
152 lines
4.8 KiB
C++
//===--- tools/extra/clang-rename/ClangRename.cpp - Clang rename tool -----===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// \brief This file implements a clang-rename tool that automatically finds and
|
|
/// renames symbols in C++ code.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "../USRFindingAction.h"
|
|
#include "../RenamingAction.h"
|
|
#include "clang/AST/ASTConsumer.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/Basic/FileManager.h"
|
|
#include "clang/Basic/LangOptions.h"
|
|
#include "clang/Basic/TargetInfo.h"
|
|
#include "clang/Basic/TargetOptions.h"
|
|
#include "clang/Frontend/CommandLineSourceLoc.h"
|
|
#include "clang/Frontend/CompilerInstance.h"
|
|
#include "clang/Frontend/FrontendAction.h"
|
|
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
|
#include "clang/Lex/Lexer.h"
|
|
#include "clang/Lex/Preprocessor.h"
|
|
#include "clang/Parse/ParseAST.h"
|
|
#include "clang/Parse/Parser.h"
|
|
#include "clang/Rewrite/Core/Rewriter.h"
|
|
#include "clang/Tooling/CommonOptionsParser.h"
|
|
#include "clang/Tooling/Refactoring.h"
|
|
#include "clang/Tooling/Tooling.h"
|
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
|
#include "llvm/Support/Host.h"
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string>
|
|
#include <time.h>
|
|
#include <vector>
|
|
|
|
using namespace llvm;
|
|
|
|
cl::OptionCategory ClangRenameCategory("Clang-rename options");
|
|
|
|
static cl::opt<std::string>
|
|
NewName(
|
|
"new-name",
|
|
cl::desc("The new name to change the symbol to."),
|
|
cl::cat(ClangRenameCategory));
|
|
static cl::opt<unsigned>
|
|
SymbolOffset(
|
|
"offset",
|
|
cl::desc("Locates the symbol by offset as opposed to <line>:<column>."),
|
|
cl::cat(ClangRenameCategory));
|
|
static cl::opt<bool>
|
|
Inplace(
|
|
"i",
|
|
cl::desc("Overwrite edited <file>s."),
|
|
cl::cat(ClangRenameCategory));
|
|
static cl::opt<bool>
|
|
PrintName(
|
|
"pn",
|
|
cl::desc("Print the found symbol's name prior to renaming to stderr."),
|
|
cl::cat(ClangRenameCategory));
|
|
static cl::opt<bool>
|
|
PrintLocations(
|
|
"pl",
|
|
cl::desc("Print the locations affected by renaming to stderr."),
|
|
cl::cat(ClangRenameCategory));
|
|
|
|
#define CLANG_RENAME_VERSION "0.0.1"
|
|
|
|
static void PrintVersion() {
|
|
outs() << "clang-rename version " << CLANG_RENAME_VERSION << "\n";
|
|
}
|
|
|
|
using namespace clang;
|
|
|
|
const char RenameUsage[] = "A tool to rename symbols in C/C++ code.\n\
|
|
clang-rename renames every occurrence of a symbol found at <offset> in\n\
|
|
<source0>. If -i is specified, the edited files are overwritten to disk.\n\
|
|
Otherwise, the results are written to stdout.\n";
|
|
|
|
int main(int argc, const char **argv) {
|
|
cl::SetVersionPrinter(PrintVersion);
|
|
tooling::CommonOptionsParser OP(argc, argv, ClangRenameCategory, RenameUsage);
|
|
|
|
// Check the arguments for correctness.
|
|
|
|
if (NewName.empty()) {
|
|
errs() << "clang-rename: no new name provided.\n\n";
|
|
cl::PrintHelpMessage();
|
|
exit(1);
|
|
}
|
|
|
|
// Get the USRs.
|
|
auto Files = OP.getSourcePathList();
|
|
tooling::RefactoringTool Tool(OP.getCompilations(), Files);
|
|
rename::USRFindingAction USRAction(SymbolOffset);
|
|
|
|
// Find the USRs.
|
|
Tool.run(tooling::newFrontendActionFactory(&USRAction).get());
|
|
const auto &USRs = USRAction.getUSRs();
|
|
const auto &PrevName = USRAction.getUSRSpelling();
|
|
|
|
if (PrevName.empty())
|
|
// An error should have already been printed.
|
|
exit(1);
|
|
|
|
if (PrintName)
|
|
errs() << "clang-rename: found name: " << PrevName;
|
|
|
|
// Perform the renaming.
|
|
rename::RenamingAction RenameAction(NewName, PrevName, USRs,
|
|
Tool.getReplacements(), PrintLocations);
|
|
auto Factory = tooling::newFrontendActionFactory(&RenameAction);
|
|
int res;
|
|
|
|
if (Inplace) {
|
|
res = Tool.runAndSave(Factory.get());
|
|
} else {
|
|
res = Tool.run(Factory.get());
|
|
|
|
// Write every file to stdout. Right now we just barf the files without any
|
|
// indication of which files start where, other than that we print the files
|
|
// in the same order we see them.
|
|
LangOptions DefaultLangOptions;
|
|
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts =
|
|
new DiagnosticOptions();
|
|
TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts);
|
|
DiagnosticsEngine Diagnostics(
|
|
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()),
|
|
&*DiagOpts, &DiagnosticPrinter, false);
|
|
auto &FileMgr = Tool.getFiles();
|
|
SourceManager Sources(Diagnostics, FileMgr);
|
|
Rewriter Rewrite(Sources, DefaultLangOptions);
|
|
|
|
Tool.applyAllReplacements(Rewrite);
|
|
for (const auto &File : Files) {
|
|
const auto *Entry = FileMgr.getFile(File);
|
|
auto ID = Sources.translateFile(Entry);
|
|
Rewrite.getEditBuffer(ID).write(outs());
|
|
}
|
|
}
|
|
|
|
exit(res);
|
|
}
|