Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -1,5 +1,5 @@ add_subdirectory(clang-apply-replacements) -add_subdirectory(clang-rename) +add_subdirectory(clang-refactor) add_subdirectory(clang-reorder-fields) add_subdirectory(modularize) if(CLANG_ENABLE_STATIC_ANALYZER) @@ -23,4 +23,3 @@ if( CLANG_TOOLS_EXTRA_INCLUDE_DOCS ) add_subdirectory(docs) endif() - Index: TemplatedClassFunction.cpp =================================================================== --- /dev/null +++ TemplatedClassFunction.cpp @@ -0,0 +1,22 @@ +template +class A { +public: + void foo() /* Test 1 */ {} // CHECK: void bar() /* Test 1 */ {} +}; + +int main(int argc, char **argv) { + A a; + a.foo(); /* Test 2 */ // CHECK: a.bar() /* Test 2 */ + return 0; +} + +// Test 1. +// RUN: clang-refactor rename -offset=48 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-refactor rename -offset=162 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// +// Currently unsupported test. +// XFAIL: * + +// To find offsets after modifying the file, use: +// grep -Ubo 'foo.*' Index: clang-refactor/CMakeLists.txt =================================================================== --- /dev/null +++ clang-refactor/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories( + USREngine + modules + ) + +add_subdirectory(driver) +add_subdirectory(USREngine) +add_subdirectory(modules) +add_subdirectory(editor-integrations) Index: clang-refactor/USREngine/CMakeLists.txt =================================================================== --- clang-refactor/USREngine/CMakeLists.txt +++ clang-refactor/USREngine/CMakeLists.txt @@ -1,10 +1,9 @@ -set(LLVM_LINK_COMPONENTS support) +set(LLVM_LINK_COMPONENTS Support) -add_clang_library(clangRename +add_clang_library(clangRefactorUSREngine USRFinder.cpp USRFindingAction.cpp USRLocFinder.cpp - RenamingAction.cpp LINK_LIBS clangAST @@ -12,7 +11,4 @@ clangBasic clangIndex clangLex - clangToolingCore ) - -add_subdirectory(tool) Index: clang-refactor/USREngine/USRFinder.h =================================================================== --- clang-refactor/USREngine/USRFinder.h +++ clang-refactor/USREngine/USRFinder.h @@ -1,4 +1,4 @@ -//===--- tools/extra/clang-rename/USRFinder.h - Clang rename tool ---------===// +//===--- tools/extra/clang-refactor/USRFinder.h - USREngine ---------------===// // // The LLVM Compiler Infrastructure // @@ -12,6 +12,7 @@ /// code. /// //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDER_H @@ -29,7 +30,7 @@ class SourceLocation; class NamedDecl; -namespace rename { +namespace clang_refactor { // Given an AST context and a point, returns a NamedDecl identifying the symbol // at the point. Returns null if nothing is found at the point. Index: clang-refactor/USREngine/USRFinder.cpp =================================================================== --- clang-refactor/USREngine/USRFinder.cpp +++ clang-refactor/USREngine/USRFinder.cpp @@ -1,4 +1,4 @@ -//===--- tools/extra/clang-rename/USRFinder.cpp - Clang rename tool -------===// +//===--- tools/extra/clang-refactor/USRFinder.cpp - USREngine -------------===// // // The LLVM Compiler Infrastructure // @@ -23,7 +23,7 @@ using namespace llvm; namespace clang { -namespace rename { +namespace clang_refactor { // NamedDeclFindingASTVisitor recursively visits each AST node to find the // symbol underneath the cursor. @@ -78,32 +78,28 @@ const SourceLocation TypeEndLoc = Lexer::getLocForEndOfToken( TypeBeginLoc, 0, Context.getSourceManager(), Context.getLangOpts()); if (const auto *TemplateTypeParm = - dyn_cast(Loc.getType())) { + dyn_cast(Loc.getType())) return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc); - } if (const auto *TemplateSpecType = - dyn_cast(Loc.getType())) { + dyn_cast(Loc.getType())) return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(), TypeBeginLoc, TypeEndLoc); - } return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc, TypeEndLoc); } bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) { for (const auto *Initializer : ConstructorDecl->inits()) { - if (!Initializer->isWritten()) { + if (!Initializer->isWritten()) // Ignore implicit initializers. continue; - } if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) { const SourceLocation InitBeginLoc = Initializer->getSourceLocation(), InitEndLoc = Lexer::getLocForEndOfToken( InitBeginLoc, 0, Context.getSourceManager(), Context.getLangOpts()); - if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc)) { + if (!setResult(FieldDecl, InitBeginLoc, InitEndLoc)) return false; - } } } return true; @@ -129,20 +125,17 @@ // \returns false on success. bool setResult(const NamedDecl *Decl, SourceLocation Start, SourceLocation End) { - if (!Decl) { + if (!Decl) return true; - } if (Name.empty()) { // Offset is used to find the declaration. if (!Start.isValid() || !Start.isFileID() || !End.isValid() || - !End.isFileID() || !isPointWithin(Start, End)) { + !End.isFileID() || !isPointWithin(Start, End)) return true; - } } else { // Fully qualified name is used to find the declaration. - if (Name != Decl->getQualifiedNameAsString()) { + if (Name != Decl->getQualifiedNameAsString()) return true; - } } Result = Decl; return false; @@ -182,15 +175,13 @@ const SourceLocation FileLoc = CurrDecl->getLocStart(); StringRef FileName = Context.getSourceManager().getFilename(FileLoc); // FIXME: Add test. - if (FileName == SearchFile) { + if (FileName == SearchFile) Visitor.TraverseDecl(CurrDecl); - } } NestedNameSpecifierLocFinder Finder(const_cast(Context)); - for (const auto &Location : Finder.getNestedNameSpecifierLocations()) { + for (const auto &Location : Finder.getNestedNameSpecifierLocations()) Visitor.handleNestedNameSpecifierLoc(Location); - } return Visitor.getNamedDecl(); } @@ -213,5 +204,5 @@ return std::string(Buff.data(), Buff.size()); } -} // namespace rename +} // namespace clang_refactor } // namespace clang Index: clang-refactor/USREngine/USRFindingAction.h =================================================================== --- /dev/null +++ clang-refactor/USREngine/USRFindingAction.h @@ -0,0 +1,50 @@ +//===--- tools/extra/clang-refactor/USRFindingAction.h - USREngine --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Provides an action to find all relevant USRs at a point. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_USRENGINE_USRFINDINGACTION_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_USRENGINE_USRFINDINGACTION_H + +#include "clang/AST/ASTTypeTraits.h" +#include "clang/Frontend/FrontendAction.h" + +#include +#include + +namespace clang { +class ASTConsumer; +class CompilerInstance; +class NamedDecl; + +namespace clang_refactor { + +struct USRFindingAction { + USRFindingAction(ArrayRef SymbolOffsets, + ArrayRef QualifiedNames) + : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames) {} + std::unique_ptr newASTConsumer(); + + const std::vector &getUSRSpellings() { return SpellingNames; } + const std::vector> &getUSRList() { return USRList; } + +private: + std::vector SymbolOffsets; + std::vector QualifiedNames; + std::vector SpellingNames; + std::vector> USRList; +}; + +} // namespace clang_refactor +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_USRENGINE_USRFINDINGACTION_H Index: clang-refactor/USREngine/USRFindingAction.cpp =================================================================== --- clang-refactor/USREngine/USRFindingAction.cpp +++ clang-refactor/USREngine/USRFindingAction.cpp @@ -1,4 +1,4 @@ -//===--- tools/extra/clang-rename/USRFindingAction.cpp - Clang rename tool ===// +//===--- tools/extra/clang-refactor/USRFindingAction.cpp - USREngine ------===// // // The LLVM Compiler Infrastructure // @@ -18,6 +18,7 @@ #include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/FileManager.h" @@ -30,13 +31,11 @@ #include "clang/Tooling/Tooling.h" #include #include -#include -#include using namespace llvm; namespace clang { -namespace rename { +namespace clang_refactor { namespace { // \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to @@ -45,20 +44,17 @@ // to virtual method. class AdditionalUSRFinder : public RecursiveASTVisitor { public: - explicit AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context, - std::vector *USRs) - : FoundDecl(FoundDecl), Context(Context), USRs(USRs) {} + explicit AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context) + : FoundDecl(FoundDecl), Context(Context) {} - void Find() { + std::vector Find() { // Fill OverriddenMethods and PartialSpecs storages. TraverseDecl(Context.getTranslationUnitDecl()); if (const auto *MethodDecl = dyn_cast(FoundDecl)) { addUSRsOfOverridenFunctions(MethodDecl); - for (const auto &OverriddenMethod : OverriddenMethods) { - if (checkIfOverriddenFunctionAscends(OverriddenMethod)) { + for (const auto &OverriddenMethod : OverriddenMethods) + if (checkIfOverriddenFunctionAscends(OverriddenMethod)) USRSet.insert(getUSRForDecl(OverriddenMethod)); - } - } } else if (const auto *RecordDecl = dyn_cast(FoundDecl)) { handleCXXRecordDecl(RecordDecl); } else if (const auto *TemplateDecl = @@ -67,13 +63,12 @@ } else { USRSet.insert(getUSRForDecl(FoundDecl)); } - USRs->insert(USRs->end(), USRSet.begin(), USRSet.end()); + return std::vector(USRSet.begin(), USRSet.end()); } bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) { - if (MethodDecl->isVirtual()) { + if (MethodDecl->isVirtual()) OverriddenMethods.push_back(MethodDecl); - } return true; } @@ -87,46 +82,41 @@ void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) { RecordDecl = RecordDecl->getDefinition(); if (const auto *ClassTemplateSpecDecl = - dyn_cast(RecordDecl)) { + dyn_cast(RecordDecl)) handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate()); - } + addUSRsOfCtorDtors(RecordDecl); } void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) { - for (const auto *Specialization : TemplateDecl->specializations()) { + for (const auto *Specialization : TemplateDecl->specializations()) addUSRsOfCtorDtors(Specialization); - } - for (const auto *PartialSpec : PartialSpecs) { - if (PartialSpec->getSpecializedTemplate() == TemplateDecl) { + + for (const auto *PartialSpec : PartialSpecs) + if (PartialSpec->getSpecializedTemplate() == TemplateDecl) addUSRsOfCtorDtors(PartialSpec); - } - } addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl()); } void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) { RecordDecl = RecordDecl->getDefinition(); - for (const auto *CtorDecl : RecordDecl->ctors()) { + for (const auto *CtorDecl : RecordDecl->ctors()) USRSet.insert(getUSRForDecl(CtorDecl)); - } USRSet.insert(getUSRForDecl(RecordDecl->getDestructor())); USRSet.insert(getUSRForDecl(RecordDecl)); } void addUSRsOfOverridenFunctions(const CXXMethodDecl *MethodDecl) { USRSet.insert(getUSRForDecl(MethodDecl)); - for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) { + for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) // Recursively visit each OverridenMethod. addUSRsOfOverridenFunctions(OverriddenMethod); - } } bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) { for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) { - if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end()) { + if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end()) return true; - } return checkIfOverriddenFunctionAscends(OverriddenMethod); } return false; @@ -134,70 +124,84 @@ const Decl *FoundDecl; ASTContext &Context; - std::vector *USRs; std::set USRSet; std::vector OverriddenMethods; std::vector PartialSpecs; }; } // namespace -struct NamedDeclFindingConsumer : public ASTConsumer { - void HandleTranslationUnit(ASTContext &Context) override { - const SourceManager &SourceMgr = Context.getSourceManager(); - // The file we look for the USR in will always be the main source file. +class NamedDeclFindingConsumer : public ASTConsumer { +public: + explicit NamedDeclFindingConsumer( + ArrayRef SymbolOffsets, ArrayRef QualifiedNames, + std::vector &SpellingNames, + std::vector> &USRList) + : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames), + SpellingNames(SpellingNames), USRList(USRList) { + } + +private: + void FindSymbol(ASTContext &Context, const SourceManager &SourceMgr, + unsigned SymbolOffset, const std::string &QualifiedName) { const SourceLocation Point = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()) .getLocWithOffset(SymbolOffset); + if (!Point.isValid()) return; const NamedDecl *FoundDecl = nullptr; - if (OldName.empty()) { + + if (QualifiedName.empty()) FoundDecl = getNamedDeclAt(Context, Point); - } else { - FoundDecl = getNamedDeclFor(Context, OldName); - } + else + FoundDecl = getNamedDeclFor(Context, QualifiedName); + if (FoundDecl == nullptr) { - if (OldName.empty()) { + if (QualifiedName.empty()) { FullSourceLoc FullLoc(Point, SourceMgr); - errs() << "clang-rename: could not find symbol at " + errs() << "clang-refactor rename: could not find symbol at " << SourceMgr.getFilename(Point) << ":" << FullLoc.getSpellingLineNumber() << ":" << FullLoc.getSpellingColumnNumber() << " (offset " << SymbolOffset << ").\n"; - } else - errs() << "clang-rename: could not find symbol " << OldName << ".\n"; + exit(1); + } else { + errs() << "USREngine: could not find symbol " << QualifiedName << ".\n"; + exit(1); + } return; } - // If FoundDecl is a constructor or destructor, we want to instead take the - // Decl of the corresponding class. - if (const auto *CtorDecl = dyn_cast(FoundDecl)) { + // If FoundDecl is a constructor or destructor, we want to instead take + // the Decl of the corresponding class. + if (const auto *CtorDecl = dyn_cast(FoundDecl)) FoundDecl = CtorDecl->getParent(); - } else if (const auto *DtorDecl = dyn_cast(FoundDecl)) { + else if (const auto *DtorDecl = dyn_cast(FoundDecl)) FoundDecl = DtorDecl->getParent(); - } - *SpellingName = FoundDecl->getNameAsString(); - AdditionalUSRFinder Finder(FoundDecl, Context, USRs); - Finder.Find(); + SpellingNames.push_back(FoundDecl->getNameAsString()); + AdditionalUSRFinder Finder(FoundDecl, Context); + USRList.push_back(Finder.Find()); + } + + void HandleTranslationUnit(ASTContext &Context) override { + const SourceManager &SourceMgr = Context.getSourceManager(); + for (unsigned Offset : SymbolOffsets) + FindSymbol(Context, SourceMgr, Offset, ""); + for (const std::string &QualifiedName : QualifiedNames) + FindSymbol(Context, SourceMgr, 0, QualifiedName); } - unsigned SymbolOffset; - std::string OldName; - std::string *SpellingName; - std::vector *USRs; + ArrayRef SymbolOffsets; + ArrayRef QualifiedNames; + std::vector &SpellingNames; + std::vector> &USRList; }; std::unique_ptr USRFindingAction::newASTConsumer() { - std::unique_ptr Consumer( - new NamedDeclFindingConsumer); - SpellingName = ""; - Consumer->SymbolOffset = SymbolOffset; - Consumer->OldName = OldName; - Consumer->USRs = &USRs; - Consumer->SpellingName = &SpellingName; - return std::move(Consumer); + return llvm::make_unique( + SymbolOffsets, QualifiedNames, SpellingNames, USRList); } -} // namespace rename +} // namespace clang_refactor } // namespace clang Index: clang-refactor/USREngine/USRLocFinder.h =================================================================== --- clang-refactor/USREngine/USRLocFinder.h +++ clang-refactor/USREngine/USRLocFinder.h @@ -1,4 +1,4 @@ -//===--- tools/extra/clang-rename/USRLocFinder.h - Clang rename tool ------===// +//===--- tools/extra/clang-refactor/USRLocFinder.h - USREngine ------------===// // // The LLVM Compiler Infrastructure // @@ -22,14 +22,14 @@ #include namespace clang { -namespace rename { +namespace clang_refactor { // FIXME: make this an AST matcher. Wouldn't that be awesome??? I agree! std::vector getLocationsOfUSRs(const std::vector &USRs, llvm::StringRef PrevName, Decl *Decl); -} // namespace rename +} // namespace clang_refactor } // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_LOC_FINDER_H Index: clang-refactor/USREngine/USRLocFinder.cpp =================================================================== --- clang-refactor/USREngine/USRLocFinder.cpp +++ clang-refactor/USREngine/USRLocFinder.cpp @@ -1,4 +1,4 @@ -//===--- tools/extra/clang-rename/USRLocFinder.cpp - Clang rename tool ----===// +//===--- tools/extra/clang-refactor/USRLocFinder.cpp - USREngine ----------===// // // The LLVM Compiler Infrastructure // @@ -26,7 +26,7 @@ using namespace llvm; namespace clang { -namespace rename { +namespace clang_refactor { namespace { // \brief This visitor recursively searches for all instances of a USR in a @@ -44,23 +44,20 @@ bool VisitCXXConstructorDecl(clang::CXXConstructorDecl *ConstructorDecl) { for (const auto *Initializer : ConstructorDecl->inits()) { - if (!Initializer->isWritten()) { + if (!Initializer->isWritten()) // Ignore implicit initializers. continue; - } if (const clang::FieldDecl *FieldDecl = Initializer->getMember()) { - if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end()) { + if (USRSet.find(getUSRForDecl(FieldDecl)) != USRSet.end()) LocationsFound.push_back(Initializer->getSourceLocation()); - } } } return true; } bool VisitNamedDecl(const NamedDecl *Decl) { - if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) { + if (USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) checkAndAddLocation(Decl->getLocation()); - } return true; } @@ -92,15 +89,14 @@ bool VisitTypeLoc(const TypeLoc Loc) { if (USRSet.find(getUSRForDecl(Loc.getType()->getAsCXXRecordDecl())) != - USRSet.end()) { + USRSet.end()) checkAndAddLocation(Loc.getBeginLoc()); - } + if (const auto *TemplateTypeParm = dyn_cast(Loc.getType())) { if (USRSet.find(getUSRForDecl(TemplateTypeParm->getDecl())) != - USRSet.end()) { + USRSet.end()) checkAndAddLocation(Loc.getBeginLoc()); - } } return true; } @@ -118,9 +114,8 @@ while (NameLoc) { const NamespaceDecl *Decl = NameLoc.getNestedNameSpecifier()->getAsNamespace(); - if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) { + if (Decl && USRSet.find(getUSRForDecl(Decl)) != USRSet.end()) checkAndAddLocation(NameLoc.getLocalBeginLoc()); - } NameLoc = NameLoc.getPrefix(); } } @@ -134,11 +129,10 @@ Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc), Context.getSourceManager(), Context.getLangOpts()); size_t Offset = TokenName.find(PrevName); - if (Offset != StringRef::npos) { + if (Offset != StringRef::npos) // The token of the source location we find actually has the old // name. LocationsFound.push_back(BeginLoc.getLocWithOffset(Offset)); - } } const std::set USRSet; @@ -154,11 +148,10 @@ USRLocFindingASTVisitor Visitor(USRs, PrevName, Decl->getASTContext()); Visitor.TraverseDecl(Decl); NestedNameSpecifierLocFinder Finder(Decl->getASTContext()); - for (const auto &Location : Finder.getNestedNameSpecifierLocations()) { + for (const auto &Location : Finder.getNestedNameSpecifierLocations()) Visitor.handleNestedNameSpecifierLoc(Location); - } return Visitor.getLocationsFound(); } -} // namespace rename +} // namespace clang_refactor } // namespace clang Index: clang-refactor/driver/CMakeLists.txt =================================================================== --- /dev/null +++ clang-refactor/driver/CMakeLists.txt @@ -0,0 +1,18 @@ +set(LLVM_LINK_COMPONENTS + Support + ) + +add_clang_executable(clang-refactor + Driver.cpp + ) + +target_link_libraries(clang-refactor + clangAST + clangBasic + clangFrontend + clangTooling + + clangRefactorRenameModule + + clangRefactorUSREngine + ) Index: clang-refactor/driver/ClangRefactorOptions.h =================================================================== --- /dev/null +++ clang-refactor/driver/ClangRefactorOptions.h @@ -0,0 +1,67 @@ +//===--- tools/extra/clang-refactor/ClangRefactorOptions.h ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines common options for clang-refactor subtools. +/// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/CommonOptionsParser.h" + +#ifndef CLANG_REFACTOR_OPTIONS_H +#define CLANG_REFACTOR_OPTIONS_H + +using namespace llvm; + +namespace clang { +namespace clang_refactor { + +// FIXME: Adjust libTooling so that these options would be displayed, too. +static cl::OptionCategory + ClangRefactorCommonOptions("clang-refactor common options"); + +static cl::list SymbolOffsets( + "offset", + cl::desc("Locates the symbol by offset as opposed to :."), + cl::ZeroOrMore, cl::cat(ClangRefactorCommonOptions)); +static cl::opt Inplace("i", cl::desc("Overwrite edited s."), + cl::cat(ClangRefactorCommonOptions)); +static cl::list + QualifiedNames("qualified-name", + cl::desc("The fully qualified name of the symbol."), + cl::ZeroOrMore, cl::cat(ClangRefactorCommonOptions)); + +namespace rename_module { + +static cl::OptionCategory + ClangRefactorRenameCategory("clang-refactor rename options"); + +static cl::list + NewNames("new-name", cl::desc("The new name to change the symbol to."), + cl::ZeroOrMore, cl::cat(ClangRefactorRenameCategory)); +static cl::opt PrintName( + "pn", + cl::desc("Print the found symbol's name prior to renaming to stderr."), + cl::cat(ClangRefactorRenameCategory)); +static cl::opt PrintLocations( + "pl", cl::desc("Print the locations affected by renaming to stderr."), + cl::cat(ClangRefactorRenameCategory)); +static cl::opt ExportFixes( + "export-fixes", cl::desc("YAML file to store suggested fixes in."), + cl::value_desc("filename"), cl::cat(ClangRefactorRenameCategory)); +static cl::opt + Input("input", cl::desc("YAML file to load oldname-newname pairs from."), + cl::Optional, cl::cat(ClangRefactorRenameCategory)); + +} // namespace rename_module + +} // namespace clang_refactor +} // namespace clang + +#endif // CLANG_REFACTOR_OPTIONS_H Index: clang-refactor/driver/Driver.cpp =================================================================== --- /dev/null +++ clang-refactor/driver/Driver.cpp @@ -0,0 +1,53 @@ +//===---- tools/extra/clang-refactor/Driver.cpp - clang-refactor driver ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// \file This file implements clang-refactor driver. +// +//===----------------------------------------------------------------------===// + +#include "Rename.h" + +#include "llvm/ADT/StringSwitch.h" + +#include +#include + +using namespace clang; +using namespace llvm; + +const char HelpMessage[] = + "USAGE: clang-refactor [subcommand] [options] [... ]\n" + "\n" + "Subcommands:\n" + " rename: rename the symbol found at s or by s in " + ".\n"; + +static int printHelpMessage(int argc, const char *argv[]) { + outs() << HelpMessage; + return 0; +} + +int main(int argc, const char **argv) { + if (argc > 1) { + using MainFunction = std::function; + MainFunction Func = + StringSwitch(argv[1]) + .Cases("-help", "--help", printHelpMessage) + .Case("rename", clang_refactor::rename_module::RenameModuleMain) + .Default(nullptr); + if (Func) { + std::string Invocation = std::string(argv[0]) + " " + argv[1]; + argv[1] = Invocation.c_str(); + return Func(argc - 1, argv + 1); + } + } + + printHelpMessage(argc, argv); + return 0; +} Index: clang-refactor/driver/Rename.h =================================================================== --- /dev/null +++ clang-refactor/driver/Rename.h @@ -0,0 +1,203 @@ +//===--- tools/extra/clang-refactor/Rename.h - rename module driver -------===// +// +// 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 driver of rename module of clang-refactor. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_RENAME_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_RENAME_H + +#include "USRFindingAction.h" +#include "rename/RenamingAction.h" +#include "ClangRefactorOptions.h" + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TokenKinds.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Refactoring.h" +#include "clang/Tooling/ReplacementsYaml.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +using namespace llvm; +using namespace clang; + +/// \brief An oldname -> newname rename. +struct RenameAllInfo { + unsigned Offset = 0; + std::string OldName; + std::string NewName; +}; + +LLVM_YAML_IS_SEQUENCE_VECTOR(RenameAllInfo) + +namespace llvm { +namespace yaml { + +/// \brief Specialized MappingTraits to describe how a RenameAllInfo is +/// (de)serialized. +template <> struct MappingTraits { + static void mapping(IO &IO, RenameAllInfo &Info) { + IO.mapOptional("Offset", Info.Offset); + IO.mapOptional("OldName", Info.OldName); + IO.mapRequired("NewName", Info.NewName); + } +}; + +} // end namespace yaml +} // end namespace llvm + +namespace clang { +namespace clang_refactor { +namespace rename_module { + +int RenameModuleMain(int argc, const char **argv) { + tooling::CommonOptionsParser OP(argc, argv, ClangRefactorRenameCategory); + + if (!Input.empty()) { + // Populate QualifiedNames and NewNames from a YAML file. + ErrorOr> Buffer = + llvm::MemoryBuffer::getFile(Input); + if (!Buffer) { + errs() << "clang-refactor rename: failed to read " << Input << ": " + << Buffer.getError().message() << "\n"; + return 1; + } + + std::vector Infos; + llvm::yaml::Input YAML(Buffer.get()->getBuffer()); + YAML >> Infos; + for (const auto &Info : Infos) { + if (!Info.OldName.empty()) + QualifiedNames.push_back(Info.OldName); + else + SymbolOffsets.push_back(Info.Offset); + NewNames.push_back(Info.NewName); + } + } + + // Check the arguments for correctness. + if (NewNames.empty()) { + errs() << "clang-refactor rename: -new-name or -input is required.\n\n"; + exit(1); + } + + // Check if NewNames is a valid identifier in C++17. + LangOptions Options; + Options.CPlusPlus = true; + Options.CPlusPlus1z = true; + IdentifierTable Table(Options); + for (const auto &NewName : NewNames) { + auto NewNameTokKind = Table.get(NewName).getTokenID(); + if (!tok::isAnyIdentifier(NewNameTokKind)) { + errs() << "ERROR: new name is not a valid identifier in C++17.\n\n"; + exit(1); + } + } + + if (SymbolOffsets.size() + QualifiedNames.size() != NewNames.size()) { + errs() << "clang-refactor rename: number of symbol offsets(" + << SymbolOffsets.size() << ") + number of qualified names (" + << QualifiedNames.size() << ") must be equal to number of new names(" + << NewNames.size() << ").\n\n"; + cl::PrintHelpMessage(); + exit(1); + } + + auto Files = OP.getSourcePathList(); + tooling::RefactoringTool Tool(OP.getCompilations(), Files); + USRFindingAction FindingAction(SymbolOffsets, QualifiedNames); + Tool.run(tooling::newFrontendActionFactory(&FindingAction).get()); + const std::vector> &USRList = + FindingAction.getUSRList(); + const std::vector &PrevNames = FindingAction.getUSRSpellings(); + if (PrintName) { + for (const auto &PrevName : PrevNames) { + outs() << "clang-refactor rename found name: " << PrevName << '\n'; + } + } + + // Perform the renaming. + RenamingAction RenameAction(NewNames, PrevNames, USRList, + Tool.getReplacements(), PrintLocations); + std::unique_ptr Factory = + tooling::newFrontendActionFactory(&RenameAction); + int ExitCode; + + if (Inplace) { + ExitCode = Tool.runAndSave(Factory.get()); + } else { + ExitCode = Tool.run(Factory.get()); + + if (!ExportFixes.empty()) { + std::error_code EC; + llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::F_None); + if (EC) { + llvm::errs() << "Error opening output file: " << EC.message() << '\n'; + exit(1); + } + + // Export replacements. + tooling::TranslationUnitReplacements TUR; + const auto &FileToReplacements = Tool.getReplacements(); + for (const auto &Entry : FileToReplacements) + TUR.Replacements.insert(TUR.Replacements.end(), Entry.second.begin(), + Entry.second.end()); + + yaml::Output YAML(OS); + YAML << TUR; + OS.close(); + exit(0); + } + + // 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 DiagOpts = new DiagnosticOptions(); + TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts); + DiagnosticsEngine Diagnostics( + IntrusiveRefCntPtr(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(ExitCode); +} + +} // namespace rename_module +} // namespace clang_refactor +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_REFACTOR_RENAME_H Index: clang-refactor/editor-integrations/CMakeLists.txt =================================================================== --- /dev/null +++ clang-refactor/editor-integrations/CMakeLists.txt @@ -0,0 +1,6 @@ +install(PROGRAMS clang-refactor-rename.py + DESTINATION share/clang + COMPONENT clang-refactor) +install(PROGRAMS clang-refactor-rename.el + DESTINATION share/clang + COMPONENT clang-refactor) Index: clang-refactor/editor-integrations/clang-refactor-rename.el =================================================================== --- clang-refactor/editor-integrations/clang-refactor-rename.el +++ clang-refactor/editor-integrations/clang-refactor-rename.el @@ -1,26 +1,26 @@ -;;; clang-rename.el --- Renames every occurrence of a symbol found at . +;;; clang-refactor-rename.el --- Renames symbols found at . ;; Keywords: tools, c ;;; Commentary: -;; To install clang-rename.el make sure the directory of this file is in your -;; 'load-path' and add +;; To install clang-refactor-rename.el make sure the directory of this file is +;; in your 'load-path' and add ;; -;; (require 'clang-rename) +;; (require 'clang-refactor-rename) ;; ;; to your .emacs configuration. ;;; Code: -(defcustom clang-rename-binary "clang-rename" - "Path to clang-rename executable." +(defcustom clang-refactor "clang-refactor" + "Path to clang-refactor executable." :type 'hook :options '(turn-on-auto-fill flyspell-mode) :group 'wp) -(defun clang-rename (new-name) - "Rename all instances of the symbol at the point using clang-rename" +(defun clang-refactor-rename (new-name) + "Rename all instances of the symbol at the point using clang-refactor rename" (interactive "sEnter a new name: ") (let (;; Emacs offset is 1-based. (offset (- (point) 1)) @@ -29,9 +29,9 @@ (let ((rename-command (format "bash -f -c '%s -offset=%s -new-name=%s -i %s'" - clang-rename-binary offset new-name file-name))) - (message (format "Running clang-rename command %s" rename-command)) - ;; Run clang-rename via bash. + clang-refactor-binary offset new-name file-name))) + (message (format "Running clang-refactor command %s" rename-command)) + ;; Run clang-refactor via bash. (shell-command rename-command) ;; Reload buffer. (revert-buffer t t) @@ -39,6 +39,6 @@ ) ) -(provide 'clang-rename) +(provide 'clang-refactor) -;;; clang-rename.el ends here +;;; clang-refactor.el ends here Index: clang-refactor/editor-integrations/clang-refactor-rename.py =================================================================== --- clang-refactor/editor-integrations/clang-refactor-rename.py +++ clang-refactor/editor-integrations/clang-refactor-rename.py @@ -1,15 +1,16 @@ ''' -Minimal clang-rename integration with Vim. +Minimal clang-refactor rename integration with Vim. Before installing make sure one of the following is satisfied: -* clang-rename is in your PATH -* `g:clang_rename_path` in ~/.vimrc points to valid clang-rename executable -* `binary` in clang-rename.py points to valid to clang-rename executable +* clang-refactor is in your PATH +* `g:clang_rename_path` in ~/.vimrc points to valid clang-refactor executable +* `binary` in clang-refactor rename.py points to valid to clang-refactor +executable To install, simply put this into your ~/.vimrc - noremap cr :pyf /clang-rename.py + noremap cr :pyf /clang-refactor-rename.py IMPORTANT NOTE: Before running the tool, make sure you saved the file. @@ -23,11 +24,11 @@ import sys def main(): - binary = 'clang-rename' + binary = 'clang-refactor' if vim.eval('exists("g:clang_rename_path")') == "1": binary = vim.eval('g:clang_rename_path') - # Get arguments for clang-rename binary. + # Get arguments for clang-refactor binary. offset = int(vim.eval('line2byte(line("."))+col(".")')) - 2 if offset < 0: print >> sys.stderr, '''Couldn\'t determine cursor position. @@ -38,9 +39,10 @@ new_name_request_message = 'type new name:' new_name = vim.eval("input('{}\n')".format(new_name_request_message)) - # Call clang-rename. + # Call clang-refactor rename module. command = [binary, filename, + 'rename', '-i', '-offset', str(offset), '-new-name', str(new_name)] Index: clang-refactor/modules/CMakeLists.txt =================================================================== --- /dev/null +++ clang-refactor/modules/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(rename) Index: clang-refactor/modules/rename/CMakeLists.txt =================================================================== --- /dev/null +++ clang-refactor/modules/rename/CMakeLists.txt @@ -0,0 +1,13 @@ +set(LLVM_LINK_COMPONENTS Support) + +add_clang_library(clangRefactorRenameModule + RenamingAction.cpp + + LINK_LIBS + clangAST + clangBasic + clangFrontend + clangToolingCore + + clangRefactorUSREngine + ) Index: clang-refactor/modules/rename/RenamingAction.h =================================================================== --- clang-refactor/modules/rename/RenamingAction.h +++ clang-refactor/modules/rename/RenamingAction.h @@ -1,4 +1,4 @@ -//===--- tools/extra/clang-rename/RenamingAction.h - Clang rename tool ----===// +//===--- tools/extra/clang-refactor/RenamingAction.h ----------------------===// // // The LLVM Compiler Infrastructure // @@ -21,7 +21,8 @@ class ASTConsumer; class CompilerInstance; -namespace rename { +namespace clang_refactor { +namespace rename_module { class RenamingAction { public: @@ -41,7 +42,9 @@ std::map &FileToReplaces; bool PrintLocations; }; -} -} + +} // namespace rename_module +} // namespace clang_refactor +} // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_RENAMING_ACTION_H Index: clang-refactor/modules/rename/RenamingAction.cpp =================================================================== --- clang-refactor/modules/rename/RenamingAction.cpp +++ clang-refactor/modules/rename/RenamingAction.cpp @@ -1,4 +1,4 @@ -//===--- tools/extra/clang-rename/RenamingAction.cpp - Clang rename tool --===// +//===--- tools/extra/clang-refactor/RenamingAction.cpp --------------------===// // // The LLVM Compiler Infrastructure // @@ -30,7 +30,8 @@ using namespace llvm; namespace clang { -namespace rename { +namespace clang_refactor { +namespace rename_module { class RenamingASTConsumer : public ASTConsumer { public: @@ -65,8 +66,9 @@ for (const auto &Loc : RenamingCandidates) { if (PrintLocations) { FullSourceLoc FullLoc(Loc, SourceMgr); - errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc) - << ":" << FullLoc.getSpellingLineNumber() << ":" + errs() << "clang-refactor rename: renamed at: " + << SourceMgr.getFilename(Loc) << ":" + << FullLoc.getSpellingLineNumber() << ":" << FullLoc.getSpellingColumnNumber() << "\n"; } // FIXME: better error handling. @@ -90,5 +92,6 @@ FileToReplaces, PrintLocations); } -} // namespace rename +} // namespace rename_module +} // namespace clang_refactor } // namespace clang Index: clang-rename/USRFindingAction.h =================================================================== --- clang-rename/USRFindingAction.h +++ /dev/null @@ -1,47 +0,0 @@ -//===--- tools/extra/clang-rename/USRFindingAction.h - 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 Provides an action to find all relevant USRs at a point. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H - -#include "clang/Frontend/FrontendAction.h" - -namespace clang { -class ASTConsumer; -class CompilerInstance; -class NamedDecl; - -namespace rename { - -struct USRFindingAction { - USRFindingAction(unsigned Offset, const std::string &Name) - : SymbolOffset(Offset), OldName(Name) {} - std::unique_ptr newASTConsumer(); - - // \brief get the spelling of the USR(s) as it would appear in source files. - const std::string &getUSRSpelling() { return SpellingName; } - - const std::vector &getUSRs() { return USRs; } - -private: - unsigned SymbolOffset; - std::string OldName; - std::string SpellingName; - std::vector USRs; -}; - -} // namespace rename -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_RENAME_USR_FINDING_ACTION_H Index: clang-rename/tool/CMakeLists.txt =================================================================== --- clang-rename/tool/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -add_clang_executable(clang-rename ClangRename.cpp) - -target_link_libraries(clang-rename - clangBasic - clangFrontend - clangRename - clangRewrite - clangTooling - clangToolingCore - ) - -install(TARGETS clang-rename RUNTIME DESTINATION bin) - -install(PROGRAMS clang-rename.py - DESTINATION share/clang - COMPONENT clang-rename) -install(PROGRAMS clang-rename.el - DESTINATION share/clang - COMPONENT clang-rename) Index: clang-rename/tool/ClangRename.cpp =================================================================== --- clang-rename/tool/ClangRename.cpp +++ /dev/null @@ -1,310 +0,0 @@ -//===--- 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 "../RenamingAction.h" -#include "../USRFindingAction.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticOptions.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TokenKinds.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Rewrite/Core/Rewriter.h" -#include "clang/Tooling/CommonOptionsParser.h" -#include "clang/Tooling/Refactoring.h" -#include "clang/Tooling/ReplacementsYaml.h" -#include "clang/Tooling/Tooling.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/YAMLTraits.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include - -using namespace llvm; - -using namespace clang; - -cl::OptionCategory ClangRenameAtCategory("clang-rename rename-at options"); -cl::OptionCategory ClangRenameAllCategory("clang-rename rename-all options"); - -const char RenameAtUsage[] = "A tool to rename symbols in C/C++ code.\n\ -clang-rename renames every occurrence of a symbol found at in\n\ -. If -i is specified, the edited files are overwritten to disk.\n\ -Otherwise, the results are written to stdout.\n"; - -const char RenameAllUsage[] = "A tool to rename symbols in C/C++ code.\n\ -clang-rename performs renaming given pairs {offset | old-name} -> new-name.\n"; - -static int renameAtMain(int argc, const char *argv[]); -static int renameAllMain(int argc, const char *argv[]); -static int helpMain(int argc, const char *argv[]); - -/// \brief An oldname -> newname rename. -struct RenameAllInfo { - std::string OldName; - unsigned Offset = 0; - std::string NewName; -}; - -LLVM_YAML_IS_SEQUENCE_VECTOR(RenameAllInfo) - -namespace llvm { -namespace yaml { - -/// \brief Specialized MappingTraits to describe how a RenameAllInfo is -/// (de)serialized. -template <> struct MappingTraits { - static void mapping(IO &IO, RenameAllInfo &Info) { - IO.mapOptional("OldName", Info.OldName); - IO.mapOptional("Offset", Info.Offset); - IO.mapRequired("NewName", Info.NewName); - } -}; - -} // end namespace yaml -} // end namespace llvm - -int main(int argc, const char **argv) { - if (argc > 1) { - using MainFunction = std::function; - MainFunction Func = StringSwitch(argv[1]) - .Case("rename-at", renameAtMain) - .Case("rename-all", renameAllMain) - .Cases("-help", "--help", helpMain) - .Default(nullptr); - - if (Func) { - std::string Invocation = std::string(argv[0]) + " " + argv[1]; - argv[1] = Invocation.c_str(); - return Func(argc - 1, argv + 1); - } else { - return renameAtMain(argc, argv); - } - } - - helpMain(argc, argv); - return 1; -} - -int subcommandMain(bool isRenameAll, int argc, const char **argv) { - cl::OptionCategory *Category = nullptr; - const char *Usage = nullptr; - if (isRenameAll) { - Category = &ClangRenameAllCategory; - Usage = RenameAllUsage; - } else { - Category = &ClangRenameAtCategory; - Usage = RenameAtUsage; - } - - cl::list NewNames( - "new-name", cl::desc("The new name to change the symbol to."), - (isRenameAll ? cl::ZeroOrMore : cl::Required), cl::cat(*Category)); - cl::list SymbolOffsets( - "offset", - cl::desc("Locates the symbol by offset as opposed to :."), - (isRenameAll ? cl::ZeroOrMore : cl::Required), cl::cat(*Category)); - cl::list OldNames( - "old-name", - cl::desc( - "The fully qualified name of the symbol, if -offset is not used."), - (isRenameAll ? cl::ZeroOrMore : cl::Optional), - cl::cat(ClangRenameAllCategory)); - cl::opt Inplace("i", cl::desc("Overwrite edited s."), - cl::cat(*Category)); - cl::opt PrintName( - "pn", - cl::desc("Print the found symbol's name prior to renaming to stderr."), - cl::cat(ClangRenameAtCategory)); - cl::opt PrintLocations( - "pl", cl::desc("Print the locations affected by renaming to stderr."), - cl::cat(ClangRenameAtCategory)); - cl::opt ExportFixes( - "export-fixes", cl::desc("YAML file to store suggested fixes in."), - cl::value_desc("filename"), cl::cat(*Category)); - cl::opt Input( - "input", cl::desc("YAML file to load oldname-newname pairs from."), - cl::Optional, cl::cat(ClangRenameAllCategory)); - - tooling::CommonOptionsParser OP(argc, argv, *Category, Usage); - - if (!Input.empty()) { - // Populate OldNames and NewNames from a YAML file. - ErrorOr> Buffer = - llvm::MemoryBuffer::getFile(Input); - if (!Buffer) { - errs() << "clang-rename: failed to read " << Input << ": " - << Buffer.getError().message() << "\n"; - return 1; - } - - std::vector Infos; - llvm::yaml::Input YAML(Buffer.get()->getBuffer()); - YAML >> Infos; - for (const auto &Info : Infos) { - if (!Info.OldName.empty()) - OldNames.push_back(Info.OldName); - else - SymbolOffsets.push_back(Info.Offset); - NewNames.push_back(Info.NewName); - } - } - - // Check the arguments for correctness. - - if (NewNames.empty()) { - errs() << "clang-rename: either -new-name or -input is required.\n\n"; - exit(1); - } - - // Check if NewNames is a valid identifier in C++17. - for (const auto &NewName : NewNames) { - LangOptions Options; - Options.CPlusPlus = true; - Options.CPlusPlus1z = true; - IdentifierTable Table(Options); - auto NewNameTokKind = Table.get(NewName).getTokenID(); - if (!tok::isAnyIdentifier(NewNameTokKind)) { - errs() << "ERROR: new name is not a valid identifier in C++17.\n\n"; - exit(1); - } - } - - if (!OldNames.empty() && OldNames.size() != NewNames.size()) { - errs() << "clang-rename: number of old names (" << OldNames.size() - << ") do not equal to number of new names (" << NewNames.size() - << ").\n\n"; - cl::PrintHelpMessage(); - exit(1); - } - - if (!SymbolOffsets.empty() && SymbolOffsets.size() != NewNames.size()) { - errs() << "clang-rename: number of symbol offsets (" << SymbolOffsets.size() - << ") do not equal to number of new names (" << NewNames.size() - << ").\n\n"; - cl::PrintHelpMessage(); - exit(1); - } - - std::vector> USRList; - std::vector PrevNames; - auto Files = OP.getSourcePathList(); - tooling::RefactoringTool Tool(OP.getCompilations(), Files); - unsigned Count = OldNames.size() ? OldNames.size() : SymbolOffsets.size(); - for (unsigned I = 0; I < Count; ++I) { - unsigned SymbolOffset = SymbolOffsets.empty() ? 0 : SymbolOffsets[I]; - const std::string &OldName = OldNames.empty() ? std::string() : OldNames[I]; - - // Get the USRs. - rename::USRFindingAction USRAction(SymbolOffset, OldName); - - // Find the USRs. - Tool.run(tooling::newFrontendActionFactory(&USRAction).get()); - const auto &USRs = USRAction.getUSRs(); - USRList.push_back(USRs); - const auto &PrevName = USRAction.getUSRSpelling(); - PrevNames.push_back(PrevName); - - if (PrevName.empty()) { - // An error should have already been printed. - exit(1); - } - - if (PrintName) { - errs() << "clang-rename: found name: " << PrevName << '\n'; - } - } - - // Perform the renaming. - rename::RenamingAction RenameAction(NewNames, PrevNames, USRList, - Tool.getReplacements(), PrintLocations); - auto Factory = tooling::newFrontendActionFactory(&RenameAction); - int ExitCode; - - if (Inplace) { - ExitCode = Tool.runAndSave(Factory.get()); - } else { - ExitCode = Tool.run(Factory.get()); - - if (!ExportFixes.empty()) { - std::error_code EC; - llvm::raw_fd_ostream OS(ExportFixes, EC, llvm::sys::fs::F_None); - if (EC) { - llvm::errs() << "Error opening output file: " << EC.message() << '\n'; - exit(1); - } - - // Export replacements. - tooling::TranslationUnitReplacements TUR; - const auto &FileToReplacements = Tool.getReplacements(); - for (const auto &Entry : FileToReplacements) - TUR.Replacements.insert(TUR.Replacements.end(), Entry.second.begin(), - Entry.second.end()); - - yaml::Output YAML(OS); - YAML << TUR; - OS.close(); - exit(0); - } - - // 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 DiagOpts = new DiagnosticOptions(); - TextDiagnosticPrinter DiagnosticPrinter(errs(), &*DiagOpts); - DiagnosticsEngine Diagnostics( - IntrusiveRefCntPtr(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(ExitCode); -} - -/// \brief Top level help. -/// FIXME It would be better if this could be auto-generated. -static int helpMain(int argc, const char *argv[]) { - errs() << "Usage: clang-rename {rename-at|rename-all} [OPTION]...\n\n" - "A tool to rename symbols in C/C++ code.\n\n" - "Subcommands:\n" - " rename-at: Perform rename off of a location in a file. (This " - "is the default.)\n" - " rename-all: Perform rename of all symbols matching one or more " - "fully qualified names.\n"; - return 0; -} - -static int renameAtMain(int argc, const char *argv[]) { - return subcommandMain(false, argc, argv); -} - -static int renameAllMain(int argc, const char *argv[]) { - return subcommandMain(true, argc, argv); -} Index: docs/clang-refactor/index.rst =================================================================== --- /dev/null +++ docs/clang-refactor/index.rst @@ -0,0 +1,32 @@ +============== +Clang-Refactor +============== + +.. contents:: + +See also: + +.. toctree:: + :maxdepth: 1 + +:program:`clang-refactor` is a Clang-based refactoring "master" tool. It is home +for refactoring submodules, such as `rename`. :program:`clang-refactor` is only +a prototype at the moment and most of its parts may significantly change. + +.. code-block:: console + + $ clang-refactor --help + + USAGE: clang-refactor [subcommand] [options] [... ] + + Subcommands: + rename: rename the symbol found at s or by s in . + +======= +Modules +======= + +.. toctree:: + :maxdepth: 1 + + rename.rst Index: docs/clang-refactor/rename.rst =================================================================== --- /dev/null +++ docs/clang-refactor/rename.rst @@ -0,0 +1,112 @@ +====== +Rename +====== + +.. contents:: + +See also: + +.. toctree:: + :maxdepth: 1 + + +`rename` is a module of `clang-refactor`, a C++ "master" refactoring tool. Its +purpose is to perform efficient renaming actions in large-scale projects such as +renaming classes, functions, variables, arguments, namespaces etc. + +The tool is in a very early development stage, so you might encounter bugs and +crashes. Submitting reports with information about how to reproduce the issue +to `the LLVM bugtracker `_ will definitely help the +project. If you have any ideas or suggestions, you might want to put a feature +request there. + +Using Rename module +=================== + +:program:`clang-refactor` is a `LibTooling +`_-based tool, and it's easier to +work with if you set up a compile command database for your project (for an +example of how to do this see `How To Setup Tooling For LLVM +`_). You can also +specify compilation options on the command line after `--`: + +.. code-block:: console + + $ clang-refactor rename -offset=42 -new-name=foo test.cpp -- -Imy_project/include -DMY_DEFINES ... + + +To get an offset of a symbol in a file run + +.. code-block:: console + + $ grep -FUbo 'foo' file.cpp + + +The tool currently supports renaming actions inside a single translation unit +only. It is planned to extend the tool's functionality to support multi-TU +renaming actions in the future. + +:program:`clang-refactor` also aims to be easily integrated into popular text +editors, such as Vim and Emacs, and improve the workflow of users. + +Although a command line interface exists, it is highly recommended to use the +text editor interface instead for better experience. + +You can also identify one or more symbols to be renamed by giving the fully +qualified name: + +.. code-block:: console + + $ clang-refactor rename-old-name=foo -new-name=bar test.cpp + + +Alternatively, { offset | old name } -> new name pairs can be put into a YAML +file: + +.. code-block:: yaml + + --- + - OldName: foo + NewName: bar + - Offset: 42 + NewName: baz + ... + + +That way you can avoid spelling out all the names as command line arguments: + +.. code-block:: console + + $ clang-refactor rename -input=test.yaml test.cpp + + +Vim Integration +=============== + +You can call :program:`clang-refactor rename` directly from Vim! To set up +:program:`clang-refactor-rename` integration for Vim see +`clang-refactor/editor-integrations/clang-refactor-rename.py +`_. + +Please note that **you have to save all buffers, in which the replacement will +happen before running the tool**. + +Once installed, you can point your cursor to symbols you want to rename, press +`cr` and type new desired name. The ` key +`_ +is a reference to a specific key defined by the mapleader variable and is bound +to backslash by default. + +Emacs Integration +================= + +You can also use :program:`clang-refactor` while using Emacs! To set up +:program:`clang-refactor rename` integration for Emacs see +`clang-refactor/editor-integrations/clang-refactor-rename.el +`_. + +Once installed, you can point your cursor to symbols you want to rename, press +`M-X`, type `clang-refactor rename` and new desired name. + +Please note that **you have to save all buffers, in which the replacement will +happen before running the tool**. Index: docs/clang-rename.rst =================================================================== --- docs/clang-rename.rst +++ /dev/null @@ -1,193 +0,0 @@ -============ -Clang-Rename -============ - -.. contents:: - -See also: - -.. toctree:: - :maxdepth: 1 - - -:program:`clang-rename` is a C++ refactoring tool. Its purpose is to perform -efficient renaming actions in large-scale projects such as renaming classes, -functions, variables, arguments, namespaces etc. - -The tool is in a very early development stage, so you might encounter bugs and -crashes. Submitting reports with information about how to reproduce the issue -to `the LLVM bugtracker `_ will definitely help the -project. If you have any ideas or suggestions, you might want to put a feature -request there. - -Using Clang-Rename -================== - -:program:`clang-rename` is a `LibTooling -`_-based tool, and it's easier to -work with if you set up a compile command database for your project (for an -example of how to do this see `How To Setup Tooling For LLVM -`_). You can also -specify compilation options on the command line after `--`: - -.. code-block:: console - - $ clang-rename -offset=42 -new-name=foo test.cpp -- -Imy_project/include -DMY_DEFINES ... - - -To get an offset of a symbol in a file run - -.. code-block:: console - - $ grep -FUbo 'foo' file.cpp - - -The tool currently supports renaming actions inside a single translation unit -only. It is planned to extend the tool's functionality to support multi-TU -renaming actions in the future. - -:program:`clang-rename` also aims to be easily integrated into popular text -editors, such as Vim and Emacs, and improve the workflow of users. - -Although a command line interface exists, it is highly recommended to use the -text editor interface instead for better experience. - -You can also identify one or more symbols to be renamed by giving the fully qualified -name: - -.. code-block:: console - - $ clang-rename rename-all -old-name=foo -new-name=bar test.cpp - - -Alternatively, old name / new name pairs can be put into a YAML file: - -.. code-block:: yaml - - --- - - OldName: foo - NewName: bar - ... - - -That way you can avoid spelling out all the names as command line arguments: - -.. code-block:: console - - $ clang-rename rename-all -input=test.yaml test.cpp - - -The YAML file also supports offsets: - -.. code-block:: yaml - - --- - - Offset: 42 - NewName: foo - ... - - -:program:`clang-rename` offers the following options: - -.. code-block:: console - - $ clang-rename -help - Usage: clang-rename {rename-at|rename-all} [OPTION]... - - A tool to rename symbols in C/C++ code. - - Subcommands: - rename-at: Perform rename off of a location in a file. (This is the default.) - rename-all: Perform rename of all symbols matching one or more fully qualified names. - - -.. code-block:: console - - $ clang-rename rename-at -help - OVERVIEW: A tool to rename symbols in C/C++ code. - clang-rename renames every occurrence of a symbol found at in - . If -i is specified, the edited files are overwritten to disk. - Otherwise, the results are written to stdout. - - USAGE: clang-rename rename-at [subcommand] [options] [... ] - - OPTIONS: - - Generic Options: - - -help - Display available options (-help-hidden for more) - -help-list - Display list of available options (-help-list-hidden for more) - -version - Display the version of this program - - clang-rename rename-at options: - - -export-fixes= - YAML file to store suggested fixes in. - -extra-arg= - Additional argument to append to the compiler command line. - -extra-arg-before= - Additional argument to prepend to the compiler command line. - -i - Overwrite edited s. - -new-name= - The new name to change the symbol to. - -offset= - Locates the symbol by offset as opposed to :. - -p= - Build path. - -pl - Print the locations affected by renaming to stderr. - -pn - Print the found symbol's name prior to renaming to stderr. - - -.. code-block:: console - - $ clang-rename rename-all -help - OVERVIEW: A tool to rename symbols in C/C++ code. - clang-rename renames every occurrence of a symbol named . - - USAGE: clang-rename rename-all [subcommand] [options] [... ] - - OPTIONS: - - Generic Options: - - -help - Display available options (-help-hidden for more). - -help-list - Display list of available options (-help-list-hidden for more). - -version - Display the version of this program. - - clang-rename rename-all options: - - -export-fixes= - YAML file to store suggested fixes in. - -extra-arg= - Additional argument to append to the compiler command line. - -extra-arg-before= - Additional argument to prepend to the compiler command line. - -i - Overwrite edited s. - -input= - YAML file to load oldname-newname pairs from. - -new-name= - The new name to change the symbol to. - -offset= - Locates the symbol by offset as opposed to :. - -old-name= - The fully qualified name of the symbol, if -offset is not used. - -p= - Build path. - - -Vim Integration -=============== - -You can call :program:`clang-rename` directly from Vim! To set up -:program:`clang-rename` integration for Vim see -`clang-rename/tool/clang-rename.py -`_. - -Please note that **you have to save all buffers, in which the replacement will -happen before running the tool**. - -Once installed, you can point your cursor to symbols you want to rename, press -`cr` and type new desired name. The ` key -`_ -is a reference to a specific key defined by the mapleader variable and is bound -to backslash by default. - -Emacs Integration -================= - -You can also use :program:`clang-rename` while using Emacs! To set up -:program:`clang-rename` integration for Emacs see -`clang-rename/tool/clang-rename.el -`_. - -Once installed, you can point your cursor to symbols you want to rename, press -`M-X`, type `clang-rename` and new desired name. - -Please note that **you have to save all buffers, in which the replacement will -happen before running the tool**. Index: docs/index.rst =================================================================== --- docs/index.rst +++ docs/index.rst @@ -24,7 +24,7 @@ include-fixer modularize pp-trace - clang-rename + clang-refactor/index Doxygen Documentation Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -44,7 +44,7 @@ clang-apply-replacements clang-include-fixer clang-query - clang-rename + clang-refactor clang-reorder-fields clang-tidy find-all-symbols Index: test/clang-refactor/rename/ClassAsTemplateArgument.cpp =================================================================== --- test/clang-refactor/rename/ClassAsTemplateArgument.cpp +++ test/clang-refactor/rename/ClassAsTemplateArgument.cpp @@ -13,9 +13,9 @@ } // Test 1. -// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=215 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=215 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/ClassFindByName.cpp =================================================================== --- test/clang-refactor/rename/ClassFindByName.cpp +++ test/clang-refactor/rename/ClassFindByName.cpp @@ -7,4 +7,4 @@ } // Test 1. -// RUN: clang-rename rename-all -old-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s Index: test/clang-refactor/rename/ClassReplacements.cpp =================================================================== --- test/clang-refactor/rename/ClassReplacements.cpp +++ test/clang-refactor/rename/ClassReplacements.cpp @@ -1,7 +1,7 @@ // RUN: rm -rf %t // RUN: mkdir -p %t/fixes // RUN: cat %s > %t.cpp -// RUN: clang-rename -offset=254 -new-name=Bar -export-fixes=%t/fixes/clang-rename.yaml %t.cpp -- +// RUN: clang-refactor rename -offset=273 -new-name=Bar -export-fixes=%t/fixes/clang-refactor-rename.yaml %t.cpp -- // RUN: clang-apply-replacements %t // RUN: sed 's,//.*,,' %t.cpp | FileCheck %s Index: test/clang-refactor/rename/ClassSimpleRenaming.cpp =================================================================== --- test/clang-refactor/rename/ClassSimpleRenaming.cpp +++ test/clang-refactor/rename/ClassSimpleRenaming.cpp @@ -6,9 +6,9 @@ void Foo::foo(int x) /* Test 2 */ {} // CHECK: void Bar::foo(int x) /* Test 2 */ {} // Test 1. -// RUN: clang-rename -offset=6 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=6 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=109 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=109 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/ClassTestMulti.cpp =================================================================== --- test/clang-refactor/rename/ClassTestMulti.cpp +++ test/clang-refactor/rename/ClassTestMulti.cpp @@ -5,7 +5,7 @@ }; // Test 1. -// RUN: clang-rename rename-all -offset=6 -new-name=Bar1 -offset=76 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=6 -new-name=Bar1 -offset=76 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/ClassTestMultiByName.cpp =================================================================== --- /dev/null +++ test/clang-refactor/rename/ClassTestMultiByName.cpp @@ -0,0 +1,8 @@ +class Foo1 { // CHECK: class Bar1 +}; + +class Foo2 { // CHECK: class Bar2 +}; + +// Test 1. +// RUN: clang-refactor rename -qualified-name=Foo1 -new-name=Bar1 -qualified-name=Foo2 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s Index: test/clang-refactor/rename/ClassTestMultiByNameYAML.cpp =================================================================== --- /dev/null +++ test/clang-refactor/rename/ClassTestMultiByNameYAML.cpp @@ -0,0 +1,10 @@ +class Foo1 { // CHECK: class Bar1 +}; + +class Foo2 { // CHECK: class Bar2 +}; + +// Test 1. +// RUN: clang-refactor rename -input %S/Inputs/ClassTestMultiByNameYAMLRenameAll.yaml %s -- | sed 's,//.*,,' | FileCheck %s +// Test 2. +// RUN: clang-refactor rename -input %S/Inputs/ClassTestMultiByNameYAMLRenameAt.yaml %s -- | sed 's,//.*,,' | FileCheck %s Index: test/clang-refactor/rename/ComplexFunctionOverride.cpp =================================================================== --- test/clang-refactor/rename/ComplexFunctionOverride.cpp +++ test/clang-refactor/rename/ComplexFunctionOverride.cpp @@ -33,15 +33,15 @@ } // Test 1. -// RUN: clang-rename -offset=26 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=26 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=109 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=109 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 3. -// RUN: clang-rename -offset=201 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=201 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 4. -// RUN: clang-rename -offset=293 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=293 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 5. -// RUN: clang-rename -offset=385 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=385 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'foo.*' Index: test/clang-refactor/rename/ComplicatedClassType.cpp =================================================================== --- test/clang-refactor/rename/ComplicatedClassType.cpp +++ test/clang-refactor/rename/ComplicatedClassType.cpp @@ -45,19 +45,19 @@ } // Test 1. -// RUN: clang-rename -offset=30 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=30 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=155 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=155 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s // Test 3. -// RUN: clang-rename -offset=1133 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=1133 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s // Test 4. -// RUN: clang-rename -offset=1266 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=1266 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s // Test 5. -// RUN: clang-rename -offset=1402 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=1402 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s // Test 6. -// RUN: clang-rename -offset=1533 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=1533 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s // Test 7. -// RUN: clang-rename -offset=1665 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=1665 -new-name=Bar %s -- -frtti | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/Ctor.cpp =================================================================== --- test/clang-refactor/rename/Ctor.cpp +++ test/clang-refactor/rename/Ctor.cpp @@ -6,9 +6,9 @@ Foo::Foo() /* Test 2 */ {} // CHECK: Bar::Bar() /* Test 2 */ {} // Test 1. -// RUN: clang-rename -offset=62 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=62 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=116 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=116 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/CtorInitializer.cpp =================================================================== --- test/clang-refactor/rename/CtorInitializer.cpp +++ test/clang-refactor/rename/CtorInitializer.cpp @@ -9,9 +9,9 @@ Qux::Qux() : Foo() /* Test 2 */ {} // CHECK: Qux::Qux() : Bar() /* Test 2 */ {} // Test 1. -// RUN: clang-rename -offset=33 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=33 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=118 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=118 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/DeclRefExpr.cpp =================================================================== --- test/clang-refactor/rename/DeclRefExpr.cpp +++ test/clang-refactor/rename/DeclRefExpr.cpp @@ -14,11 +14,11 @@ } // Test 1. -// RUN: clang-rename -offset=31 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=31 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=152 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=152 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 3. -// RUN: clang-rename -offset=271 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=271 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/Field.cpp =================================================================== --- test/clang-refactor/rename/Field.cpp +++ test/clang-refactor/rename/Field.cpp @@ -7,9 +7,9 @@ Baz::Baz() : Foo(0) /* Test 2 */ {} // CHECK: Baz::Baz() : Bar(0) // Test 1. -// RUN: clang-rename -offset=18 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=18 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=89 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=89 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/FunctionMacro.cpp =================================================================== --- test/clang-refactor/rename/FunctionMacro.cpp +++ test/clang-refactor/rename/FunctionMacro.cpp @@ -14,7 +14,7 @@ } // Test 1. -// RUN: clang-rename -offset=68 -new-name=macro_function %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=68 -new-name=macro_function %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'foo.*' Index: test/clang-refactor/rename/FunctionOverride.cpp =================================================================== --- test/clang-refactor/rename/FunctionOverride.cpp +++ test/clang-refactor/rename/FunctionOverride.cpp @@ -3,11 +3,11 @@ class C : public B { void foo(); /* Test 3 */ }; // CHECK: class C : public B { void bar(); // Test 1. -// RUN: clang-rename -offset=23 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=23 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=116 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=116 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 3. -// RUN: clang-rename -offset=209 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=209 -new-name=bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'foo.*' Index: test/clang-refactor/rename/FunctionWithClassFindByName.cpp =================================================================== --- test/clang-refactor/rename/FunctionWithClassFindByName.cpp +++ test/clang-refactor/rename/FunctionWithClassFindByName.cpp @@ -9,4 +9,4 @@ return 0; } -// RUN: clang-rename rename-all -old-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -qualified-name=Foo -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s Index: test/clang-refactor/rename/InvalidNewName.cpp =================================================================== --- /dev/null +++ test/clang-refactor/rename/InvalidNewName.cpp @@ -0,0 +1,2 @@ +// RUN: not clang-refactor rename -new-name=class -offset=133 %s 2>&1 | FileCheck %s +// CHECK: ERROR: new name is not a valid identifier in C++17. Index: test/clang-refactor/rename/MemberExprMacro.cpp =================================================================== --- test/clang-refactor/rename/MemberExprMacro.cpp +++ test/clang-refactor/rename/MemberExprMacro.cpp @@ -14,9 +14,9 @@ } // Test 1. -// RUN: clang-rename -offset=26 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=26 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=155 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=155 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/Namespace.cpp =================================================================== --- test/clang-refactor/rename/Namespace.cpp +++ test/clang-refactor/rename/Namespace.cpp @@ -7,7 +7,7 @@ } // Test 1. -// RUN: clang-rename -offset=10 -new-name=clang %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=10 -new-name=clang %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/NoNewName.cpp =================================================================== --- /dev/null +++ test/clang-refactor/rename/NoNewName.cpp @@ -0,0 +1,4 @@ +// Check for an error while -new-name argument has not been passed to +// clang-refactor rename. +// RUN: not clang-refactor rename -offset=133 %s 2>&1 | FileCheck %s +// CHECK: clang-refactor rename: -new-name or -input is required. Index: test/clang-refactor/rename/QualifiedNameNotFound.cpp =================================================================== --- /dev/null +++ test/clang-refactor/rename/QualifiedNameNotFound.cpp @@ -0,0 +1,2 @@ +// RUN: not clang-refactor rename -new-name=Foo -qualified-name=Bar %s -- 2>&1 | FileCheck %s +// CHECK: USREngine: could not find symbol Bar. Index: test/clang-refactor/rename/TemplateClassInstantiation.cpp =================================================================== --- test/clang-refactor/rename/TemplateClassInstantiation.cpp +++ test/clang-refactor/rename/TemplateClassInstantiation.cpp @@ -32,11 +32,11 @@ } // Test 1. -// RUN: clang-rename -offset=29 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=29 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=324 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=324 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s // Test 3. -// RUN: clang-rename -offset=463 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=463 -new-name=Bar %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/TemplateTypename.cpp =================================================================== --- test/clang-refactor/rename/TemplateTypename.cpp +++ test/clang-refactor/rename/TemplateTypename.cpp @@ -14,11 +14,11 @@ }; // Test 1. -// RUN: clang-rename -offset=19 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=19 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=126 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=126 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s // Test 3. -// RUN: clang-rename -offset=392 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=392 -new-name=U %s -- -fno-delayed-template-parsing | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'T.*' Index: test/clang-refactor/rename/UserDefinedConversion.cpp =================================================================== --- test/clang-refactor/rename/UserDefinedConversion.cpp +++ test/clang-refactor/rename/UserDefinedConversion.cpp @@ -18,9 +18,9 @@ } // Test 1. -// RUN: clang-rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=7 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=164 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=164 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/Variable.cpp =================================================================== --- test/clang-refactor/rename/Variable.cpp +++ test/clang-refactor/rename/Variable.cpp @@ -20,13 +20,13 @@ } // Test 1. -// RUN: clang-rename -offset=18 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=18 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=206 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=206 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 3. -// RUN: clang-rename -offset=613 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=613 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 4. -// RUN: clang-rename -offset=688 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=688 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-refactor/rename/VariableMacro.cpp =================================================================== --- test/clang-refactor/rename/VariableMacro.cpp +++ test/clang-refactor/rename/VariableMacro.cpp @@ -11,11 +11,11 @@ } // Test 1. -// RUN: clang-rename -offset=88 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=88 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 2. -// RUN: clang-rename -offset=129 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=129 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // Test 3. -// RUN: clang-rename -offset=191 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s +// RUN: clang-refactor rename -offset=191 -new-name=Bar %s -- | sed 's,//.*,,' | FileCheck %s // To find offsets after modifying the file, use: // grep -Ubo 'Foo.*' Index: test/clang-rename/ClassTestMultiByName.cpp =================================================================== --- test/clang-rename/ClassTestMultiByName.cpp +++ /dev/null @@ -1,8 +0,0 @@ -class Foo1 { // CHECK: class Bar1 -}; - -class Foo2 { // CHECK: class Bar2 -}; - -// Test 1. -// RUN: clang-rename rename-all -old-name=Foo1 -new-name=Bar1 -old-name=Foo2 -new-name=Bar2 %s -- | sed 's,//.*,,' | FileCheck %s Index: test/clang-rename/ClassTestMultiByNameYAML.cpp =================================================================== --- test/clang-rename/ClassTestMultiByNameYAML.cpp +++ /dev/null @@ -1,10 +0,0 @@ -class Foo1 { // CHECK: class Bar1 -}; - -class Foo2 { // CHECK: class Bar2 -}; - -// Test 1. -// RUN: clang-rename rename-all -input %S/Inputs/ClassTestMultiByNameYAMLRenameAll.yaml %s -- | sed 's,//.*,,' | FileCheck %s -// Test 2. -// RUN: clang-rename rename-all -input %S/Inputs/ClassTestMultiByNameYAMLRenameAt.yaml %s -- | sed 's,//.*,,' | FileCheck %s Index: test/clang-rename/InvalidNewName.cpp =================================================================== --- test/clang-rename/InvalidNewName.cpp +++ /dev/null @@ -1,2 +0,0 @@ -// RUN: not clang-rename -new-name=class -offset=133 %s 2>&1 | FileCheck %s -// CHECK: ERROR: new name is not a valid identifier in C++17. Index: test/clang-rename/InvalidOldName.cpp =================================================================== --- test/clang-rename/InvalidOldName.cpp +++ /dev/null @@ -1,2 +0,0 @@ -// RUN: not clang-rename rename-all -new-name=Foo -old-name=Bar %s -- 2>&1 | FileCheck %s -// CHECK: clang-rename: could not find symbol Bar. Index: test/clang-rename/NoNewName.cpp =================================================================== --- test/clang-rename/NoNewName.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Check for an error while -new-name argument has not been passed to -// clang-rename. -// RUN: not clang-rename -offset=133 %s 2>&1 | FileCheck %s -// CHECK: clang-rename: for the -new-name option: must be specified Index: unittests/CMakeLists.txt =================================================================== --- unittests/CMakeLists.txt +++ unittests/CMakeLists.txt @@ -6,7 +6,6 @@ endfunction() add_subdirectory(clang-apply-replacements) -add_subdirectory(clang-rename) add_subdirectory(clang-query) add_subdirectory(clang-tidy) add_subdirectory(include-fixer) Index: unittests/clang-rename/CMakeLists.txt =================================================================== --- unittests/clang-rename/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -set(LLVM_LINK_COMPONENTS - support - ) - -get_filename_component(CLANG_RENAME_SOURCE_DIR - ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-rename REALPATH) -include_directories( - ${CLANG_RENAME_SOURCE_DIR} - ) - -add_extra_unittest(ClangRenameTests - USRLocFindingTest.cpp - ${CLANG_RENAME_SOURCE_DIR}/USRFinder.cpp - ${CLANG_RENAME_SOURCE_DIR}/USRFindingAction.cpp - ) - -target_link_libraries(ClangRenameTests - clangAST - clangASTMatchers - clangBasic - clangFrontend - clangIndex - clangLex - clangTooling - ) Index: unittests/clang-rename/USRLocFindingTest.cpp =================================================================== --- unittests/clang-rename/USRLocFindingTest.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "USRFindingAction.h" -#include "clang/Tooling/Tooling.h" -#include "gtest/gtest.h" -#include -#include -#include - -namespace clang { -namespace rename { -namespace test { - -// Determines if the symbol group invariants hold. To recap, those invariants -// are: -// (1) All symbols in the same symbol group share the same USR. -// (2) Two symbols from two different groups do not share the same USR. -static void testOffsetGroups(const char *Code, - const std::vector> Groups) { - std::set AllUSRs, CurrUSR; - - for (const auto &Group : Groups) { - // Groups the invariants do not hold then the value of USR is also invalid, - // but at that point the test has already failed and USR ceases to be - // useful. - std::string USR; - for (const auto &Offset : Group) { - USRFindingAction Action(Offset, std::string()); - auto Factory = tooling::newFrontendActionFactory(&Action); - EXPECT_TRUE(tooling::runToolOnCode(Factory->create(), Code)); - const auto &USRs = Action.getUSRs(); - EXPECT_EQ(1u, USRs.size()); - USR = USRs[0]; - CurrUSR.insert(USR); - } - EXPECT_EQ(1u, CurrUSR.size()); - CurrUSR.clear(); - AllUSRs.insert(USR); - } - - EXPECT_EQ(Groups.size(), AllUSRs.size()); -} - - -TEST(USRLocFinding, FindsVarUSR) { - const char VarTest[] = "\n\ -namespace A {\n\ -int foo;\n\ -}\n\ -int foo;\n\ -int bar = foo;\n\ -int baz = A::foo;\n\ -void fun1() {\n\ - struct {\n\ - int foo;\n\ - } b = { 100 };\n\ - int foo = 100;\n\ - baz = foo;\n\ - {\n\ - extern int foo;\n\ - baz = foo;\n\ - foo = A::foo + baz;\n\ - A::foo = b.foo;\n\ - }\n\ - foo = b.foo;\n\ -}\n"; - std::vector> VarTestOffsets(3); - VarTestOffsets[0].push_back(19); - VarTestOffsets[0].push_back(63); - VarTestOffsets[0].push_back(205); - VarTestOffsets[0].push_back(223); - VarTestOffsets[1].push_back(30); - VarTestOffsets[1].push_back(45); - VarTestOffsets[1].push_back(172); - VarTestOffsets[1].push_back(187); - VarTestOffsets[2].push_back(129); - VarTestOffsets[2].push_back(148); - VarTestOffsets[2].push_back(242); - - testOffsetGroups(VarTest, VarTestOffsets); -} - -} // namespace test -} // namespace rename -} // namespace clang