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)
|
IsVisibleInNewNs)
|
||||||
.bind("using_namespace"),
|
.bind("using_namespace"),
|
||||||
this);
|
this);
|
||||||
|
// Match namespace alias declarations.
|
||||||
|
Finder->addMatcher(namespaceAliasDecl(isExpansionInFileMatching(FilePattern),
|
||||||
|
IsVisibleInNewNs)
|
||||||
|
.bind("namespace_alias"),
|
||||||
|
this);
|
||||||
|
|
||||||
// Match old namespace blocks.
|
// Match old namespace blocks.
|
||||||
Finder->addMatcher(
|
Finder->addMatcher(
|
||||||
|
@ -429,6 +434,10 @@ void ChangeNamespaceTool::run(
|
||||||
Result.Nodes.getNodeAs<UsingDirectiveDecl>(
|
Result.Nodes.getNodeAs<UsingDirectiveDecl>(
|
||||||
"using_namespace")) {
|
"using_namespace")) {
|
||||||
UsingNamespaceDecls.insert(UsingNamespace);
|
UsingNamespaceDecls.insert(UsingNamespace);
|
||||||
|
} else if (const auto *NamespaceAlias =
|
||||||
|
Result.Nodes.getNodeAs<NamespaceAliasDecl>(
|
||||||
|
"namespace_alias")) {
|
||||||
|
NamespaceAliasDecls.insert(NamespaceAlias);
|
||||||
} else if (const auto *NsDecl =
|
} else if (const auto *NsDecl =
|
||||||
Result.Nodes.getNodeAs<NamespaceDecl>("old_ns")) {
|
Result.Nodes.getNodeAs<NamespaceDecl>("old_ns")) {
|
||||||
moveOldNamespace(Result, NsDecl);
|
moveOldNamespace(Result, NsDecl);
|
||||||
|
@ -687,6 +696,38 @@ void ChangeNamespaceTool::replaceQualifiedSymbolInDeclContext(
|
||||||
ReplaceName = FromDeclNameRef;
|
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
|
// Checks if there is any using shadow declarations that can shorten the
|
||||||
// qualified name.
|
// qualified name.
|
||||||
bool Matched = false;
|
bool Matched = false;
|
||||||
|
|
|
@ -154,6 +154,9 @@ private:
|
||||||
// Records all using namespace declarations, which can be used to shorten
|
// Records all using namespace declarations, which can be used to shorten
|
||||||
// namespace specifiers.
|
// namespace specifiers.
|
||||||
llvm::SmallPtrSet<const UsingDirectiveDecl *, 8> UsingNamespaceDecls;
|
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
|
// TypeLocs of CXXCtorInitializer. Types of CXXCtorInitializers do not need to
|
||||||
// be fixed.
|
// be fixed.
|
||||||
llvm::SmallVector<TypeLoc, 8> BaseCtorInitializerTypeLocs;
|
llvm::SmallVector<TypeLoc, 8> BaseCtorInitializerTypeLocs;
|
||||||
|
|
|
@ -825,6 +825,114 @@ TEST_F(ChangeNamespaceTest, UsingNamespaceInGlobal) {
|
||||||
EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code));
|
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) {
|
TEST_F(ChangeNamespaceTest, UsingDeclAfterReference) {
|
||||||
std::string Code = "namespace glob {\n"
|
std::string Code = "namespace glob {\n"
|
||||||
"class Glob {};\n"
|
"class Glob {};\n"
|
||||||
|
|
Loading…
Reference in New Issue