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, InMainFile) {
122 int test() { return 0; }
123 static void test2() {}
125 EXPECT_THAT(getSymbols(TU, "test"),
126 ElementsAre(qName(
"test"), qName(
"test2")));
129TEST(WorkspaceSymbols, Namespaces) {
145 EXPECT_THAT(getSymbols(TU, "a"),
146 UnorderedElementsAre(
147 qName(
"ans1"), qName(
"ans1::ai1"), qName(
"ans1::ans2"),
148 qName(
"ans1::ans2::ai2"), qName(
"ans1::ans2::ans3"),
149 qName(
"ans1::ans2::ans3::ai3")));
150 EXPECT_THAT(getSymbols(TU,
"::"), ElementsAre(qName(
"ans1")));
151 EXPECT_THAT(getSymbols(TU,
"::a"), ElementsAre(qName(
"ans1")));
152 EXPECT_THAT(getSymbols(TU,
"ans1::"),
153 UnorderedElementsAre(qName(
"ans1::ai1"), qName(
"ans1::ans2"),
154 qName(
"ans1::ans2::ai2"),
155 qName(
"ans1::ans2::ans3"),
156 qName(
"ans1::ans2::ans3::ai3")));
157 EXPECT_THAT(getSymbols(TU,
"ans2::"),
158 UnorderedElementsAre(qName(
"ans1::ans2::ai2"),
159 qName(
"ans1::ans2::ans3"),
160 qName(
"ans1::ans2::ans3::ai3")));
161 EXPECT_THAT(getSymbols(TU,
"::ans1"), ElementsAre(qName(
"ans1")));
162 EXPECT_THAT(getSymbols(TU,
"::ans1::"),
163 UnorderedElementsAre(qName(
"ans1::ai1"), qName(
"ans1::ans2")));
164 EXPECT_THAT(getSymbols(TU,
"::ans1::ans2"), ElementsAre(qName(
"ans1::ans2")));
165 EXPECT_THAT(getSymbols(TU,
"::ans1::ans2::"),
166 ElementsAre(qName(
"ans1::ans2::ai2"), qName(
"ans1::ans2::ans3")));
169 EXPECT_THAT(getSymbols(TU,
"ans1::ans3::ai"),
170 UnorderedElementsAre(qName(
"ans1::ans2::ans3::ai3")));
173TEST(WorkspaceSymbols, AnonymousNamespace) {
180 EXPECT_THAT(getSymbols(TU, "test"), ElementsAre(qName(
"test")));
183TEST(WorkspaceSymbols, MultiFile) {
189 TU.AdditionalFiles["foo2.h"] = R
"cpp(
197 EXPECT_THAT(getSymbols(TU, "foo"),
198 UnorderedElementsAre(qName(
"foo"), qName(
"foo2")));
201TEST(WorkspaceSymbols, GlobalNamespaceQueries) {
217 EXPECT_THAT(getSymbols(TU, "::"),
218 UnorderedElementsAre(
219 AllOf(qName(
"Foo"), withKind(SymbolKind::Class)),
220 AllOf(qName(
"foo"), withKind(SymbolKind::Function)),
221 AllOf(qName(
"ns"), withKind(SymbolKind::Namespace))));
222 EXPECT_THAT(getSymbols(TU,
":"), IsEmpty());
223 EXPECT_THAT(getSymbols(TU,
""),
224 UnorderedElementsAre(qName(
"foo"), qName(
"Foo"), qName(
"Foo::a"),
225 qName(
"ns"), qName(
"ns::foo2")));
228TEST(WorkspaceSymbols, Enums) {
255 EXPECT_THAT(getSymbols(TU, "Red"), ElementsAre(qName(
"Red")));
256 EXPECT_THAT(getSymbols(TU,
"::Red"), ElementsAre(qName(
"Red")));
257 EXPECT_THAT(getSymbols(TU,
"Green"), ElementsAre(qName(
"Green")));
258 EXPECT_THAT(getSymbols(TU,
"Green"), ElementsAre(qName(
"Green")));
259 EXPECT_THAT(getSymbols(TU,
"Color2::Yellow"),
260 ElementsAre(qName(
"Color2::Yellow")));
261 EXPECT_THAT(getSymbols(TU,
"Yellow"), ElementsAre(qName(
"Color2::Yellow")));
263 EXPECT_THAT(getSymbols(TU,
"ns::Black"), ElementsAre(qName(
"ns::Black")));
264 EXPECT_THAT(getSymbols(TU,
"ns::Blue"), ElementsAre(qName(
"ns::Blue")));
265 EXPECT_THAT(getSymbols(TU,
"ns::Color4::White"),
266 ElementsAre(qName(
"ns::Color4::White")));
269TEST(WorkspaceSymbols, Ranking) {
278 EXPECT_THAT(getSymbols(TU, "::"), ElementsAre(qName(
"func"), qName(
"ns")));
281TEST(WorkspaceSymbols, RankingPartialNamespace) {
285 namespace ns2 { struct Foo {}; }
287 namespace ns2 { struct FooB {}; })cpp";
288 EXPECT_THAT(getSymbols(TU, "ns2::f"),
289 ElementsAre(qName(
"ns2::FooB"), qName(
"ns1::ns2::Foo")));
292TEST(WorkspaceSymbols, WithLimit) {
302 EXPECT_THAT(getSymbols(TU,
"foo"),
303 UnorderedElementsAre(
304 AllOf(qName(
"foo"), withKind(SymbolKind::Variable)),
305 AllOf(qName(
"foo2"), withKind(SymbolKind::Variable))));
307 EXPECT_THAT(getSymbols(TU,
"foo", 1), ElementsAre(qName(
"foo")));
310TEST(WorkspaceSymbols, TempSpecs) {
314 template <typename T, typename U, int X = 5> class Foo {};
315 template <typename T> class Foo<int, T> {};
316 template <> class Foo<bool, int> {};
317 template <> class Foo<bool, int, 3> {};
321 getSymbols(TU,
"Foo"),
322 UnorderedElementsAre(
323 AllOf(qName(
"Foo"), withKind(SymbolKind::Class)),
324 AllOf(qName(
"Foo<int, T>"), withKind(SymbolKind::Class)),
325 AllOf(qName(
"Foo<bool, int>"), withKind(SymbolKind::Class)),
326 AllOf(qName(
"Foo<bool, int, 3>"), withKind(SymbolKind::Class))));
331 EXPECT_TRUE(
bool(SymbolInfos)) <<
"documentSymbols returned an error";
335TEST(DocumentSymbols, BasicSymbols) {
346 Foo& operator=(const Foo&);
357 static const int KInt = 2;
358 const char* kStr = "123";
365 using int32_t = int32;
381 TU.Code = Main.code().str();
383 getSymbols(TU.build()),
385 {AllOf(withName("Foo"), withKind(SymbolKind::Class),
386 withDetail(
"class"), children()),
387 AllOf(withName(
"Foo"), withKind(SymbolKind::Class),
390 AllOf(withName(
"Foo"), withKind(SymbolKind::Constructor),
391 withDetail(
"()"), children()),
392 AllOf(withName(
"Foo"), withKind(SymbolKind::Constructor),
393 withDetail(
"(int)"), children()),
394 AllOf(withName(
"f"), withKind(SymbolKind::Method),
395 withDetail(
"void ()"), children()),
396 AllOf(withName(
"f2"), withKind(SymbolKind::Function),
397 withDetail(
"void ()"), children()),
398 AllOf(withName(
"operator="), withKind(SymbolKind::Method),
399 withDetail(
"Foo &(const Foo &)"), children()),
400 AllOf(withName(
"~Foo"), withKind(SymbolKind::Constructor),
401 withDetail(
""), children()),
402 AllOf(withName(
"Nested"), withKind(SymbolKind::Class),
405 withName(
"f"), withKind(SymbolKind::Method),
406 withDetail(
"void ()"), children()))))),
407 AllOf(withName(
"Friend"), withKind(SymbolKind::Class),
408 withDetail(
"class"), children()),
409 AllOf(withName(
"f1"), withKind(SymbolKind::Function),
410 withDetail(
"void ()"), children()),
411 AllOf(withName(
"f2"), withKind(SymbolKind::Function),
412 withDetail(
"void ()"), children()),
413 AllOf(withName(
"KInt"), withKind(SymbolKind::Variable),
414 withDetail(
"const int"), children()),
415 AllOf(withName(
"kStr"), withKind(SymbolKind::Variable),
416 withDetail(
"const char *"), children()),
417 AllOf(withName(
"f1"), withKind(SymbolKind::Function),
418 withDetail(
"void ()"), children()),
420 withName(
"foo"), withKind(SymbolKind::Namespace), withDetail(
""),
421 children(AllOf(withName(
"int32"), withKind(SymbolKind::Class),
422 withDetail(
"type alias"), children()),
423 AllOf(withName(
"int32_t"), withKind(SymbolKind::Class),
424 withDetail(
"type alias"), children()),
425 AllOf(withName(
"v1"), withKind(SymbolKind::Variable),
426 withDetail(
"int"), children()),
427 AllOf(withName(
"bar"), withKind(SymbolKind::Namespace),
429 children(AllOf(withName(
"v2"),
430 withKind(SymbolKind::Variable),
431 withDetail(
"int"), children()))),
432 AllOf(withName(
"baz"), withKind(SymbolKind::Namespace),
433 withDetail(
""), children()),
434 AllOf(withName(
"v2"), withKind(SymbolKind::Namespace),
435 withDetail(
""))))}));
438TEST(DocumentSymbols, DeclarationDefinition) {
444 void Foo::$def[[f]]() {
448 TU.Code = Main.code().str();
450 getSymbols(TU.build()),
452 AllOf(withName("Foo"), withKind(SymbolKind::Class),
454 children(AllOf(withName(
"f"), withKind(SymbolKind::Method),
455 withDetail(
"void ()"),
456 symNameRange(Main.range(
"decl"))))),
457 AllOf(withName(
"Foo::f"), withKind(SymbolKind::Method),
458 withDetail(
"void ()"), symNameRange(Main.range(
"def")))));
461TEST(DocumentSymbols, Concepts) {
464 TU.Code =
"template <typename T> concept C = requires(T t) { t.foo(); };";
466 EXPECT_THAT(getSymbols(TU.build()),
467 ElementsAre(AllOf(withName(
"C"), withDetail(
"concept"))));
470TEST(DocumentSymbols, ExternSymbol) {
479 EXPECT_THAT(getSymbols(TU.build()), IsEmpty());
482TEST(DocumentSymbols, ExternContext) {
496 EXPECT_THAT(getSymbols(TU.build()),
497 ElementsAre(withName("foo"), withName(
"Foo"),
498 AllOf(withName(
"ns"),
499 children(withName(
"bar"), withName(
"Bar")))));
502TEST(DocumentSymbols, ExportContext) {
512 EXPECT_THAT(getSymbols(TU.build()),
513 ElementsAre(withName("foo"), withName(
"Foo")));
516TEST(DocumentSymbols, NoLocals) {
519 void test(int FirstParam, int SecondParam) {
520 struct LocalClass {};
523 EXPECT_THAT(getSymbols(TU.build()), ElementsAre(withName("test")));
526TEST(DocumentSymbols, Unnamed) {
534 getSymbols(TU.build()),
535 ElementsAre(AllOf(withName("(anonymous struct)"),
536 withKind(SymbolKind::Struct), withDetail(
"struct"),
537 children(AllOf(withName(
"InUnnamed"),
538 withKind(SymbolKind::Field),
539 withDetail(
"int"), children()))),
540 AllOf(withName(
"UnnamedStruct"),
541 withKind(SymbolKind::Variable),
542 withDetail(
"struct (unnamed)"), children())));
545TEST(DocumentSymbols, InHeaderFile) {
553 int i; // declaration to finish preamble
559 EXPECT_THAT(getSymbols(TU.build()),
560 ElementsAre(withName("i"), withName(
"test")));
563TEST(DocumentSymbols, Template) {
566 template <class T> struct Tmpl {T x = 0;};
567 template <> struct Tmpl<int> {
570 extern template struct Tmpl<float>;
571 template struct Tmpl<double>;
573 template <class T, class U, class Z = float>
576 int funcTmpl<int>(double a);
578 template <class T, class U = double>
581 double varTmpl<int> = 10.0;
584 getSymbols(TU.build()),
586 AllOf(withName("Tmpl"), withKind(SymbolKind::Struct),
587 withDetail(
"template struct"),
588 children(AllOf(withName(
"x"), withKind(SymbolKind::Field),
590 AllOf(withName(
"Tmpl<int>"), withKind(SymbolKind::Struct),
591 withDetail(
"struct"),
592 children(AllOf(withName(
"y"), withDetail(
"int")))),
593 AllOf(withName(
"Tmpl<float>"), withKind(SymbolKind::Struct),
594 withDetail(
"struct"), children()),
595 AllOf(withName(
"Tmpl<double>"), withKind(SymbolKind::Struct),
596 withDetail(
"struct"), children()),
597 AllOf(withName(
"funcTmpl"), withDetail(
"template int (U)"),
599 AllOf(withName(
"funcTmpl<int>"), withDetail(
"int (double)"),
601 AllOf(withName(
"varTmpl"), withDetail(
"template int"), children()),
602 AllOf(withName(
"varTmpl<int>"), withDetail(
"double"), children())));
605TEST(DocumentSymbols, Namespaces) {
619 inline namespace nb {
624 // This is still inlined.
631 getSymbols(TU.build()),
632 ElementsAreArray<::testing::Matcher<DocumentSymbol>>(
633 {AllOf(withName("ans1"),
634 children(AllOf(withName(
"ai1"), children()),
635 AllOf(withName(
"ans2"), children(withName(
"ai2"))))),
636 AllOf(withName(
"(anonymous namespace)"), children(withName(
"test"))),
637 AllOf(withName(
"na"),
638 children(AllOf(withName(
"nb"), children(withName(
"Foo"))))),
639 AllOf(withName(
"na"),
640 children(AllOf(withName(
"nb"), children(withName(
"Bar")))))}));
643TEST(DocumentSymbols, Enums) {
662 getSymbols(TU.build()),
664 AllOf(withName("(anonymous enum)"), withDetail(
"enum"),
665 children(AllOf(withName(
"Red"), withDetail(
"(unnamed enum)")))),
666 AllOf(withName(
"Color"), withDetail(
"enum"),
667 children(AllOf(withName(
"Green"), withDetail(
"Color")))),
668 AllOf(withName(
"Color2"), withDetail(
"enum"),
669 children(AllOf(withName(
"Yellow"), withDetail(
"Color2")))),
672 children(AllOf(withName(
"(anonymous enum)"), withDetail(
"enum"),
673 children(AllOf(withName(
"Black"),
674 withDetail(
"(unnamed enum)"))))))));
680 testing::Matcher<DocumentSymbol> Matcher;
684 // Basic macro that generates symbols.
685 #define DEFINE_FLAG(X) bool FLAGS_##X; bool FLAGS_no##X
688 AllOf(withName("DEFINE_FLAG"), withDetail(
"(pretty)"),
689 children(withName(
"FLAGS_pretty"), withName(
"FLAGS_nopretty"))),
693 // Hierarchy is determined by primary (name) location.
695 namespace ID(ns) { int ID(y); }
697 AllOf(withName("ID"), withDetail(
"(ns)"),
698 children(AllOf(withName(
"ns"),
699 children(AllOf(withName(
"ID"), withDetail(
"(y)"),
700 children(withName(
"y"))))))),
704 // More typical example where macro only generates part of a decl.
705 #define TEST(A, B) class A##_##B { void go(); }; void A##_##B::go()
706 TEST(DocumentSymbols, Macro) { }
708 AllOf(withName("TEST"), withDetail(
"(DocumentSymbols, Macro)"),
709 children(AllOf(withName(
"DocumentSymbols_Macro"),
710 children(withName(
"go"))),
711 withName(
"DocumentSymbols_Macro::go"))),
716 #define NAMESPACE(NS, BODY) namespace NS { BODY }
717 NAMESPACE(a, NAMESPACE(b, int x;))
720 withName("NAMESPACE"), withDetail(
"(a, NAMESPACE(b, int x;))"),
723 children(AllOf(withName(
"NAMESPACE"),
726 children(AllOf(withName(
"b"),
727 children(withName(
"x"))))))))),
731 // Macro invoked from body is not exposed.
732 #define INNER(X) int X
733 #define OUTER(X) INNER(X)
736 AllOf(withName("OUTER"), withDetail(
"(foo)"),
737 children(withName(
"foo"))),
740 for (
const Test &T : Tests) {
742 EXPECT_THAT(getSymbols(TU.build()), ElementsAre(
T.Matcher)) <<
T.Code;
746TEST(DocumentSymbols, RangeFromMacro) {
750 class name##_Test {};
752 $expansion1[[FF]](abc);
757 $expansion2parens[[$expansion2[[FF2]]()]];
766 #define FF4(name) int name = 0
767 $FooRange[[FF4($FooSelectionRange[[foo]])]];
769 TU.Code = Main.code().str();
771 getSymbols(TU.build()),
773 AllOf(withName("FF"), withDetail(
"(abc)"),
774 children(AllOf(withName(
"abc_Test"), withDetail(
"class"),
775 symNameRange(Main.range(
"expansion1"))))),
776 AllOf(withName(
"FF2"), withDetail(
"()"),
777 symNameRange(Main.range(
"expansion2")),
778 symRange(Main.range(
"expansion2parens")),
779 children(AllOf(withName(
"Test"), withDetail(
"class"),
780 symNameRange(Main.range(
"expansion2"))))),
781 AllOf(withName(
"FF3"), withDetail(
"()"),
782 symRange(Main.range(
"fullDef")),
783 children(AllOf(withName(
"waldo"), withDetail(
"void ()"),
784 symRange(Main.range(
"fullDef"))))),
786 withName(
"FF4"), withDetail(
"(foo)"),
787 children(AllOf(withName(
"foo"), symRange(Main.range(
"FooRange")),
788 symNameRange(Main.range(
"FooSelectionRange")))))));
791TEST(DocumentSymbols, FuncTemplates) {
795 T foo() { return T{}; }
798 auto y = foo<double>();
800 TU.Code = Source.code().str();
802 EXPECT_THAT(getSymbols(TU.build()),
803 ElementsAre(AllOf(withName(
"foo"), withDetail(
"template T ()")),
804 AllOf(withName(
"x"), withDetail(
"int")),
805 AllOf(withName(
"y"), withDetail(
"double"))));
808TEST(DocumentSymbols, UsingDirectives) {
815 namespace ns_alias = ns;
817 using namespace ::ns; // check we don't loose qualifiers.
818 using namespace ns_alias; // and namespace aliases.
820 TU.Code = Source.code().str();
821 EXPECT_THAT(getSymbols(TU.build()),
822 ElementsAre(withName("ns"), withName(
"ns_alias"),
823 withName(
"using namespace ::ns"),
824 withName(
"using namespace ns_alias")));
827TEST(DocumentSymbols, TempSpecs) {
830 template <typename T, typename U, int X = 5> class Foo {};
831 template <typename T> class Foo<int, T> {};
832 template <> class Foo<bool, int> {};
833 template <> class Foo<bool, int, 3> {};
836 EXPECT_THAT(getSymbols(TU.build()),
837 UnorderedElementsAre(
838 AllOf(withName(
"Foo"), withKind(SymbolKind::Class),
839 withDetail(
"template class")),
840 AllOf(withName(
"Foo<int, T>"), withKind(SymbolKind::Class),
841 withDetail(
"template class")),
842 AllOf(withName(
"Foo<bool, int>"), withKind(SymbolKind::Class),
843 withDetail(
"class")),
844 AllOf(withName(
"Foo<bool, int, 3>"),
845 withKind(SymbolKind::Class), withDetail(
"class"))));
848TEST(DocumentSymbols, Qualifiers) {
851 namespace foo { namespace bar {
860 struct foo::bar::Cls { };
862 int foo::bar::func1() { return 10; }
863 int ::foo::bar::func2() { return 20; }
866 int bar::func3() { return 30; }
868 namespace alias = foo::bar;
869 int ::alias::func4() { return 40; }
873 EXPECT_THAT(getSymbols(TU.build()),
874 UnorderedElementsAre(
875 withName(
"foo"), withName(
"foo::bar::Cls"),
876 withName(
"foo::bar::func1"), withName(
"::foo::bar::func2"),
877 withName(
"using namespace foo"), withName(
"bar::func3"),
878 withName(
"alias"), withName(
"::alias::func4")));
881TEST(DocumentSymbols, QualifiersWithTemplateArgs) {
884 template <typename T, typename U = double> class Foo;
887 class Foo<int, double> {
893 using int_type = int;
895 // Typedefs should be preserved!
896 int Foo<int_type, double>::method1() { return 10; }
898 // Default arguments should not be shown!
899 int Foo<int>::method2() { return 20; }
901 using Foo_type = Foo<int>;
902 // If the whole type is aliased, this should be preserved too!
903 int Foo_type::method3() { return 30; }
905 EXPECT_THAT(getSymbols(TU.build()),
906 UnorderedElementsAre(
907 AllOf(withName("Foo"), withDetail(
"template class")),
908 AllOf(withName(
"Foo<int, double>"), withDetail(
"class")),
909 AllOf(withName(
"int_type"), withDetail(
"type alias")),
910 AllOf(withName(
"Foo<int_type, double>::method1"),
911 withDetail(
"int ()")),
912 AllOf(withName(
"Foo<int>::method2"), withDetail(
"int ()")),
913 AllOf(withName(
"Foo_type"), withDetail(
"type alias")),
914 AllOf(withName(
"Foo_type::method3"), withDetail(
"int ()"))));
917TEST(DocumentSymbolsTest, Ranges) {
920 $foo[[int foo(bool Argument) {
924 $variable[[char GLOBAL_VARIABLE]];
933 $field[[unsigned Baz]];
935 $getbaz[[unsigned getBaz() { return Baz; }]]
939 $forwardclass[[class ForwardClassDecl]];
941 $struct[[struct StructDefinition {
942 $structfield[[int *Pointer = nullptr]];
944 $forwardstruct[[struct StructDeclaration]];
946 $forwardfunc[[void forwardFunctionDecl(int Something)]];
948 TU.Code = Main.code().str();
950 getSymbols(TU.build()),
951 UnorderedElementsAre(
952 AllOf(withName("foo"), withKind(SymbolKind::Function),
953 withDetail(
"int (bool)"), symRange(Main.range(
"foo"))),
954 AllOf(withName(
"GLOBAL_VARIABLE"), withKind(SymbolKind::Variable),
955 withDetail(
"char"), symRange(Main.range(
"variable"))),
957 withName(
"ns"), withKind(SymbolKind::Namespace),
958 symRange(Main.range(
"ns")),
960 withName(
"Bar"), withKind(SymbolKind::Class),
961 withDetail(
"class"), symRange(Main.range(
"bar")),
963 AllOf(withName(
"Bar"), withKind(SymbolKind::Constructor),
964 withDetail(
"()"), symRange(Main.range(
"ctor"))),
965 AllOf(withName(
"~Bar"), withKind(SymbolKind::Constructor),
966 withDetail(
""), symRange(Main.range(
"dtor"))),
967 AllOf(withName(
"Baz"), withKind(SymbolKind::Field),
968 withDetail(
"unsigned int"),
969 symRange(Main.range(
"field"))),
970 AllOf(withName(
"getBaz"), withKind(SymbolKind::Method),
971 withDetail(
"unsigned int ()"),
972 symRange(Main.range(
"getbaz"))))))),
973 AllOf(withName(
"ForwardClassDecl"), withKind(SymbolKind::Class),
974 withDetail(
"class"), symRange(Main.range(
"forwardclass"))),
975 AllOf(withName(
"StructDefinition"), withKind(SymbolKind::Struct),
976 withDetail(
"struct"), symRange(Main.range(
"struct")),
977 children(AllOf(withName(
"Pointer"), withKind(SymbolKind::Field),
979 symRange(Main.range(
"structfield"))))),
980 AllOf(withName(
"StructDeclaration"), withKind(SymbolKind::Struct),
981 withDetail(
"struct"), symRange(Main.range(
"forwardstruct"))),
982 AllOf(withName(
"forwardFunctionDecl"), withKind(SymbolKind::Function),
983 withDetail(
"void (int)"),
984 symRange(Main.range(
"forwardfunc")))));
987TEST(DocumentSymbolsTest, DependentType) {
990 template <typename T> auto plus(T x, T y) -> decltype(x + y) { return x + y; }
992 template <typename Key, typename Value> class Pair {};
994 template <typename Key, typename Value>
995 struct Context : public Pair<Key, Value> {
996 using Pair<Key, Value>::Pair;
1000 getSymbols(TU.build()),
1002 AllOf(withName("plus"),
1003 withDetail(
"template auto (T, T) -> decltype(x + y)")),
1004 AllOf(withName(
"Pair"), withDetail(
"template class")),
1005 AllOf(withName(
"Context"), withDetail(
"template struct"),
1007 withName(
"Pair<type-parameter-0-0, type-parameter-0-1>"),
1008 withDetail(
"<dependent type>"))))));
1011TEST(DocumentSymbolsTest, ObjCCategoriesAndClassExtensions) {
1013 TU.
ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1015 $Cat[[@interface Cat
1018 $SneakyCat[[@interface Cat (Sneaky)
1019 - (id)sneak:(id)behavior;
1022 $MeowCat[[@interface Cat ()
1025 $PurCat[[@interface Cat ()
1029 TU.Code = Main.code().str();
1031 getSymbols(TU.build()),
1033 AllOf(withName("Cat"), symRange(Main.range(
"Cat")),
1034 children(AllOf(withName(
"+sharedCat"),
1035 withKind(SymbolKind::Method)))),
1036 AllOf(withName(
"Cat(Sneaky)"), symRange(Main.range(
"SneakyCat")),
1038 AllOf(withName(
"-sneak:"), withKind(SymbolKind::Method)))),
1040 withName(
"Cat()"), symRange(Main.range(
"MeowCat")),
1041 children(AllOf(withName(
"-meow"), withKind(SymbolKind::Method)))),
1042 AllOf(withName(
"Cat()"), symRange(Main.range(
"PurCat")),
1044 AllOf(withName(
"-pur"), withKind(SymbolKind::Method))))));
1047TEST(DocumentSymbolsTest, PragmaMarkGroups) {
1049 TU.
ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1051 $DogDef[[@interface Dog
1054 $DogImpl[[@implementation Dog
1056 + (id)sharedDoggo { return 0; }
1058 #pragma $Overrides[[mark - Overrides
1065 #pragma $Specifics[[mark - Dog Specifics
1070 @]]end // FIXME: Why doesn't this include the 'end'?
1072 #pragma $End[[mark - End
1075 TU.Code = Main.code().str();
1077 getSymbols(TU.build()),
1078 UnorderedElementsAre(
1079 AllOf(withName("Dog"), symRange(Main.range(
"DogDef"))),
1080 AllOf(withName(
"Dog"), symRange(Main.range(
"DogImpl")),
1081 children(AllOf(withName(
"+sharedDoggo"),
1082 withKind(SymbolKind::Method)),
1083 AllOf(withName(
"Overrides"),
1084 symRange(Main.range(
"Overrides")),
1085 children(AllOf(withName(
"-init"),
1086 withKind(SymbolKind::Method)),
1087 AllOf(withName(
"-bark"),
1088 withKind(SymbolKind::Method)))),
1089 AllOf(withName(
"Dog Specifics"),
1090 symRange(Main.range(
"Specifics")),
1091 children(AllOf(withName(
"-isAGoodBoy"),
1092 withKind(SymbolKind::Method)))))),
1093 AllOf(withName(
"End"), symRange(Main.range(
"End")))));
1096TEST(DocumentSymbolsTest, PragmaMarkGroupsNesting) {
1098 TU.
ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1104 #pragma mark - NotTopDecl
1109 TU.Code = Main.code().str();
1111 getSymbols(TU.build()),
1112 UnorderedElementsAre(AllOf(
1114 children(AllOf(withName(
"Foo"),
1115 children(AllOf(withName(
"Bar"),
1116 children(AllOf(withName(
"bar"),
1118 "NotTopDecl"))))))),
1119 withName(
"bar")))));
1122TEST(DocumentSymbolsTest, PragmaMarkGroupsNoNesting) {
1124 TU.
ExtraArgs = {
"-xobjective-c++",
"-Wno-objc-root-class"};
1126 #pragma mark Helpers
1127 void helpA(id obj) {}
1132 void coreMethod() {}
1134 TU.Code = Main.code().str();
1135 EXPECT_THAT(getSymbols(TU.build()),
1136 UnorderedElementsAre(withName("Helpers"), withName(
"helpA"),
1137 withName(
"(unnamed group)"),
1138 withName(
"Core"), withName(
"coreMethod")));
1144 class AbstractClass {
1146 virtual ~AbstractClass() = default;
1147 virtual void f1() = 0;
1155 void AbstractClass::f2() const {}
1157 class ImplClass final: public AbstractClass {
1163 TU.Code = Main.code().str();
1164 auto Symbols = getSymbols(TU.build());
1167 UnorderedElementsAre(
1169 withName(
"AbstractClass"),
1173 AllOf(withName(
"~AbstractClass"),
1177 AllOf(withName(
"f1"),
1187 AllOf(withName(
"f4"),
1191 AllOf(withName(
"AbstractClass::f2"),
1194 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