forked from OSchip/llvm-project
[change-namespace] consider namespace aliases to shorten qualified names.
Reviewers: hokein Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D28052 llvm-svn: 290421
This commit is contained in:
parent
0ff941620c
commit
180dac6396
|
@ -306,6 +306,11 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
|
|||
IsVisibleInNewNs)
|
||||
.bind("using_namespace"),
|
||||
this);
|
||||
// Match namespace alias declarations.
|
||||
Finder->addMatcher(namespaceAliasDecl(isExpansionInFileMatching(FilePattern),
|
||||
IsVisibleInNewNs)
|
||||
.bind("namespace_alias"),
|
||||
this);
|
||||
|
||||
// Match old namespace blocks.
|
||||
Finder->addMatcher(
|
||||
|
@ -429,6 +434,10 @@ void ChangeNamespaceTool::run(
|
|||
Result.Nodes.getNodeAs<UsingDirectiveDecl>(
|
||||
"using_namespace")) {
|
||||
UsingNamespaceDecls.insert(UsingNamespace);
|
||||
} else if (const auto *NamespaceAlias =
|
||||
Result.Nodes.getNodeAs<NamespaceAliasDecl>(
|
||||
"namespace_alias")) {
|
||||
NamespaceAliasDecls.insert(NamespaceAlias);
|
||||
} else if (const auto *NsDecl =
|
||||
Result.Nodes.getNodeAs<NamespaceDecl>("old_ns")) {
|
||||
moveOldNamespace(Result, NsDecl);
|
||||
|
@ -687,6 +696,38 @@ void ChangeNamespaceTool::replaceQualifiedSymbolInDeclContext(
|
|||
ReplaceName = FromDeclNameRef;
|
||||
}
|
||||
}
|
||||
// Checks if there is any namespace alias declarations that can shorten the
|
||||
// qualified name.
|
||||
for (const auto *NamespaceAlias : NamespaceAliasDecls) {
|
||||
if (!isDeclVisibleAtLocation(*Result.SourceManager, NamespaceAlias, DeclCtx,
|
||||
Start))
|
||||
continue;
|
||||
StringRef FromDeclNameRef = FromDeclName;
|
||||
if (FromDeclNameRef.consume_front(
|
||||
NamespaceAlias->getNamespace()->getQualifiedNameAsString() +
|
||||
"::")) {
|
||||
std::string AliasName = NamespaceAlias->getNameAsString();
|
||||
std::string AliasQualifiedName =
|
||||
NamespaceAlias->getQualifiedNameAsString();
|
||||
// We only consider namespace aliases define in the global namepspace or
|
||||
// in namespaces that are directly visible from the reference, i.e.
|
||||
// ancestor of the `OldNs`. Note that declarations in ancestor namespaces
|
||||
// but not visible in the new namespace is filtered out by
|
||||
// "IsVisibleInNewNs" matcher.
|
||||
if (AliasQualifiedName != AliasName) {
|
||||
// The alias is defined in some namespace.
|
||||
assert(StringRef(AliasQualifiedName).endswith("::" + AliasName));
|
||||
llvm::StringRef AliasNs =
|
||||
StringRef(AliasQualifiedName).drop_back(AliasName.size() + 2);
|
||||
if (!llvm::StringRef(OldNs).startswith(AliasNs))
|
||||
continue;
|
||||
}
|
||||
std::string NameWithAliasNamespace =
|
||||
(AliasName + "::" + FromDeclNameRef).str();
|
||||
if (NameWithAliasNamespace.size() < ReplaceName.size())
|
||||
ReplaceName = NameWithAliasNamespace;
|
||||
}
|
||||
}
|
||||
// Checks if there is any using shadow declarations that can shorten the
|
||||
// qualified name.
|
||||
bool Matched = false;
|
||||
|
|
|
@ -154,6 +154,9 @@ private:
|
|||
// Records all using namespace declarations, which can be used to shorten
|
||||
// namespace specifiers.
|
||||
llvm::SmallPtrSet<const UsingDirectiveDecl *, 8> UsingNamespaceDecls;
|
||||
// Records all namespace alias declarations, which can be used to shorten
|
||||
// namespace specifiers.
|
||||
llvm::SmallPtrSet<const NamespaceAliasDecl *, 8> NamespaceAliasDecls;
|
||||
// TypeLocs of CXXCtorInitializer. Types of CXXCtorInitializers do not need to
|
||||
// be fixed.
|
||||
llvm::SmallVector<TypeLoc, 8> BaseCtorInitializerTypeLocs;
|
||||
|
|
|
@ -825,6 +825,114 @@ TEST_F(ChangeNamespaceTest, UsingNamespaceInGlobal) {
|
|||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, NamespaceAliasInGlobal) {
|
||||
std::string Code = "namespace glob {\n"
|
||||
"class Glob {};\n"
|
||||
"}\n"
|
||||
"namespace glob2 { class Glob2 {}; }\n"
|
||||
"namespace gl = glob;\n"
|
||||
"namespace gl2 = ::glob2;\n"
|
||||
"namespace na {\n"
|
||||
"namespace nb {\n"
|
||||
"void f() { gl::Glob g; gl2::Glob2 g2; }\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
|
||||
std::string Expected =
|
||||
"namespace glob {\n"
|
||||
"class Glob {};\n"
|
||||
"}\n"
|
||||
"namespace glob2 { class Glob2 {}; }\n"
|
||||
"namespace gl = glob;\n"
|
||||
"namespace gl2 = ::glob2;\n"
|
||||
"\n"
|
||||
"namespace x {\n"
|
||||
"namespace y {\n"
|
||||
"void f() { gl::Glob g; gl2::Glob2 g2; }\n"
|
||||
"} // namespace y\n"
|
||||
"} // namespace x\n";
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, NamespaceAliasInNamespace) {
|
||||
std::string Code = "namespace glob {\n"
|
||||
"class Glob {};\n"
|
||||
"}\n"
|
||||
"namespace na {\n"
|
||||
"namespace nb {\n"
|
||||
"namespace gl = glob;\n"
|
||||
"void f() { gl::Glob g; }\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
|
||||
std::string Expected = "namespace glob {\n"
|
||||
"class Glob {};\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"namespace x {\n"
|
||||
"namespace y {\n"
|
||||
"namespace gl = glob;\n"
|
||||
"void f() { gl::Glob g; }\n"
|
||||
"} // namespace y\n"
|
||||
"} // namespace x\n";
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, NamespaceAliasInAncestorNamespace) {
|
||||
NewNamespace = "na::nx";
|
||||
std::string Code = "namespace glob {\n"
|
||||
"class Glob {};\n"
|
||||
"}\n"
|
||||
"namespace other { namespace gl = glob; }\n"
|
||||
"namespace na {\n"
|
||||
"namespace ga = glob;\n"
|
||||
"namespace nb {\n"
|
||||
"void f() { ga::Glob g; }\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
|
||||
std::string Expected = "namespace glob {\n"
|
||||
"class Glob {};\n"
|
||||
"}\n"
|
||||
"namespace other { namespace gl = glob; }\n"
|
||||
"namespace na {\n"
|
||||
"namespace ga = glob;\n"
|
||||
"\n"
|
||||
"namespace nx {\n"
|
||||
"void f() { ga::Glob g; }\n"
|
||||
"} // namespace nx\n"
|
||||
"} // namespace na\n";
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, NamespaceAliasInOtherNamespace) {
|
||||
std::string Code = "namespace glob {\n"
|
||||
"class Glob {};\n"
|
||||
"}\n"
|
||||
"namespace other { namespace gl = glob; }\n"
|
||||
"namespace na {\n"
|
||||
"namespace ga = glob;\n"
|
||||
"namespace nb {\n"
|
||||
"void f() { glob::Glob g; }\n"
|
||||
"} // namespace nb\n"
|
||||
"} // namespace na\n";
|
||||
|
||||
std::string Expected = "namespace glob {\n"
|
||||
"class Glob {};\n"
|
||||
"}\n"
|
||||
"namespace other { namespace gl = glob; }\n"
|
||||
"namespace na {\n"
|
||||
"namespace ga = glob;\n"
|
||||
"\n"
|
||||
"} // namespace na\n"
|
||||
"namespace x {\n"
|
||||
"namespace y {\n"
|
||||
"void f() { glob::Glob g; }\n"
|
||||
"} // namespace y\n"
|
||||
"} // namespace x\n";
|
||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
||||
}
|
||||
|
||||
TEST_F(ChangeNamespaceTest, UsingDeclAfterReference) {
|
||||
std::string Code = "namespace glob {\n"
|
||||
"class Glob {};\n"
|
||||
|
|
Loading…
Reference in New Issue