xref: /llvm-project/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp (revision e1271dd5a7ecf5cee59c8e2684b93501a1aab82d)
1 //===-- SymbolCollectorTests.cpp  -------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "Annotations.h"
10 #include "TestFS.h"
11 #include "TestTU.h"
12 #include "URI.h"
13 #include "clang-include-cleaner/Record.h"
14 #include "index/SymbolCollector.h"
15 #include "clang/Basic/FileManager.h"
16 #include "clang/Basic/FileSystemOptions.h"
17 #include "clang/Basic/SourceLocation.h"
18 #include "clang/Frontend/CompilerInstance.h"
19 #include "clang/Index/IndexingAction.h"
20 #include "clang/Index/IndexingOptions.h"
21 #include "clang/Tooling/Tooling.h"
22 #include "llvm/ADT/IntrusiveRefCntPtr.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/VirtualFileSystem.h"
26 #include "gmock/gmock-matchers.h"
27 #include "gmock/gmock.h"
28 #include "gtest/gtest.h"
29 
30 #include <memory>
31 #include <optional>
32 #include <string>
33 #include <utility>
34 
35 namespace clang {
36 namespace clangd {
37 namespace {
38 
39 using ::testing::_;
40 using ::testing::AllOf;
41 using ::testing::Contains;
42 using ::testing::Each;
43 using ::testing::ElementsAre;
44 using ::testing::Field;
45 using ::testing::IsEmpty;
46 using ::testing::Not;
47 using ::testing::Pair;
48 using ::testing::UnorderedElementsAre;
49 using ::testing::UnorderedElementsAreArray;
50 
51 // GMock helpers for matching Symbol.
52 MATCHER_P(labeled, Label, "") {
53   return (arg.Name + arg.Signature).str() == Label;
54 }
55 MATCHER_P(returnType, D, "") { return arg.ReturnType == D; }
56 MATCHER_P(doc, D, "") { return arg.Documentation == D; }
57 MATCHER_P(snippet, S, "") {
58   return (arg.Name + arg.CompletionSnippetSuffix).str() == S;
59 }
60 MATCHER_P(qName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
61 MATCHER_P(hasName, Name, "") { return arg.Name == Name; }
62 MATCHER_P(templateArgs, TemplArgs, "") {
63   return arg.TemplateSpecializationArgs == TemplArgs;
64 }
65 MATCHER_P(hasKind, Kind, "") { return arg.SymInfo.Kind == Kind; }
66 MATCHER_P(declURI, P, "") {
67   return StringRef(arg.CanonicalDeclaration.FileURI) == P;
68 }
69 MATCHER_P(defURI, P, "") { return StringRef(arg.Definition.FileURI) == P; }
70 MATCHER(includeHeader, "") { return !arg.IncludeHeaders.empty(); }
71 MATCHER_P(includeHeader, P, "") {
72   return (arg.IncludeHeaders.size() == 1) &&
73          (arg.IncludeHeaders.begin()->IncludeHeader == P);
74 }
75 MATCHER_P2(IncludeHeaderWithRef, includeHeader, References, "") {
76   return (arg.IncludeHeader == includeHeader) && (arg.References == References);
77 }
78 bool rangesMatch(const SymbolLocation &Loc, const Range &R) {
79   return std::make_tuple(Loc.Start.line(), Loc.Start.column(), Loc.End.line(),
80                          Loc.End.column()) ==
81          std::make_tuple(R.start.line, R.start.character, R.end.line,
82                          R.end.character);
83 }
84 MATCHER_P(declRange, Pos, "") {
85   return rangesMatch(arg.CanonicalDeclaration, Pos);
86 }
87 MATCHER_P(defRange, Pos, "") { return rangesMatch(arg.Definition, Pos); }
88 MATCHER_P(refCount, R, "") { return int(arg.References) == R; }
89 MATCHER_P(forCodeCompletion, IsIndexedForCodeCompletion, "") {
90   return static_cast<bool>(arg.Flags & Symbol::IndexedForCodeCompletion) ==
91          IsIndexedForCodeCompletion;
92 }
93 MATCHER(deprecated, "") { return arg.Flags & Symbol::Deprecated; }
94 MATCHER(implementationDetail, "") {
95   return arg.Flags & Symbol::ImplementationDetail;
96 }
97 MATCHER(visibleOutsideFile, "") {
98   return static_cast<bool>(arg.Flags & Symbol::VisibleOutsideFile);
99 }
100 MATCHER(refRange, "") {
101   const Ref &Pos = ::testing::get<0>(arg);
102   const Range &Range = ::testing::get<1>(arg);
103   return rangesMatch(Pos.Location, Range);
104 }
105 MATCHER_P2(OverriddenBy, Subject, Object, "") {
106   return arg == Relation{Subject.ID, RelationKind::OverriddenBy, Object.ID};
107 }
108 MATCHER(isSpelled, "") {
109   return static_cast<bool>(arg.Kind & RefKind::Spelled);
110 }
111 ::testing::Matcher<const std::vector<Ref> &>
112 haveRanges(const std::vector<Range> Ranges) {
113   return ::testing::UnorderedPointwise(refRange(), Ranges);
114 }
115 
116 class ShouldCollectSymbolTest : public ::testing::Test {
117 public:
118   void build(llvm::StringRef HeaderCode, llvm::StringRef Code = "") {
119     File.HeaderFilename = HeaderName;
120     File.Filename = FileName;
121     File.HeaderCode = std::string(HeaderCode);
122     File.Code = std::string(Code);
123     AST = File.build();
124   }
125 
126   // build() must have been called.
127   bool shouldCollect(llvm::StringRef Name, bool Qualified = true) {
128     assert(AST);
129     const NamedDecl &ND =
130         Qualified ? findDecl(*AST, Name) : findUnqualifiedDecl(*AST, Name);
131     const SourceManager &SM = AST->getSourceManager();
132     bool MainFile = isInsideMainFile(ND.getBeginLoc(), SM);
133     return SymbolCollector::shouldCollectSymbol(
134         ND, AST->getASTContext(), SymbolCollector::Options(), MainFile);
135   }
136 
137 protected:
138   std::string HeaderName = "f.h";
139   std::string FileName = "f.cpp";
140   TestTU File;
141   std::optional<ParsedAST> AST; // Initialized after build.
142 };
143 
144 TEST_F(ShouldCollectSymbolTest, ShouldCollectSymbol) {
145   build(R"(
146     namespace nx {
147     class X{};
148     auto f() { int Local; } // auto ensures function body is parsed.
149     struct { int x; } var;
150     }
151   )",
152         R"(
153     class InMain {};
154     namespace { class InAnonymous {}; }
155     static void g();
156   )");
157   auto AST = File.build();
158   EXPECT_TRUE(shouldCollect("nx"));
159   EXPECT_TRUE(shouldCollect("nx::X"));
160   EXPECT_TRUE(shouldCollect("nx::f"));
161   EXPECT_TRUE(shouldCollect("InMain"));
162   EXPECT_TRUE(shouldCollect("InAnonymous", /*Qualified=*/false));
163   EXPECT_TRUE(shouldCollect("g"));
164 
165   EXPECT_FALSE(shouldCollect("Local", /*Qualified=*/false));
166 }
167 
168 TEST_F(ShouldCollectSymbolTest, CollectLocalClassesAndVirtualMethods) {
169   build(R"(
170     namespace nx {
171     auto f() {
172       int Local;
173       auto LocalLambda = [&](){
174         Local++;
175         class ClassInLambda{};
176         return Local;
177       };
178     } // auto ensures function body is parsed.
179     auto foo() {
180       class LocalBase {
181         virtual void LocalVirtual();
182         void LocalConcrete();
183         int BaseMember;
184       };
185     }
186     } // namespace nx
187   )",
188         "");
189   auto AST = File.build();
190   EXPECT_FALSE(shouldCollect("Local", /*Qualified=*/false));
191   EXPECT_TRUE(shouldCollect("ClassInLambda", /*Qualified=*/false));
192   EXPECT_TRUE(shouldCollect("LocalBase", /*Qualified=*/false));
193   EXPECT_TRUE(shouldCollect("LocalVirtual", /*Qualified=*/false));
194   EXPECT_TRUE(shouldCollect("LocalConcrete", /*Qualified=*/false));
195   EXPECT_FALSE(shouldCollect("BaseMember", /*Qualified=*/false));
196   EXPECT_FALSE(shouldCollect("Local", /*Qualified=*/false));
197 }
198 
199 TEST_F(ShouldCollectSymbolTest, NoPrivateProtoSymbol) {
200   HeaderName = "f.proto.h";
201   build(
202       R"(// Generated by the protocol buffer compiler.  DO NOT EDIT!
203          namespace nx {
204            enum Outer_Enum : int {
205              Outer_Enum_KIND1,
206              Outer_Enum_Kind_2,
207            };
208            bool Outer_Enum_IsValid(int);
209 
210            class Outer_Inner {};
211            class Outer {
212              using Inner = Outer_Inner;
213              using Enum = Outer_Enum;
214              static constexpr Enum KIND1 = Outer_Enum_KIND1;
215              static constexpr Enum Kind_2 = Outer_Enum_Kind_2;
216              static bool Enum_IsValid(int);
217              int &x();
218              void set_x();
219              void _internal_set_x();
220 
221              int &Outer_y();
222            };
223            enum Foo {
224              FOO_VAL1,
225              Foo_VAL2,
226            };
227            bool Foo_IsValid(int);
228          })");
229 
230   // Make sure all the mangled names for Outer::Enum is discarded.
231   EXPECT_FALSE(shouldCollect("nx::Outer_Enum"));
232   EXPECT_FALSE(shouldCollect("nx::Outer_Enum_KIND1"));
233   EXPECT_FALSE(shouldCollect("nx::Outer_Enum_Kind_2"));
234   EXPECT_FALSE(shouldCollect("nx::Outer_Enum_IsValid"));
235   // But nested aliases are preserved.
236   EXPECT_TRUE(shouldCollect("nx::Outer::Enum"));
237   EXPECT_TRUE(shouldCollect("nx::Outer::KIND1"));
238   EXPECT_TRUE(shouldCollect("nx::Outer::Kind_2"));
239   EXPECT_TRUE(shouldCollect("nx::Outer::Enum_IsValid"));
240 
241   // Check for Outer::Inner.
242   EXPECT_FALSE(shouldCollect("nx::Outer_Inner"));
243   EXPECT_TRUE(shouldCollect("nx::Outer"));
244   EXPECT_TRUE(shouldCollect("nx::Outer::Inner"));
245 
246   // Make sure field related information is preserved, unless it's explicitly
247   // marked with `_internal_`.
248   EXPECT_TRUE(shouldCollect("nx::Outer::x"));
249   EXPECT_TRUE(shouldCollect("nx::Outer::set_x"));
250   EXPECT_FALSE(shouldCollect("nx::Outer::_internal_set_x"));
251   EXPECT_TRUE(shouldCollect("nx::Outer::Outer_y"));
252 
253   // Handling of a top-level enum
254   EXPECT_TRUE(shouldCollect("nx::Foo::FOO_VAL1"));
255   EXPECT_TRUE(shouldCollect("nx::FOO_VAL1"));
256   EXPECT_TRUE(shouldCollect("nx::Foo_IsValid"));
257   // Our heuristic goes wrong here, if the user has a nested name that starts
258   // with parent's name.
259   EXPECT_FALSE(shouldCollect("nx::Foo::Foo_VAL2"));
260   EXPECT_FALSE(shouldCollect("nx::Foo_VAL2"));
261 }
262 
263 TEST_F(ShouldCollectSymbolTest, DoubleCheckProtoHeaderComment) {
264   HeaderName = "f.proto.h";
265   build(R"(
266     namespace nx {
267       class Top_Level {};
268       enum Kind {
269         Kind_Fine
270       };
271     }
272   )");
273   EXPECT_TRUE(shouldCollect("nx::Top_Level"));
274   EXPECT_TRUE(shouldCollect("nx::Kind_Fine"));
275 }
276 
277 class SymbolIndexActionFactory : public tooling::FrontendActionFactory {
278 public:
279   SymbolIndexActionFactory(SymbolCollector::Options COpts)
280       : COpts(std::move(COpts)) {}
281 
282   std::unique_ptr<FrontendAction> create() override {
283     class IndexAction : public ASTFrontendAction {
284     public:
285       IndexAction(std::shared_ptr<index::IndexDataConsumer> DataConsumer,
286                   const index::IndexingOptions &Opts,
287                   std::shared_ptr<include_cleaner::PragmaIncludes> PI)
288           : DataConsumer(std::move(DataConsumer)), Opts(Opts),
289             PI(std::move(PI)) {}
290 
291       std::unique_ptr<ASTConsumer>
292       CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
293         PI->record(CI);
294         return createIndexingASTConsumer(DataConsumer, Opts,
295                                          CI.getPreprocessorPtr());
296       }
297 
298       bool BeginInvocation(CompilerInstance &CI) override {
299         // Make the compiler parse all comments.
300         CI.getLangOpts().CommentOpts.ParseAllComments = true;
301         return true;
302       }
303 
304     private:
305       std::shared_ptr<index::IndexDataConsumer> DataConsumer;
306       index::IndexingOptions Opts;
307       std::shared_ptr<include_cleaner::PragmaIncludes> PI;
308     };
309     index::IndexingOptions IndexOpts;
310     IndexOpts.SystemSymbolFilter =
311         index::IndexingOptions::SystemSymbolFilterKind::All;
312     IndexOpts.IndexFunctionLocals = true;
313     std::shared_ptr<include_cleaner::PragmaIncludes> PI =
314         std::make_shared<include_cleaner::PragmaIncludes>();
315     COpts.PragmaIncludes = PI.get();
316     Collector = std::make_shared<SymbolCollector>(COpts);
317     return std::make_unique<IndexAction>(Collector, std::move(IndexOpts),
318                                          std::move(PI));
319   }
320 
321   std::shared_ptr<SymbolCollector> Collector;
322   SymbolCollector::Options COpts;
323 };
324 
325 class SymbolCollectorTest : public ::testing::Test {
326 public:
327   SymbolCollectorTest()
328       : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
329         TestHeaderName(testPath("symbol.h")),
330         TestFileName(testPath("symbol.cc")) {
331     TestHeaderURI = URI::create(TestHeaderName).toString();
332     TestFileURI = URI::create(TestFileName).toString();
333   }
334 
335   // Note that unlike TestTU, no automatic header guard is added.
336   // HeaderCode should start with #pragma once to be treated as modular.
337   bool runSymbolCollector(llvm::StringRef HeaderCode, llvm::StringRef MainCode,
338                           const std::vector<std::string> &ExtraArgs = {}) {
339     llvm::IntrusiveRefCntPtr<FileManager> Files(
340         new FileManager(FileSystemOptions(), InMemoryFileSystem));
341 
342     auto Factory = std::make_unique<SymbolIndexActionFactory>(CollectorOpts);
343 
344     std::vector<std::string> Args = {"symbol_collector", "-fsyntax-only",
345                                      "-xc++", "-include", TestHeaderName};
346     Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
347     // This allows to override the "-xc++" with something else, i.e.
348     // -xobjective-c++.
349     Args.push_back(TestFileName);
350 
351     tooling::ToolInvocation Invocation(
352         Args, Factory->create(), Files.get(),
353         std::make_shared<PCHContainerOperations>());
354 
355     // Multiple calls to runSymbolCollector with different contents will fail
356     // to update the filesystem! Why are we sharing one across tests, anyway?
357     EXPECT_TRUE(InMemoryFileSystem->addFile(
358         TestHeaderName, 0, llvm::MemoryBuffer::getMemBuffer(HeaderCode)));
359     EXPECT_TRUE(InMemoryFileSystem->addFile(
360         TestFileName, 0, llvm::MemoryBuffer::getMemBuffer(MainCode)));
361     Invocation.run();
362     Symbols = Factory->Collector->takeSymbols();
363     Refs = Factory->Collector->takeRefs();
364     Relations = Factory->Collector->takeRelations();
365     return true;
366   }
367 
368 protected:
369   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
370   std::string TestHeaderName;
371   std::string TestHeaderURI;
372   std::string TestFileName;
373   std::string TestFileURI;
374   SymbolSlab Symbols;
375   RefSlab Refs;
376   RelationSlab Relations;
377   SymbolCollector::Options CollectorOpts;
378 };
379 
380 TEST_F(SymbolCollectorTest, CollectSymbols) {
381   const std::string Header = R"(
382     class Foo {
383       Foo() {}
384       Foo(int a) {}
385       void f();
386       friend void f1();
387       friend class Friend;
388       Foo& operator=(const Foo&);
389       ~Foo();
390       class Nested {
391       void f();
392       };
393     };
394     class Friend {
395     };
396 
397     void f1();
398     inline void f2() {}
399     static const int KInt = 2;
400     const char* kStr = "123";
401 
402     namespace {
403     void ff() {} // ignore
404     }
405 
406     void f1() {
407       auto LocalLambda = [&](){
408         class ClassInLambda{};
409       };
410     }
411 
412     namespace foo {
413     // Type alias
414     typedef int int32;
415     using int32_t = int32;
416 
417     // Variable
418     int v1;
419 
420     // Namespace
421     namespace bar {
422     int v2;
423     }
424     // Namespace alias
425     namespace baz = bar;
426 
427     using bar::v2;
428     } // namespace foo
429   )";
430   runSymbolCollector(Header, /*Main=*/"");
431   EXPECT_THAT(Symbols,
432               UnorderedElementsAreArray(
433                   {AllOf(qName("Foo"), forCodeCompletion(true)),
434                    AllOf(qName("Foo::Foo"), forCodeCompletion(false)),
435                    AllOf(qName("Foo::Foo"), forCodeCompletion(false)),
436                    AllOf(qName("Foo::f"), forCodeCompletion(false)),
437                    AllOf(qName("Foo::~Foo"), forCodeCompletion(false)),
438                    AllOf(qName("Foo::operator="), forCodeCompletion(false)),
439                    AllOf(qName("Foo::Nested"), forCodeCompletion(false)),
440                    AllOf(qName("Foo::Nested::f"), forCodeCompletion(false)),
441                    AllOf(qName("ClassInLambda"), forCodeCompletion(false)),
442                    AllOf(qName("Friend"), forCodeCompletion(true)),
443                    AllOf(qName("f1"), forCodeCompletion(true)),
444                    AllOf(qName("f2"), forCodeCompletion(true)),
445                    AllOf(qName("KInt"), forCodeCompletion(true)),
446                    AllOf(qName("kStr"), forCodeCompletion(true)),
447                    AllOf(qName("foo"), forCodeCompletion(true)),
448                    AllOf(qName("foo::bar"), forCodeCompletion(true)),
449                    AllOf(qName("foo::int32"), forCodeCompletion(true)),
450                    AllOf(qName("foo::int32_t"), forCodeCompletion(true)),
451                    AllOf(qName("foo::v1"), forCodeCompletion(true)),
452                    AllOf(qName("foo::bar::v2"), forCodeCompletion(true)),
453                    AllOf(qName("foo::v2"), forCodeCompletion(true)),
454                    AllOf(qName("foo::baz"), forCodeCompletion(true))}));
455 }
456 
457 TEST_F(SymbolCollectorTest, FileLocal) {
458   const std::string Header = R"(
459     class Foo {};
460     namespace {
461       class Ignored {};
462     }
463     void bar();
464   )";
465   const std::string Main = R"(
466     class ForwardDecl;
467     void bar() {}
468     static void a();
469     class B {};
470     namespace {
471       void c();
472     }
473   )";
474   runSymbolCollector(Header, Main);
475   EXPECT_THAT(Symbols,
476               UnorderedElementsAre(
477                   AllOf(qName("Foo"), visibleOutsideFile()),
478                   AllOf(qName("bar"), visibleOutsideFile()),
479                   AllOf(qName("a"), Not(visibleOutsideFile())),
480                   AllOf(qName("B"), Not(visibleOutsideFile())),
481                   AllOf(qName("c"), Not(visibleOutsideFile())),
482                   // FIXME: ForwardDecl likely *is* visible outside.
483                   AllOf(qName("ForwardDecl"), Not(visibleOutsideFile()))));
484 }
485 
486 TEST_F(SymbolCollectorTest, Template) {
487   Annotations Header(R"(
488     // Primary template and explicit specialization are indexed, instantiation
489     // is not.
490     template <class T, class U> struct [[Tmpl]] {T $xdecl[[x]] = 0;};
491     template <> struct $specdecl[[Tmpl]]<int, bool> {};
492     template <class U> struct $partspecdecl[[Tmpl]]<bool, U> {};
493     extern template struct Tmpl<float, bool>;
494     template struct Tmpl<double, bool>;
495   )");
496   runSymbolCollector(Header.code(), /*Main=*/"");
497   EXPECT_THAT(Symbols,
498               UnorderedElementsAre(
499                   AllOf(qName("Tmpl"), declRange(Header.range()),
500                         forCodeCompletion(true)),
501                   AllOf(qName("Tmpl"), declRange(Header.range("specdecl")),
502                         forCodeCompletion(false)),
503                   AllOf(qName("Tmpl"), declRange(Header.range("partspecdecl")),
504                         forCodeCompletion(false)),
505                   AllOf(qName("Tmpl::x"), declRange(Header.range("xdecl")),
506                         forCodeCompletion(false))));
507 }
508 
509 TEST_F(SymbolCollectorTest, templateArgs) {
510   Annotations Header(R"(
511     template <class X> class $barclasstemp[[Bar]] {};
512     template <class T, class U, template<typename> class Z, int Q>
513     struct [[Tmpl]] { T $xdecl[[x]] = 0; };
514 
515     // template-template, non-type and type full spec
516     template <> struct $specdecl[[Tmpl]]<int, bool, Bar, 3> {};
517 
518     // template-template, non-type and type partial spec
519     template <class U, int T> struct $partspecdecl[[Tmpl]]<bool, U, Bar, T> {};
520     // instantiation
521     extern template struct Tmpl<float, bool, Bar, 8>;
522     // instantiation
523     template struct Tmpl<double, bool, Bar, 2>;
524 
525     template <typename ...> class $fooclasstemp[[Foo]] {};
526     // parameter-packs full spec
527     template<> class $parampack[[Foo]]<Bar<int>, int, double> {};
528     // parameter-packs partial spec
529     template<class T> class $parampackpartial[[Foo]]<T, T> {};
530 
531     template <int ...> class $bazclasstemp[[Baz]] {};
532     // non-type parameter-packs full spec
533     template<> class $parampacknontype[[Baz]]<3, 5, 8> {};
534     // non-type parameter-packs partial spec
535     template<int T> class $parampacknontypepartial[[Baz]]<T, T> {};
536 
537     template <template <class> class ...> class $fozclasstemp[[Foz]] {};
538     // template-template parameter-packs full spec
539     template<> class $parampacktempltempl[[Foz]]<Bar, Bar> {};
540     // template-template parameter-packs partial spec
541     template<template <class> class T>
542     class $parampacktempltemplpartial[[Foz]]<T, T> {};
543   )");
544   runSymbolCollector(Header.code(), /*Main=*/"");
545   EXPECT_THAT(
546       Symbols,
547       AllOf(
548           Contains(AllOf(qName("Tmpl"), templateArgs("<int, bool, Bar, 3>"),
549                          declRange(Header.range("specdecl")),
550                          forCodeCompletion(false))),
551           Contains(AllOf(qName("Tmpl"), templateArgs("<bool, U, Bar, T>"),
552                          declRange(Header.range("partspecdecl")),
553                          forCodeCompletion(false))),
554           Contains(AllOf(qName("Foo"), templateArgs("<Bar<int>, int, double>"),
555                          declRange(Header.range("parampack")),
556                          forCodeCompletion(false))),
557           Contains(AllOf(qName("Foo"), templateArgs("<T, T>"),
558                          declRange(Header.range("parampackpartial")),
559                          forCodeCompletion(false))),
560           Contains(AllOf(qName("Baz"), templateArgs("<3, 5, 8>"),
561                          declRange(Header.range("parampacknontype")),
562                          forCodeCompletion(false))),
563           Contains(AllOf(qName("Baz"), templateArgs("<T, T>"),
564                          declRange(Header.range("parampacknontypepartial")),
565                          forCodeCompletion(false))),
566           Contains(AllOf(qName("Foz"), templateArgs("<Bar, Bar>"),
567                          declRange(Header.range("parampacktempltempl")),
568                          forCodeCompletion(false))),
569           Contains(AllOf(qName("Foz"), templateArgs("<T, T>"),
570                          declRange(Header.range("parampacktempltemplpartial")),
571                          forCodeCompletion(false)))));
572 }
573 
574 TEST_F(SymbolCollectorTest, ObjCRefs) {
575   Annotations Header(R"(
576   @interface Person
577   - (void)$talk[[talk]];
578   - (void)$say[[say]]:(id)something;
579   @end
580   @interface Person (Category)
581   - (void)categoryMethod;
582   - (void)multiArg:(id)a method:(id)b;
583   @end
584   )");
585   Annotations Main(R"(
586   @implementation Person
587   - (void)$talk[[talk]] {}
588   - (void)$say[[say]]:(id)something {}
589   @end
590 
591   void fff(Person *p) {
592     [p $talk[[talk]]];
593     [p $say[[say]]:0];
594     [p categoryMethod];
595     [p multiArg:0 method:0];
596   }
597   )");
598   CollectorOpts.RefFilter = RefKind::All;
599   CollectorOpts.CollectMainFileRefs = true;
600   TestFileName = testPath("test.m");
601   runSymbolCollector(Header.code(), Main.code(),
602                      {"-fblocks", "-xobjective-c++", "-Wno-objc-root-class"});
603   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Person::talk").ID,
604                                   haveRanges(Main.ranges("talk")))));
605   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Person::say:").ID,
606                                   haveRanges(Main.ranges("say")))));
607   EXPECT_THAT(Refs,
608               Contains(Pair(findSymbol(Symbols, "Person::categoryMethod").ID,
609                             ElementsAre(isSpelled()))));
610   EXPECT_THAT(Refs,
611               Contains(Pair(findSymbol(Symbols, "Person::multiArg:method:").ID,
612                             ElementsAre(isSpelled()))));
613 }
614 
615 TEST_F(SymbolCollectorTest, ObjCSymbols) {
616   const std::string Header = R"(
617     @interface Person
618     - (void)someMethodName:(void*)name1 lastName:(void*)lName;
619     @end
620 
621     @implementation Person
622     - (void)someMethodName:(void*)name1 lastName:(void*)lName{
623       int foo;
624       ^(int param){ int bar; };
625     }
626     @end
627 
628     @interface Person (MyCategory)
629     - (void)someMethodName2:(void*)name2;
630     @end
631 
632     @implementation Person (MyCategory)
633     - (void)someMethodName2:(void*)name2 {
634       int foo2;
635     }
636     @end
637 
638     @protocol MyProtocol
639     - (void)someMethodName3:(void*)name3;
640     @end
641   )";
642   TestFileName = testPath("test.m");
643   runSymbolCollector(Header, /*Main=*/"", {"-fblocks", "-xobjective-c++"});
644   EXPECT_THAT(Symbols,
645               UnorderedElementsAre(
646                   qName("Person"), qName("Person::someMethodName:lastName:"),
647                   AllOf(qName("MyCategory"), forCodeCompletion(false)),
648                   qName("Person::someMethodName2:"), qName("MyProtocol"),
649                   qName("MyProtocol::someMethodName3:")));
650 }
651 
652 TEST_F(SymbolCollectorTest, ObjCPropertyImpl) {
653   const std::string Header = R"(
654     @interface Container
655     @property(nonatomic) int magic;
656     @end
657 
658     @implementation Container
659     @end
660   )";
661   TestFileName = testPath("test.m");
662   runSymbolCollector(Header, /*Main=*/"", {"-xobjective-c++"});
663   EXPECT_THAT(Symbols, Contains(qName("Container")));
664   EXPECT_THAT(Symbols, Contains(qName("Container::magic")));
665   // FIXME: Results also contain Container::_magic on some platforms.
666   //        Figure out why it's platform-dependent.
667 }
668 
669 TEST_F(SymbolCollectorTest, ObjCLocations) {
670   Annotations Header(R"(
671     // Declared in header, defined in main.
672     @interface $dogdecl[[Dog]]
673     @end
674     @interface $fluffydecl[[Dog]] (Fluffy)
675     @end
676   )");
677   Annotations Main(R"(
678     @interface Dog ()
679     @end
680     @implementation $dogdef[[Dog]]
681     @end
682     @implementation $fluffydef[[Dog]] (Fluffy)
683     @end
684     // Category with no declaration (only implementation).
685     @implementation $ruff[[Dog]] (Ruff)
686     @end
687     // Implicitly defined interface.
688     @implementation $catdog[[CatDog]]
689     @end
690   )");
691   runSymbolCollector(Header.code(), Main.code(),
692                      {"-xobjective-c++", "-Wno-objc-root-class"});
693   EXPECT_THAT(Symbols,
694               UnorderedElementsAre(
695                   AllOf(qName("Dog"), declRange(Header.range("dogdecl")),
696                         defRange(Main.range("dogdef"))),
697                   AllOf(qName("Fluffy"), declRange(Header.range("fluffydecl")),
698                         defRange(Main.range("fluffydef"))),
699                   AllOf(qName("CatDog"), declRange(Main.range("catdog")),
700                         defRange(Main.range("catdog"))),
701                   AllOf(qName("Ruff"), declRange(Main.range("ruff")),
702                         defRange(Main.range("ruff")))));
703 }
704 
705 TEST_F(SymbolCollectorTest, ObjCForwardDecls) {
706   Annotations Header(R"(
707     // Forward declared in header, declared and defined in main.
708     @protocol Barker;
709     @class Dog;
710     // Never fully declared so Clang latches onto this decl.
711     @class $catdogdecl[[CatDog]];
712   )");
713   Annotations Main(R"(
714     @protocol $barkerdecl[[Barker]]
715     - (void)woof;
716     @end
717     @interface $dogdecl[[Dog]]<Barker>
718     - (void)woof;
719     @end
720     @implementation $dogdef[[Dog]]
721     - (void)woof {}
722     @end
723     @implementation $catdogdef[[CatDog]]
724     @end
725   )");
726   runSymbolCollector(Header.code(), Main.code(),
727                      {"-xobjective-c++", "-Wno-objc-root-class"});
728   EXPECT_THAT(Symbols,
729               UnorderedElementsAre(
730                   AllOf(qName("CatDog"), declRange(Header.range("catdogdecl")),
731                         defRange(Main.range("catdogdef"))),
732                   AllOf(qName("Dog"), declRange(Main.range("dogdecl")),
733                         defRange(Main.range("dogdef"))),
734                   AllOf(qName("Barker"), declRange(Main.range("barkerdecl"))),
735                   qName("Barker::woof"), qName("Dog::woof")));
736 }
737 
738 TEST_F(SymbolCollectorTest, ObjCClassExtensions) {
739   Annotations Header(R"(
740     @interface $catdecl[[Cat]]
741     @end
742   )");
743   Annotations Main(R"(
744     @interface Cat ()
745     - (void)meow;
746     @end
747     @interface Cat ()
748     - (void)pur;
749     @end
750   )");
751   runSymbolCollector(Header.code(), Main.code(),
752                      {"-xobjective-c++", "-Wno-objc-root-class"});
753   EXPECT_THAT(Symbols,
754               UnorderedElementsAre(
755                   AllOf(qName("Cat"), declRange(Header.range("catdecl"))),
756                   qName("Cat::meow"), qName("Cat::pur")));
757 }
758 
759 TEST_F(SymbolCollectorTest, ObjCFrameworkIncludeHeader) {
760   CollectorOpts.CollectIncludePath = true;
761   auto FrameworksPath = testPath("Frameworks/");
762   std::string FrameworkHeader = R"(
763     __attribute((objc_root_class))
764     @interface NSObject
765     @end
766   )";
767   InMemoryFileSystem->addFile(
768       testPath("Frameworks/Foundation.framework/Headers/NSObject.h"), 0,
769       llvm::MemoryBuffer::getMemBuffer(FrameworkHeader));
770   std::string PrivateFrameworkHeader = R"(
771     #import <Foundation/NSObject.h>
772 
773     @interface PrivateClass : NSObject
774     @end
775   )";
776   InMemoryFileSystem->addFile(
777       testPath(
778           "Frameworks/Foundation.framework/PrivateHeaders/NSObject+Private.h"),
779       0, llvm::MemoryBuffer::getMemBuffer(PrivateFrameworkHeader));
780 
781   std::string Header = R"(
782     #import <Foundation/NSObject+Private.h>
783     #import <Foundation/NSObject.h>
784 
785     @interface Container : NSObject
786     @end
787   )";
788   std::string Main = "";
789   TestFileName = testPath("test.m");
790   runSymbolCollector(Header, Main, {"-F", FrameworksPath, "-xobjective-c++"});
791   EXPECT_THAT(
792       Symbols,
793       UnorderedElementsAre(
794           AllOf(qName("NSObject"), includeHeader("<Foundation/NSObject.h>")),
795           AllOf(qName("PrivateClass"),
796                 includeHeader("<Foundation/NSObject+Private.h>")),
797           AllOf(qName("Container"))));
798 
799   // After adding the umbrella headers, we should use that spelling instead.
800   std::string UmbrellaHeader = R"(
801     #import <Foundation/NSObject.h>
802   )";
803   InMemoryFileSystem->addFile(
804       testPath("Frameworks/Foundation.framework/Headers/Foundation.h"), 0,
805       llvm::MemoryBuffer::getMemBuffer(UmbrellaHeader));
806   std::string PrivateUmbrellaHeader = R"(
807     #import <Foundation/NSObject+Private.h>
808   )";
809   InMemoryFileSystem->addFile(
810       testPath("Frameworks/Foundation.framework/PrivateHeaders/"
811                "Foundation_Private.h"),
812       0, llvm::MemoryBuffer::getMemBuffer(PrivateUmbrellaHeader));
813   runSymbolCollector(Header, Main, {"-F", FrameworksPath, "-xobjective-c++"});
814   EXPECT_THAT(
815       Symbols,
816       UnorderedElementsAre(
817           AllOf(qName("NSObject"), includeHeader("<Foundation/Foundation.h>")),
818           AllOf(qName("PrivateClass"),
819                 includeHeader("<Foundation/Foundation_Private.h>")),
820           AllOf(qName("Container"))));
821 
822   runSymbolCollector(Header, Main,
823                      {"-iframework", FrameworksPath, "-xobjective-c++"});
824   EXPECT_THAT(
825       Symbols,
826       UnorderedElementsAre(
827           AllOf(qName("NSObject"), includeHeader("<Foundation/Foundation.h>")),
828           AllOf(qName("PrivateClass"),
829                 includeHeader("<Foundation/Foundation_Private.h>")),
830           AllOf(qName("Container"))));
831 }
832 
833 TEST_F(SymbolCollectorTest, Locations) {
834   Annotations Header(R"cpp(
835     // Declared in header, defined in main.
836     extern int $xdecl[[X]];
837     class $clsdecl[[Cls]];
838     void $printdecl[[print]]();
839 
840     // Declared in header, defined nowhere.
841     extern int $zdecl[[Z]];
842 
843     void $foodecl[[fo\
844 o]]();
845   )cpp");
846   Annotations Main(R"cpp(
847     int $xdef[[X]] = 42;
848     class $clsdef[[Cls]] {};
849     void $printdef[[print]]() {}
850 
851     // Declared/defined in main only.
852     int $ydecl[[Y]];
853   )cpp");
854   runSymbolCollector(Header.code(), Main.code());
855   EXPECT_THAT(Symbols,
856               UnorderedElementsAre(
857                   AllOf(qName("X"), declRange(Header.range("xdecl")),
858                         defRange(Main.range("xdef"))),
859                   AllOf(qName("Cls"), declRange(Header.range("clsdecl")),
860                         defRange(Main.range("clsdef"))),
861                   AllOf(qName("print"), declRange(Header.range("printdecl")),
862                         defRange(Main.range("printdef"))),
863                   AllOf(qName("Z"), declRange(Header.range("zdecl"))),
864                   AllOf(qName("foo"), declRange(Header.range("foodecl"))),
865                   AllOf(qName("Y"), declRange(Main.range("ydecl")))));
866 }
867 
868 TEST_F(SymbolCollectorTest, Refs) {
869   Annotations Header(R"(
870   #define MACRO(X) (X + 1)
871   class Foo {
872   public:
873     Foo() {}
874     Foo(int);
875   };
876   class Bar;
877   void func();
878 
879   namespace NS {} // namespace ref is ignored
880   )");
881   Annotations Main(R"(
882   class $bar[[Bar]] {};
883 
884   void $func[[func]]();
885 
886   void fff() {
887     $foo[[Foo]] foo;
888     $bar[[Bar]] bar;
889     $func[[func]]();
890     int abc = 0;
891     $foo[[Foo]] foo2 = abc;
892     abc = $macro[[MACRO]](1);
893   }
894   )");
895   Annotations SymbolsOnlyInMainCode(R"(
896   #define FUNC(X) (X+1)
897   int a;
898   void b() {}
899   static const int c = FUNC(1);
900   class d {};
901   )");
902   CollectorOpts.RefFilter = RefKind::All;
903   CollectorOpts.CollectMacro = true;
904   runSymbolCollector(Header.code(),
905                      (Main.code() + SymbolsOnlyInMainCode.code()).str());
906   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Foo").ID,
907                                   haveRanges(Main.ranges("foo")))));
908   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Bar").ID,
909                                   haveRanges(Main.ranges("bar")))));
910   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "func").ID,
911                                   haveRanges(Main.ranges("func")))));
912   EXPECT_THAT(Refs, Not(Contains(Pair(findSymbol(Symbols, "NS").ID, _))));
913   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "MACRO").ID,
914                                   haveRanges(Main.ranges("macro")))));
915   // - (a, b) externally visible and should have refs.
916   // - (c, FUNC) externally invisible and had no refs collected.
917   auto MainSymbols =
918       TestTU::withHeaderCode(SymbolsOnlyInMainCode.code()).headerSymbols();
919   EXPECT_THAT(Refs, Contains(Pair(findSymbol(MainSymbols, "a").ID, _)));
920   EXPECT_THAT(Refs, Contains(Pair(findSymbol(MainSymbols, "b").ID, _)));
921   EXPECT_THAT(Refs, Not(Contains(Pair(findSymbol(MainSymbols, "c").ID, _))));
922   EXPECT_THAT(Refs, Not(Contains(Pair(findSymbol(MainSymbols, "FUNC").ID, _))));
923 
924   // Run the collector again with CollectMainFileRefs = true.
925   // We need to recreate InMemoryFileSystem because runSymbolCollector()
926   // calls MemoryBuffer::getMemBuffer(), which makes the buffers unusable
927   // after runSymbolCollector() exits.
928   InMemoryFileSystem = new llvm::vfs::InMemoryFileSystem();
929   CollectorOpts.CollectMainFileRefs = true;
930   runSymbolCollector(Header.code(),
931                      (Main.code() + SymbolsOnlyInMainCode.code()).str());
932   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "a").ID, _)));
933   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "b").ID, _)));
934   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "c").ID, _)));
935   // However, references to main-file macros are not collected.
936   EXPECT_THAT(Refs, Not(Contains(Pair(findSymbol(Symbols, "FUNC").ID, _))));
937 }
938 
939 TEST_F(SymbolCollectorTest, RefContainers) {
940   Annotations Code(R"cpp(
941     int $toplevel1[[f1]](int);
942     void f2() {
943       (void) $ref1a[[f1]](1);
944       auto fptr = &$ref1b[[f1]];
945     }
946     int $toplevel2[[v1]] = $ref2[[f1]](2);
947     void f3(int arg = $ref3[[f1]](3));
948     struct S1 {
949       int $classscope1[[member1]] = $ref4[[f1]](4);
950       int $classscope2[[member2]] = 42;
951     };
952     constexpr int f4(int x) { return x + 1; }
953     template <int I = $ref5[[f4]](0)> struct S2 {};
954     S2<$ref6[[f4]](0)> v2;
955     S2<$ref7a[[f4]](0)> f5(S2<$ref7b[[f4]](0)>);
956     namespace N {
957       void $namespacescope1[[f6]]();
958       int $namespacescope2[[v3]];
959     }
960   )cpp");
961   CollectorOpts.RefFilter = RefKind::All;
962   CollectorOpts.CollectMainFileRefs = true;
963   runSymbolCollector("", Code.code());
964   auto FindRefWithRange = [&](Range R) -> std::optional<Ref> {
965     for (auto &Entry : Refs) {
966       for (auto &Ref : Entry.second) {
967         if (rangesMatch(Ref.Location, R))
968           return Ref;
969       }
970     }
971     return std::nullopt;
972   };
973   auto Container = [&](llvm::StringRef RangeName) {
974     auto Ref = FindRefWithRange(Code.range(RangeName));
975     EXPECT_TRUE(bool(Ref));
976     return Ref->Container;
977   };
978   EXPECT_EQ(Container("ref1a"),
979             findSymbol(Symbols, "f2").ID); // function body (call)
980   EXPECT_EQ(Container("ref1b"),
981             findSymbol(Symbols, "f2").ID); // function body (address-of)
982   EXPECT_EQ(Container("ref2"),
983             findSymbol(Symbols, "v1").ID); // variable initializer
984   EXPECT_EQ(Container("ref3"),
985             findSymbol(Symbols, "f3").ID); // function parameter default value
986   EXPECT_EQ(Container("ref4"),
987             findSymbol(Symbols, "S1::member1").ID); // member initializer
988   EXPECT_EQ(Container("ref5"),
989             findSymbol(Symbols, "S2").ID); // template parameter default value
990   EXPECT_EQ(Container("ref6"),
991             findSymbol(Symbols, "v2").ID); // type of variable
992   EXPECT_EQ(Container("ref7a"),
993             findSymbol(Symbols, "f5").ID); // return type of function
994   EXPECT_EQ(Container("ref7b"),
995             findSymbol(Symbols, "f5").ID); // parameter type of function
996 
997   EXPECT_FALSE(Container("classscope1").isNull());
998   EXPECT_FALSE(Container("namespacescope1").isNull());
999 
1000   EXPECT_EQ(Container("toplevel1"), Container("toplevel2"));
1001   EXPECT_EQ(Container("classscope1"), Container("classscope2"));
1002   EXPECT_EQ(Container("namespacescope1"), Container("namespacescope2"));
1003 
1004   EXPECT_NE(Container("toplevel1"), Container("namespacescope1"));
1005   EXPECT_NE(Container("toplevel1"), Container("classscope1"));
1006   EXPECT_NE(Container("classscope1"), Container("namespacescope1"));
1007 }
1008 
1009 TEST_F(SymbolCollectorTest, MacroRefInHeader) {
1010   Annotations Header(R"(
1011   #define $foo[[FOO]](X) (X + 1)
1012   #define $bar[[BAR]](X) (X + 2)
1013 
1014   // Macro defined multiple times.
1015   #define $ud1[[UD]] 1
1016   int ud_1 = $ud1[[UD]];
1017   #undef UD
1018 
1019   #define $ud2[[UD]] 2
1020   int ud_2 = $ud2[[UD]];
1021   #undef UD
1022 
1023   // Macros from token concatenations not included.
1024   #define $concat[[CONCAT]](X) X##A()
1025   #define $prepend[[PREPEND]](X) MACRO##X()
1026   #define $macroa[[MACROA]]() 123
1027   int B = $concat[[CONCAT]](MACRO);
1028   int D = $prepend[[PREPEND]](A);
1029 
1030   void fff() {
1031     int abc = $foo[[FOO]](1) + $bar[[BAR]]($foo[[FOO]](1));
1032   }
1033   )");
1034   CollectorOpts.RefFilter = RefKind::All;
1035   CollectorOpts.RefsInHeaders = true;
1036   // Need this to get the SymbolID for macros for tests.
1037   CollectorOpts.CollectMacro = true;
1038 
1039   runSymbolCollector(Header.code(), "");
1040 
1041   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "FOO").ID,
1042                                   haveRanges(Header.ranges("foo")))));
1043   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "BAR").ID,
1044                                   haveRanges(Header.ranges("bar")))));
1045   // No unique ID for multiple symbols named UD. Check for ranges only.
1046   EXPECT_THAT(Refs, Contains(Pair(_, haveRanges(Header.ranges("ud1")))));
1047   EXPECT_THAT(Refs, Contains(Pair(_, haveRanges(Header.ranges("ud2")))));
1048   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "CONCAT").ID,
1049                                   haveRanges(Header.ranges("concat")))));
1050   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "PREPEND").ID,
1051                                   haveRanges(Header.ranges("prepend")))));
1052   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "MACROA").ID,
1053                                   haveRanges(Header.ranges("macroa")))));
1054 }
1055 
1056 TEST_F(SymbolCollectorTest, MacroRefWithoutCollectingSymbol) {
1057   Annotations Header(R"(
1058   #define $foo[[FOO]](X) (X + 1)
1059   int abc = $foo[[FOO]](1);
1060   )");
1061   CollectorOpts.RefFilter = RefKind::All;
1062   CollectorOpts.RefsInHeaders = true;
1063   CollectorOpts.CollectMacro = false;
1064   runSymbolCollector(Header.code(), "");
1065   EXPECT_THAT(Refs, Contains(Pair(_, haveRanges(Header.ranges("foo")))));
1066 }
1067 
1068 TEST_F(SymbolCollectorTest, MacrosWithRefFilter) {
1069   Annotations Header("#define $macro[[MACRO]](X) (X + 1)");
1070   Annotations Main("void foo() { int x = $macro[[MACRO]](1); }");
1071   CollectorOpts.RefFilter = RefKind::Unknown;
1072   runSymbolCollector(Header.code(), Main.code());
1073   EXPECT_THAT(Refs, IsEmpty());
1074 }
1075 
1076 TEST_F(SymbolCollectorTest, SpelledReferences) {
1077   struct {
1078     llvm::StringRef Header;
1079     llvm::StringRef Main;
1080     llvm::StringRef TargetSymbolName;
1081   } TestCases[] = {
1082     {
1083       R"cpp(
1084         struct Foo;
1085         #define MACRO Foo
1086       )cpp",
1087       R"cpp(
1088         struct $spelled[[Foo]] {
1089           $spelled[[Foo]]();
1090           ~$spelled[[Foo]]();
1091         };
1092         $spelled[[Foo]] Variable1;
1093         $implicit[[MACRO]] Variable2;
1094       )cpp",
1095       "Foo",
1096     },
1097     {
1098       R"cpp(
1099         class Foo {
1100         public:
1101           Foo() = default;
1102         };
1103       )cpp",
1104       R"cpp(
1105         void f() { Foo $implicit[[f]]; f = $spelled[[Foo]]();}
1106       )cpp",
1107       "Foo::Foo" /// constructor.
1108     },
1109     { // Unclean identifiers
1110       R"cpp(
1111         struct Foo {};
1112       )cpp",
1113       R"cpp(
1114         $spelled[[Fo\
1115 o]] f{};
1116       )cpp",
1117       "Foo",
1118     },
1119   };
1120   CollectorOpts.RefFilter = RefKind::All;
1121   CollectorOpts.RefsInHeaders = false;
1122   for (const auto& T : TestCases) {
1123     SCOPED_TRACE(T.Header + "\n---\n" + T.Main);
1124     Annotations Header(T.Header);
1125     Annotations Main(T.Main);
1126     // Reset the file system.
1127     InMemoryFileSystem = new llvm::vfs::InMemoryFileSystem;
1128     runSymbolCollector(Header.code(), Main.code());
1129 
1130     const auto SpelledRanges = Main.ranges("spelled");
1131     const auto ImplicitRanges = Main.ranges("implicit");
1132     RefSlab::Builder SpelledSlabBuilder, ImplicitSlabBuilder;
1133     const auto TargetID = findSymbol(Symbols, T.TargetSymbolName).ID;
1134     for (const auto &SymbolAndRefs : Refs) {
1135       const auto ID = SymbolAndRefs.first;
1136       if (ID != TargetID)
1137         continue;
1138       for (const auto &Ref : SymbolAndRefs.second)
1139         if ((Ref.Kind & RefKind::Spelled) != RefKind::Unknown)
1140           SpelledSlabBuilder.insert(ID, Ref);
1141         else
1142           ImplicitSlabBuilder.insert(ID, Ref);
1143     }
1144     const auto SpelledRefs = std::move(SpelledSlabBuilder).build(),
1145                ImplicitRefs = std::move(ImplicitSlabBuilder).build();
1146     EXPECT_EQ(SpelledRanges.empty(), SpelledRefs.empty());
1147     EXPECT_EQ(ImplicitRanges.empty(), ImplicitRefs.empty());
1148     if (!SpelledRanges.empty())
1149       EXPECT_THAT(SpelledRefs,
1150                   Contains(Pair(TargetID, haveRanges(SpelledRanges))));
1151     if (!ImplicitRanges.empty())
1152       EXPECT_THAT(ImplicitRefs,
1153                   Contains(Pair(TargetID, haveRanges(ImplicitRanges))));
1154   }
1155 }
1156 
1157 TEST_F(SymbolCollectorTest, NameReferences) {
1158   CollectorOpts.RefFilter = RefKind::All;
1159   CollectorOpts.RefsInHeaders = true;
1160   Annotations Header(R"(
1161     class [[Foo]] {
1162     public:
1163       [[Foo]]() {}
1164       ~[[Foo]]() {}
1165     };
1166   )");
1167   CollectorOpts.RefFilter = RefKind::All;
1168   runSymbolCollector(Header.code(), "");
1169   // When we find references for class Foo, we expect to see all
1170   // constructor/destructor references.
1171   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Foo").ID,
1172                                   haveRanges(Header.ranges()))));
1173 }
1174 
1175 TEST_F(SymbolCollectorTest, RefsOnMacros) {
1176   // Refs collected from SymbolCollector behave in the same way as
1177   // AST-based xrefs.
1178   CollectorOpts.RefFilter = RefKind::All;
1179   CollectorOpts.RefsInHeaders = true;
1180   Annotations Header(R"(
1181     #define TYPE(X) X
1182     #define FOO Foo
1183     #define CAT(X, Y) X##Y
1184     class [[Foo]] {};
1185     void test() {
1186       TYPE([[Foo]]) foo;
1187       [[FOO]] foo2;
1188       TYPE(TYPE([[Foo]])) foo3;
1189       [[CAT]](Fo, o) foo4;
1190     }
1191   )");
1192   CollectorOpts.RefFilter = RefKind::All;
1193   runSymbolCollector(Header.code(), "");
1194   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Foo").ID,
1195                                   haveRanges(Header.ranges()))));
1196 }
1197 
1198 TEST_F(SymbolCollectorTest, HeaderAsMainFile) {
1199   CollectorOpts.RefFilter = RefKind::All;
1200   Annotations Header(R"(
1201   class $Foo[[Foo]] {};
1202 
1203   void $Func[[Func]]() {
1204     $Foo[[Foo]] fo;
1205   }
1206   )");
1207   // We should collect refs to main-file symbols in all cases:
1208 
1209   // 1. The main file is normal .cpp file.
1210   TestFileName = testPath("foo.cpp");
1211   runSymbolCollector("", Header.code());
1212   EXPECT_THAT(Refs,
1213               UnorderedElementsAre(Pair(findSymbol(Symbols, "Foo").ID,
1214                                         haveRanges(Header.ranges("Foo"))),
1215                                    Pair(findSymbol(Symbols, "Func").ID,
1216                                         haveRanges(Header.ranges("Func")))));
1217 
1218   // 2. Run the .h file as main file.
1219   TestFileName = testPath("foo.h");
1220   runSymbolCollector("", Header.code(),
1221                      /*ExtraArgs=*/{"-xobjective-c++-header"});
1222   EXPECT_THAT(Symbols, UnorderedElementsAre(qName("Foo"), qName("Func")));
1223   EXPECT_THAT(Refs,
1224               UnorderedElementsAre(Pair(findSymbol(Symbols, "Foo").ID,
1225                                         haveRanges(Header.ranges("Foo"))),
1226                                    Pair(findSymbol(Symbols, "Func").ID,
1227                                         haveRanges(Header.ranges("Func")))));
1228 
1229   // 3. Run the .hh file as main file (without "-x c++-header").
1230   TestFileName = testPath("foo.hh");
1231   runSymbolCollector("", Header.code());
1232   EXPECT_THAT(Symbols, UnorderedElementsAre(qName("Foo"), qName("Func")));
1233   EXPECT_THAT(Refs,
1234               UnorderedElementsAre(Pair(findSymbol(Symbols, "Foo").ID,
1235                                         haveRanges(Header.ranges("Foo"))),
1236                                    Pair(findSymbol(Symbols, "Func").ID,
1237                                         haveRanges(Header.ranges("Func")))));
1238 }
1239 
1240 TEST_F(SymbolCollectorTest, RefsInHeaders) {
1241   CollectorOpts.RefFilter = RefKind::All;
1242   CollectorOpts.RefsInHeaders = true;
1243   CollectorOpts.CollectMacro = true;
1244   Annotations Header(R"(
1245   #define $macro[[MACRO]](x) (x+1)
1246   class $foo[[Foo]] {};
1247   )");
1248   runSymbolCollector(Header.code(), "");
1249   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Foo").ID,
1250                                   haveRanges(Header.ranges("foo")))));
1251   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "MACRO").ID,
1252                                   haveRanges(Header.ranges("macro")))));
1253 }
1254 
1255 TEST_F(SymbolCollectorTest, BaseOfRelations) {
1256   std::string Header = R"(
1257   class Base {};
1258   class Derived : public Base {};
1259   )";
1260   runSymbolCollector(Header, /*Main=*/"");
1261   const Symbol &Base = findSymbol(Symbols, "Base");
1262   const Symbol &Derived = findSymbol(Symbols, "Derived");
1263   EXPECT_THAT(Relations,
1264               Contains(Relation{Base.ID, RelationKind::BaseOf, Derived.ID}));
1265 }
1266 
1267 TEST_F(SymbolCollectorTest, OverrideRelationsSimpleInheritance) {
1268   std::string Header = R"cpp(
1269     class A {
1270       virtual void foo();
1271     };
1272     class B : public A {
1273       void foo() override;  // A::foo
1274       virtual void bar();
1275     };
1276     class C : public B {
1277       void bar() override;  // B::bar
1278     };
1279     class D: public C {
1280       void foo() override;  // B::foo
1281       void bar() override;  // C::bar
1282     };
1283   )cpp";
1284   runSymbolCollector(Header, /*Main=*/"");
1285   const Symbol &AFoo = findSymbol(Symbols, "A::foo");
1286   const Symbol &BFoo = findSymbol(Symbols, "B::foo");
1287   const Symbol &DFoo = findSymbol(Symbols, "D::foo");
1288 
1289   const Symbol &BBar = findSymbol(Symbols, "B::bar");
1290   const Symbol &CBar = findSymbol(Symbols, "C::bar");
1291   const Symbol &DBar = findSymbol(Symbols, "D::bar");
1292 
1293   std::vector<Relation> Result;
1294   for (const Relation &R : Relations)
1295     if (R.Predicate == RelationKind::OverriddenBy)
1296       Result.push_back(R);
1297   EXPECT_THAT(Result, UnorderedElementsAre(
1298                           OverriddenBy(AFoo, BFoo), OverriddenBy(BBar, CBar),
1299                           OverriddenBy(BFoo, DFoo), OverriddenBy(CBar, DBar)));
1300 }
1301 
1302 TEST_F(SymbolCollectorTest, OverrideRelationsMultipleInheritance) {
1303   std::string Header = R"cpp(
1304     class A {
1305       virtual void foo();
1306     };
1307     class B {
1308       virtual void bar();
1309     };
1310     class C : public B {
1311       void bar() override;  // B::bar
1312       virtual void baz();
1313     }
1314     class D : public A, C {
1315       void foo() override;  // A::foo
1316       void bar() override;  // C::bar
1317       void baz() override;  // C::baz
1318     };
1319   )cpp";
1320   runSymbolCollector(Header, /*Main=*/"");
1321   const Symbol &AFoo = findSymbol(Symbols, "A::foo");
1322   const Symbol &BBar = findSymbol(Symbols, "B::bar");
1323   const Symbol &CBar = findSymbol(Symbols, "C::bar");
1324   const Symbol &CBaz = findSymbol(Symbols, "C::baz");
1325   const Symbol &DFoo = findSymbol(Symbols, "D::foo");
1326   const Symbol &DBar = findSymbol(Symbols, "D::bar");
1327   const Symbol &DBaz = findSymbol(Symbols, "D::baz");
1328 
1329   std::vector<Relation> Result;
1330   for (const Relation &R : Relations)
1331     if (R.Predicate == RelationKind::OverriddenBy)
1332       Result.push_back(R);
1333   EXPECT_THAT(Result, UnorderedElementsAre(
1334                           OverriddenBy(BBar, CBar), OverriddenBy(AFoo, DFoo),
1335                           OverriddenBy(CBar, DBar), OverriddenBy(CBaz, DBaz)));
1336 }
1337 
1338 TEST_F(SymbolCollectorTest, CountReferences) {
1339   const std::string Header = R"(
1340     class W;
1341     class X {};
1342     class Y;
1343     class Z {}; // not used anywhere
1344     Y* y = nullptr;  // used in header doesn't count
1345     #define GLOBAL_Z(name) Z name;
1346   )";
1347   const std::string Main = R"(
1348     W* w = nullptr;
1349     W* w2 = nullptr; // only one usage counts
1350     X x();
1351     class V;
1352     class Y{}; // definition doesn't count as a reference
1353     V* v = nullptr;
1354     GLOBAL_Z(z); // Not a reference to Z, we don't spell the type.
1355   )";
1356   CollectorOpts.CountReferences = true;
1357   runSymbolCollector(Header, Main);
1358   EXPECT_THAT(
1359       Symbols,
1360       UnorderedElementsAreArray(
1361           {AllOf(qName("W"), refCount(1)), AllOf(qName("X"), refCount(1)),
1362            AllOf(qName("Y"), refCount(0)), AllOf(qName("Z"), refCount(0)),
1363            AllOf(qName("y"), refCount(0)), AllOf(qName("z"), refCount(0)),
1364            AllOf(qName("x"), refCount(0)), AllOf(qName("w"), refCount(0)),
1365            AllOf(qName("w2"), refCount(0)), AllOf(qName("V"), refCount(1)),
1366            AllOf(qName("v"), refCount(0))}));
1367 }
1368 
1369 TEST_F(SymbolCollectorTest, SymbolRelativeNoFallback) {
1370   runSymbolCollector("class Foo {};", /*Main=*/"");
1371   EXPECT_THAT(Symbols, UnorderedElementsAre(
1372                            AllOf(qName("Foo"), declURI(TestHeaderURI))));
1373 }
1374 
1375 TEST_F(SymbolCollectorTest, SymbolRelativeWithFallback) {
1376   TestHeaderName = "x.h";
1377   TestFileName = "x.cpp";
1378   TestHeaderURI = URI::create(testPath(TestHeaderName)).toString();
1379   CollectorOpts.FallbackDir = testRoot();
1380   runSymbolCollector("class Foo {};", /*Main=*/"");
1381   EXPECT_THAT(Symbols, UnorderedElementsAre(
1382                            AllOf(qName("Foo"), declURI(TestHeaderURI))));
1383 }
1384 
1385 TEST_F(SymbolCollectorTest, UnittestURIScheme) {
1386   // Use test URI scheme from URITests.cpp
1387   TestHeaderName = testPath("x.h");
1388   TestFileName = testPath("x.cpp");
1389   runSymbolCollector("class Foo {};", /*Main=*/"");
1390   EXPECT_THAT(Symbols, UnorderedElementsAre(
1391                            AllOf(qName("Foo"), declURI("unittest:///x.h"))));
1392 }
1393 
1394 TEST_F(SymbolCollectorTest, IncludeEnums) {
1395   const std::string Header = R"(
1396     enum {
1397       Red
1398     };
1399     enum Color {
1400       Green
1401     };
1402     enum class Color2 {
1403       Yellow
1404     };
1405     namespace ns {
1406     enum {
1407       Black
1408     };
1409     }
1410     class Color3 {
1411       enum {
1412         Blue
1413       };
1414     };
1415   )";
1416   runSymbolCollector(Header, /*Main=*/"");
1417   EXPECT_THAT(Symbols,
1418               UnorderedElementsAre(
1419                   AllOf(qName("Red"), forCodeCompletion(true)),
1420                   AllOf(qName("Color"), forCodeCompletion(true)),
1421                   AllOf(qName("Green"), forCodeCompletion(true)),
1422                   AllOf(qName("Color2"), forCodeCompletion(true)),
1423                   AllOf(qName("Color2::Yellow"), forCodeCompletion(true)),
1424                   AllOf(qName("ns"), forCodeCompletion(true)),
1425                   AllOf(qName("ns::Black"), forCodeCompletion(true)),
1426                   AllOf(qName("Color3"), forCodeCompletion(true)),
1427                   AllOf(qName("Color3::Blue"), forCodeCompletion(true))));
1428 }
1429 
1430 TEST_F(SymbolCollectorTest, NamelessSymbols) {
1431   const std::string Header = R"(
1432     struct {
1433       int a;
1434     } Foo;
1435   )";
1436   runSymbolCollector(Header, /*Main=*/"");
1437   EXPECT_THAT(Symbols, UnorderedElementsAre(qName("Foo"),
1438                                             qName("(anonymous struct)::a")));
1439 }
1440 
1441 TEST_F(SymbolCollectorTest, SymbolFormedFromRegisteredSchemeFromMacro) {
1442 
1443   Annotations Header(R"(
1444     #define FF(name) \
1445       class name##_Test {};
1446 
1447     $expansion[[FF]](abc);
1448 
1449     #define FF2() \
1450       class $spelling[[Test]] {};
1451 
1452     FF2();
1453   )");
1454 
1455   runSymbolCollector(Header.code(), /*Main=*/"");
1456   EXPECT_THAT(Symbols,
1457               UnorderedElementsAre(
1458                   AllOf(qName("abc_Test"), declRange(Header.range("expansion")),
1459                         declURI(TestHeaderURI)),
1460                   AllOf(qName("Test"), declRange(Header.range("spelling")),
1461                         declURI(TestHeaderURI))));
1462 }
1463 
1464 TEST_F(SymbolCollectorTest, SymbolFormedByCLI) {
1465   Annotations Header(R"(
1466     #ifdef NAME
1467     class $expansion[[NAME]] {};
1468     #endif
1469   )");
1470   runSymbolCollector(Header.code(), /*Main=*/"", /*ExtraArgs=*/{"-DNAME=name"});
1471   EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(
1472                            qName("name"), declRange(Header.range("expansion")),
1473                            declURI(TestHeaderURI))));
1474 }
1475 
1476 TEST_F(SymbolCollectorTest, SymbolsInMainFile) {
1477   const std::string Main = R"(
1478     class Foo {};
1479     void f1();
1480     inline void f2() {}
1481 
1482     namespace {
1483     void ff() {}
1484     }
1485     namespace foo {
1486     namespace {
1487     class Bar {};
1488     }
1489     }
1490     void main_f() {}
1491     void f1() {}
1492   )";
1493   runSymbolCollector(/*Header=*/"", Main);
1494   EXPECT_THAT(Symbols, UnorderedElementsAre(
1495                            qName("Foo"), qName("f1"), qName("f2"), qName("ff"),
1496                            qName("foo"), qName("foo::Bar"), qName("main_f")));
1497 }
1498 
1499 TEST_F(SymbolCollectorTest, Documentation) {
1500   const std::string Header = R"(
1501     // doc Foo
1502     class Foo {
1503       // doc f
1504       int f();
1505     };
1506   )";
1507   CollectorOpts.StoreAllDocumentation = false;
1508   runSymbolCollector(Header, /* Main */ "");
1509   EXPECT_THAT(Symbols,
1510               UnorderedElementsAre(
1511                   AllOf(qName("Foo"), doc("doc Foo"), forCodeCompletion(true)),
1512                   AllOf(qName("Foo::f"), doc(""), returnType(""),
1513                         forCodeCompletion(false))));
1514 
1515   CollectorOpts.StoreAllDocumentation = true;
1516   runSymbolCollector(Header, /* Main */ "");
1517   EXPECT_THAT(Symbols,
1518               UnorderedElementsAre(
1519                   AllOf(qName("Foo"), doc("doc Foo"), forCodeCompletion(true)),
1520                   AllOf(qName("Foo::f"), doc("doc f"), returnType(""),
1521                         forCodeCompletion(false))));
1522 }
1523 
1524 TEST_F(SymbolCollectorTest, DocumentationInMain) {
1525   const std::string Header = R"(
1526     // doc Foo
1527     class Foo {
1528       void f();
1529     };
1530   )";
1531   const std::string Main = R"(
1532     // doc f
1533     void Foo::f() {}
1534   )";
1535   CollectorOpts.StoreAllDocumentation = true;
1536   runSymbolCollector(Header, Main);
1537   EXPECT_THAT(Symbols,
1538               UnorderedElementsAre(
1539                   AllOf(qName("Foo"), doc("doc Foo"), forCodeCompletion(true)),
1540                   AllOf(qName("Foo::f"), doc("doc f"), returnType(""),
1541                         forCodeCompletion(false))));
1542 }
1543 
1544 TEST_F(SymbolCollectorTest, DocumentationAtDeclThenDef) {
1545   const std::string Header = R"(
1546     class Foo {
1547       // doc f decl
1548       void f();
1549     };
1550   )";
1551   const std::string Main = R"(
1552     // doc f def
1553     void Foo::f() {}
1554   )";
1555   CollectorOpts.StoreAllDocumentation = true;
1556   runSymbolCollector(Header, Main);
1557   EXPECT_THAT(Symbols,
1558               UnorderedElementsAre(AllOf(qName("Foo")),
1559                                    AllOf(qName("Foo::f"), doc("doc f decl"))));
1560 }
1561 
1562 TEST_F(SymbolCollectorTest, DocumentationAtDefThenDecl) {
1563   const std::string Header = R"(
1564     // doc f def
1565     void f() {}
1566 
1567     // doc f decl
1568     void f();
1569   )";
1570   CollectorOpts.StoreAllDocumentation = true;
1571   runSymbolCollector(Header, "" /*Main*/);
1572   EXPECT_THAT(Symbols,
1573               UnorderedElementsAre(AllOf(qName("f"), doc("doc f def"))));
1574 }
1575 
1576 TEST_F(SymbolCollectorTest, ClassMembers) {
1577   const std::string Header = R"(
1578     class Foo {
1579       void f() {}
1580       void g();
1581       static void sf() {}
1582       static void ssf();
1583       static int x;
1584     };
1585   )";
1586   const std::string Main = R"(
1587     void Foo::g() {}
1588     void Foo::ssf() {}
1589   )";
1590   runSymbolCollector(Header, Main);
1591   EXPECT_THAT(
1592       Symbols,
1593       UnorderedElementsAre(
1594           qName("Foo"),
1595           AllOf(qName("Foo::f"), returnType(""), forCodeCompletion(false)),
1596           AllOf(qName("Foo::g"), returnType(""), forCodeCompletion(false)),
1597           AllOf(qName("Foo::sf"), returnType(""), forCodeCompletion(false)),
1598           AllOf(qName("Foo::ssf"), returnType(""), forCodeCompletion(false)),
1599           AllOf(qName("Foo::x"), returnType(""), forCodeCompletion(false))));
1600 }
1601 
1602 TEST_F(SymbolCollectorTest, Scopes) {
1603   const std::string Header = R"(
1604     namespace na {
1605     class Foo {};
1606     namespace nb {
1607     class Bar {};
1608     }
1609     }
1610   )";
1611   runSymbolCollector(Header, /*Main=*/"");
1612   EXPECT_THAT(Symbols,
1613               UnorderedElementsAre(qName("na"), qName("na::nb"),
1614                                    qName("na::Foo"), qName("na::nb::Bar")));
1615 }
1616 
1617 TEST_F(SymbolCollectorTest, ExternC) {
1618   const std::string Header = R"(
1619     extern "C" { class Foo {}; }
1620     namespace na {
1621     extern "C" { class Bar {}; }
1622     }
1623   )";
1624   runSymbolCollector(Header, /*Main=*/"");
1625   EXPECT_THAT(Symbols, UnorderedElementsAre(qName("na"), qName("Foo"),
1626                                             qName("na::Bar")));
1627 }
1628 
1629 TEST_F(SymbolCollectorTest, SkipInlineNamespace) {
1630   const std::string Header = R"(
1631     namespace na {
1632     inline namespace nb {
1633     class Foo {};
1634     }
1635     }
1636     namespace na {
1637     // This is still inlined.
1638     namespace nb {
1639     class Bar {};
1640     }
1641     }
1642   )";
1643   runSymbolCollector(Header, /*Main=*/"");
1644   EXPECT_THAT(Symbols,
1645               UnorderedElementsAre(qName("na"), qName("na::nb"),
1646                                    qName("na::Foo"), qName("na::Bar")));
1647 }
1648 
1649 TEST_F(SymbolCollectorTest, SymbolWithDocumentation) {
1650   const std::string Header = R"(
1651     namespace nx {
1652     /// Foo comment.
1653     int ff(int x, double y) { return 0; }
1654     }
1655   )";
1656   runSymbolCollector(Header, /*Main=*/"");
1657   EXPECT_THAT(
1658       Symbols,
1659       UnorderedElementsAre(
1660           qName("nx"), AllOf(qName("nx::ff"), labeled("ff(int x, double y)"),
1661                              returnType("int"), doc("Foo comment."))));
1662 }
1663 
1664 TEST_F(SymbolCollectorTest, snippet) {
1665   const std::string Header = R"(
1666     namespace nx {
1667     void f() {}
1668     int ff(int x, double y) { return 0; }
1669     }
1670   )";
1671   runSymbolCollector(Header, /*Main=*/"");
1672   EXPECT_THAT(Symbols,
1673               UnorderedElementsAre(
1674                   qName("nx"),
1675                   AllOf(qName("nx::f"), labeled("f()"), snippet("f()")),
1676                   AllOf(qName("nx::ff"), labeled("ff(int x, double y)"),
1677                         snippet("ff(${1:int x}, ${2:double y})"))));
1678 }
1679 
1680 TEST_F(SymbolCollectorTest, IncludeHeaderSameAsFileURI) {
1681   CollectorOpts.CollectIncludePath = true;
1682   runSymbolCollector("#pragma once\nclass Foo {};", /*Main=*/"");
1683   EXPECT_THAT(Symbols, UnorderedElementsAre(
1684                            AllOf(qName("Foo"), declURI(TestHeaderURI))));
1685   EXPECT_THAT(Symbols.begin()->IncludeHeaders,
1686               UnorderedElementsAre(IncludeHeaderWithRef(TestHeaderURI, 1u)));
1687 }
1688 
1689 TEST_F(SymbolCollectorTest, CanonicalSTLHeader) {
1690   CollectorOpts.CollectIncludePath = true;
1691   runSymbolCollector(
1692       R"cpp(
1693       namespace std {
1694         class string {};
1695         // Move overloads have special handling.
1696         template <typename _T> T&& move(_T&& __value);
1697         template <typename _I, typename _O> _O move(_I, _I, _O);
1698         template <typename _T, typename _O, typename _I> _O move(
1699           _T&&, _O, _O, _I);
1700       }
1701       )cpp",
1702       /*Main=*/"");
1703   EXPECT_THAT(
1704       Symbols,
1705       UnorderedElementsAre(
1706           qName("std"),
1707           AllOf(qName("std::string"), declURI(TestHeaderURI),
1708                 includeHeader("<string>")),
1709           // Parameter names are demangled.
1710           AllOf(labeled("move(T &&value)"), includeHeader("<utility>")),
1711           AllOf(labeled("move(I, I, O)"), includeHeader("<algorithm>")),
1712           AllOf(labeled("move(T &&, O, O, I)"), includeHeader("<algorithm>"))));
1713 }
1714 
1715 TEST_F(SymbolCollectorTest, IWYUPragma) {
1716   CollectorOpts.CollectIncludePath = true;
1717   const std::string Header = R"(
1718     // IWYU pragma: private, include the/good/header.h
1719     class Foo {};
1720   )";
1721   runSymbolCollector(Header, /*Main=*/"");
1722   EXPECT_THAT(Symbols, UnorderedElementsAre(
1723                            AllOf(qName("Foo"), declURI(TestHeaderURI),
1724                                  includeHeader("\"the/good/header.h\""))));
1725 }
1726 
1727 TEST_F(SymbolCollectorTest, IWYUPragmaWithDoubleQuotes) {
1728   CollectorOpts.CollectIncludePath = true;
1729   const std::string Header = R"(
1730     // IWYU pragma: private, include "the/good/header.h"
1731     class Foo {};
1732   )";
1733   runSymbolCollector(Header, /*Main=*/"");
1734   EXPECT_THAT(Symbols, UnorderedElementsAre(
1735                            AllOf(qName("Foo"), declURI(TestHeaderURI),
1736                                  includeHeader("\"the/good/header.h\""))));
1737 }
1738 
1739 TEST_F(SymbolCollectorTest, IWYUPragmaExport) {
1740   CollectorOpts.CollectIncludePath = true;
1741   const std::string Header = R"cpp(#pragma once
1742     #include "exporter.h"
1743   )cpp";
1744   auto ExporterFile = testPath("exporter.h");
1745   InMemoryFileSystem->addFile(
1746       ExporterFile, 0, llvm::MemoryBuffer::getMemBuffer(R"cpp(#pragma once
1747     #include "private.h" // IWYU pragma: export
1748   )cpp"));
1749   auto PrivateFile = testPath("private.h");
1750   InMemoryFileSystem->addFile(
1751       PrivateFile, 0, llvm::MemoryBuffer::getMemBuffer("class Foo {};"));
1752   runSymbolCollector(Header, /*Main=*/"",
1753                      /*ExtraArgs=*/{"-I", testRoot()});
1754   EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(
1755                            qName("Foo"),
1756                            includeHeader(URI::create(ExporterFile).toString()),
1757                            declURI(URI::create(PrivateFile).toString()))));
1758 }
1759 
1760 TEST_F(SymbolCollectorTest, MainFileIsHeaderWhenSkipIncFile) {
1761   CollectorOpts.CollectIncludePath = true;
1762   // To make this case as hard as possible, we won't tell clang main is a
1763   // header. No extension, no -x c++-header.
1764   TestFileName = testPath("no_ext_main");
1765   TestFileURI = URI::create(TestFileName).toString();
1766   auto IncFile = testPath("test.inc");
1767   auto IncURI = URI::create(IncFile).toString();
1768   InMemoryFileSystem->addFile(IncFile, 0,
1769                               llvm::MemoryBuffer::getMemBuffer("class X {};"));
1770   runSymbolCollector("", R"cpp(
1771     // Can't use #pragma once in a main file clang doesn't think is a header.
1772     #ifndef MAIN_H_
1773     #define MAIN_H_
1774     #include "test.inc"
1775     #endif
1776   )cpp",
1777                      /*ExtraArgs=*/{"-I", testRoot()});
1778   EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(qName("X"), declURI(IncURI),
1779                                                   includeHeader(TestFileURI))));
1780 }
1781 
1782 TEST_F(SymbolCollectorTest, IncFileInNonHeader) {
1783   CollectorOpts.CollectIncludePath = true;
1784   TestFileName = testPath("main.cc");
1785   TestFileURI = URI::create(TestFileName).toString();
1786   auto IncFile = testPath("test.inc");
1787   auto IncURI = URI::create(IncFile).toString();
1788   InMemoryFileSystem->addFile(IncFile, 0,
1789                               llvm::MemoryBuffer::getMemBuffer("class X {};"));
1790   runSymbolCollector("", R"cpp(
1791     #include "test.inc"
1792   )cpp",
1793                      /*ExtraArgs=*/{"-I", testRoot()});
1794   EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(qName("X"), declURI(IncURI),
1795                                                   Not(includeHeader()))));
1796 }
1797 
1798 // Features that depend on header-guards are fragile. Header guards are only
1799 // recognized when the file ends, so we have to defer checking for them.
1800 TEST_F(SymbolCollectorTest, HeaderGuardDetected) {
1801   CollectorOpts.CollectIncludePath = true;
1802   CollectorOpts.CollectMacro = true;
1803   runSymbolCollector(R"cpp(
1804     #ifndef HEADER_GUARD_
1805     #define HEADER_GUARD_
1806 
1807     // Symbols are seen before the header guard is complete.
1808     #define MACRO
1809     int decl();
1810 
1811     #endif // Header guard is recognized here.
1812   )cpp",
1813                      "");
1814   EXPECT_THAT(Symbols, Not(Contains(qName("HEADER_GUARD_"))));
1815   EXPECT_THAT(Symbols, Each(includeHeader()));
1816 }
1817 
1818 TEST_F(SymbolCollectorTest, NonModularHeader) {
1819   auto TU = TestTU::withHeaderCode("int x();");
1820   EXPECT_THAT(TU.headerSymbols(), ElementsAre(includeHeader()));
1821 
1822   // Files missing include guards aren't eligible for insertion.
1823   TU.ImplicitHeaderGuard = false;
1824   EXPECT_THAT(TU.headerSymbols(), ElementsAre(Not(includeHeader())));
1825 
1826   // We recognize some patterns of trying to prevent insertion.
1827   TU = TestTU::withHeaderCode(R"cpp(
1828 #ifndef SECRET
1829 #error "This file isn't safe to include directly"
1830 #endif
1831     int x();
1832     )cpp");
1833   TU.ExtraArgs.push_back("-DSECRET"); // *we're* able to include it.
1834   EXPECT_THAT(TU.headerSymbols(), ElementsAre(Not(includeHeader())));
1835 }
1836 
1837 TEST_F(SymbolCollectorTest, AvoidUsingFwdDeclsAsCanonicalDecls) {
1838   CollectorOpts.CollectIncludePath = true;
1839   Annotations Header(R"(
1840     #pragma once
1841     // Forward declarations of TagDecls.
1842     class C;
1843     struct S;
1844     union U;
1845 
1846     // Canonical declarations.
1847     class $cdecl[[C]] {};
1848     struct $sdecl[[S]] {};
1849     union $udecl[[U]] {int $xdecl[[x]]; bool $ydecl[[y]];};
1850   )");
1851   runSymbolCollector(Header.code(), /*Main=*/"");
1852   EXPECT_THAT(
1853       Symbols,
1854       UnorderedElementsAre(
1855           AllOf(qName("C"), declURI(TestHeaderURI),
1856                 declRange(Header.range("cdecl")), includeHeader(TestHeaderURI),
1857                 defURI(TestHeaderURI), defRange(Header.range("cdecl"))),
1858           AllOf(qName("S"), declURI(TestHeaderURI),
1859                 declRange(Header.range("sdecl")), includeHeader(TestHeaderURI),
1860                 defURI(TestHeaderURI), defRange(Header.range("sdecl"))),
1861           AllOf(qName("U"), declURI(TestHeaderURI),
1862                 declRange(Header.range("udecl")), includeHeader(TestHeaderURI),
1863                 defURI(TestHeaderURI), defRange(Header.range("udecl"))),
1864           AllOf(qName("U::x"), declURI(TestHeaderURI),
1865                 declRange(Header.range("xdecl")), defURI(TestHeaderURI),
1866                 defRange(Header.range("xdecl"))),
1867           AllOf(qName("U::y"), declURI(TestHeaderURI),
1868                 declRange(Header.range("ydecl")), defURI(TestHeaderURI),
1869                 defRange(Header.range("ydecl")))));
1870 }
1871 
1872 TEST_F(SymbolCollectorTest, ClassForwardDeclarationIsCanonical) {
1873   CollectorOpts.CollectIncludePath = true;
1874   runSymbolCollector(/*Header=*/"#pragma once\nclass X;",
1875                      /*Main=*/"class X {};");
1876   EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(
1877                            qName("X"), declURI(TestHeaderURI),
1878                            includeHeader(TestHeaderURI), defURI(TestFileURI))));
1879 }
1880 
1881 TEST_F(SymbolCollectorTest, UTF16Character) {
1882   // ö is 2-bytes.
1883   Annotations Header(/*Header=*/"class [[pörk]] {};");
1884   runSymbolCollector(Header.code(), /*Main=*/"");
1885   EXPECT_THAT(Symbols, UnorderedElementsAre(
1886                            AllOf(qName("pörk"), declRange(Header.range()))));
1887 }
1888 
1889 TEST_F(SymbolCollectorTest, DoNotIndexSymbolsInFriendDecl) {
1890   Annotations Header(R"(
1891     namespace nx {
1892       class $z[[Z]] {};
1893       class X {
1894         friend class Y;
1895         friend class Z;
1896         friend void foo();
1897         friend void $bar[[bar]]() {}
1898       };
1899       class $y[[Y]] {};
1900       void $foo[[foo]]();
1901     }
1902   )");
1903   runSymbolCollector(Header.code(), /*Main=*/"");
1904 
1905   EXPECT_THAT(Symbols,
1906               UnorderedElementsAre(
1907                   qName("nx"), qName("nx::X"),
1908                   AllOf(qName("nx::Y"), declRange(Header.range("y"))),
1909                   AllOf(qName("nx::Z"), declRange(Header.range("z"))),
1910                   AllOf(qName("nx::foo"), declRange(Header.range("foo"))),
1911                   AllOf(qName("nx::bar"), declRange(Header.range("bar")))));
1912 }
1913 
1914 TEST_F(SymbolCollectorTest, ReferencesInFriendDecl) {
1915   const std::string Header = R"(
1916     class X;
1917     class Y;
1918   )";
1919   const std::string Main = R"(
1920     class C {
1921       friend ::X;
1922       friend class Y;
1923     };
1924   )";
1925   CollectorOpts.CountReferences = true;
1926   runSymbolCollector(Header, Main);
1927   EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(qName("X"), refCount(1)),
1928                                             AllOf(qName("Y"), refCount(1)),
1929                                             AllOf(qName("C"), refCount(0))));
1930 }
1931 
1932 TEST_F(SymbolCollectorTest, Origin) {
1933   CollectorOpts.Origin = SymbolOrigin::Static;
1934   runSymbolCollector("class Foo {};", /*Main=*/"");
1935   EXPECT_THAT(Symbols, UnorderedElementsAre(
1936                            Field(&Symbol::Origin, SymbolOrigin::Static)));
1937   InMemoryFileSystem = new llvm::vfs::InMemoryFileSystem;
1938   CollectorOpts.CollectMacro = true;
1939   runSymbolCollector("#define FOO", /*Main=*/"");
1940   EXPECT_THAT(Symbols, UnorderedElementsAre(
1941                            Field(&Symbol::Origin, SymbolOrigin::Static)));
1942 }
1943 
1944 TEST_F(SymbolCollectorTest, CollectMacros) {
1945   CollectorOpts.CollectIncludePath = true;
1946   Annotations Header(R"(
1947     #pragma once
1948     #define X 1
1949     #define $mac[[MAC]](x) int x
1950     #define $used[[USED]](y) float y;
1951 
1952     MAC(p);
1953   )");
1954 
1955   Annotations Main(R"(
1956     #define $main[[MAIN]] 1
1957      USED(t);
1958   )");
1959   CollectorOpts.CountReferences = true;
1960   CollectorOpts.CollectMacro = true;
1961   runSymbolCollector(Header.code(), Main.code());
1962   EXPECT_THAT(
1963       Symbols,
1964       UnorderedElementsAre(
1965           qName("p"), qName("t"),
1966           AllOf(qName("X"), declURI(TestHeaderURI),
1967                 includeHeader(TestHeaderURI)),
1968           AllOf(labeled("MAC(x)"), refCount(0),
1969 
1970                 declRange(Header.range("mac")), visibleOutsideFile()),
1971           AllOf(labeled("USED(y)"), refCount(1),
1972                 declRange(Header.range("used")), visibleOutsideFile()),
1973           AllOf(labeled("MAIN"), refCount(0), declRange(Main.range("main")),
1974                 Not(visibleOutsideFile()))));
1975 }
1976 
1977 TEST_F(SymbolCollectorTest, DeprecatedSymbols) {
1978   const std::string Header = R"(
1979     void TestClangc() __attribute__((deprecated("", "")));
1980     void TestClangd();
1981   )";
1982   runSymbolCollector(Header, /**/ "");
1983   EXPECT_THAT(Symbols, UnorderedElementsAre(
1984                            AllOf(qName("TestClangc"), deprecated()),
1985                            AllOf(qName("TestClangd"), Not(deprecated()))));
1986 }
1987 
1988 TEST_F(SymbolCollectorTest, implementationDetail) {
1989   const std::string Header = R"(
1990     #define DECL_NAME(x, y) x##_##y##_Decl
1991     #define DECL(x, y) class DECL_NAME(x, y) {};
1992     DECL(X, Y); // X_Y_Decl
1993 
1994     class Public {};
1995   )";
1996   runSymbolCollector(Header, /**/ "");
1997   EXPECT_THAT(Symbols,
1998               UnorderedElementsAre(
1999                   AllOf(qName("X_Y_Decl"), implementationDetail()),
2000                   AllOf(qName("Public"), Not(implementationDetail()))));
2001 }
2002 
2003 TEST_F(SymbolCollectorTest, UsingDecl) {
2004   const char *Header = R"(
2005   void foo();
2006   namespace std {
2007     using ::foo;
2008   })";
2009   runSymbolCollector(Header, /**/ "");
2010   EXPECT_THAT(Symbols, Contains(qName("std::foo")));
2011 }
2012 
2013 TEST_F(SymbolCollectorTest, CBuiltins) {
2014   // In C, printf in stdio.h is a redecl of an implicit builtin.
2015   const char *Header = R"(
2016     extern int printf(const char*, ...);
2017   )";
2018   runSymbolCollector(Header, /**/ "", {"-xc"});
2019   EXPECT_THAT(Symbols, Contains(qName("printf")));
2020 }
2021 
2022 TEST_F(SymbolCollectorTest, InvalidSourceLoc) {
2023   const char *Header = R"(
2024       void operator delete(void*)
2025         __attribute__((__externally_visible__));)";
2026   runSymbolCollector(Header, /**/ "");
2027   EXPECT_THAT(Symbols, Contains(qName("operator delete")));
2028 }
2029 
2030 TEST_F(SymbolCollectorTest, BadUTF8) {
2031   // Extracted from boost/spirit/home/support/char_encoding/iso8859_1.hpp
2032   // This looks like UTF-8 and fools clang, but has high-ISO-8859-1 comments.
2033   const char *Header = "int PUNCT = 0;\n"
2034                        "/* \xa1 */ int types[] = { /* \xa1 */PUNCT };";
2035   CollectorOpts.RefFilter = RefKind::All;
2036   CollectorOpts.RefsInHeaders = true;
2037   runSymbolCollector(Header, "");
2038   EXPECT_THAT(Symbols, Contains(AllOf(qName("types"), doc("\xef\xbf\xbd "))));
2039   EXPECT_THAT(Symbols, Contains(qName("PUNCT")));
2040   // Reference is stored, although offset within line is not reliable.
2041   EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "PUNCT").ID, _)));
2042 }
2043 
2044 TEST_F(SymbolCollectorTest, MacrosInHeaders) {
2045   CollectorOpts.CollectMacro = true;
2046   TestFileName = testPath("test.h");
2047   runSymbolCollector("", "#define X");
2048   EXPECT_THAT(Symbols,
2049               UnorderedElementsAre(AllOf(qName("X"), forCodeCompletion(true))));
2050 }
2051 
2052 // Regression test for a crash-bug we used to have.
2053 TEST_F(SymbolCollectorTest, UndefOfModuleMacro) {
2054   auto TU = TestTU::withCode(R"cpp(#include "bar.h")cpp");
2055   TU.AdditionalFiles["bar.h"] = R"cpp(
2056     #include "foo.h"
2057     #undef X
2058     )cpp";
2059   TU.AdditionalFiles["foo.h"] = "#define X 1";
2060   TU.AdditionalFiles["module.modulemap"] = R"cpp(
2061     module foo {
2062      header "foo.h"
2063      export *
2064    }
2065    )cpp";
2066   TU.ExtraArgs.push_back("-fmodules");
2067   TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("module.modulemap"));
2068   TU.OverlayRealFileSystemForModules = true;
2069 
2070   TU.build();
2071   // We mostly care about not crashing, but verify that we didn't insert garbage
2072   // about X too.
2073   EXPECT_THAT(TU.headerSymbols(), Not(Contains(qName("X"))));
2074 }
2075 
2076 TEST_F(SymbolCollectorTest, NoCrashOnObjCMethodCStyleParam) {
2077   auto TU = TestTU::withCode(R"objc(
2078     @interface Foo
2079     - (void)fun:(bool)foo, bool bar;
2080     @end
2081   )objc");
2082   TU.ExtraArgs.push_back("-xobjective-c++");
2083 
2084   TU.build();
2085   // We mostly care about not crashing.
2086   EXPECT_THAT(TU.headerSymbols(),
2087               UnorderedElementsAre(qName("Foo"), qName("Foo::fun:")));
2088 }
2089 
2090 TEST_F(SymbolCollectorTest, Reserved) {
2091   const char *Header = R"cpp(
2092     #pragma once
2093     void __foo();
2094     namespace _X { int secret; }
2095   )cpp";
2096 
2097   CollectorOpts.CollectReserved = true;
2098   runSymbolCollector(Header, "");
2099   EXPECT_THAT(Symbols, UnorderedElementsAre(qName("__foo"), qName("_X"),
2100                                             qName("_X::secret")));
2101 
2102   CollectorOpts.CollectReserved = false;
2103   runSymbolCollector(Header, "");
2104   EXPECT_THAT(Symbols, UnorderedElementsAre(qName("__foo"), qName("_X"),
2105                                             qName("_X::secret")));
2106 
2107   // Ugly: for some reason we reuse the test filesystem across tests.
2108   // You can't overwrite the same filename with new content!
2109   InMemoryFileSystem = new llvm::vfs::InMemoryFileSystem;
2110   runSymbolCollector("#pragma GCC system_header\n" + std::string(Header), "");
2111   EXPECT_THAT(Symbols, IsEmpty());
2112 }
2113 
2114 TEST_F(SymbolCollectorTest, ReservedSymbolInIntrinsicHeader) {
2115   const char *Header = R"cpp(
2116     #pragma once
2117     void __foo();
2118   )cpp";
2119 
2120   TestHeaderName = "xintrin.h";
2121   TestHeaderURI = URI::create(testPath(TestHeaderName)).toString();
2122   InMemoryFileSystem = new llvm::vfs::InMemoryFileSystem;
2123   CollectorOpts.FallbackDir = testRoot();
2124   runSymbolCollector("#pragma GCC system_header\n" + std::string(Header), "");
2125   EXPECT_THAT(Symbols, UnorderedElementsAre(qName("__foo")));
2126 }
2127 
2128 TEST_F(SymbolCollectorTest, Concepts) {
2129   const char *Header = R"cpp(
2130     template <class T>
2131     concept A = sizeof(T) <= 8;
2132   )cpp";
2133   runSymbolCollector("", Header, {"-std=c++20"});
2134   EXPECT_THAT(Symbols,
2135               UnorderedElementsAre(AllOf(
2136                   qName("A"), hasKind(clang::index::SymbolKind::Concept))));
2137 }
2138 
2139 TEST_F(SymbolCollectorTest, IncludeHeaderForwardDecls) {
2140   CollectorOpts.CollectIncludePath = true;
2141   const std::string Header = R"cpp(#pragma once
2142 struct Foo;
2143 #include "full.h"
2144 )cpp";
2145   auto FullFile = testPath("full.h");
2146   InMemoryFileSystem->addFile(FullFile, 0,
2147                               llvm::MemoryBuffer::getMemBuffer(R"cpp(
2148 #pragma once
2149 struct Foo {};)cpp"));
2150   runSymbolCollector(Header, /*Main=*/"",
2151                      /*ExtraArgs=*/{"-I", testRoot()});
2152   EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(
2153                            qName("Foo"),
2154                            includeHeader(URI::create(FullFile).toString()))))
2155       << *Symbols.begin();
2156 }
2157 } // namespace
2158 } // namespace clangd
2159 } // namespace clang
2160