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; }
35MATCHER_P(withKind, Kind,
"") {
return arg.kind == Kind; }
41template <
class... ChildMatchers>
42::testing::Matcher<DocumentSymbol> children(ChildMatchers... ChildrenM) {
46template <
typename... Tags>
47::testing::Matcher<DocumentSymbol> withSymbolTags(Tags... tags) {
52std::vector<SymbolInformation> getSymbols(
TestTU &TU, llvm::StringRef Query,
56 EXPECT_TRUE(
bool(SymbolInfos)) <<
"workspaceSymbols returned an error";
60TEST(WorkspaceSymbols, Macros) {
69 EXPECT_THAT(getSymbols(TU,
"macro"),
70 ElementsAre(AllOf(qName(
"MACRO"), withKind(SymbolKind::String))));
73TEST(WorkspaceSymbols, NoLocals) {
76 void test(int FirstParam, int SecondParam) {
80 EXPECT_THAT(getSymbols(TU, "l"), ElementsAre(qName(
"LocalClass")));
81 EXPECT_THAT(getSymbols(TU,
"p"), IsEmpty());
84TEST(WorkspaceSymbols, Globals) {
91 struct GlobalStruct {};)cpp";
95 EXPECT_THAT(getSymbols(TU, "global"),
97 AllOf(qName(
"GlobalStruct"), withKind(SymbolKind::Struct)),
98 AllOf(qName(
"global_func"), withKind(SymbolKind::Function)),
99 AllOf(qName(
"global_var"), withKind(SymbolKind::Variable))));
102TEST(WorkspaceSymbols, Unnamed) {
107 } UnnamedStruct;)cpp";
111 EXPECT_THAT(getSymbols(TU, "UnnamedStruct"),
112 ElementsAre(AllOf(qName(
"UnnamedStruct"),
113 withKind(SymbolKind::Variable))));
114 EXPECT_THAT(getSymbols(TU,
"InUnnamed"),
115 ElementsAre(AllOf(qName(
"(unnamed struct)::InUnnamed"),
116 withKind(SymbolKind::Field))));
119TEST(WorkspaceSymbols, TypeAlias) {
125 using StructAlias = Struct;
126 using ClassAlias = Class;
130 getSymbols(TU, "Struct"),
131 UnorderedElementsAre(AllOf(qName(
"Struct"), withKind(SymbolKind::Struct)),
132 AllOf(qName(
"Container::StructAlias"),
133 withKind(SymbolKind::Struct))));
135 getSymbols(TU,
"Class"),
136 UnorderedElementsAre(
137 AllOf(qName(
"Class"), withKind(SymbolKind::Class)),
138 AllOf(qName(
"Container::ClassAlias"), withKind(SymbolKind::Class))));
141TEST(WorkspaceSymbols, InMainFile) {
144 int test() { return 0; }
145 static void test2() {}
147 EXPECT_THAT(getSymbols(TU, "test"),
148 ElementsAre(qName(
"test"), qName(
"test2")));
151TEST(WorkspaceSymbols, Namespaces) {
167 EXPECT_THAT(getSymbols(TU, "a"),
168 UnorderedElementsAre(
169 qName(
"ans1"), qName(
"ans1::ai1"), qName(
"ans1::ans2"),
170 qName(
"ans1::ans2::ai2"), qName(
"ans1::ans2::ans3"),
171 qName(
"ans1::ans2::ans3::ai3")));
172 EXPECT_THAT(getSymbols(TU,
"::"), ElementsAre(qName(
"ans1")));
173 EXPECT_THAT(getSymbols(TU,
"::a"), ElementsAre(qName(
"ans1")));
174 EXPECT_THAT(getSymbols(TU,
"ans1::"),
175 UnorderedElementsAre(qName(
"ans1::ai1"), qName(
"ans1::ans2"),
176 qName(
"ans1::ans2::ai2"),
177 qName(
"ans1::ans2::ans3"),
178 qName(
"ans1::ans2::ans3::ai3")));
179 EXPECT_THAT(getSymbols(TU,
"ans2::"),
180 UnorderedElementsAre(qName(
"ans1::ans2::ai2"),
181 qName(
"ans1::ans2::ans3"),
182 qName(
"ans1::ans2::ans3::ai3")));
183 EXPECT_THAT(getSymbols(TU,
"::ans1"), ElementsAre(qName(
"ans1")));
184 EXPECT_THAT(getSymbols(TU,
"::ans1::"),
185 UnorderedElementsAre(qName(
"ans1::ai1"), qName(
"ans1::ans2")));
186 EXPECT_THAT(getSymbols(TU,
"::ans1::ans2"), ElementsAre(qName(
"ans1::ans2")));
187 EXPECT_THAT(getSymbols(TU,
"::ans1::ans2::"),
188 ElementsAre(qName(
"ans1::ans2::ai2"), qName(
"ans1::ans2::ans3")));
191 EXPECT_THAT(getSymbols(TU,
"ans1::ans3::ai"),
192 UnorderedElementsAre(qName(
"ans1::ans2::ans3::ai3")));
195TEST(WorkspaceSymbols, AnonymousNamespace) {
202 EXPECT_THAT(getSymbols(TU, "test"), ElementsAre(qName(
"test")));
205TEST(WorkspaceSymbols, MultiFile) {
211 TU.AdditionalFiles["foo2.h"] = R
"cpp(
219 EXPECT_THAT(getSymbols(TU, "foo"),
220 UnorderedElementsAre(qName(
"foo"), qName(
"foo2")));
223TEST(WorkspaceSymbols, GlobalNamespaceQueries) {
239 EXPECT_THAT(getSymbols(TU, "::"),
240 UnorderedElementsAre(
241 AllOf(qName(
"Foo"), withKind(SymbolKind::Class)),
242 AllOf(qName(
"foo"), withKind(SymbolKind::Function)),
243 AllOf(qName(
"ns"), withKind(SymbolKind::Namespace))));
244 EXPECT_THAT(getSymbols(TU,
":"), IsEmpty());
245 EXPECT_THAT(getSymbols(TU,
""),
246 UnorderedElementsAre(qName(
"foo"), qName(
"Foo"), qName(
"Foo::a"),
247 qName(
"ns"), qName(
"ns::foo2")));
250TEST(WorkspaceSymbols, Enums) {
277 EXPECT_THAT(getSymbols(TU, "Red"), ElementsAre(qName(
"Red")));
278 EXPECT_THAT(getSymbols(TU,
"::Red"), ElementsAre(qName(
"Red")));
279 EXPECT_THAT(getSymbols(TU,
"Green"), ElementsAre(qName(
"Green")));
280 EXPECT_THAT(getSymbols(TU,
"Green"), ElementsAre(qName(
"Green")));
281 EXPECT_THAT(getSymbols(TU,
"Color2::Yellow"),
282 ElementsAre(qName(
"Color2::Yellow")));
283 EXPECT_THAT(getSymbols(TU,
"Yellow"), ElementsAre(qName(
"Color2::Yellow")));
285 EXPECT_THAT(getSymbols(TU,
"ns::Black"), ElementsAre(qName(
"ns::Black")));
286 EXPECT_THAT(getSymbols(TU,
"ns::Blue"), ElementsAre(qName(
"ns::Blue")));
287 EXPECT_THAT(getSymbols(TU,
"ns::Color4::White"),
288 ElementsAre(qName(
"ns::Color4::White")));
291TEST(WorkspaceSymbols, Ranking) {
300 EXPECT_THAT(getSymbols(TU, "::"), ElementsAre(qName(
"func"), qName(
"ns")));
303TEST(WorkspaceSymbols, RankingPartialNamespace) {
307 namespace ns2 { struct Foo {}; }
309 namespace ns2 { struct FooB {}; })cpp";
310 EXPECT_THAT(getSymbols(TU, "ns2::f"),
311 ElementsAre(qName(
"ns2::FooB"), qName(
"ns1::ns2::Foo")));
314TEST(WorkspaceSymbols, WithLimit) {
324 EXPECT_THAT(getSymbols(TU,
"foo"),
325 UnorderedElementsAre(
326 AllOf(qName(
"foo"), withKind(SymbolKind::Variable)),
327 AllOf(qName(
"foo2"), withKind(SymbolKind::Variable))));
329 EXPECT_THAT(getSymbols(TU,
"foo", 1), ElementsAre(qName(
"foo")));
332TEST(WorkspaceSymbols, TempSpecs) {
336 template <typename T, typename U, int X = 5> class Foo {};
337 template <typename T> class Foo<int, T> {};
338 template <> class Foo<bool, int> {};
339 template <> class Foo<bool, int, 3> {};
343 getSymbols(TU,
"Foo"),
344 UnorderedElementsAre(
345 AllOf(qName(
"Foo"), withKind(SymbolKind::Class)),
346 AllOf(qName(
"Foo<int, T>"), withKind(SymbolKind::Class)),
347 AllOf(qName(
"Foo<bool, int>"), withKind(SymbolKind::Class)),
348 AllOf(qName(
"Foo<bool, int, 3>"), withKind(SymbolKind::Class))));
353 EXPECT_TRUE(
bool(SymbolInfos)) <<
"documentSymbols returned an error";
357TEST(DocumentSymbols, BasicSymbols) {
368 Foo& operator=(const Foo&);
379 static const int KInt = 2;
380 const char* kStr = "123";
387 using int32_t = int32;
403 TU.Code = Main.code().str();
405 getSymbols(TU.build()),
407 {AllOf(withName("Foo"), withKind(SymbolKind::Class),
408 withDetail(
"class"), children()),
409 AllOf(withName(
"Foo"), withKind(SymbolKind::Class),
412 AllOf(withName(
"Foo"), withKind(SymbolKind::Constructor),
413 withDetail(
"()"), children()),
414 AllOf(withName(
"Foo"), withKind(SymbolKind::Constructor),
415 withDetail(
"(int)"), children()),
416 AllOf(withName(
"f"), withKind(SymbolKind::Method),
417 withDetail(
"void ()"), children()),
418 AllOf(withName(
"f2"), withKind(SymbolKind::Function),
419 withDetail(
"void ()"), children()),
420 AllOf(withName(
"operator="), withKind(SymbolKind::Method),
421 withDetail(
"Foo &(const Foo &)"), children()),
422 AllOf(withName(
"~Foo"), withKind(SymbolKind::Constructor),
423 withDetail(
""), children()),
424 AllOf(withName(
"Nested"), withKind(SymbolKind::Class),
427 withName(
"f"), withKind(SymbolKind::Method),
428 withDetail(
"void ()"), children()))))),
429 AllOf(withName(
"Friend"), withKind(SymbolKind::Class),
430 withDetail(
"class"), children()),
431 AllOf(withName(
"f1"), withKind(SymbolKind::Function),
432 withDetail(
"void ()"), children()),
433 AllOf(withName(
"f2"), withKind(SymbolKind::Function),
434 withDetail(
"void ()"), children()),
435 AllOf(withName(
"KInt"), withKind(SymbolKind::Variable),
436 withDetail(
"const int"), children()),
437 AllOf(withName(
"kStr"), withKind(SymbolKind::Variable),
438 withDetail(
"const char *"), children()),
439 AllOf(withName(
"f1"), withKind(SymbolKind::Function),
440 withDetail(
"void ()"), children()),
442 withName(
"foo"), withKind(SymbolKind::Namespace), withDetail(
""),
443 children(AllOf(withName(
"int32"), withKind(SymbolKind::Class),
444 withDetail(
"type alias"), children()),
445 AllOf(withName(
"int32_t"), withKind(SymbolKind::Class),
446 withDetail(
"type alias"), children()),
447 AllOf(withName(
"v1"), withKind(SymbolKind::Variable),
448 withDetail(
"int"), children()),
449 AllOf(withName(
"bar"), withKind(SymbolKind::Namespace),
451 children(AllOf(withName(
"v2"),
452 withKind(SymbolKind::Variable),
453 withDetail(
"int"), children()))),
454 AllOf(withName(
"baz"), withKind(SymbolKind::Namespace),
455 withDetail(
""), children()),
456 AllOf(withName(
"v2"), withKind(SymbolKind::Namespace),
457 withDetail(
""))))}));
460TEST(DocumentSymbols, DeclarationDefinition) {
466 void Foo::$def[[f]]() {
470 TU.Code = Main.code().str();
472 getSymbols(TU.build()),
474 AllOf(withName("Foo"), withKind(SymbolKind::Class),
476 children(AllOf(withName(
"f"), withKind(SymbolKind::Method),
477 withDetail(
"void ()"),
478 symNameRange(Main.range(
"decl"))))),
479 AllOf(withName(
"Foo::f"), withKind(SymbolKind::Method),
480 withDetail(
"void ()"), symNameRange(Main.range(
"def")))));
483TEST(DocumentSymbols, Concepts) {
486 TU.Code =
"template <typename T> concept C = requires(T t) { t.foo(); };";
488 EXPECT_THAT(getSymbols(TU.build()),
489 ElementsAre(AllOf(withName(
"C"), withDetail(
"concept"))));
492TEST(DocumentSymbols, ExternSymbol) {
501 EXPECT_THAT(getSymbols(TU.build()), IsEmpty());
504TEST(DocumentSymbols, ExternContext) {
518 EXPECT_THAT(getSymbols(TU.build()),
519 ElementsAre(withName("foo"), withName(
"Foo"),
520 AllOf(withName(
"ns"),
521 children(withName(
"bar"), withName(
"Bar")))));
524TEST(DocumentSymbols, ExportContext) {
534 EXPECT_THAT(getSymbols(TU.build()),
535 ElementsAre(withName("foo"), withName(
"Foo")));
538TEST(DocumentSymbols, NoLocals) {
541 void test(int FirstParam, int SecondParam) {
542 struct LocalClass {};
545 EXPECT_THAT(getSymbols(TU.build()), ElementsAre(withName("test")));
548TEST(DocumentSymbols, Unnamed) {
556 getSymbols(TU.build()),
557 ElementsAre(AllOf(withName("(anonymous struct)"),
558 withKind(SymbolKind::Struct), withDetail(
"struct"),
559 children(AllOf(withName(
"InUnnamed"),
560 withKind(SymbolKind::Field),
561 withDetail(
"int"), children()))),
562 AllOf(withName(
"UnnamedStruct"),
563 withKind(SymbolKind::Variable),
564 withDetail(
"struct (unnamed)"), children())));
567TEST(DocumentSymbols, InHeaderFile) {
575 int i; // declaration to finish preamble
581 EXPECT_THAT(getSymbols(TU.build()),
582 ElementsAre(withName("i"), withName(
"test")));
585TEST(DocumentSymbols, Template) {
588 template <class T> struct Tmpl {T x = 0;};
589 template <> struct Tmpl<int> {
592 extern template struct Tmpl<float>;
593 template struct Tmpl<double>;
595 template <class T, class U, class Z = float>
598 int funcTmpl<int>(double a);
600 template <class T, class U = double>
603 double varTmpl<int> = 10.0;
606 getSymbols(TU.build()),
608 AllOf(withName("Tmpl"), withKind(SymbolKind::Struct),
609 withDetail(
"template struct"),
610 children(AllOf(withName(
"x"), withKind(SymbolKind::Field),
612 AllOf(withName(
"Tmpl<int>"), withKind(SymbolKind::Struct),
613 withDetail(
"struct"),
614 children(AllOf(withName(
"y"), withDetail(
"int")))),
615 AllOf(withName(
"Tmpl<float>"), withKind(SymbolKind::Struct),
616 withDetail(
"struct"), children()),
617 AllOf(withName(
"Tmpl<double>"), withKind(SymbolKind::Struct),
618 withDetail(
"struct"), children()),
619 AllOf(withName(
"funcTmpl"), withDetail(
"template int (U)"),
621 AllOf(withName(
"funcTmpl<int>"), withDetail(
"int (double)"),
623 AllOf(withName(
"varTmpl"), withDetail(
"template int"), children()),
624 AllOf(withName(
"varTmpl<int>"), withDetail(
"double"), children())));
627TEST(DocumentSymbols, Namespaces) {
641 inline namespace nb {
646 // This is still inlined.
653 getSymbols(TU.build()),
654 ElementsAreArray<::testing::Matcher<DocumentSymbol>>(
655 {AllOf(withName("ans1"),
656 children(AllOf(withName(
"ai1"), children()),
657 AllOf(withName(
"ans2"), children(withName(
"ai2"))))),
658 AllOf(withName(
"(anonymous namespace)"), children(withName(
"test"))),
659 AllOf(withName(
"na"),
660 children(AllOf(withName(
"nb"), children(withName(
"Foo"))))),
661 AllOf(withName(
"na"),
662 children(AllOf(withName(
"nb"), children(withName(
"Bar")))))}));
665TEST(DocumentSymbols, Enums) {
684 getSymbols(TU.build()),
686 AllOf(withName("(anonymous enum)"), withDetail(
"enum"),
687 children(AllOf(withName(
"Red"), withDetail(
"(unnamed enum)")))),
688 AllOf(withName(
"Color"), withDetail(
"enum"),
689 children(AllOf(withName(
"Green"), withDetail(
"Color")))),
690 AllOf(withName(
"Color2"), withDetail(
"enum"),
691 children(AllOf(withName(
"Yellow"), withDetail(
"Color2")))),
694 children(AllOf(withName(
"(anonymous enum)"), withDetail(
"enum"),
695 children(AllOf(withName(
"Black"),
696 withDetail(
"(unnamed enum)"))))))));
702 testing::Matcher<DocumentSymbol> Matcher;
706 // Basic macro that generates symbols.
707 #define DEFINE_FLAG(X) bool FLAGS_##X; bool FLAGS_no##X
710 AllOf(withName("DEFINE_FLAG"), withDetail(
"(pretty)"),
711 children(withName(
"FLAGS_pretty"), withName(
"FLAGS_nopretty"))),
715 // Hierarchy is determined by primary (name) location.
717 namespace ID(ns) { int ID(y); }
719 AllOf(withName("ID"), withDetail(
"(ns)"),
720 children(AllOf(withName(
"ns"),
721 children(AllOf(withName(
"ID"), withDetail(
"(y)"),
722 children(withName(
"y"))))))),
726 // More typical example where macro only generates part of a decl.
727 #define TEST(A, B) class A##_##B { void go(); }; void A##_##B::go()
728 TEST(DocumentSymbols, Macro) { }
730 AllOf(withName("TEST"), withDetail(
"(DocumentSymbols, Macro)"),
731 children(AllOf(withName(
"DocumentSymbols_Macro"),
732 children(withName(
"go"))),
733 withName(
"DocumentSymbols_Macro::go"))),
738 #define NAMESPACE(NS, BODY) namespace NS { BODY }
739 NAMESPACE(a, NAMESPACE(b, int x;))
742 withName("NAMESPACE"), withDetail(
"(a, NAMESPACE(b, int x;))"),
745 children(AllOf(withName(
"NAMESPACE"),
748 children(AllOf(withName(
"b"),
749 children(withName(
"x"))))))))),
753 // Macro invoked from body is not exposed.
754 #define INNER(X) int X
755 #define OUTER(X) INNER(X)
758 AllOf(withName("OUTER"), withDetail(
"(foo)"),
759 children(withName(
"foo"))),
762 for (
const Test &T : Tests) {
764 EXPECT_THAT(getSymbols(TU.build()), ElementsAre(
T.Matcher)) <<
T.Code;
768TEST(DocumentSymbols, RangeFromMacro) {
772 class name##_Test {};
774 $expansion1[[FF]](abc);
779 $expansion2parens[[$expansion2[[FF2]]()]];
788 #define FF4(name) int name = 0
789 $FooRange[[FF4($FooSelectionRange[[foo]])]];
791 TU.Code = Main.code().str();
793 getSymbols(TU.build()),
795 AllOf(withName("FF"), withDetail(
"(abc)"),
796 children(AllOf(withName(
"abc_Test"), withDetail(
"class"),
797 symNameRange(Main.range(
"expansion1"))))),
798 AllOf(withName(
"FF2"), withDetail(
"()"),
799 symNameRange(Main.range(
"expansion2")),
800 symRange(Main.range(
"expansion2parens")),
801 children(AllOf(withName(
"Test"), withDetail(
"class"),
802 symNameRange(Main.range(
"expansion2"))))),
803 AllOf(withName(
"FF3"), withDetail(
"()"),
804 symRange(Main.range(
"fullDef")),
805 children(AllOf(withName(
"waldo"), withDetail(
"void ()"),
806 symRange(Main.range(
"fullDef"))))),
808 withName(
"FF4"), withDetail(
"(foo)"),
809 children(AllOf(withName(
"foo"), symRange(Main.range(
"FooRange")),
810 symNameRange(Main.range(
"FooSelectionRange")))))));
813TEST(DocumentSymbols, FuncTemplates) {
817 T foo() { return T{}; }
820 auto y = foo<double>();
822 TU.Code = Source.code().str();
824 EXPECT_THAT(getSymbols(TU.build()),
825 ElementsAre(AllOf(withName(
"foo"), withDetail(
"template T ()")),
826 AllOf(withName(
"x"), withDetail(
"int")),
827 AllOf(withName(
"y"), withDetail(
"double"))));
830TEST(DocumentSymbols, UsingDirectives) {
837 namespace ns_alias = ns;
839 using namespace ::ns; // check we don't loose qualifiers.
840 using namespace ns_alias; // and namespace aliases.
842 TU.Code = Source.code().str();
843 EXPECT_THAT(getSymbols(TU.build()),
844 ElementsAre(withName("ns"), withName(
"ns_alias"),
845 withName(
"using namespace ::ns"),
846 withName(
"using namespace ns_alias")));
849TEST(DocumentSymbols, TempSpecs) {
852 template <typename T, typename U, int X = 5> class Foo {};
853 template <typename T> class Foo<int, T> {};
854 template <> class Foo<bool, int> {};
855 template <> class Foo<bool, int, 3> {};
858 EXPECT_THAT(getSymbols(TU.build()),
859 UnorderedElementsAre(
860 AllOf(withName(
"Foo"), withKind(SymbolKind::Class),
861 withDetail(
"template class")),
862 AllOf(withName(
"Foo<int, T>"), withKind(SymbolKind::Class),
863 withDetail(
"template class")),
864 AllOf(withName(
"Foo<bool, int>"), withKind(SymbolKind::Class),
865 withDetail(
"class")),
866 AllOf(withName(
"Foo<bool, int, 3>"),
867 withKind(SymbolKind::Class), withDetail(
"class"))));
870TEST(DocumentSymbols, Qualifiers) {
873 namespace foo { namespace bar {
882 struct foo::bar::Cls { };
884 int foo::bar::func1() { return 10; }
885 int ::foo::bar::func2() { return 20; }
888 int bar::func3() { return 30; }
890 namespace alias = foo::bar;
891 int ::alias::func4() { return 40; }
895 EXPECT_THAT(getSymbols(TU.build()),
896 UnorderedElementsAre(
897 withName(
"foo"), withName(
"foo::bar::Cls"),
898 withName(
"foo::bar::func1"), withName(
"::foo::bar::func2"),
899 withName(
"using namespace foo"), withName(
"bar::func3"),
900 withName(
"alias"), withName(
"::alias::func4")));
903TEST(DocumentSymbols, QualifiersWithTemplateArgs) {
906 template <typename T, typename U = double> class Foo;
909 class Foo<int, double> {
915 using int_type = int;
917 // Typedefs should be preserved!
918 int Foo<int_type, double>::method1() { return 10; }
920 // Default arguments should not be shown!
921 int Foo<int>::method2() { return 20; }
923 using Foo_type = Foo<int>;
924 // If the whole type is aliased, this should be preserved too!
925 int Foo_type::method3() { return 30; }
927 EXPECT_THAT(getSymbols(TU.build()),
928 UnorderedElementsAre(
929 AllOf(withName("Foo"), withDetail(
"template class")),
930 AllOf(withName(
"Foo<int, double>"), withDetail(
"class")),
931 AllOf(withName(
"int_type"), withDetail(
"type alias")),
932 AllOf(withName(
"Foo<int_type, double>::method1"),
933 withDetail(
"int ()")),
934 AllOf(withName(
"Foo<int>::method2"), withDetail(
"int ()")),
935 AllOf(withName(
"Foo_type"), withDetail(
"type alias")),
936 AllOf(withName(
"Foo_type::method3"), withDetail(
"int ()"))));
939TEST(DocumentSymbolsTest, Ranges) {
942 $foo[[int foo(bool Argument) {
946 $variable[[char GLOBAL_VARIABLE]];
955 $field[[unsigned Baz]];
957 $getbaz[[unsigned getBaz() { return Baz; }]]
961 $forwardclass[[class ForwardClassDecl]];
963 $struct[[struct StructDefinition {
964 $structfield[[int *Pointer = nullptr]];
966 $forwardstruct[[struct StructDeclaration]];
968 $forwardfunc[[void forwardFunctionDecl(int Something)]];
970 TU.Code = Main.code().str();
972 getSymbols(TU.build()),
973 UnorderedElementsAre(
974 AllOf(withName("foo"), withKind(SymbolKind::Function),
975 withDetail(
"int (bool)"), symRange(Main.range(
"foo"))),
976 AllOf(withName(
"GLOBAL_VARIABLE"), withKind(SymbolKind::Variable),
977 withDetail(
"char"), symRange(Main.range(
"variable"))),
979 withName(
"ns"), withKind(SymbolKind::Namespace),
980 symRange(Main.range(
"ns")),
982 withName(
"Bar"), withKind(SymbolKind::Class),
983 withDetail(
"class"), symRange(Main.range(
"bar")),
985 AllOf(withName(
"Bar"), withKind(SymbolKind::Constructor),
986 withDetail(
"()"), symRange(Main.range(
"ctor"))),
987 AllOf(withName(
"~Bar"), withKind(SymbolKind::Constructor),
988 withDetail(
""), symRange(Main.range(
"dtor"))),
989 AllOf(withName(
"Baz"), withKind(SymbolKind::Field),
990 withDetail(
"unsigned int"),
991 symRange(Main.range(
"field"))),
992 AllOf(withName(
"getBaz"), withKind(SymbolKind::Method),
993 withDetail(
"unsigned int ()"),
994 symRange(Main.range(
"getbaz"))))))),
995 AllOf(withName(
"ForwardClassDecl"), withKind(SymbolKind::Class),
996 withDetail(
"class"), symRange(Main.range(
"forwardclass"))),
997 AllOf(withName(
"StructDefinition"), withKind(SymbolKind::Struct),
998 withDetail(
"struct"), symRange(Main.range(
"struct")),
999 children(AllOf(withName(
"Pointer"), withKind(SymbolKind::Field),
1000 withDetail(
"int *"),
1001 symRange(Main.range(
"structfield"))))),
1002 AllOf(withName(
"StructDeclaration"), withKind(SymbolKind::Struct),
1003 withDetail(
"struct"), symRange(Main.range(
"forwardstruct"))),
1004 AllOf(withName(
"forwardFunctionDecl"), withKind(SymbolKind::Function),
1005 withDetail(
"void (int)"),
1006 symRange(Main.range(
"forwardfunc")))));
1009TEST(DocumentSymbolsTest, DependentType) {
1012 template <typename T> auto plus(T x, T y) -> decltype(x + y) { return x + y; }
1014 template <typename Key, typename Value> class Pair {};
1016 template <typename Key, typename Value>
1017 struct Context : public Pair<Key, Value> {
1018 using Pair<Key, Value>::Pair;
1022 getSymbols(TU.build()),
1024 AllOf(withName("plus"),
1025 withDetail(
"template auto (T, T) -> decltype(x + y)")),
1026 AllOf(withName(
"Pair"), withDetail(
"template class")),
1027 AllOf(withName(
"Context"), withDetail(
"template struct"),
1029 withName(
"Pair<type-parameter-0-0, type-parameter-0-1>"),
1030 withDetail(
"<dependent type>"))))));
1033TEST(DocumentSymbolsTest, ObjCCategoriesAndClassExtensions) {
1035 TU.
ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1037 $Cat[[@interface Cat
1040 $SneakyCat[[@interface Cat (Sneaky)
1041 - (id)sneak:(id)behavior;
1044 $MeowCat[[@interface Cat ()
1047 $PurCat[[@interface Cat ()
1051 TU.Code = Main.code().str();
1053 getSymbols(TU.build()),
1055 AllOf(withName("Cat"), symRange(Main.range(
"Cat")),
1056 children(AllOf(withName(
"+sharedCat"),
1057 withKind(SymbolKind::Method)))),
1058 AllOf(withName(
"Cat(Sneaky)"), symRange(Main.range(
"SneakyCat")),
1060 AllOf(withName(
"-sneak:"), withKind(SymbolKind::Method)))),
1062 withName(
"Cat()"), symRange(Main.range(
"MeowCat")),
1063 children(AllOf(withName(
"-meow"), withKind(SymbolKind::Method)))),
1064 AllOf(withName(
"Cat()"), symRange(Main.range(
"PurCat")),
1066 AllOf(withName(
"-pur"), withKind(SymbolKind::Method))))));
1069TEST(DocumentSymbolsTest, PragmaMarkGroups) {
1071 TU.
ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1073 $DogDef[[@interface Dog
1076 $DogImpl[[@implementation Dog
1078 + (id)sharedDoggo { return 0; }
1080 #pragma $Overrides[[mark - Overrides
1087 #pragma $Specifics[[mark - Dog Specifics
1092 @]]end // FIXME: Why doesn't this include the 'end'?
1094 #pragma $End[[mark - End
1097 TU.Code = Main.code().str();
1099 getSymbols(TU.build()),
1100 UnorderedElementsAre(
1101 AllOf(withName("Dog"), symRange(Main.range(
"DogDef"))),
1102 AllOf(withName(
"Dog"), symRange(Main.range(
"DogImpl")),
1103 children(AllOf(withName(
"+sharedDoggo"),
1104 withKind(SymbolKind::Method)),
1105 AllOf(withName(
"Overrides"),
1106 symRange(Main.range(
"Overrides")),
1107 children(AllOf(withName(
"-init"),
1108 withKind(SymbolKind::Method)),
1109 AllOf(withName(
"-bark"),
1110 withKind(SymbolKind::Method)))),
1111 AllOf(withName(
"Dog Specifics"),
1112 symRange(Main.range(
"Specifics")),
1113 children(AllOf(withName(
"-isAGoodBoy"),
1114 withKind(SymbolKind::Method)))))),
1115 AllOf(withName(
"End"), symRange(Main.range(
"End")))));
1118TEST(DocumentSymbolsTest, PragmaMarkGroupsNesting) {
1120 TU.
ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1126 #pragma mark - NotTopDecl
1131 TU.Code = Main.code().str();
1133 getSymbols(TU.build()),
1134 UnorderedElementsAre(AllOf(
1136 children(AllOf(withName(
"Foo"),
1137 children(AllOf(withName(
"Bar"),
1138 children(AllOf(withName(
"bar"),
1140 "NotTopDecl"))))))),
1141 withName(
"bar")))));
1144TEST(DocumentSymbolsTest, PragmaMarkGroupsNoNesting) {
1146 TU.
ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1148 #pragma mark Helpers
1149 void helpA(id obj) {}
1154 void coreMethod() {}
1156 TU.Code = Main.code().str();
1157 EXPECT_THAT(getSymbols(TU.build()),
1158 UnorderedElementsAre(withName("Helpers"), withName(
"helpA"),
1159 withName(
"(unnamed group)"),
1160 withName(
"Core"), withName(
"coreMethod")));
1166 class AbstractClass {
1168 virtual ~AbstractClass() = default;
1169 virtual void f1() = 0;
1177 void AbstractClass::f2() const {}
1179 class ImplClass final: public AbstractClass {
1185 TU.Code = Main.code().str();
1186 auto Symbols = getSymbols(TU.build());
1189 UnorderedElementsAre(
1191 withName(
"AbstractClass"),
1195 AllOf(withName(
"~AbstractClass"),
1199 AllOf(withName(
"f1"),
1209 AllOf(withName(
"f4"),
1213 AllOf(withName(
"AbstractClass::f2"),
1216 AllOf(withName(
"ImplClass"),
Same as llvm::Annotations, but adjusts functions to LSP-specific types for positions and ranges.
Stores and provides access to parsed AST.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
uint32_t SymbolTags
A bitmask type representing symbol tags supported by LSP.
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< SymbolTag > tags
The tags for this symbol.
std::vector< DocumentSymbol > children
Children of this symbol, e.g. properties of a class.
std::vector< std::string > ExtraArgs
static TestTU withCode(llvm::StringRef Code)
llvm::StringMap< std::string > AdditionalFiles