Index: change-namespace/ChangeNamespace.cpp =================================================================== --- change-namespace/ChangeNamespace.cpp +++ change-namespace/ChangeNamespace.cpp @@ -559,13 +559,15 @@ SourceLocation Start = getLocAfterNamespaceLBrace( NsDecl, *Result.SourceManager, Result.Context->getLangOpts()); assert(Start.isValid() && "Can't find l_brace for namespace."); - SourceLocation End = NsDecl->getRBraceLoc().getLocWithOffset(-1); - // Create a replacement that deletes the code in the old namespace merely for - // retrieving offset and length from it. - const auto R = createReplacement(Start, End, "", *Result.SourceManager); + // Create a replacement merely for retrieving file path and start offset. + const auto R = createReplacement(Start, Start, "", *Result.SourceManager); MoveNamespace MoveNs; MoveNs.Offset = R.getOffset(); - MoveNs.Length = R.getLength(); + // The replacement contains token range, but we need to be more accurate and + // calculate offsets directly. Note that the range is from the location just + // past the left brace to the location right before the right brace. + MoveNs.Length = Result.SourceManager->getFileOffset(NsDecl->getRBraceLoc()) - + Result.SourceManager->getFileOffset(Start); // Insert the new namespace after `DiffOldNamespace`. For example, if // `OldNamespace` is "a::b::c" and `NewNamespace` is `a::x::y`, then Index: unittests/change-namespace/ChangeNamespaceTests.cpp =================================================================== --- unittests/change-namespace/ChangeNamespaceTests.cpp +++ unittests/change-namespace/ChangeNamespaceTests.cpp @@ -110,12 +110,52 @@ "namespace nc {\n" "class A {};\n" "} // namespace nc\n" + "} // namespace nb\n" + "} // namespace na\n"; + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); +} + +TEST_F(ChangeNamespaceTest, NewNsNestedInOldNsWithSurroundingNewLines) { + NewNamespace = "na::nb::nc"; + std::string Code = "namespace na {\n" + "namespace nb {\n" + "\n" + "class A {};\n" + "\n" + "} // namespace nb\n" + "} // namespace na\n"; + std::string Expected = "namespace na {\n" + "namespace nb {\n" + "namespace nc {\n" + "\n" + "class A {};\n" "\n" + "} // namespace nc\n" "} // namespace nb\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); } +TEST_F(ChangeNamespaceTest, MoveOldNsWithSurroundingNewLines) { + NewNamespace = "nx::ny"; + std::string Code = "namespace na {\n" + "namespace nb {\n" + "\n" + "class A {};\n" + "\n" + "} // namespace nb\n" + "} // namespace na\n"; + std::string Expected = "\n\n" + "namespace nx {\n" + "namespace ny {\n" + "\n" + "class A {};\n" + "\n" + "} // namespace ny\n" + "} // namespace nx\n"; + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); +} + TEST_F(ChangeNamespaceTest, NewNsNestedInOldNsWithRefs) { NewNamespace = "na::nb::nc"; std::string Code = "namespace na {\n" @@ -134,7 +174,6 @@ "class C {};\n" "void f() { A a; B b; }\n" "} // namespace nc\n" - "\n" "} // namespace nb\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); @@ -1497,7 +1536,7 @@ "void f() {\n" " GG g;\n" "}\n" - "} // namespace nc\n\n" + "} // namespace nc\n" "} // namespace nb\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); @@ -1554,7 +1593,7 @@ " struct Derived::Nested nested;\n" " const struct Derived::Nested *nested_ptr;\n" "}\n" - "} // namespace nc\n\n" + "} // namespace nc\n" "} // namespace nb\n" "} // namespace na\n"; EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));