14 #include "llvm/ADT/StringRef.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
23 using ::testing::AllOf;
24 using ::testing::ElementsAre;
25 using ::testing::ElementsAreArray;
26 using ::testing::Field;
27 using ::testing::IsEmpty;
28 using ::testing::UnorderedElementsAre;
32 if (arg.containerName.empty())
33 return arg.name ==
Name;
34 return (arg.containerName +
"::" + arg.name) ==
Name;
36 MATCHER_P(WithName, N,
"") {
return arg.name == N; }
42 template <
class... ChildMatchers>
43 ::testing::Matcher<DocumentSymbol>
Children(ChildMatchers... ChildrenM) {
47 std::vector<SymbolInformation> getSymbols(TestTU &TU, llvm::StringRef Query,
51 EXPECT_TRUE(
bool(SymbolInfos)) <<
"workspaceSymbols returned an error";
55 TEST(WorkspaceSymbols, Macros) {
64 EXPECT_THAT(getSymbols(TU,
"macro"),
68 TEST(WorkspaceSymbols, NoLocals) {
71 void test(int FirstParam, int SecondParam) {
75 EXPECT_THAT(getSymbols(TU, "l"), IsEmpty());
76 EXPECT_THAT(getSymbols(TU,
"p"), IsEmpty());
79 TEST(WorkspaceSymbols, Globals) {
81 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
86 struct GlobalStruct {};)cpp";
90 EXPECT_THAT(getSymbols(TU, "global"),
97 TEST(WorkspaceSymbols, Unnamed) {
99 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
102 } UnnamedStruct;)cpp";
106 EXPECT_THAT(getSymbols(TU, "UnnamedStruct"),
107 ElementsAre(AllOf(QName(
"UnnamedStruct"),
109 EXPECT_THAT(getSymbols(TU,
"InUnnamed"),
110 ElementsAre(AllOf(QName(
"(anonymous struct)::InUnnamed"),
114 TEST(WorkspaceSymbols, InMainFile) {
118 static void test2() {}
120 EXPECT_THAT(getSymbols(TU, "test"),
121 ElementsAre(QName(
"test"), QName(
"test2")));
124 TEST(WorkspaceSymbols, Namespaces) {
126 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
137 EXPECT_THAT(getSymbols(TU, "a"),
138 UnorderedElementsAre(QName(
"ans1"), QName(
"ans1::ai1"),
140 QName(
"ans1::ans2::ai2")));
141 EXPECT_THAT(getSymbols(TU,
"::"), ElementsAre(QName(
"ans1")));
142 EXPECT_THAT(getSymbols(TU,
"::a"), ElementsAre(QName(
"ans1")));
143 EXPECT_THAT(getSymbols(TU,
"ans1::"),
144 UnorderedElementsAre(QName(
"ans1::ai1"), QName(
"ans1::ans2")));
145 EXPECT_THAT(getSymbols(TU,
"::ans1"), ElementsAre(QName(
"ans1")));
146 EXPECT_THAT(getSymbols(TU,
"::ans1::"),
147 UnorderedElementsAre(QName(
"ans1::ai1"), QName(
"ans1::ans2")));
148 EXPECT_THAT(getSymbols(TU,
"::ans1::ans2"), ElementsAre(QName(
"ans1::ans2")));
149 EXPECT_THAT(getSymbols(TU,
"::ans1::ans2::"),
150 ElementsAre(QName(
"ans1::ans2::ai2")));
153 TEST(WorkspaceSymbols, AnonymousNamespace) {
160 EXPECT_THAT(getSymbols(TU, "test"), ElementsAre(QName(
"test")));
163 TEST(WorkspaceSymbols, MultiFile) {
165 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
169 TU.AdditionalFiles["foo2.h"] = R
"cpp(
177 EXPECT_THAT(getSymbols(TU, "foo"),
178 UnorderedElementsAre(QName(
"foo"), QName(
"foo2")));
181 TEST(WorkspaceSymbols, GlobalNamespaceQueries) {
183 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
197 EXPECT_THAT(getSymbols(TU, "::"),
198 UnorderedElementsAre(
202 EXPECT_THAT(getSymbols(TU,
":"), IsEmpty());
203 EXPECT_THAT(getSymbols(TU,
""), IsEmpty());
206 TEST(WorkspaceSymbols, Enums) {
208 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
233 EXPECT_THAT(getSymbols(TU, "Red"), ElementsAre(QName(
"Red")));
234 EXPECT_THAT(getSymbols(TU,
"::Red"), ElementsAre(QName(
"Red")));
235 EXPECT_THAT(getSymbols(TU,
"Green"), ElementsAre(QName(
"Green")));
236 EXPECT_THAT(getSymbols(TU,
"Green"), ElementsAre(QName(
"Green")));
237 EXPECT_THAT(getSymbols(TU,
"Color2::Yellow"),
238 ElementsAre(QName(
"Color2::Yellow")));
239 EXPECT_THAT(getSymbols(TU,
"Yellow"), ElementsAre(QName(
"Color2::Yellow")));
241 EXPECT_THAT(getSymbols(TU,
"ns::Black"), ElementsAre(QName(
"ns::Black")));
242 EXPECT_THAT(getSymbols(TU,
"ns::Blue"), ElementsAre(QName(
"ns::Blue")));
243 EXPECT_THAT(getSymbols(TU,
"ns::Color4::White"),
244 ElementsAre(QName(
"ns::Color4::White")));
247 TEST(WorkspaceSymbols, Ranking) {
249 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
256 EXPECT_THAT(getSymbols(TU, "::"), ElementsAre(QName(
"func"), QName(
"ns")));
259 TEST(WorkspaceSymbols, WithLimit) {
261 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
269 EXPECT_THAT(getSymbols(TU,
"foo"),
270 UnorderedElementsAre(
274 EXPECT_THAT(getSymbols(TU,
"foo", 1), ElementsAre(QName(
"foo")));
277 TEST(WorkspaceSymbols, TempSpecs) {
279 TU.ExtraArgs = {
"-xc++"};
281 template <typename T, typename U, int X = 5> class Foo {};
282 template <typename T> class Foo<int, T> {};
283 template <> class Foo<bool, int> {};
284 template <> class Foo<bool, int, 3> {};
288 getSymbols(TU,
"Foo"),
289 UnorderedElementsAre(
296 std::vector<DocumentSymbol> getSymbols(ParsedAST AST) {
298 EXPECT_TRUE(
bool(SymbolInfos)) <<
"documentSymbols returned an error";
302 TEST(DocumentSymbols, BasicSymbols) {
312 Foo& operator=(const Foo&);
323 static const int KInt = 2;
324 const char* kStr = "123";
331 using int32_t = int32;
347 TU.Code = Main.code().str();
349 getSymbols(TU.build()),
355 AllOf(WithName(
"Foo"),
359 AllOf(WithName(
"operator="),
361 AllOf(WithName(
"~Foo"),
391 TEST(DocumentSymbols, DeclarationDefinition) {
397 void Foo::$def[[f]]() {
401 TU.Code = Main.code().str();
403 getSymbols(TU.build()),
407 SymNameRange(Main.range(
"decl"))))),
409 SymNameRange(Main.range(
"def")))));
412 TEST(DocumentSymbols, Concepts) {
414 TU.ExtraArgs = {
"-std=c++20"};
415 TU.Code =
"template <typename T> concept C = requires(T t) { t.foo(); };";
417 EXPECT_THAT(getSymbols(TU.build()), ElementsAre(WithName(
"C")));
420 TEST(DocumentSymbols, ExternSymbol) {
422 TU.AdditionalFiles[
"foo.h"] = R
"cpp(
429 EXPECT_THAT(getSymbols(TU.build()), IsEmpty());
432 TEST(DocumentSymbols, NoLocals) {
435 void test(int FirstParam, int SecondParam) {
436 struct LocalClass {};
439 EXPECT_THAT(getSymbols(TU.build()), ElementsAre(WithName("test")));
442 TEST(DocumentSymbols, Unnamed) {
450 getSymbols(TU.build()),
453 Children(AllOf(WithName(
"InUnnamed"),
459 TEST(DocumentSymbols, InHeaderFile) {
461 TU.AdditionalFiles[
"bar.h"] = R
"cpp(
470 EXPECT_THAT(getSymbols(TU.build()), ElementsAre(WithName("test")));
473 TEST(DocumentSymbols, Template) {
476 template <class T> struct Tmpl {T x = 0;};
477 template <> struct Tmpl<int> {
480 extern template struct Tmpl<float>;
481 template struct Tmpl<double>;
483 template <class T, class U, class Z = float>
486 int funcTmpl<int>(double a);
488 template <class T, class U = double>
491 double varTmpl<int> = 10.0;
494 getSymbols(TU.build()),
504 AllOf(WithName(
"funcTmpl"),
Children()),
505 AllOf(WithName(
"funcTmpl<int>"),
Children()),
506 AllOf(WithName(
"varTmpl"),
Children()),
507 AllOf(WithName(
"varTmpl<int>"),
Children())));
510 TEST(DocumentSymbols, Namespaces) {
524 inline namespace nb {
529 // This is still inlined.
536 getSymbols(TU.build()),
537 ElementsAreArray<::testing::Matcher<DocumentSymbol>>(
538 {AllOf(WithName("ans1"),
540 AllOf(WithName(
"ans2"),
Children(WithName(
"ai2"))))),
541 AllOf(WithName(
"(anonymous namespace)"),
Children(WithName(
"test"))),
542 AllOf(WithName(
"na"),
544 AllOf(WithName(
"na"),
548 TEST(DocumentSymbols, Enums) {
567 getSymbols(TU.build()),
569 AllOf(WithName("(anonymous enum)"),
Children(WithName(
"Red"))),
570 AllOf(WithName(
"Color"),
Children(WithName(
"Green"))),
571 AllOf(WithName(
"Color2"),
Children(WithName(
"Yellow"))),
572 AllOf(WithName(
"ns"),
Children(AllOf(WithName(
"(anonymous enum)"),
576 TEST(DocumentSymbols, FromMacro) {
580 class name##_Test {};
582 $expansion[[FF]](abc);
585 class $spelling[[Test]] {};
589 TU.Code = Main.code().str();
591 getSymbols(TU.build()),
593 AllOf(WithName("abc_Test"), SymNameRange(Main.range(
"expansion"))),
594 AllOf(WithName(
"Test"), SymNameRange(Main.range(
"spelling")))));
597 TEST(DocumentSymbols, FuncTemplates) {
599 Annotations Source(R
"cpp(
604 auto y = foo<double>();
606 TU.Code = Source.code().str();
608 EXPECT_THAT(getSymbols(TU.build()),
609 ElementsAre(WithName(
"foo"), WithName(
"x"), WithName(
"y")));
612 TEST(DocumentSymbols, UsingDirectives) {
614 Annotations Source(R
"cpp(
619 namespace ns_alias = ns;
621 using namespace ::ns; // check we don't loose qualifiers.
622 using namespace ns_alias; // and namespace aliases.
624 TU.Code = Source.code().str();
625 EXPECT_THAT(getSymbols(TU.build()),
626 ElementsAre(WithName("ns"), WithName(
"ns_alias"),
627 WithName(
"using namespace ::ns"),
628 WithName(
"using namespace ns_alias")));
631 TEST(DocumentSymbols, TempSpecs) {
634 template <typename T, typename U, int X = 5> class Foo {};
635 template <typename T> class Foo<int, T> {};
636 template <> class Foo<bool, int> {};
637 template <> class Foo<bool, int, 3> {};
641 getSymbols(TU.build()),
642 UnorderedElementsAre(
649 TEST(DocumentSymbols, Qualifiers) {
652 namespace foo { namespace bar {
661 struct foo::bar::Cls { };
663 int foo::bar::func1() { return 10; }
664 int ::foo::bar::func2() { return 20; }
667 int bar::func3() { return 30; }
669 namespace alias = foo::bar;
670 int ::alias::func4() { return 40; }
674 EXPECT_THAT(getSymbols(TU.build()),
675 UnorderedElementsAre(
676 WithName(
"foo"), WithName(
"foo::bar::Cls"),
677 WithName(
"foo::bar::func1"), WithName(
"::foo::bar::func2"),
678 WithName(
"using namespace foo"), WithName(
"bar::func3"),
679 WithName(
"alias"), WithName(
"::alias::func4")));
682 TEST(DocumentSymbols, QualifiersWithTemplateArgs) {
685 template <typename T, typename U = double> class Foo;
688 class Foo<int, double> {
694 using int_type = int;
696 // Typedefs should be preserved!
697 int Foo<int_type, double>::method1() { return 10; }
699 // Default arguments should not be shown!
700 int Foo<int>::method2() { return 20; }
702 using Foo_type = Foo<int>;
703 // If the whole type is aliased, this should be preserved too!
704 int Foo_type::method3() { return 30; }
707 getSymbols(TU.build()),
708 UnorderedElementsAre(WithName("Foo"), WithName(
"Foo<int, double>"),
709 WithName(
"int_type"),
710 WithName(
"Foo<int_type, double>::method1"),
711 WithName(
"Foo<int>::method2"), WithName(
"Foo_type"),
712 WithName(
"Foo_type::method3")));
715 TEST(DocumentSymbolsTest, Ranges) {
718 $foo[[int foo(bool Argument) {
722 $variable[[char GLOBAL_VARIABLE]];
731 $field[[unsigned Baz]];
733 $getbaz[[unsigned getBaz() { return Baz; }]]
737 $forwardclass[[class ForwardClassDecl]];
739 $struct[[struct StructDefinition {
740 $structfield[[int *Pointer = nullptr]];
742 $forwardstruct[[struct StructDeclaration]];
744 $forwardfunc[[void forwardFunctionDecl(int Something)]];
746 TU.Code = Main.code().str();
748 getSymbols(TU.build()),
749 UnorderedElementsAre(
751 SymRange(Main.range(
"foo"))),
753 SymRange(Main.range(
"variable"))),
756 SymRange(Main.range(
"ns")),
759 SymRange(Main.range(
"bar")),
762 SymRange(Main.range(
"ctor"))),
764 SymRange(Main.range(
"dtor"))),
766 SymRange(Main.range(
"field"))),
768 SymRange(Main.range(
"getbaz"))))))),
770 SymRange(Main.range(
"forwardclass"))),
772 SymRange(Main.range(
"struct")),
774 SymRange(Main.range(
"structfield"))))),
776 SymRange(Main.range(
"forwardstruct"))),
778 SymRange(Main.range(
"forwardfunc")))));