forked from OSchip/llvm-project
Handle adding new nested namespace in old namespace.
Reviewers: hokein Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D26456 llvm-svn: 286486
This commit is contained in:
parent
231c655851
commit
6aa9416d06
|
@ -57,16 +57,19 @@ SourceLocation EndLocationForType(TypeLoc TLoc) {
|
|||
}
|
||||
|
||||
// Returns the containing namespace of `InnerNs` by skipping `PartialNsName`.
|
||||
// If the `InnerNs` does not have `PartialNsName` as suffix, nullptr is
|
||||
// returned.
|
||||
// If the `InnerNs` does not have `PartialNsName` as suffix, or `PartialNsName`
|
||||
// is empty, nullptr is returned.
|
||||
// For example, if `InnerNs` is "a::b::c" and `PartialNsName` is "b::c", then
|
||||
// the NamespaceDecl of namespace "a" will be returned.
|
||||
const NamespaceDecl *getOuterNamespace(const NamespaceDecl *InnerNs,
|
||||
llvm::StringRef PartialNsName) {
|
||||
if (!InnerNs || PartialNsName.empty())
|
||||
return nullptr;
|
||||
const auto *CurrentContext = llvm::cast<DeclContext>(InnerNs);
|
||||
const auto *CurrentNs = InnerNs;
|
||||
llvm::SmallVector<llvm::StringRef, 4> PartialNsNameSplitted;
|
||||
PartialNsName.split(PartialNsNameSplitted, "::");
|
||||
PartialNsName.split(PartialNsNameSplitted, "::", /*MaxSplit=*/-1,
|
||||
/*KeepEmpty=*/false);
|
||||
while (!PartialNsNameSplitted.empty()) {
|
||||
// Get the inner-most namespace in CurrentContext.
|
||||
while (CurrentContext && !llvm::isa<NamespaceDecl>(CurrentContext))
|
||||
|
@ -468,16 +471,20 @@ void ChangeNamespaceTool::moveOldNamespace(
|
|||
// "x::y" will be inserted inside the existing namespace "a" and after "a::b".
|
||||
// `OuterNs` is the first namespace in `DiffOldNamespace`, e.g. "namespace b"
|
||||
// in the above example.
|
||||
// FIXME: consider the case where DiffOldNamespace is empty.
|
||||
// If there is no outer namespace (i.e. DiffOldNamespace is empty), the new
|
||||
// namespace will be a nested namespace in the old namespace.
|
||||
const NamespaceDecl *OuterNs = getOuterNamespace(NsDecl, DiffOldNamespace);
|
||||
SourceLocation LocAfterNs =
|
||||
getStartOfNextLine(OuterNs->getRBraceLoc(), *Result.SourceManager,
|
||||
Result.Context->getLangOpts());
|
||||
assert(LocAfterNs.isValid() &&
|
||||
"Failed to get location after DiffOldNamespace");
|
||||
SourceLocation InsertionLoc = Start;
|
||||
if (OuterNs) {
|
||||
SourceLocation LocAfterNs =
|
||||
getStartOfNextLine(OuterNs->getRBraceLoc(), *Result.SourceManager,
|
||||
Result.Context->getLangOpts());
|
||||
assert(LocAfterNs.isValid() &&
|
||||
"Failed to get location after DiffOldNamespace");
|
||||
InsertionLoc = LocAfterNs;
|
||||
}
|
||||
MoveNs.InsertionOffset = Result.SourceManager->getFileOffset(
|
||||
Result.SourceManager->getSpellingLoc(LocAfterNs));
|
||||
|
||||
Result.SourceManager->getSpellingLoc(InsertionLoc));
|
||||
MoveNs.FID = Result.SourceManager->getFileID(Start);
|
||||
MoveNs.SourceMgr = Result.SourceManager;
|
||||
MoveNamespaces[R.getFilePath()].push_back(MoveNs);
|
||||
|
|
|
@ -97,6 +97,48 @@ TEST_F(ChangeNamespaceTest, SimpleMoveWithoutTypeRefs) {
|
|||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, NewNsNestedInOldNs) {
|
||||
NewNamespace = "na::nb::nc";
|
||||
std::string Code = "namespace na {\n"
|
||||
"namespace nb {\n"
|
||||
"class A {};\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
std::string Expected = "namespace na {\n"
|
||||
"namespace nb {\n"
|
||||
"namespace nc {\n"
|
||||
"class A {};\n"
|
||||
"} // namespace nc\n"
|
||||
"\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, NewNsNestedInOldNsWithRefs) {
|
||||
NewNamespace = "na::nb::nc";
|
||||
std::string Code = "namespace na {\n"
|
||||
"class A {};\n"
|
||||
"namespace nb {\n"
|
||||
"class B {};\n"
|
||||
"class C {};\n"
|
||||
"void f() { A a; B b; }\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
std::string Expected = "namespace na {\n"
|
||||
"class A {};\n"
|
||||
"namespace nb {\n"
|
||||
"namespace nc {\n"
|
||||
"class B {};\n"
|
||||
"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));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, SimpleMoveIntoAnotherNestedNamespace) {
|
||||
NewNamespace = "na::nc";
|
||||
std::string Code = "namespace na {\n"
|
||||
|
|
Loading…
Reference in New Issue