12#include "llvm/ADT/StringRef.h"
13#include "gmock/gmock.h"
14#include "gtest/gtest.h"
21using ::testing::AllOf;
22using ::testing::ElementsAre;
23using ::testing::ElementsAreArray;
24using ::testing::Field;
25using ::testing::IsEmpty;
26using ::testing::UnorderedElementsAre;
30 if (arg.containerName.empty())
31 return arg.name ==
Name;
32 return (arg.containerName +
"::" + arg.name) ==
Name;
34MATCHER_P(withName, N,
"") {
return arg.name == N; }
36MATCHER_P(withDetail, Detail,
"") {
return arg.detail == Detail; }
40MATCHER_P(symNameRange, Range,
"") {
return arg.selectionRange ==
Range; }
41template <
class... ChildMatchers>
42::testing::Matcher<DocumentSymbol> children(ChildMatchers... ChildrenM) {
46std::vector<SymbolInformation> getSymbols(TestTU &TU, llvm::StringRef Query,
50 EXPECT_TRUE(
bool(SymbolInfos)) <<
"workspaceSymbols returned an error";
54TEST(WorkspaceSymbols, Macros) {
63 EXPECT_THAT(getSymbols(TU,
"macro"),
64 ElementsAre(AllOf(qName(
"MACRO"), withKind(SymbolKind::String))));
67TEST(WorkspaceSymbols, NoLocals) {
70 void test(int FirstParam, int SecondParam) {
74 EXPECT_THAT(getSymbols(TU, "l"), ElementsAre(qName(
"LocalClass")));
75 EXPECT_THAT(getSymbols(TU,
"p"), IsEmpty());
78TEST(WorkspaceSymbols, Globals) {
80 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
85 struct GlobalStruct {};)cpp";
89 EXPECT_THAT(getSymbols(TU, "global"),
91 AllOf(qName(
"GlobalStruct"), withKind(SymbolKind::Struct)),
92 AllOf(qName(
"global_func"), withKind(SymbolKind::Function)),
93 AllOf(qName(
"global_var"), withKind(SymbolKind::Variable))));
96TEST(WorkspaceSymbols, Unnamed) {
98 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
101 } UnnamedStruct;)cpp";
105 EXPECT_THAT(getSymbols(TU, "UnnamedStruct"),
106 ElementsAre(AllOf(qName(
"UnnamedStruct"),
107 withKind(SymbolKind::Variable))));
108 EXPECT_THAT(getSymbols(TU,
"InUnnamed"),
109 ElementsAre(AllOf(qName(
"(anonymous struct)::InUnnamed"),
110 withKind(SymbolKind::Field))));
113TEST(WorkspaceSymbols, InMainFile) {
117 static void test2() {}
119 EXPECT_THAT(getSymbols(TU, "test"),
120 ElementsAre(qName(
"test"), qName(
"test2")));
123TEST(WorkspaceSymbols, Namespaces) {
125 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
139 EXPECT_THAT(getSymbols(TU, "a"),
140 UnorderedElementsAre(
141 qName(
"ans1"), qName(
"ans1::ai1"), qName(
"ans1::ans2"),
142 qName(
"ans1::ans2::ai2"), qName(
"ans1::ans2::ans3"),
143 qName(
"ans1::ans2::ans3::ai3")));
144 EXPECT_THAT(getSymbols(TU,
"::"), ElementsAre(qName(
"ans1")));
145 EXPECT_THAT(getSymbols(TU,
"::a"), ElementsAre(qName(
"ans1")));
146 EXPECT_THAT(getSymbols(TU,
"ans1::"),
147 UnorderedElementsAre(qName(
"ans1::ai1"), qName(
"ans1::ans2"),
148 qName(
"ans1::ans2::ai2"),
149 qName(
"ans1::ans2::ans3"),
150 qName(
"ans1::ans2::ans3::ai3")));
151 EXPECT_THAT(getSymbols(TU,
"ans2::"),
152 UnorderedElementsAre(qName(
"ans1::ans2::ai2"),
153 qName(
"ans1::ans2::ans3"),
154 qName(
"ans1::ans2::ans3::ai3")));
155 EXPECT_THAT(getSymbols(TU,
"::ans1"), ElementsAre(qName(
"ans1")));
156 EXPECT_THAT(getSymbols(TU,
"::ans1::"),
157 UnorderedElementsAre(qName(
"ans1::ai1"), qName(
"ans1::ans2")));
158 EXPECT_THAT(getSymbols(TU,
"::ans1::ans2"), ElementsAre(qName(
"ans1::ans2")));
159 EXPECT_THAT(getSymbols(TU,
"::ans1::ans2::"),
160 ElementsAre(qName(
"ans1::ans2::ai2"), qName(
"ans1::ans2::ans3")));
163 EXPECT_THAT(getSymbols(TU,
"ans1::ans3::ai"),
164 UnorderedElementsAre(qName(
"ans1::ans2::ans3::ai3")));
167TEST(WorkspaceSymbols, AnonymousNamespace) {
174 EXPECT_THAT(getSymbols(TU, "test"), ElementsAre(qName(
"test")));
177TEST(WorkspaceSymbols, MultiFile) {
179 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
183 TU.AdditionalFiles["foo2.h"] = R
"cpp(
191 EXPECT_THAT(getSymbols(TU, "foo"),
192 UnorderedElementsAre(qName(
"foo"), qName(
"foo2")));
195TEST(WorkspaceSymbols, GlobalNamespaceQueries) {
197 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
211 EXPECT_THAT(getSymbols(TU, "::"),
212 UnorderedElementsAre(
213 AllOf(qName(
"Foo"), withKind(SymbolKind::Class)),
214 AllOf(qName(
"foo"), withKind(SymbolKind::Function)),
215 AllOf(qName(
"ns"), withKind(SymbolKind::Namespace))));
216 EXPECT_THAT(getSymbols(TU,
":"), IsEmpty());
217 EXPECT_THAT(getSymbols(TU,
""),
218 UnorderedElementsAre(qName(
"foo"), qName(
"Foo"), qName(
"Foo::a"),
219 qName(
"ns"), qName(
"ns::foo2")));
222TEST(WorkspaceSymbols, Enums) {
224 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
249 EXPECT_THAT(getSymbols(TU, "Red"), ElementsAre(qName(
"Red")));
250 EXPECT_THAT(getSymbols(TU,
"::Red"), ElementsAre(qName(
"Red")));
251 EXPECT_THAT(getSymbols(TU,
"Green"), ElementsAre(qName(
"Green")));
252 EXPECT_THAT(getSymbols(TU,
"Green"), ElementsAre(qName(
"Green")));
253 EXPECT_THAT(getSymbols(TU,
"Color2::Yellow"),
254 ElementsAre(qName(
"Color2::Yellow")));
255 EXPECT_THAT(getSymbols(TU,
"Yellow"), ElementsAre(qName(
"Color2::Yellow")));
257 EXPECT_THAT(getSymbols(TU,
"ns::Black"), ElementsAre(qName(
"ns::Black")));
258 EXPECT_THAT(getSymbols(TU,
"ns::Blue"), ElementsAre(qName(
"ns::Blue")));
259 EXPECT_THAT(getSymbols(TU,
"ns::Color4::White"),
260 ElementsAre(qName(
"ns::Color4::White")));
263TEST(WorkspaceSymbols, Ranking) {
265 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
272 EXPECT_THAT(getSymbols(TU, "::"), ElementsAre(qName(
"func"), qName(
"ns")));
275TEST(WorkspaceSymbols, RankingPartialNamespace) {
279 namespace ns2 { struct Foo {}; }
281 namespace ns2 { struct FooB {}; })cpp";
282 EXPECT_THAT(getSymbols(TU, "ns2::f"),
283 ElementsAre(qName(
"ns2::FooB"), qName(
"ns1::ns2::Foo")));
286TEST(WorkspaceSymbols, WithLimit) {
288 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
296 EXPECT_THAT(getSymbols(TU,
"foo"),
297 UnorderedElementsAre(
298 AllOf(qName(
"foo"), withKind(SymbolKind::Variable)),
299 AllOf(qName(
"foo2"), withKind(SymbolKind::Variable))));
301 EXPECT_THAT(getSymbols(TU,
"foo", 1), ElementsAre(qName(
"foo")));
304TEST(WorkspaceSymbols, TempSpecs) {
306 TU.ExtraArgs = {
"-xc++"};
308 template <typename T, typename U, int X = 5> class Foo {};
309 template <typename T> class Foo<int, T> {};
310 template <> class Foo<bool, int> {};
311 template <> class Foo<bool, int, 3> {};
315 getSymbols(TU,
"Foo"),
316 UnorderedElementsAre(
317 AllOf(qName(
"Foo"), withKind(SymbolKind::Class)),
318 AllOf(qName(
"Foo<int, T>"), withKind(SymbolKind::Class)),
319 AllOf(qName(
"Foo<bool, int>"), withKind(SymbolKind::Class)),
320 AllOf(qName(
"Foo<bool, int, 3>"), withKind(SymbolKind::Class))));
323std::vector<DocumentSymbol> getSymbols(ParsedAST
AST) {
325 EXPECT_TRUE(
bool(SymbolInfos)) <<
"documentSymbols returned an error";
329TEST(DocumentSymbols, BasicSymbols) {
339 Foo& operator=(const Foo&);
350 static const int KInt = 2;
351 const char* kStr = "123";
358 using int32_t = int32;
374 TU.Code = Main.code().str();
376 getSymbols(TU.build()),
378 {AllOf(withName("Foo"), withKind(SymbolKind::Class),
379 withDetail(
"class"), children()),
380 AllOf(withName(
"Foo"), withKind(SymbolKind::Class),
383 AllOf(withName(
"Foo"), withKind(SymbolKind::Constructor),
384 withDetail(
"()"), children()),
385 AllOf(withName(
"Foo"), withKind(SymbolKind::Constructor),
386 withDetail(
"(int)"), children()),
387 AllOf(withName(
"f"), withKind(SymbolKind::Method),
388 withDetail(
"void ()"), children()),
389 AllOf(withName(
"operator="), withKind(SymbolKind::Method),
390 withDetail(
"Foo &(const Foo &)"), children()),
391 AllOf(withName(
"~Foo"), withKind(SymbolKind::Constructor),
392 withDetail(
""), children()),
393 AllOf(withName(
"Nested"), withKind(SymbolKind::Class),
396 withName(
"f"), withKind(SymbolKind::Method),
397 withDetail(
"void ()"), children()))))),
398 AllOf(withName(
"Friend"), withKind(SymbolKind::Class),
399 withDetail(
"class"), children()),
400 AllOf(withName(
"f1"), withKind(SymbolKind::Function),
401 withDetail(
"void ()"), children()),
402 AllOf(withName(
"f2"), withKind(SymbolKind::Function),
403 withDetail(
"void ()"), children()),
404 AllOf(withName(
"KInt"), withKind(SymbolKind::Variable),
405 withDetail(
"const int"), children()),
406 AllOf(withName(
"kStr"), withKind(SymbolKind::Variable),
407 withDetail(
"const char *"), children()),
408 AllOf(withName(
"f1"), withKind(SymbolKind::Function),
409 withDetail(
"void ()"), children()),
411 withName(
"foo"), withKind(SymbolKind::Namespace), withDetail(
""),
412 children(AllOf(withName(
"int32"), withKind(SymbolKind::Class),
413 withDetail(
"type alias"), children()),
414 AllOf(withName(
"int32_t"), withKind(SymbolKind::Class),
415 withDetail(
"type alias"), children()),
416 AllOf(withName(
"v1"), withKind(SymbolKind::Variable),
417 withDetail(
"int"), children()),
418 AllOf(withName(
"bar"), withKind(SymbolKind::Namespace),
420 children(AllOf(withName(
"v2"),
421 withKind(SymbolKind::Variable),
422 withDetail(
"int"), children()))),
423 AllOf(withName(
"baz"), withKind(SymbolKind::Namespace),
424 withDetail(
""), children()),
425 AllOf(withName(
"v2"), withKind(SymbolKind::Namespace),
426 withDetail(
""))))}));
429TEST(DocumentSymbols, DeclarationDefinition) {
435 void Foo::$def[[f]]() {
439 TU.Code = Main.code().str();
441 getSymbols(TU.build()),
443 AllOf(withName("Foo"), withKind(SymbolKind::Class),
445 children(AllOf(withName(
"f"), withKind(SymbolKind::Method),
446 withDetail(
"void ()"),
447 symNameRange(Main.range(
"decl"))))),
448 AllOf(withName(
"Foo::f"), withKind(SymbolKind::Method),
449 withDetail(
"void ()"), symNameRange(Main.range(
"def")))));
452TEST(DocumentSymbols, Concepts) {
454 TU.ExtraArgs = {
"-std=c++20"};
455 TU.Code =
"template <typename T> concept C = requires(T t) { t.foo(); };";
457 EXPECT_THAT(getSymbols(TU.build()),
458 ElementsAre(AllOf(withName(
"C"), withDetail(
"concept"))));
461TEST(DocumentSymbols, ExternSymbol) {
463 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
470 EXPECT_THAT(getSymbols(TU.build()), IsEmpty());
473TEST(DocumentSymbols, ExternContext) {
487 EXPECT_THAT(getSymbols(TU.build()),
488 ElementsAre(withName("foo"), withName(
"Foo"),
489 AllOf(withName(
"ns"),
490 children(withName(
"bar"), withName(
"Bar")))));
493TEST(DocumentSymbols, ExportContext) {
495 TU.ExtraArgs = {
"-std=c++20"};
503 EXPECT_THAT(getSymbols(TU.build()),
504 ElementsAre(withName("foo"), withName(
"Foo")));
507TEST(DocumentSymbols, NoLocals) {
510 void test(int FirstParam, int SecondParam) {
511 struct LocalClass {};
514 EXPECT_THAT(getSymbols(TU.build()), ElementsAre(withName("test")));
517TEST(DocumentSymbols, Unnamed) {
525 getSymbols(TU.build()),
526 ElementsAre(AllOf(withName("(anonymous struct)"),
527 withKind(SymbolKind::Struct), withDetail(
"struct"),
528 children(AllOf(withName(
"InUnnamed"),
529 withKind(SymbolKind::Field),
530 withDetail(
"int"), children()))),
531 AllOf(withName(
"UnnamedStruct"),
532 withKind(SymbolKind::Variable),
533 withDetail(
"struct (unnamed)"), children())));
536TEST(DocumentSymbols, InHeaderFile) {
538 TU.AdditionalFiles[
"bar.h"] = R
"cpp(
543 int i; // declaration to finish preamble
548 EXPECT_THAT(getSymbols(TU.build()),
549 ElementsAre(withName("i"), withName(
"test")));
552TEST(DocumentSymbols, Template) {
555 template <class T> struct Tmpl {T x = 0;};
556 template <> struct Tmpl<int> {
559 extern template struct Tmpl<float>;
560 template struct Tmpl<double>;
562 template <class T, class U, class Z = float>
565 int funcTmpl<int>(double a);
567 template <class T, class U = double>
570 double varTmpl<int> = 10.0;
573 getSymbols(TU.build()),
575 AllOf(withName("Tmpl"), withKind(SymbolKind::Struct),
576 withDetail(
"template struct"),
577 children(AllOf(withName(
"x"), withKind(SymbolKind::Field),
579 AllOf(withName(
"Tmpl<int>"), withKind(SymbolKind::Struct),
580 withDetail(
"struct"),
581 children(AllOf(withName(
"y"), withDetail(
"int")))),
582 AllOf(withName(
"Tmpl<float>"), withKind(SymbolKind::Struct),
583 withDetail(
"struct"), children()),
584 AllOf(withName(
"Tmpl<double>"), withKind(SymbolKind::Struct),
585 withDetail(
"struct"), children()),
586 AllOf(withName(
"funcTmpl"), withDetail(
"template int (U)"),
588 AllOf(withName(
"funcTmpl<int>"), withDetail(
"int (double)"),
590 AllOf(withName(
"varTmpl"), withDetail(
"template int"), children()),
591 AllOf(withName(
"varTmpl<int>"), withDetail(
"double"), children())));
594TEST(DocumentSymbols, Namespaces) {
608 inline namespace nb {
613 // This is still inlined.
620 getSymbols(TU.build()),
621 ElementsAreArray<::testing::Matcher<DocumentSymbol>>(
622 {AllOf(withName("ans1"),
623 children(AllOf(withName(
"ai1"), children()),
624 AllOf(withName(
"ans2"), children(withName(
"ai2"))))),
625 AllOf(withName(
"(anonymous namespace)"), children(withName(
"test"))),
626 AllOf(withName(
"na"),
627 children(AllOf(withName(
"nb"), children(withName(
"Foo"))))),
628 AllOf(withName(
"na"),
629 children(AllOf(withName(
"nb"), children(withName(
"Bar")))))}));
632TEST(DocumentSymbols, Enums) {
651 getSymbols(TU.build()),
653 AllOf(withName("(anonymous enum)"), withDetail(
"enum"),
654 children(AllOf(withName(
"Red"), withDetail(
"(unnamed)")))),
655 AllOf(withName(
"Color"), withDetail(
"enum"),
656 children(AllOf(withName(
"Green"), withDetail(
"Color")))),
657 AllOf(withName(
"Color2"), withDetail(
"enum"),
658 children(AllOf(withName(
"Yellow"), withDetail(
"Color2")))),
659 AllOf(withName(
"ns"),
660 children(AllOf(withName(
"(anonymous enum)"), withDetail(
"enum"),
661 children(AllOf(withName(
"Black"),
662 withDetail(
"(unnamed)"))))))));
668 testing::Matcher<DocumentSymbol> Matcher;
672 // Basic macro that generates symbols.
673 #define DEFINE_FLAG(X) bool FLAGS_##X; bool FLAGS_no##X
676 AllOf(withName("DEFINE_FLAG"), withDetail(
"(pretty)"),
677 children(withName(
"FLAGS_pretty"), withName(
"FLAGS_nopretty"))),
681 // Hierarchy is determined by primary (name) location.
683 namespace ID(ns) { int ID(y); }
685 AllOf(withName("ID"), withDetail(
"(ns)"),
686 children(AllOf(withName(
"ns"),
687 children(AllOf(withName(
"ID"), withDetail(
"(y)"),
688 children(withName(
"y"))))))),
692 // More typical example where macro only generates part of a decl.
693 #define TEST(A, B) class A##_##B { void go(); }; void A##_##B::go()
694 TEST(DocumentSymbols, Macro) { }
696 AllOf(withName("TEST"), withDetail(
"(DocumentSymbols, Macro)"),
697 children(AllOf(withName(
"DocumentSymbols_Macro"),
698 children(withName(
"go"))),
699 withName(
"DocumentSymbols_Macro::go"))),
704 #define NAMESPACE(NS, BODY) namespace NS { BODY }
705 NAMESPACE(a, NAMESPACE(b, int x;))
708 withName("NAMESPACE"), withDetail(
"(a, NAMESPACE(b, int x;))"),
711 children(AllOf(withName(
"NAMESPACE"),
714 children(AllOf(withName(
"b"),
715 children(withName(
"x"))))))))),
719 // Macro invoked from body is not exposed.
720 #define INNER(X) int X
721 #define OUTER(X) INNER(X)
724 AllOf(withName("OUTER"), withDetail(
"(foo)"),
725 children(withName(
"foo"))),
728 for (
const Test &T : Tests) {
730 EXPECT_THAT(getSymbols(TU.build()), ElementsAre(
T.Matcher)) <<
T.Code;
734TEST(DocumentSymbols, RangeFromMacro) {
738 class name##_Test {};
740 $expansion1[[FF]](abc);
745 $expansion2parens[[$expansion2[[FF2]]()]];
754 #define FF4(name) int name = 0
755 $FooRange[[FF4($FooSelectionRange[[foo]])]];
757 TU.Code = Main.code().str();
759 getSymbols(TU.build()),
761 AllOf(withName("FF"), withDetail(
"(abc)"),
762 children(AllOf(withName(
"abc_Test"), withDetail(
"class"),
763 symNameRange(Main.range(
"expansion1"))))),
764 AllOf(withName(
"FF2"), withDetail(
"()"),
765 symNameRange(Main.range(
"expansion2")),
766 symRange(Main.range(
"expansion2parens")),
767 children(AllOf(withName(
"Test"), withDetail(
"class"),
768 symNameRange(Main.range(
"expansion2"))))),
769 AllOf(withName(
"FF3"), withDetail(
"()"),
770 symRange(Main.range(
"fullDef")),
771 children(AllOf(withName(
"waldo"), withDetail(
"void ()"),
772 symRange(Main.range(
"fullDef"))))),
774 withName(
"FF4"), withDetail(
"(foo)"),
775 children(AllOf(withName(
"foo"), symRange(Main.range(
"FooRange")),
776 symNameRange(Main.range(
"FooSelectionRange")))))));
779TEST(DocumentSymbols, FuncTemplates) {
781 Annotations Source(R
"cpp(
786 auto y = foo<double>();
788 TU.Code = Source.code().str();
790 EXPECT_THAT(getSymbols(TU.build()),
791 ElementsAre(AllOf(withName(
"foo"), withDetail(
"template T ()")),
792 AllOf(withName(
"x"), withDetail(
"int")),
793 AllOf(withName(
"y"), withDetail(
"double"))));
796TEST(DocumentSymbols, UsingDirectives) {
798 Annotations Source(R
"cpp(
803 namespace ns_alias = ns;
805 using namespace ::ns; // check we don't loose qualifiers.
806 using namespace ns_alias; // and namespace aliases.
808 TU.Code = Source.code().str();
809 EXPECT_THAT(getSymbols(TU.build()),
810 ElementsAre(withName("ns"), withName(
"ns_alias"),
811 withName(
"using namespace ::ns"),
812 withName(
"using namespace ns_alias")));
815TEST(DocumentSymbols, TempSpecs) {
818 template <typename T, typename U, int X = 5> class Foo {};
819 template <typename T> class Foo<int, T> {};
820 template <> class Foo<bool, int> {};
821 template <> class Foo<bool, int, 3> {};
824 EXPECT_THAT(getSymbols(TU.build()),
825 UnorderedElementsAre(
826 AllOf(withName(
"Foo"), withKind(SymbolKind::Class),
827 withDetail(
"template class")),
828 AllOf(withName(
"Foo<int, T>"), withKind(SymbolKind::Class),
829 withDetail(
"template class")),
830 AllOf(withName(
"Foo<bool, int>"), withKind(SymbolKind::Class),
831 withDetail(
"class")),
832 AllOf(withName(
"Foo<bool, int, 3>"),
833 withKind(SymbolKind::Class), withDetail(
"class"))));
836TEST(DocumentSymbols, Qualifiers) {
839 namespace foo { namespace bar {
848 struct foo::bar::Cls { };
850 int foo::bar::func1() { return 10; }
851 int ::foo::bar::func2() { return 20; }
854 int bar::func3() { return 30; }
856 namespace alias = foo::bar;
857 int ::alias::func4() { return 40; }
861 EXPECT_THAT(getSymbols(TU.build()),
862 UnorderedElementsAre(
863 withName(
"foo"), withName(
"foo::bar::Cls"),
864 withName(
"foo::bar::func1"), withName(
"::foo::bar::func2"),
865 withName(
"using namespace foo"), withName(
"bar::func3"),
866 withName(
"alias"), withName(
"::alias::func4")));
869TEST(DocumentSymbols, QualifiersWithTemplateArgs) {
872 template <typename T, typename U = double> class Foo;
875 class Foo<int, double> {
881 using int_type = int;
883 // Typedefs should be preserved!
884 int Foo<int_type, double>::method1() { return 10; }
886 // Default arguments should not be shown!
887 int Foo<int>::method2() { return 20; }
889 using Foo_type = Foo<int>;
890 // If the whole type is aliased, this should be preserved too!
891 int Foo_type::method3() { return 30; }
893 EXPECT_THAT(getSymbols(TU.build()),
894 UnorderedElementsAre(
895 AllOf(withName("Foo"), withDetail(
"template class")),
896 AllOf(withName(
"Foo<int, double>"), withDetail(
"class")),
897 AllOf(withName(
"int_type"), withDetail(
"type alias")),
898 AllOf(withName(
"Foo<int_type, double>::method1"),
899 withDetail(
"int ()")),
900 AllOf(withName(
"Foo<int>::method2"), withDetail(
"int ()")),
901 AllOf(withName(
"Foo_type"), withDetail(
"type alias")),
902 AllOf(withName(
"Foo_type::method3"), withDetail(
"int ()"))));
905TEST(DocumentSymbolsTest, Ranges) {
908 $foo[[int foo(bool Argument) {
912 $variable[[char GLOBAL_VARIABLE]];
921 $field[[unsigned Baz]];
923 $getbaz[[unsigned getBaz() { return Baz; }]]
927 $forwardclass[[class ForwardClassDecl]];
929 $struct[[struct StructDefinition {
930 $structfield[[int *Pointer = nullptr]];
932 $forwardstruct[[struct StructDeclaration]];
934 $forwardfunc[[void forwardFunctionDecl(int Something)]];
936 TU.Code = Main.code().str();
938 getSymbols(TU.build()),
939 UnorderedElementsAre(
940 AllOf(withName("foo"), withKind(SymbolKind::Function),
941 withDetail(
"int (bool)"), symRange(Main.range(
"foo"))),
942 AllOf(withName(
"GLOBAL_VARIABLE"), withKind(SymbolKind::Variable),
943 withDetail(
"char"), symRange(Main.range(
"variable"))),
945 withName(
"ns"), withKind(SymbolKind::Namespace),
946 symRange(Main.range(
"ns")),
948 withName(
"Bar"), withKind(SymbolKind::Class),
949 withDetail(
"class"), symRange(Main.range(
"bar")),
951 AllOf(withName(
"Bar"), withKind(SymbolKind::Constructor),
952 withDetail(
"()"), symRange(Main.range(
"ctor"))),
953 AllOf(withName(
"~Bar"), withKind(SymbolKind::Constructor),
954 withDetail(
""), symRange(Main.range(
"dtor"))),
955 AllOf(withName(
"Baz"), withKind(SymbolKind::Field),
956 withDetail(
"unsigned int"),
957 symRange(Main.range(
"field"))),
958 AllOf(withName(
"getBaz"), withKind(SymbolKind::Method),
959 withDetail(
"unsigned int ()"),
960 symRange(Main.range(
"getbaz"))))))),
961 AllOf(withName(
"ForwardClassDecl"), withKind(SymbolKind::Class),
962 withDetail(
"class"), symRange(Main.range(
"forwardclass"))),
963 AllOf(withName(
"StructDefinition"), withKind(SymbolKind::Struct),
964 withDetail(
"struct"), symRange(Main.range(
"struct")),
965 children(AllOf(withName(
"Pointer"), withKind(SymbolKind::Field),
967 symRange(Main.range(
"structfield"))))),
968 AllOf(withName(
"StructDeclaration"), withKind(SymbolKind::Struct),
969 withDetail(
"struct"), symRange(Main.range(
"forwardstruct"))),
970 AllOf(withName(
"forwardFunctionDecl"), withKind(SymbolKind::Function),
971 withDetail(
"void (int)"),
972 symRange(Main.range(
"forwardfunc")))));
975TEST(DocumentSymbolsTest, DependentType) {
978 template <typename T> auto plus(T x, T y) -> decltype(x + y) { return x + y; }
980 template <typename Key, typename Value> class Pair {};
982 template <typename Key, typename Value>
983 struct Context : public Pair<Key, Value> {
984 using Pair<Key, Value>::Pair;
988 getSymbols(TU.build()),
990 AllOf(withName("plus"),
991 withDetail(
"template auto (T, T) -> decltype(x + y)")),
992 AllOf(withName(
"Pair"), withDetail(
"template class")),
993 AllOf(withName(
"Context"), withDetail(
"template struct"),
995 withName(
"Pair<type-parameter-0-0, type-parameter-0-1>"),
996 withDetail(
"<dependent type>"))))));
999TEST(DocumentSymbolsTest, ObjCCategoriesAndClassExtensions) {
1001 TU.ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1002 Annotations Main(R
"cpp(
1003 $Cat[[@interface Cat
1006 $SneakyCat[[@interface Cat (Sneaky)
1007 - (id)sneak:(id)behavior;
1010 $MeowCat[[@interface Cat ()
1013 $PurCat[[@interface Cat ()
1017 TU.Code = Main.code().str();
1019 getSymbols(TU.build()),
1021 AllOf(withName("Cat"), symRange(Main.range(
"Cat")),
1022 children(AllOf(withName(
"+sharedCat"),
1023 withKind(SymbolKind::Method)))),
1024 AllOf(withName(
"Cat(Sneaky)"), symRange(Main.range(
"SneakyCat")),
1026 AllOf(withName(
"-sneak:"), withKind(SymbolKind::Method)))),
1028 withName(
"Cat()"), symRange(Main.range(
"MeowCat")),
1029 children(AllOf(withName(
"-meow"), withKind(SymbolKind::Method)))),
1030 AllOf(withName(
"Cat()"), symRange(Main.range(
"PurCat")),
1032 AllOf(withName(
"-pur"), withKind(SymbolKind::Method))))));
1035TEST(DocumentSymbolsTest, PragmaMarkGroups) {
1037 TU.ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1038 Annotations Main(R
"cpp(
1039 $DogDef[[@interface Dog
1042 $DogImpl[[@implementation Dog
1044 + (id)sharedDoggo { return 0; }
1046 #pragma $Overrides[[mark - Overrides
1053 #pragma $Specifics[[mark - Dog Specifics
1058 @]]end // FIXME: Why doesn't this include the 'end'?
1060 #pragma $End[[mark - End
1063 TU.Code = Main.code().str();
1065 getSymbols(TU.build()),
1066 UnorderedElementsAre(
1067 AllOf(withName("Dog"), symRange(Main.range(
"DogDef"))),
1068 AllOf(withName(
"Dog"), symRange(Main.range(
"DogImpl")),
1069 children(AllOf(withName(
"+sharedDoggo"),
1070 withKind(SymbolKind::Method)),
1071 AllOf(withName(
"Overrides"),
1072 symRange(Main.range(
"Overrides")),
1073 children(AllOf(withName(
"-init"),
1074 withKind(SymbolKind::Method)),
1075 AllOf(withName(
"-bark"),
1076 withKind(SymbolKind::Method)))),
1077 AllOf(withName(
"Dog Specifics"),
1078 symRange(Main.range(
"Specifics")),
1079 children(AllOf(withName(
"-isAGoodBoy"),
1080 withKind(SymbolKind::Method)))))),
1081 AllOf(withName(
"End"), symRange(Main.range(
"End")))));
1084TEST(DocumentSymbolsTest, PragmaMarkGroupsNesting) {
1086 TU.ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1087 Annotations Main(R
"cpp(
1092 #pragma mark - NotTopDecl
1097 TU.Code = Main.code().str();
1099 getSymbols(TU.build()),
1100 UnorderedElementsAre(AllOf(
1102 children(AllOf(withName(
"Foo"),
1103 children(AllOf(withName(
"Bar"),
1104 children(AllOf(withName(
"bar"),
1106 "NotTopDecl"))))))),
1107 withName(
"bar")))));
1110TEST(DocumentSymbolsTest, PragmaMarkGroupsNoNesting) {
1112 TU.ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1113 Annotations Main(R
"cpp(
1114 #pragma mark Helpers
1115 void helpA(id obj) {}
1120 void coreMethod() {}
1122 TU.Code = Main.code().str();
1123 EXPECT_THAT(getSymbols(TU.build()),
1124 UnorderedElementsAre(withName("Helpers"), withName(
"helpA"),
1125 withName(
"(unnamed group)"),
1126 withName(
"Core"), withName(
"coreMethod")));
llvm::SmallString< 256U > Name
CharSourceRange Range
SourceRange for the file name.
std::string testPath(PathRef File, llvm::sys::path::Style Style)
TEST(BackgroundQueueTest, Priority)
llvm::Expected< std::vector< DocumentSymbol > > getDocumentSymbols(ParsedAST &AST)
Retrieves the symbols contained in the "main file" section of an AST in the same order that they appe...
llvm::Expected< std::vector< SymbolInformation > > getWorkspaceSymbols(llvm::StringRef Query, int Limit, const SymbolIndex *const Index, llvm::StringRef HintPath)
Searches for the symbols matching Query.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::vector< DocumentSymbol > children
Children of this symbol, e.g. properties of a class.
static TestTU withCode(llvm::StringRef Code)