[clang-tools-extra] 2e851c4 - [clangd] Populate detail field in document symbols
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 18 07:53:50 PST 2021
Author: lightmelodies
Date: 2021-02-18T16:53:41+01:00
New Revision: 2e851c4172a35cc37fe6bf4ce8150c628fd66c0c
URL: https://github.com/llvm/llvm-project/commit/2e851c4172a35cc37fe6bf4ce8150c628fd66c0c
DIFF: https://github.com/llvm/llvm-project/commit/2e851c4172a35cc37fe6bf4ce8150c628fd66c0c.diff
LOG: [clangd] Populate detail field in document symbols
This commit fix https://github.com/clangd/clangd/issues/520 and https://github.com/clangd/clangd/issues/601.
{F15544293}
Reviewed By: sammccall
Differential Revision: https://reviews.llvm.org/D96751
Added:
Modified:
clang-tools-extra/clangd/FindSymbols.cpp
clang-tools-extra/clangd/test/symbols.test
clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp
index e75a74b4b05c..ca4b8dafa5a0 100644
--- a/clang-tools-extra/clangd/FindSymbols.cpp
+++ b/clang-tools-extra/clangd/FindSymbols.cpp
@@ -172,6 +172,38 @@ getWorkspaceSymbols(llvm::StringRef Query, int Limit,
}
namespace {
+std::string getSymbolDetail(ASTContext &Ctx, const NamedDecl &ND) {
+ PrintingPolicy P(Ctx.getPrintingPolicy());
+ P.SuppressScope = true;
+ P.SuppressUnwrittenScope = true;
+ P.AnonymousTagLocations = false;
+ P.PolishForDeclaration = true;
+ std::string Detail;
+ llvm::raw_string_ostream OS(Detail);
+ if (ND.getDescribedTemplateParams()) {
+ OS << "template ";
+ }
+ if (const auto *VD = dyn_cast<ValueDecl>(&ND)) {
+ // FIXME: better printing for dependent type
+ if (isa<CXXConstructorDecl>(VD)) {
+ std::string ConstructorType = VD->getType().getAsString(P);
+ // Print constructor type as "(int)" instead of "void (int)".
+ llvm::StringRef WithoutVoid = ConstructorType;
+ WithoutVoid.consume_front("void ");
+ OS << WithoutVoid;
+ } else if (!isa<CXXDestructorDecl>(VD)) {
+ VD->getType().print(OS, P);
+ }
+ } else if (const auto *TD = dyn_cast<TagDecl>(&ND)) {
+ OS << TD->getKindName();
+ } else if (isa<TypedefNameDecl>(&ND)) {
+ OS << "type alias";
+ } else if (isa<ConceptDecl>(&ND)) {
+ OS << "concept";
+ }
+ return std::move(OS.str());
+}
+
llvm::Optional<DocumentSymbol> declToSym(ASTContext &Ctx, const NamedDecl &ND) {
auto &SM = Ctx.getSourceManager();
@@ -193,6 +225,7 @@ llvm::Optional<DocumentSymbol> declToSym(ASTContext &Ctx, const NamedDecl &ND) {
SI.deprecated = ND.isDeprecated();
SI.range = Range{sourceLocToPosition(SM, SymbolRange->getBegin()),
sourceLocToPosition(SM, SymbolRange->getEnd())};
+ SI.detail = getSymbolDetail(Ctx, ND);
SourceLocation NameLoc = ND.getLocation();
SourceLocation FallbackNameLoc;
diff --git a/clang-tools-extra/clangd/test/symbols.test b/clang-tools-extra/clangd/test/symbols.test
index 6ab058da8836..af5d74123630 100644
--- a/clang-tools-extra/clangd/test/symbols.test
+++ b/clang-tools-extra/clangd/test/symbols.test
@@ -1,5 +1,5 @@
# RUN: clangd --index-file=%S/Inputs/symbols.test.yaml -lit-test < %s | FileCheck %s
-{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"workspace":{"symbol":{"symbolKind":{"valueSet": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}}}},"trace":"off"}}
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"textDocument":{"documentSymbol":{"hierarchicalDocumentSymbolSupport":true}},"workspace":{"symbol":{"symbolKind":{"valueSet": [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}}}},"trace":"off"}}
---
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"void foo(); int main() { foo(); }\n"}}}
---
@@ -34,40 +34,54 @@
# CHECK-NEXT: "jsonrpc": "2.0",
# CHECK-NEXT: "result": [
# CHECK-NEXT: {
-# CHECK-NEXT: "containerName": "",
+# CHECK-NEXT: "detail": "void ()",
# CHECK-NEXT: "kind": 12,
-# CHECK-NEXT: "location": {
-# CHECK-NEXT: "range": {
-# CHECK-NEXT: "end": {
-# CHECK-NEXT: "character": {{.*}},
-# CHECK-NEXT: "line": {{.*}}
-# CHECK-NEXT: },
-# CHECK-NEXT: "start": {
-# CHECK-NEXT: "character": {{.*}},
-# CHECK-NEXT: "line": {{.*}}
-# CHECK-NEXT: }
+# CHECK-NEXT: "name": "foo",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": {{.*}},
+# CHECK-NEXT: "line": {{.*}}
# CHECK-NEXT: },
-# CHECK-NEXT: "uri": "file://{{.*}}/main.cpp"
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": {{.*}},
+# CHECK-NEXT: "line": {{.*}}
+# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "name": "foo"
-# CHECK-NEXT: }
+# CHECK-NEXT: "selectionRange": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": {{.*}},
+# CHECK-NEXT: "line": {{.*}}
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": {{.*}},
+# CHECK-NEXT: "line": {{.*}}
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: },
# CHECK-NEXT: {
-# CHECK-NEXT: "containerName": "",
+# CHECK-NEXT: "detail": "int ()",
# CHECK-NEXT: "kind": 12,
-# CHECK-NEXT: "location": {
-# CHECK-NEXT: "range": {
-# CHECK-NEXT: "end": {
-# CHECK-NEXT: "character": {{.*}},
-# CHECK-NEXT: "line": {{.*}}
-# CHECK-NEXT: },
-# CHECK-NEXT: "start": {
-# CHECK-NEXT: "character": {{.*}},
-# CHECK-NEXT: "line": {{.*}}
-# CHECK-NEXT: }
+# CHECK-NEXT: "name": "main",
+# CHECK-NEXT: "range": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": {{.*}},
+# CHECK-NEXT: "line": {{.*}}
# CHECK-NEXT: },
-# CHECK-NEXT: "uri": "file://{{.*}}/main.cpp"
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": {{.*}},
+# CHECK-NEXT: "line": {{.*}}
+# CHECK-NEXT: }
# CHECK-NEXT: },
-# CHECK-NEXT: "name": "main"
+# CHECK-NEXT: "selectionRange": {
+# CHECK-NEXT: "end": {
+# CHECK-NEXT: "character": {{.*}},
+# CHECK-NEXT: "line": {{.*}}
+# CHECK-NEXT: },
+# CHECK-NEXT: "start": {
+# CHECK-NEXT: "character": {{.*}},
+# CHECK-NEXT: "line": {{.*}}
+# CHECK-NEXT: }
+# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT:}
diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
index 37d042c4495f..f1b2ff626c2c 100644
--- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
@@ -35,6 +35,7 @@ MATCHER_P(QName, Name, "") {
}
MATCHER_P(WithName, N, "") { return arg.name == N; }
MATCHER_P(WithKind, Kind, "") { return arg.kind == Kind; }
+MATCHER_P(WithDetail, Detail, "") { return arg.detail == Detail; }
MATCHER_P(SymRange, Range, "") { return arg.range == Range; }
// GMock helpers for matching DocumentSymbol.
@@ -374,44 +375,55 @@ TEST(DocumentSymbols, BasicSymbols) {
EXPECT_THAT(
getSymbols(TU.build()),
ElementsAreArray(
- {AllOf(WithName("Foo"), WithKind(SymbolKind::Class), Children()),
+ {AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
+ WithDetail("class"), Children()),
AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
- Children(AllOf(WithName("Foo"),
- WithKind(SymbolKind::Constructor), Children()),
- AllOf(WithName("Foo"),
- WithKind(SymbolKind::Constructor), Children()),
- AllOf(WithName("f"), WithKind(SymbolKind::Method),
- Children()),
- AllOf(WithName("operator="),
- WithKind(SymbolKind::Method), Children()),
- AllOf(WithName("~Foo"),
- WithKind(SymbolKind::Constructor), Children()),
- AllOf(WithName("Nested"), WithKind(SymbolKind::Class),
- Children(AllOf(WithName("f"),
- WithKind(SymbolKind::Method),
- Children()))))),
- AllOf(WithName("Friend"), WithKind(SymbolKind::Class), Children()),
- AllOf(WithName("f1"), WithKind(SymbolKind::Function), Children()),
- AllOf(WithName("f2"), WithKind(SymbolKind::Function), Children()),
- AllOf(WithName("KInt"), WithKind(SymbolKind::Variable), Children()),
- AllOf(WithName("kStr"), WithKind(SymbolKind::Variable), Children()),
- AllOf(WithName("f1"), WithKind(SymbolKind::Function), Children()),
+ WithDetail("class"),
+ Children(
+ AllOf(WithName("Foo"), WithKind(SymbolKind::Constructor),
+ WithDetail("()"), Children()),
+ AllOf(WithName("Foo"), WithKind(SymbolKind::Constructor),
+ WithDetail("(int)"), Children()),
+ AllOf(WithName("f"), WithKind(SymbolKind::Method),
+ WithDetail("void ()"), Children()),
+ AllOf(WithName("operator="), WithKind(SymbolKind::Method),
+ WithDetail("Foo &(const Foo &)"), Children()),
+ AllOf(WithName("~Foo"), WithKind(SymbolKind::Constructor),
+ WithDetail(""), Children()),
+ AllOf(WithName("Nested"), WithKind(SymbolKind::Class),
+ WithDetail("class"),
+ Children(AllOf(
+ WithName("f"), WithKind(SymbolKind::Method),
+ WithDetail("void ()"), Children()))))),
+ AllOf(WithName("Friend"), WithKind(SymbolKind::Class),
+ WithDetail("class"), Children()),
+ AllOf(WithName("f1"), WithKind(SymbolKind::Function),
+ WithDetail("void ()"), Children()),
+ AllOf(WithName("f2"), WithKind(SymbolKind::Function),
+ WithDetail("void ()"), Children()),
+ AllOf(WithName("KInt"), WithKind(SymbolKind::Variable),
+ WithDetail("const int"), Children()),
+ AllOf(WithName("kStr"), WithKind(SymbolKind::Variable),
+ WithDetail("const char *"), Children()),
+ AllOf(WithName("f1"), WithKind(SymbolKind::Function),
+ WithDetail("void ()"), 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))))}));
+ WithName("foo"), WithKind(SymbolKind::Namespace), WithDetail(""),
+ Children(AllOf(WithName("int32"), WithKind(SymbolKind::Class),
+ WithDetail("type alias"), Children()),
+ AllOf(WithName("int32_t"), WithKind(SymbolKind::Class),
+ WithDetail("type alias"), Children()),
+ AllOf(WithName("v1"), WithKind(SymbolKind::Variable),
+ WithDetail("int"), Children()),
+ AllOf(WithName("bar"), WithKind(SymbolKind::Namespace),
+ WithDetail(""),
+ Children(AllOf(WithName("v2"),
+ WithKind(SymbolKind::Variable),
+ WithDetail("int"), Children()))),
+ AllOf(WithName("baz"), WithKind(SymbolKind::Namespace),
+ WithDetail(""), Children()),
+ AllOf(WithName("v2"), WithKind(SymbolKind::Namespace),
+ WithDetail(""))))}));
}
TEST(DocumentSymbols, DeclarationDefinition) {
@@ -429,10 +441,12 @@ TEST(DocumentSymbols, DeclarationDefinition) {
getSymbols(TU.build()),
ElementsAre(
AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
+ WithDetail("class"),
Children(AllOf(WithName("f"), WithKind(SymbolKind::Method),
+ WithDetail("void ()"),
SymNameRange(Main.range("decl"))))),
AllOf(WithName("Foo::f"), WithKind(SymbolKind::Method),
- SymNameRange(Main.range("def")))));
+ WithDetail("void ()"), SymNameRange(Main.range("def")))));
}
TEST(DocumentSymbols, Concepts) {
@@ -440,7 +454,8 @@ TEST(DocumentSymbols, Concepts) {
TU.ExtraArgs = {"-std=c++20"};
TU.Code = "template <typename T> concept C = requires(T t) { t.foo(); };";
- EXPECT_THAT(getSymbols(TU.build()), ElementsAre(WithName("C")));
+ EXPECT_THAT(getSymbols(TU.build()),
+ ElementsAre(AllOf(WithName("C"), WithDetail("concept"))));
}
TEST(DocumentSymbols, ExternSymbol) {
@@ -508,12 +523,14 @@ TEST(DocumentSymbols, Unnamed) {
)cpp";
EXPECT_THAT(
getSymbols(TU.build()),
- ElementsAre(
- AllOf(WithName("(anonymous struct)"), WithKind(SymbolKind::Struct),
- Children(AllOf(WithName("InUnnamed"),
- WithKind(SymbolKind::Field), Children()))),
- AllOf(WithName("UnnamedStruct"), WithKind(SymbolKind::Variable),
- Children())));
+ ElementsAre(AllOf(WithName("(anonymous struct)"),
+ WithKind(SymbolKind::Struct), WithDetail("struct"),
+ Children(AllOf(WithName("InUnnamed"),
+ WithKind(SymbolKind::Field),
+ WithDetail("int"), Children()))),
+ AllOf(WithName("UnnamedStruct"),
+ WithKind(SymbolKind::Variable),
+ WithDetail("struct (anonymous)"), Children())));
}
TEST(DocumentSymbols, InHeaderFile) {
@@ -556,17 +573,22 @@ TEST(DocumentSymbols, Template) {
getSymbols(TU.build()),
ElementsAre(
AllOf(WithName("Tmpl"), WithKind(SymbolKind::Struct),
- Children(AllOf(WithName("x"), WithKind(SymbolKind::Field)))),
+ WithDetail("template struct"),
+ Children(AllOf(WithName("x"), WithKind(SymbolKind::Field),
+ WithDetail("T")))),
AllOf(WithName("Tmpl<int>"), WithKind(SymbolKind::Struct),
- Children(WithName("y"))),
+ WithDetail("struct"),
+ Children(AllOf(WithName("y"), WithDetail("int")))),
AllOf(WithName("Tmpl<float>"), WithKind(SymbolKind::Struct),
- Children()),
+ WithDetail("struct"), Children()),
AllOf(WithName("Tmpl<double>"), WithKind(SymbolKind::Struct),
+ WithDetail("struct"), Children()),
+ AllOf(WithName("funcTmpl"), WithDetail("template int (U)"),
+ Children()),
+ AllOf(WithName("funcTmpl<int>"), WithDetail("int (double)"),
Children()),
- AllOf(WithName("funcTmpl"), Children()),
- AllOf(WithName("funcTmpl<int>"), Children()),
- AllOf(WithName("varTmpl"), Children()),
- AllOf(WithName("varTmpl<int>"), Children())));
+ AllOf(WithName("varTmpl"), WithDetail("template int"), Children()),
+ AllOf(WithName("varTmpl<int>"), WithDetail("double"), Children())));
}
TEST(DocumentSymbols, Namespaces) {
@@ -628,11 +650,16 @@ TEST(DocumentSymbols, Enums) {
EXPECT_THAT(
getSymbols(TU.build()),
ElementsAre(
- AllOf(WithName("(anonymous enum)"), Children(WithName("Red"))),
- AllOf(WithName("Color"), Children(WithName("Green"))),
- AllOf(WithName("Color2"), Children(WithName("Yellow"))),
- AllOf(WithName("ns"), Children(AllOf(WithName("(anonymous enum)"),
- Children(WithName("Black")))))));
+ AllOf(WithName("(anonymous enum)"), WithDetail("enum"),
+ Children(AllOf(WithName("Red"), WithDetail("(anonymous)")))),
+ AllOf(WithName("Color"), WithDetail("enum"),
+ Children(AllOf(WithName("Green"), WithDetail("Color")))),
+ AllOf(WithName("Color2"), WithDetail("enum"),
+ Children(AllOf(WithName("Yellow"), WithDetail("Color2")))),
+ AllOf(WithName("ns"),
+ Children(AllOf(WithName("(anonymous enum)"), WithDetail("enum"),
+ Children(AllOf(WithName("Black"),
+ WithDetail("(anonymous)"))))))));
}
TEST(DocumentSymbols, FromMacro) {
@@ -656,12 +683,13 @@ TEST(DocumentSymbols, FromMacro) {
}]]
)");
TU.Code = Main.code().str();
- EXPECT_THAT(
- getSymbols(TU.build()),
- ElementsAre(
- AllOf(WithName("abc_Test"), SymNameRange(Main.range("expansion1"))),
- AllOf(WithName("Test"), SymNameRange(Main.range("expansion2"))),
- AllOf(WithName("waldo"), SymRange(Main.range("fullDef")))));
+ EXPECT_THAT(getSymbols(TU.build()),
+ ElementsAre(AllOf(WithName("abc_Test"), WithDetail("class"),
+ SymNameRange(Main.range("expansion1"))),
+ AllOf(WithName("Test"), WithDetail("class"),
+ SymNameRange(Main.range("expansion2"))),
+ AllOf(WithName("waldo"), WithDetail("void ()"),
+ SymRange(Main.range("fullDef")))));
}
TEST(DocumentSymbols, FuncTemplates) {
@@ -676,7 +704,9 @@ TEST(DocumentSymbols, FuncTemplates) {
TU.Code = Source.code().str();
// Make sure we only see the template declaration, not instantiations.
EXPECT_THAT(getSymbols(TU.build()),
- ElementsAre(WithName("foo"), WithName("x"), WithName("y")));
+ ElementsAre(AllOf(WithName("foo"), WithDetail("template T ()")),
+ AllOf(WithName("x"), WithDetail("int")),
+ AllOf(WithName("y"), WithDetail("double"))));
}
TEST(DocumentSymbols, UsingDirectives) {
@@ -707,13 +737,16 @@ TEST(DocumentSymbols, TempSpecs) {
template <> class Foo<bool, int, 3> {};
)cpp";
// Foo is higher ranked because of exact name match.
- EXPECT_THAT(
- getSymbols(TU.build()),
- UnorderedElementsAre(
- AllOf(WithName("Foo"), WithKind(SymbolKind::Class)),
- AllOf(WithName("Foo<int, T>"), WithKind(SymbolKind::Class)),
- AllOf(WithName("Foo<bool, int>"), WithKind(SymbolKind::Class)),
- AllOf(WithName("Foo<bool, int, 3>"), WithKind(SymbolKind::Class))));
+ EXPECT_THAT(getSymbols(TU.build()),
+ UnorderedElementsAre(
+ AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
+ WithDetail("template class")),
+ AllOf(WithName("Foo<int, T>"), WithKind(SymbolKind::Class),
+ WithDetail("template class")),
+ AllOf(WithName("Foo<bool, int>"), WithKind(SymbolKind::Class),
+ WithDetail("class")),
+ AllOf(WithName("Foo<bool, int, 3>"),
+ WithKind(SymbolKind::Class), WithDetail("class"))));
}
TEST(DocumentSymbols, Qualifiers) {
@@ -773,13 +806,16 @@ TEST(DocumentSymbols, QualifiersWithTemplateArgs) {
// If the whole type is aliased, this should be preserved too!
int Foo_type::method3() { return 30; }
)cpp";
- EXPECT_THAT(
- getSymbols(TU.build()),
- 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")));
+ EXPECT_THAT(getSymbols(TU.build()),
+ UnorderedElementsAre(
+ AllOf(WithName("Foo"), WithDetail("template class")),
+ AllOf(WithName("Foo<int, double>"), WithDetail("class")),
+ AllOf(WithName("int_type"), WithDetail("type alias")),
+ AllOf(WithName("Foo<int_type, double>::method1"),
+ WithDetail("int ()")),
+ AllOf(WithName("Foo<int>::method2"), WithDetail("int ()")),
+ AllOf(WithName("Foo_type"), WithDetail("type alias")),
+ AllOf(WithName("Foo_type::method3"), WithDetail("int ()"))));
}
TEST(DocumentSymbolsTest, Ranges) {
@@ -818,36 +854,64 @@ TEST(DocumentSymbolsTest, Ranges) {
getSymbols(TU.build()),
UnorderedElementsAre(
AllOf(WithName("foo"), WithKind(SymbolKind::Function),
- SymRange(Main.range("foo"))),
+ WithDetail("int (bool)"), SymRange(Main.range("foo"))),
AllOf(WithName("GLOBAL_VARIABLE"), WithKind(SymbolKind::Variable),
- SymRange(Main.range("variable"))),
+ WithDetail("char"), SymRange(Main.range("variable"))),
AllOf(
WithName("ns"), WithKind(SymbolKind::Namespace),
SymRange(Main.range("ns")),
Children(AllOf(
WithName("Bar"), WithKind(SymbolKind::Class),
- SymRange(Main.range("bar")),
+ WithDetail("class"), SymRange(Main.range("bar")),
Children(
AllOf(WithName("Bar"), WithKind(SymbolKind::Constructor),
- SymRange(Main.range("ctor"))),
+ WithDetail("()"), SymRange(Main.range("ctor"))),
AllOf(WithName("~Bar"), WithKind(SymbolKind::Constructor),
- SymRange(Main.range("dtor"))),
+ WithDetail(""), SymRange(Main.range("dtor"))),
AllOf(WithName("Baz"), WithKind(SymbolKind::Field),
+ WithDetail("unsigned int"),
SymRange(Main.range("field"))),
AllOf(WithName("getBaz"), WithKind(SymbolKind::Method),
+ WithDetail("unsigned int ()"),
SymRange(Main.range("getbaz"))))))),
AllOf(WithName("ForwardClassDecl"), WithKind(SymbolKind::Class),
- SymRange(Main.range("forwardclass"))),
+ WithDetail("class"), SymRange(Main.range("forwardclass"))),
AllOf(WithName("StructDefinition"), WithKind(SymbolKind::Struct),
- SymRange(Main.range("struct")),
+ WithDetail("struct"), SymRange(Main.range("struct")),
Children(AllOf(WithName("Pointer"), WithKind(SymbolKind::Field),
+ WithDetail("int *"),
SymRange(Main.range("structfield"))))),
AllOf(WithName("StructDeclaration"), WithKind(SymbolKind::Struct),
- SymRange(Main.range("forwardstruct"))),
+ WithDetail("struct"), SymRange(Main.range("forwardstruct"))),
AllOf(WithName("forwardFunctionDecl"), WithKind(SymbolKind::Function),
+ WithDetail("void (int)"),
SymRange(Main.range("forwardfunc")))));
}
+TEST(DocumentSymbolsTest, DependentType) {
+ TestTU TU;
+ TU.Code = R"(
+ template <typename T> auto plus(T x, T y) -> decltype(x + y) { return x + y; }
+
+ template <typename Key, typename Value> class Pair {};
+
+ template <typename Key, typename Value>
+ struct Context : public Pair<Key, Value> {
+ using Pair<Key, Value>::Pair;
+ };
+ )";
+ EXPECT_THAT(
+ getSymbols(TU.build()),
+ ElementsAre(
+ AllOf(WithName("plus"),
+ WithDetail("template auto (T, T) -> decltype(x + y)")),
+ AllOf(WithName("Pair"), WithDetail("template class")),
+ AllOf(WithName("Context"), WithDetail("template struct"),
+ Children(AllOf(
+ WithName("Pair<type-parameter-0-0, type-parameter-0-1>"),
+ WithDetail("<dependent type>"))))));
+}
+
} // namespace
} // namespace clangd
} // namespace clang
More information about the cfe-commits
mailing list