[clang-tools-extra] r368842 - [clangd] Print qualifiers of out-of-line definitions in document outline
Ilya Biryukov via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 14 05:51:05 PDT 2019
Author: ibiryukov
Date: Wed Aug 14 05:51:04 2019
New Revision: 368842
URL: http://llvm.org/viewvc/llvm-project?rev=368842&view=rev
Log:
[clangd] Print qualifiers of out-of-line definitions in document outline
Summary: To improve the UX around navigating and searching through the results.
Reviewers: hokein
Reviewed By: hokein
Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66215
Modified:
clang-tools-extra/trunk/clangd/AST.cpp
clang-tools-extra/trunk/clangd/unittests/FindSymbolsTests.cpp
Modified: clang-tools-extra/trunk/clangd/AST.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/AST.cpp?rev=368842&r1=368841&r2=368842&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/AST.cpp (original)
+++ clang-tools-extra/trunk/clangd/AST.cpp Wed Aug 14 05:51:04 2019
@@ -12,6 +12,9 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/TemplateBase.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
@@ -96,10 +99,27 @@ std::string printQualifiedName(const Nam
return QName;
}
+static bool isAnonymous(const DeclarationName &N) {
+ return N.isIdentifier() && !N.getAsIdentifierInfo();
+}
+
+/// Returns a nested name specifier of \p ND if it was present in the source,
+/// e.g.
+/// void ns::something::foo() -> returns 'ns::something'
+/// void foo() -> returns null
+static NestedNameSpecifier *getQualifier(const NamedDecl &ND) {
+ if (auto *V = llvm::dyn_cast<DeclaratorDecl>(&ND))
+ return V->getQualifier();
+ if (auto *T = llvm::dyn_cast<TagDecl>(&ND))
+ return T->getQualifier();
+ return nullptr;
+}
+
std::string printName(const ASTContext &Ctx, const NamedDecl &ND) {
std::string Name;
llvm::raw_string_ostream Out(Name);
PrintingPolicy PP(Ctx.getLangOpts());
+
// Handle 'using namespace'. They all have the same name - <using-directive>.
if (auto *UD = llvm::dyn_cast<UsingDirectiveDecl>(&ND)) {
Out << "using namespace ";
@@ -108,19 +128,27 @@ std::string printName(const ASTContext &
UD->getNominatedNamespaceAsWritten()->printName(Out);
return Out.str();
}
- ND.getDeclName().print(Out, PP);
- if (!Out.str().empty()) {
- Out << printTemplateSpecializationArgs(ND);
- return Out.str();
+
+ if (isAnonymous(ND.getDeclName())) {
+ // Come up with a presentation for an anonymous entity.
+ if (isa<NamespaceDecl>(ND))
+ return "(anonymous namespace)";
+ if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND))
+ return ("(anonymous " + Cls->getKindName() + ")").str();
+ if (isa<EnumDecl>(ND))
+ return "(anonymous enum)";
+ return "(anonymous)";
}
- // The name was empty, so present an anonymous entity.
- if (isa<NamespaceDecl>(ND))
- return "(anonymous namespace)";
- if (auto *Cls = llvm::dyn_cast<RecordDecl>(&ND))
- return ("(anonymous " + Cls->getKindName() + ")").str();
- if (isa<EnumDecl>(ND))
- return "(anonymous enum)";
- return "(anonymous)";
+
+ // Print nested name qualifier if it was written in the source code.
+ if (auto *Qualifier = getQualifier(ND))
+ Qualifier->print(Out, PP);
+ // Print the name itself.
+ ND.getDeclName().print(Out, PP);
+ // Print template arguments.
+ Out << printTemplateSpecializationArgs(ND);
+
+ return Out.str();
}
std::string printTemplateSpecializationArgs(const NamedDecl &ND) {
Modified: clang-tools-extra/trunk/clangd/unittests/FindSymbolsTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/FindSymbolsTests.cpp?rev=368842&r1=368841&r2=368842&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/FindSymbolsTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/FindSymbolsTests.cpp Wed Aug 14 05:51:04 2019
@@ -19,7 +19,6 @@ namespace clangd {
namespace {
using ::testing::AllOf;
-using ::testing::AnyOf;
using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
using ::testing::Field;
@@ -414,21 +413,22 @@ TEST_F(DocumentSymbolsTest, BasicSymbols
AllOf(WithName("KInt"), WithKind(SymbolKind::Variable), Children()),
AllOf(WithName("kStr"), WithKind(SymbolKind::Variable), Children()),
AllOf(WithName("f1"), WithKind(SymbolKind::Function), Children()),
- AllOf(WithName("foo"), WithKind(SymbolKind::Namespace),
- Children(
- AllOf(WithName("int32"), WithKind(SymbolKind::Class),
- Children()),
- AllOf(WithName("int32_t"), WithKind(SymbolKind::Class),
- Children()),
- AllOf(WithName("v1"), WithKind(SymbolKind::Variable),
- Children()),
- AllOf(WithName("bar"), WithKind(SymbolKind::Namespace),
- Children(AllOf(WithName("v2"),
- WithKind(SymbolKind::Variable),
- Children()))),
- AllOf(WithName("baz"), WithKind(SymbolKind::Namespace),
- Children()),
- AllOf(WithName("v2"), WithKind(SymbolKind::Namespace))))}));
+ AllOf(
+ WithName("foo"), WithKind(SymbolKind::Namespace),
+ Children(
+ AllOf(WithName("int32"), WithKind(SymbolKind::Class),
+ Children()),
+ AllOf(WithName("int32_t"), WithKind(SymbolKind::Class),
+ Children()),
+ AllOf(WithName("v1"), WithKind(SymbolKind::Variable),
+ Children()),
+ AllOf(WithName("bar"), WithKind(SymbolKind::Namespace),
+ Children(AllOf(WithName("v2"),
+ WithKind(SymbolKind::Variable),
+ Children()))),
+ AllOf(WithName("baz"), WithKind(SymbolKind::Namespace),
+ Children()),
+ AllOf(WithName("v2"), WithKind(SymbolKind::Namespace))))}));
}
TEST_F(DocumentSymbolsTest, DeclarationDefinition) {
@@ -442,13 +442,14 @@ TEST_F(DocumentSymbolsTest, DeclarationD
)");
addFile(FilePath, Main.code());
- EXPECT_THAT(getSymbols(FilePath),
- ElementsAre(AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
- Children(AllOf(
- WithName("f"), WithKind(SymbolKind::Method),
- SymNameRange(Main.range("decl"))))),
- AllOf(WithName("f"), WithKind(SymbolKind::Method),
- SymNameRange(Main.range("def")))));
+ EXPECT_THAT(
+ getSymbols(FilePath),
+ ElementsAre(
+ AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
+ Children(AllOf(WithName("f"), WithKind(SymbolKind::Method),
+ SymNameRange(Main.range("decl"))))),
+ AllOf(WithName("Foo::f"), WithKind(SymbolKind::Method),
+ SymNameRange(Main.range("def")))));
}
TEST_F(DocumentSymbolsTest, ExternSymbol) {
@@ -684,5 +685,69 @@ TEST_F(DocumentSymbolsTest, TempSpecs) {
AllOf(WithName("Foo<bool, int, 3>"), WithKind(SymbolKind::Class))));
}
+TEST_F(DocumentSymbolsTest, Qualifiers) {
+ addFile("foo.cpp", R"cpp(
+ namespace foo { namespace bar {
+ struct Cls;
+
+ int func1();
+ int func2();
+ int func3();
+ int func4();
+ }}
+
+ struct foo::bar::Cls { };
+
+ int foo::bar::func1() { return 10; }
+ int ::foo::bar::func2() { return 20; }
+
+ using namespace foo;
+ int bar::func3() { return 30; }
+
+ namespace alias = foo::bar;
+ int ::alias::func4() { return 40; }
+ )cpp");
+
+ // All the qualifiers should be preserved exactly as written.
+ EXPECT_THAT(getSymbols("foo.cpp"),
+ UnorderedElementsAre(
+ WithName("foo"), WithName("foo::bar::Cls"),
+ WithName("foo::bar::func1"), WithName("::foo::bar::func2"),
+ WithName("using namespace foo"), WithName("bar::func3"),
+ WithName("alias"), WithName("::alias::func4")));
+}
+
+TEST_F(DocumentSymbolsTest, QualifiersWithTemplateArgs) {
+ addFile("foo.cpp", R"cpp(
+ template <typename T, typename U = double> class Foo;
+
+ template <>
+ class Foo<int, double> {
+ int method1();
+ int method2();
+ int method3();
+ };
+
+ using int_type = int;
+
+ // Typedefs should be preserved!
+ int Foo<int_type, double>::method1() { return 10; }
+
+ // Default arguments should not be shown!
+ int Foo<int>::method2() { return 20; }
+
+ using Foo_type = Foo<int>;
+ // If the whole type is aliased, this should be preserved too!
+ int Foo_type::method3() { return 30; }
+ )cpp");
+ EXPECT_THAT(
+ getSymbols("foo.cpp"),
+ UnorderedElementsAre(WithName("Foo"), WithName("Foo<int, double>"),
+ WithName("int_type"),
+ WithName("Foo<int_type, double>::method1"),
+ WithName("Foo<int>::method2"), WithName("Foo_type"),
+ WithName("Foo_type::method3")));
+}
+
} // namespace clangd
} // namespace clang
More information about the cfe-commits
mailing list