[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