Index: clang-rename/RenamingAction.cpp =================================================================== --- clang-rename/RenamingAction.cpp +++ clang-rename/RenamingAction.cpp @@ -57,19 +57,16 @@ } auto PrevNameLen = PrevName.length(); - if (PrintLocations) - for (const auto &Loc : RenamingCandidates) { + for (const auto &Loc : RenamingCandidates) { + if (PrintLocations) { FullSourceLoc FullLoc(Loc, SourceMgr); errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc) << ":" << FullLoc.getSpellingLineNumber() << ":" << FullLoc.getSpellingColumnNumber() << "\n"; - Replaces.insert(tooling::Replacement(SourceMgr, Loc, PrevNameLen, - NewName)); } - else - for (const auto &Loc : RenamingCandidates) - Replaces.insert(tooling::Replacement(SourceMgr, Loc, PrevNameLen, - NewName)); + Replaces.insert(tooling::Replacement(SourceMgr, Loc, PrevNameLen, + NewName)); + } } private: Index: clang-rename/USRFinder.cpp =================================================================== --- clang-rename/USRFinder.cpp +++ clang-rename/USRFinder.cpp @@ -77,6 +77,11 @@ Decl->getNameAsString().length()); } + bool VisitTypeLoc(const TypeLoc Loc) { + return setResult(Loc.getType()->getAsCXXRecordDecl(), + Loc.getBeginLoc(), Loc.getEndLoc()); + } + // Other: const NamedDecl *getNamedDecl() { Index: clang-rename/USRLocFinder.cpp =================================================================== --- clang-rename/USRLocFinder.cpp +++ clang-rename/USRLocFinder.cpp @@ -136,17 +136,6 @@ return true; } - bool VisitCXXConstructExpr(const CXXConstructExpr *Expr) { - CXXConstructorDecl *Decl = Expr->getConstructor(); - - if (getUSRForDecl(Decl) == USR) { - // This takes care of 'new ' expressions. - LocationsFound.push_back(Expr->getLocation()); - } - - return true; - } - bool VisitCXXStaticCastExpr(clang::CXXStaticCastExpr *Expr) { return handleCXXNamedCastExpr(Expr); } @@ -163,6 +152,18 @@ return handleCXXNamedCastExpr(Expr); } + // Other visitors: + + // FIXME: Given "clang::TypeLoc" this currently pushes "clang::" location to + // the LocationsFound storage while it should push "TypeLoc" location. I don't + // know how to address it yet, but it should fix quite many bugs. + bool VisitTypeLoc(const TypeLoc Loc) { + if (getUSRForDecl(Loc.getType()->getAsCXXRecordDecl()) == USR) { + LocationsFound.push_back(Loc.getLocStart()); + } + return true; + } + // Non-visitors: // \brief Returns a list of unique locations. Duplicate or overlapping Index: test/clang-rename/ClassNameInFunctionDefenition.cpp =================================================================== --- test/clang-rename/ClassNameInFunctionDefenition.cpp +++ test/clang-rename/ClassNameInFunctionDefenition.cpp @@ -1,17 +1,10 @@ -// Currently unsupported test. // RUN: cat %s > %t.cpp -// FIXME: clang-rename doesn't recognize symbol in class function definition. +// RUN: clang-rename -offset=136 -new-name=Bar %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s -class Foo { +class Foo { // CHECK: class Bar { public: void foo(int x); }; -void Foo::foo(int x) {} -// ^ this one - -int main() { - Foo obj; - obj.foo(0); - return 0; -} +void Foo::foo(int x) {} // CHECK: void Bar::foo(int x) {} Index: test/clang-rename/ComplicatedClassType.cpp =================================================================== --- test/clang-rename/ComplicatedClassType.cpp +++ test/clang-rename/ComplicatedClassType.cpp @@ -1,30 +1,31 @@ -// Unsupported test. // RUN: cat %s > %t.cpp -// FIXME: This test contains very simple constructions likely to be seen in any -// project and therefore passing this test is a slight sign of success. -// Currently, the test fails badly. +// RUN: clang-rename -offset=220 -new-name=Bar %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s + +// Forward declaration. +class Foo; // CHECK: class Bar; class Foo { // CHECK: class Bar { - public: - Foo(int value = 0) : x(value) {} // Bar(int value=0) : x(value) {} +public: + Foo(int value = 0) : x(value) {} // CHECK: Bar(int value = 0) : x(value) {} - Foo& operator++(int) { // Bar& operator++(int) { + Foo &operator++(int) { // CHECK: Bar &operator++(int) { x++; return *this; } - bool operator<(Foo const& rhs) { // bool operator<(Bar const &rhs) { + bool operator<(Foo const &rhs) { // CHECK: bool operator<(Bar const &rhs) { return this->x < rhs.x; } - private: +private: int x; }; int main() { - Foo* Pointer = 0; // CHECK: Bar *Pointer = 0; + Foo *Pointer = 0; // CHECK: Bar *Pointer = 0; Foo Variable = Foo(10); // CHECK: Bar Variable = Bar(10); - for (Foo it; it < Variable; it++) { // for (Bar it; it < Variable; it++) {} + for (Foo it; it < Variable; it++) { // CHECK: for (Bar it; it < Variable; it++) { } return 0; } Index: test/clang-rename/ComplicatedClassTypeInCustomNamespace.cpp =================================================================== --- /dev/null +++ test/clang-rename/ComplicatedClassTypeInCustomNamespace.cpp @@ -0,0 +1,42 @@ +// RUN: cat %s > %t.cpp +// RUN: clang-rename -offset=327 -new-name=Bar %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s + +// Currently unsupported test. +// FIXME: clang-rename currently fails to get correct while renaming types with +// nested name specifier. +// XFAIL: * + +namespace baz { + +// Forward declaration. +class Foo; // CHECK: class Bar; + +class Foo { // CHECK: class Bar { + public: + Foo(int value = 0) : x(value) {} // CHECK: Bar(int value = 0) : x(value) {} + + Foo &operator++(int) { // CHECK: Bar &operator++(int) { + x++; + return *this; + } + + bool operator<(Foo const &rhs) { // CHECK: bool operator<(Bar const &rhs) { + return this->x < rhs.x; + } + + private: + int x; +}; + +Foo Instance; // CHECK: Bar Instance; + +} + +int main() { + baz::Foo *Pointer = 0; // CHECK: baz::Bar *Pointer = 0; + baz::Foo Variable = baz::Foo(10); // CHECK: baz::Bar Variable = baz::Bar(10); + for (baz::Foo it; it < Variable; it++) { // CHECK: for (baz::Bar it; it < Variable; it++) {} + } + return 0; +} Index: test/clang-rename/NestedNamespace.cpp =================================================================== --- /dev/null +++ test/clang-rename/NestedNamespace.cpp @@ -0,0 +1,42 @@ +// RUN: cat %s > %t.cpp +// RUN: clang-rename -offset=274 -new-name=Bar %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s + +// Currently unsupported test. +// FIXME: Teach clang-rename to rename namespace in nested constructions. +// XFAIL: * + +namespace Baz { +namespace Foo { // CHECK: namespace Bar { +class A { +public: + static int aFunction() { return 0; } +}; +int FooFunction() { return 0; } +namespace Qux { +class B { +public: + static int bFunction() { return 0; } +}; +int QuxFunction() { return 0; } +} // namespace Qux +} // namespace Foo +} // namespace Baz + +int main() { + + // Variable type tests. + Baz::Foo::A a; // CHECK: Baz::Bar::A a; + Baz::Foo::Qux::B b; // CHECK: Baz::Bar::Qux::B b; + unsigned i = 42; + for (Baz::Foo::A c; i < 100; i++); // CHECK: for (Baz::Bar::A c; i < 100; i++); + for (Baz::Foo::Qux::B d; i < 200; i++); // CHECK: for (Baz::Bar::Qux::B d; i < 200; i++); + + // Function tests. + int x = Baz::Foo::A::aFunction(); // CHECK: int x = Baz::Bar::A::aFunction(); + x = Baz::Foo::FooFunction(); // CHECK: x = Baz::Bar::FooFunction(); + x = Baz::Foo::Qux::B::bFunction(); // CHECK: x = Baz::Bar::Qux::B::bFunction(); + x = Baz::Foo::Qux::QuxFunction(); // CHECK: x = Baz::Bar::Qux::QuxFunction(); + + return 0; +} Index: test/clang-rename/TemplateTypename.cpp =================================================================== --- test/clang-rename/TemplateTypename.cpp +++ test/clang-rename/TemplateTypename.cpp @@ -1,12 +1,20 @@ -// Currently unsupported test. // RUN: cat %s > %t.cpp +// RUN: clang-rename -offset=270 -new-name=U %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s + +// Currently unsupported test. // FIXME: clang-rename should be able to rename template parameters correctly. +// XFAIL: * -template -T foo(T arg, T& ref, T* ptr) { - T value; +template // CHECK: template +class Foo { +T foo(T arg, T& ref, T* ptr) { // CHECK: U foo(U arg, U& ref, U* ptr) { + T value; // CHECK: U value; int number = 42; - value = (T)number; - value = static_cast(number); + value = (T)number; // CHECK: value = (U)number; + value = static_cast(number); // CHECK: value = static_cast(number); return value; } + +T member; // CHECK: U member; +}; Index: test/clang-rename/UserDefinedConversionFindByConversion.cpp =================================================================== --- test/clang-rename/UserDefinedConversionFindByConversion.cpp +++ test/clang-rename/UserDefinedConversionFindByConversion.cpp @@ -1,11 +1,10 @@ -// Currently unsupported test. // RUN: cat %s > %t.cpp -// FIXME: clang-rename should handle conversions from a class type to another -// type. +// RUN: clang-rename -offset=136 -new-name=Bar %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo {}; // CHECK: class Bar {}; -class Baz { // CHECK: class Bar { +class Baz { operator Foo() const { // CHECK: operator Bar() const { Foo foo; // CHECK: Bar foo; return foo; Index: test/clang-rename/UserDefinedConversionFindByTypeDeclaration.cpp =================================================================== --- test/clang-rename/UserDefinedConversionFindByTypeDeclaration.cpp +++ test/clang-rename/UserDefinedConversionFindByTypeDeclaration.cpp @@ -1,7 +1,6 @@ -// Currently unsupported test. // RUN: cat %s > %t.cpp -// FIXME: while renaming class/struct clang-rename should be able to change -// this type name corresponding user-defined conversions, too. +// RUN: clang-rename -offset=136 -new-name=Bar %t.cpp -i -- +// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s class Foo { // CHECK: class Bar { // ^ offset must be here