brintos

brintos / llvm-project-archived public Read only

0
0
Text · 78.2 KiB · 7ed08d7 Raw
2832 lines · cpp
1//===-- XRefsTests.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-exception6//7//===----------------------------------------------------------------------===//8#include "Annotations.h"9#include "AST.h"10#include "ParsedAST.h"11#include "Protocol.h"12#include "SourceCode.h"13#include "SyncAPI.h"14#include "TestFS.h"15#include "TestTU.h"16#include "XRefs.h"17#include "index/MemIndex.h"18#include "clang/AST/Decl.h"19#include "clang/Basic/SourceLocation.h"20#include "llvm/ADT/StringRef.h"21#include "llvm/Support/Casting.h"22#include "llvm/Support/Error.h"23#include "llvm/Support/Path.h"24#include "llvm/Support/ScopedPrinter.h"25#include "gmock/gmock.h"26#include "gtest/gtest.h"27#include <optional>28#include <string>29#include <vector>30 31namespace clang {32namespace clangd {33namespace {34 35using ::testing::AllOf;36using ::testing::ElementsAre;37using ::testing::Eq;38using ::testing::IsEmpty;39using ::testing::Matcher;40using ::testing::UnorderedElementsAre;41using ::testing::UnorderedElementsAreArray;42using ::testing::UnorderedPointwise;43 44std::string guard(llvm::StringRef Code) {45  return "#pragma once\n" + Code.str();46}47 48MATCHER_P2(FileRange, File, Range, "") {49  return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;50}51MATCHER(declRange, "") {52  const LocatedSymbol &Sym = ::testing::get<0>(arg);53  const Range &Range = ::testing::get<1>(arg);54  return Sym.PreferredDeclaration.range == Range;55}56 57// Extracts ranges from an annotated example, and constructs a matcher for a58// highlight set. Ranges should be named $read/$write as appropriate.59Matcher<const std::vector<DocumentHighlight> &>60highlightsFrom(const Annotations &Test) {61  std::vector<DocumentHighlight> Expected;62  auto Add = [&](const Range &R, DocumentHighlightKind K) {63    Expected.emplace_back();64    Expected.back().range = R;65    Expected.back().kind = K;66  };67  for (const auto &Range : Test.ranges())68    Add(Range, DocumentHighlightKind::Text);69  for (const auto &Range : Test.ranges("read"))70    Add(Range, DocumentHighlightKind::Read);71  for (const auto &Range : Test.ranges("write"))72    Add(Range, DocumentHighlightKind::Write);73  return UnorderedElementsAreArray(Expected);74}75 76TEST(HighlightsTest, All) {77  const char *Tests[] = {78      R"cpp(// Local variable79        int main() {80          int [[bonjour]];81          $write[[^bonjour]] = 2;82          int test1 = $read[[bonjour]];83        }84      )cpp",85 86      R"cpp(// Struct87        namespace ns1 {88        struct [[MyClass]] {89          static void foo([[MyClass]]*) {}90        };91        } // namespace ns192        int main() {93          ns1::[[My^Class]]* Params;94        }95      )cpp",96 97      R"cpp(// Function98        int [[^foo]](int) { return 0; }99        int main() {100          [[foo]]([[foo]](42));101          auto *X = &[[foo]];102        }103      )cpp",104 105      R"cpp(// Function parameter in decl106        void foo(int [[^bar]]);107      )cpp",108      R"cpp(// Not touching any identifiers.109        struct Foo {110          [[~]]Foo() {};111        };112        void foo() {113          Foo f;114          f.[[^~]]Foo();115        }116      )cpp",117      R"cpp(// ObjC methods with split selectors.118        @interface Foo119          +(void) [[x]]:(int)a [[y]]:(int)b;120        @end121        @implementation Foo122          +(void) [[x]]:(int)a [[y]]:(int)b {}123        @end124        void go() {125          [Foo [[x]]:2 [[^y]]:4];126        }127      )cpp",128      R"cpp( // Label129        int main() {130          goto [[^theLabel]];131          [[theLabel]]:132            return 1;133        }134      )cpp",135  };136  for (const char *Test : Tests) {137    Annotations T(Test);138    auto TU = TestTU::withCode(T.code());139    TU.ExtraArgs.push_back("-xobjective-c++");140    auto AST = TU.build();141    EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T))142        << Test;143  }144}145 146TEST(HighlightsTest, ControlFlow) {147  const char *Tests[] = {148      R"cpp(149        // Highlight same-function returns.150        int fib(unsigned n) {151          if (n <= 1) [[ret^urn]] 1;152          [[return]] fib(n - 1) + fib(n - 2);153 154          // Returns from other functions not highlighted.155          auto Lambda = [] { return; };156          class LocalClass { void x() { return; } };157        }158      )cpp",159 160      R"cpp(161        #define FAIL() return false162        #define DO(x) { x; }163        bool foo(int n) {164          if (n < 0) [[FAIL]]();165          DO([[re^turn]] true)166        }167      )cpp",168 169      R"cpp(170        // Highlight loop control flow171        int magic() {172          int counter = 0;173          [[^for]] (char c : "fruit loops!") {174            if (c == ' ') [[continue]];175            counter += c;176            if (c == '!') [[break]];177            if (c == '?') [[return]] -1;178          }179          return counter;180        }181      )cpp",182 183      R"cpp(184        // Highlight loop and same-loop control flow185        void nonsense() {186          [[while]] (true) {187            if (false) [[bre^ak]];188            switch (1) break;189            [[continue]];190          }191        }192      )cpp",193 194      R"cpp(195        // Highlight switch for break (but not other breaks).196        void describe(unsigned n) {197          [[switch]](n) {198          case 0:199            break;200          [[default]]:201            [[^break]];202          }203        }204      )cpp",205 206      R"cpp(207        // Highlight case and exits for switch-break (but not other cases).208        void describe(unsigned n) {209          [[switch]](n) {210          case 0:211            break;212          [[case]] 1:213          [[default]]:214            [[return]];215            [[^break]];216          }217        }218      )cpp",219 220      R"cpp(221        // Highlight exits and switch for case222        void describe(unsigned n) {223          [[switch]](n) {224          case 0:225            break;226          [[case]] 1:227          [[d^efault]]:228            [[return]];229            [[break]];230          }231        }232      )cpp",233 234      R"cpp(235        // Highlight nothing for switch.236        void describe(unsigned n) {237          s^witch(n) {238          case 0:239            break;240          case 1:241          default:242            return;243            break;244          }245        }246      )cpp",247 248      R"cpp(249        // FIXME: match exception type against catch blocks250        int catchy() {251          try {                     // wrong: highlight try with matching catch252            try {                   // correct: has no matching catch253              [[thr^ow]] "oh no!";254            } catch (int) { }       // correct: catch doesn't match type255            [[return]] -1;          // correct: exits the matching catch256          } catch (const char*) { } // wrong: highlight matching catch257          [[return]] 42;            // wrong: throw doesn't exit function258        }259      )cpp",260 261      R"cpp(262        // Loop highlights goto exiting the loop, but not jumping within it.263        void jumpy() {264          [[wh^ile]](1) {265            up:266            if (0) [[goto]] out;267            goto up;268          }269          out: return;270        }271      )cpp",272  };273  for (const char *Test : Tests) {274    Annotations T(Test);275    auto TU = TestTU::withCode(T.code());276    TU.ExtraArgs.push_back("-fexceptions"); // FIXME: stop testing on PS4.277    auto AST = TU.build();278    EXPECT_THAT(findDocumentHighlights(AST, T.point()), highlightsFrom(T))279        << Test;280  }281}282 283MATCHER_P3(sym, Name, Decl, DefOrNone, "") {284  std::optional<Range> Def = DefOrNone;285  if (Name != arg.Name) {286    *result_listener << "Name is " << arg.Name;287    return false;288  }289  if (Decl != arg.PreferredDeclaration.range) {290    *result_listener << "Declaration is "291                     << llvm::to_string(arg.PreferredDeclaration);292    return false;293  }294  if (!Def && !arg.Definition)295    return true;296  if (Def && !arg.Definition) {297    *result_listener << "Has no definition";298    return false;299  }300  if (!Def && arg.Definition) {301    *result_listener << "Definition is " << llvm::to_string(*arg.Definition);302    return false;303  }304  if (arg.Definition->range != *Def) {305    *result_listener << "Definition is " << llvm::to_string(*arg.Definition);306    return false;307  }308  return true;309}310 311MATCHER_P(sym, Name, "") { return arg.Name == Name; }312 313MATCHER_P(rangeIs, R, "") { return arg.Loc.range == R; }314MATCHER_P(containerIs, C, "") {315  return arg.Loc.containerName.value_or("") == C;316}317MATCHER_P(attrsAre, A, "") { return arg.Attributes == A; }318MATCHER_P(hasID, ID, "") { return arg.ID == ID; }319 320TEST(LocateSymbol, WithIndex) {321  Annotations SymbolHeader(R"cpp(322        class $forward[[Forward]];323        class $foo[[Foo]] {};324 325        void $f1[[f1]]();326 327        inline void $f2[[f2]]() {}328      )cpp");329  Annotations SymbolCpp(R"cpp(330      class $forward[[forward]] {};331      void  $f1[[f1]]() {}332    )cpp");333 334  TestTU TU;335  TU.Code = std::string(SymbolCpp.code());336  TU.HeaderCode = std::string(SymbolHeader.code());337  auto Index = TU.index();338  auto LocateWithIndex = [&Index](const Annotations &Main) {339    auto AST = TestTU::withCode(Main.code()).build();340    return clangd::locateSymbolAt(AST, Main.point(), Index.get());341  };342 343  Annotations Test(R"cpp(// only declaration in AST.344        void [[f1]]();345        int main() {346          ^f1();347        }348      )cpp");349  EXPECT_THAT(LocateWithIndex(Test),350              ElementsAre(sym("f1", Test.range(), SymbolCpp.range("f1"))));351 352  Test = Annotations(R"cpp(// definition in AST.353        void [[f1]]() {}354        int main() {355          ^f1();356        }357      )cpp");358  EXPECT_THAT(LocateWithIndex(Test),359              ElementsAre(sym("f1", SymbolHeader.range("f1"), Test.range())));360 361  Test = Annotations(R"cpp(// forward declaration in AST.362        class [[Foo]];363        F^oo* create();364      )cpp");365  EXPECT_THAT(LocateWithIndex(Test),366              ElementsAre(sym("Foo", Test.range(), SymbolHeader.range("foo"))));367 368  Test = Annotations(R"cpp(// definition in AST.369        class [[Forward]] {};370        F^orward create();371      )cpp");372  EXPECT_THAT(373      LocateWithIndex(Test),374      ElementsAre(sym("Forward", SymbolHeader.range("forward"), Test.range())));375}376 377TEST(LocateSymbol, AnonymousStructFields) {378  auto Code = Annotations(R"cpp(379    struct $2[[Foo]] {380      struct { int $1[[x]]; };381      void foo() {382        // Make sure the implicit base is skipped.383        $1^x = 42;384      }385    };386    // Check that we don't skip explicit bases.387    int a = $2^Foo{}.x;388  )cpp");389  TestTU TU = TestTU::withCode(Code.code());390  auto AST = TU.build();391  EXPECT_THAT(locateSymbolAt(AST, Code.point("1"), TU.index().get()),392              UnorderedElementsAre(sym("x", Code.range("1"), Code.range("1"))));393  EXPECT_THAT(394      locateSymbolAt(AST, Code.point("2"), TU.index().get()),395      UnorderedElementsAre(sym("Foo", Code.range("2"), Code.range("2"))));396}397 398TEST(LocateSymbol, FindOverrides) {399  auto Code = Annotations(R"cpp(400    class Foo {401      virtual void $1[[fo^o]]() = 0;402    };403    class Bar : public Foo {404      void $2[[foo]]() override;405    };406  )cpp");407  TestTU TU = TestTU::withCode(Code.code());408  auto AST = TU.build();409  EXPECT_THAT(locateSymbolAt(AST, Code.point(), TU.index().get()),410              UnorderedElementsAre(sym("foo", Code.range("1"), std::nullopt),411                                   sym("foo", Code.range("2"), std::nullopt)));412}413 414TEST(LocateSymbol, FindOverridesFromDefObjC) {415  auto Code = Annotations(R"objc(416    @protocol Fooey417    - (void)foo;418    @end419    @interface Base420    - (void)foo;421    @end422    @interface Foo : Base<Fooey>423    - (void)$1[[foo]];424    @end425 426    @interface Bar : Foo427    - (void)$2[[foo]];428    @end429    @implementation Bar430    - (void)$3[[fo^o]] {}431    @end432  )objc");433  TestTU TU = TestTU::withCode(Code.code());434  TU.ExtraArgs.push_back("-xobjective-c++");435  auto AST = TU.build();436  EXPECT_THAT(437      locateSymbolAt(AST, Code.point(), TU.index().get()),438      UnorderedElementsAre(sym("foo", Code.range("1"), std::nullopt),439                           sym("foo", Code.range("2"), Code.range("3"))));440}441 442TEST(LocateSymbol, NoOverridesFromDeclObjC) {443  auto Code = Annotations(R"objc(444    @protocol Fooey445    - (void)foo;446    @end447    @interface Base448    - (void)foo;449    @end450    @interface Foo : Base<Fooey>451    - (void)foo;452    @end453 454    @interface Bar : Foo455    - (void)$2[[fo^o]];456    @end457    @implementation Bar458    - (void)$3[[foo]] {}459    @end460  )objc");461  TestTU TU = TestTU::withCode(Code.code());462  TU.ExtraArgs.push_back("-xobjective-c++");463  auto AST = TU.build();464  EXPECT_THAT(465      locateSymbolAt(AST, Code.point(), TU.index().get()),466      UnorderedElementsAre(sym("foo", Code.range("2"), Code.range("3"))));467}468 469TEST(LocateSymbol, ObjCNoOverridesOnUsage) {470  auto Code = Annotations(R"objc(471    @interface Foo472    - (void)foo;473    @end474 475    @interface Bar : Foo476    - (void)$1[[foo]];477    @end478    @implementation Bar479    - (void)$2[[foo]] {}480    @end481    void doSomething(Bar *bar) {482      [bar fo^o];483    }484  )objc");485  TestTU TU = TestTU::withCode(Code.code());486  TU.ExtraArgs.push_back("-xobjective-c++");487  auto AST = TU.build();488  EXPECT_THAT(489      locateSymbolAt(AST, Code.point(), TU.index().get()),490      UnorderedElementsAre(sym("foo", Code.range("1"), Code.range("2"))));491}492 493TEST(LocateSymbol, WithIndexPreferredLocation) {494  Annotations SymbolHeader(R"cpp(495        class $p[[Proto]] {};496        void $f[[func]]() {};497      )cpp");498  TestTU TU;499  TU.HeaderCode = std::string(SymbolHeader.code());500  TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files.501  auto Index = TU.index();502 503  Annotations Test(R"cpp(// only declaration in AST.504        // Shift to make range different.505        class Proto;506        void func() {}507        P$p^roto* create() {508          fu$f^nc();509          return nullptr;510        }511      )cpp");512 513  auto AST = TestTU::withCode(Test.code()).build();514  {515    auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get());516    auto CodeGenLoc = SymbolHeader.range("p");517    EXPECT_THAT(Locs, ElementsAre(sym("Proto", CodeGenLoc, CodeGenLoc)));518  }519  {520    auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get());521    auto CodeGenLoc = SymbolHeader.range("f");522    EXPECT_THAT(Locs, ElementsAre(sym("func", CodeGenLoc, CodeGenLoc)));523  }524}525 526TEST(LocateSymbol, All) {527  // Ranges in tests:528  //   $decl is the declaration location (if absent, no symbol is located)529  //   $def is the definition location (if absent, symbol has no definition)530  //   unnamed range becomes both $decl and $def.531  const char *Tests[] = {532      R"cpp(533        struct X {534          union {535            int [[a]];536            float b;537          };538        };539        int test(X &x) {540          return x.^a;541        }542      )cpp",543 544      R"cpp(// Local variable545        int main() {546          int [[bonjour]];547          ^bonjour = 2;548          int test1 = bonjour;549        }550      )cpp",551 552      R"cpp(// Struct553        namespace ns1 {554        struct [[MyClass]] {};555        } // namespace ns1556        int main() {557          ns1::My^Class* Params;558        }559      )cpp",560 561      R"cpp(// Function definition via pointer562        void [[foo]](int) {}563        int main() {564          auto *X = &^foo;565        }566      )cpp",567 568      R"cpp(// Function declaration via call569        int $decl[[foo]](int);570        int main() {571          return ^foo(42);572        }573      )cpp",574 575      R"cpp(// Field576        struct Foo { int [[x]]; };577        int main() {578          Foo bar;579          (void)bar.^x;580        }581      )cpp",582 583      R"cpp(// Field, member initializer584        struct Foo {585          int [[x]];586          Foo() : ^x(0) {}587        };588      )cpp",589 590      R"cpp(// Field, field designator591        struct Foo { int [[x]]; };592        int main() {593          Foo bar = { .^x = 2 };594        }595      )cpp",596 597      R"cpp(// Method call598        struct Foo { int $decl[[x]](); };599        int main() {600          Foo bar;601          bar.^x();602        }603      )cpp",604 605      R"cpp(// Typedef606        typedef int $decl[[Foo]];607        int main() {608          ^Foo bar;609        }610      )cpp",611 612      R"cpp(// Template type parameter613        template <typename [[T]]>614        void foo() { ^T t; }615      )cpp",616 617      R"cpp(// Template template type parameter618        template <template<typename> class [[T]]>619        void foo() { ^T<int> t; }620      )cpp",621 622      R"cpp(// Namespace623        namespace $decl[[ns]] {624        struct Foo { static void bar(); };625        } // namespace ns626        int main() { ^ns::Foo::bar(); }627      )cpp",628 629      R"cpp(// Macro630       class TTT { public: int a; };631       #define [[FF]](S) if (int b = S.a) {}632       void f() {633         TTT t;634         F^F(t);635       }636      )cpp",637 638      R"cpp(// Macro argument639       int [[i]];640       #define ADDRESSOF(X) &X;641       int *j = ADDRESSOF(^i);642      )cpp",643      R"cpp(// Macro argument appearing multiple times in expansion644        #define VALIDATE_TYPE(x) (void)x;645        #define ASSERT(expr)       \646          do {                     \647            VALIDATE_TYPE(expr);   \648            if (!expr);            \649          } while (false)650        bool [[waldo]]() { return true; }651        void foo() {652          ASSERT(wa^ldo());653        }654      )cpp",655      R"cpp(// Symbol concatenated inside macro (not supported)656       int *pi;657       #define POINTER(X) p ## X;658       int x = *POINTER(^i);659      )cpp",660 661      R"cpp(// Forward class declaration662        class $decl[[Foo]];663        class $def[[Foo]] {};664        F^oo* foo();665      )cpp",666 667      R"cpp(// Function declaration668        void $decl[[foo]]();669        void g() { f^oo(); }670        void $def[[foo]]() {}671      )cpp",672 673      R"cpp(674        #define FF(name) class name##_Test {};675        [[FF]](my);676        void f() { my^_Test a; }677      )cpp",678 679      R"cpp(680         #define FF() class [[Test]] {};681         FF();682         void f() { T^est a; }683      )cpp",684 685      R"cpp(// explicit template specialization686        template <typename T>687        struct Foo { void bar() {} };688 689        template <>690        struct [[Foo]]<int> { void bar() {} };691 692        void foo() {693          Foo<char> abc;694          Fo^o<int> b;695        }696      )cpp",697 698      R"cpp(// implicit template specialization699        template <typename T>700        struct [[Foo]] { void bar() {} };701        template <>702        struct Foo<int> { void bar() {} };703        void foo() {704          Fo^o<char> abc;705          Foo<int> b;706        }707      )cpp",708 709      R"cpp(// partial template specialization710        template <typename T>711        struct Foo { void bar() {} };712        template <typename T>713        struct [[Foo]]<T*> { void bar() {} };714        ^Foo<int*> x;715      )cpp",716 717      R"cpp(// function template specializations718        template <class T>719        void foo(T) {}720        template <>721        void [[foo]](int) {}722        void bar() {723          fo^o(10);724        }725      )cpp",726 727      R"cpp(// variable template decls728        template <class T>729        T var = T();730 731        template <>732        double [[var]]<int> = 10;733 734        double y = va^r<int>;735      )cpp",736 737      R"cpp(// No implicit constructors738        struct X {739          X(X&& x) = default;740        };741        X $decl[[makeX]]();742        void foo() {743          auto x = m^akeX();744        }745      )cpp",746 747      R"cpp(748        struct X {749          X& $decl[[operator]]++();750        };751        void foo(X& x) {752          +^+x;753        }754      )cpp",755 756      R"cpp(757        struct S1 { void f(); };758        struct S2 { S1 * $decl[[operator]]->(); };759        void test(S2 s2) {760          s2-^>f();761        }762      )cpp",763 764      R"cpp(// Declaration of explicit template specialization765        template <typename T>766        struct $decl[[$def[[Foo]]]] {};767 768        template <>769        struct Fo^o<int> {};770      )cpp",771 772      R"cpp(// Declaration of partial template specialization773        template <typename T>774        struct $decl[[$def[[Foo]]]] {};775 776        template <typename T>777        struct Fo^o<T*> {};778      )cpp",779 780      R"cpp(// Definition on ClassTemplateDecl781        namespace ns {782          // Forward declaration.783          template<typename T>784          struct $decl[[Foo]];785 786          template <typename T>787          struct $def[[Foo]] {};788        }789 790        using ::ns::Fo^o;791      )cpp",792 793      R"cpp(// auto builtin type (not supported)794        ^auto x = 42;795      )cpp",796 797      R"cpp(// auto on lambda798        auto x = [[[]]]{};799        ^auto y = x;800      )cpp",801 802      R"cpp(// auto on struct803        namespace ns1 {804        struct [[S1]] {};805        } // namespace ns1806 807        ^auto x = ns1::S1{};808      )cpp",809 810      R"cpp(// decltype on struct811        namespace ns1 {812        struct [[S1]] {};813        } // namespace ns1814 815        ns1::S1 i;816        ^decltype(i) j;817      )cpp",818 819      R"cpp(// decltype(auto) on struct820        namespace ns1 {821        struct [[S1]] {};822        } // namespace ns1823 824        ns1::S1 i;825        ns1::S1& j = i;826        ^decltype(auto) k = j;827      )cpp",828 829      R"cpp(// auto on template class830        template<typename T> class [[Foo]] {};831 832        ^auto x = Foo<int>();833      )cpp",834 835      R"cpp(// auto on template class with forward declared class836        template<typename T> class [[Foo]] {};837        class X;838 839        ^auto x = Foo<X>();840      )cpp",841 842      R"cpp(// auto on specialized template class843        template<typename T> class Foo {};844        template<> class [[Foo]]<int> {};845 846        ^auto x = Foo<int>();847      )cpp",848 849      R"cpp(// auto on initializer list.850        namespace std851        {852          template<class _E>853          class [[initializer_list]] { const _E *a, *b; };854        }855 856        ^auto i = {1,2};857      )cpp",858 859      R"cpp(// auto function return with trailing type860        struct [[Bar]] {};861        ^auto test() -> decltype(Bar()) {862          return Bar();863        }864      )cpp",865 866      R"cpp(// decltype in trailing return type867        struct [[Bar]] {};868        auto test() -> ^decltype(Bar()) {869          return Bar();870        }871      )cpp",872 873      R"cpp(// auto in function return874        struct [[Bar]] {};875        ^auto test() {876          return Bar();877        }878      )cpp",879 880      R"cpp(// auto& in function return881        struct [[Bar]] {};882        ^auto& test() {883          static Bar x;884          return x;885        }886      )cpp",887 888      R"cpp(// auto* in function return889        struct [[Bar]] {};890        ^auto* test() {891          Bar* x;892          return x;893        }894      )cpp",895 896      R"cpp(// const auto& in function return897        struct [[Bar]] {};898        const ^auto& test() {899          static Bar x;900          return x;901        }902      )cpp",903 904      R"cpp(// auto lambda param where there's a single instantiation905        struct [[Bar]] {};906        auto Lambda = [](^auto){ return 0; };907        int x = Lambda(Bar{});908      )cpp",909 910      R"cpp(// decltype(auto) in function return911        struct [[Bar]] {};912        ^decltype(auto) test() {913          return Bar();914        }915      )cpp",916 917      R"cpp(// decltype of function with trailing return type.918        struct [[Bar]] {};919        auto test() -> decltype(Bar()) {920          return Bar();921        }922        void foo() {923          ^decltype(test()) i = test();924        }925      )cpp",926 927      R"cpp(// auto with dependent type928        template <typename>929        struct [[A]] {};930        template <typename T>931        void foo(A<T> a) {932          ^auto copy = a;933        }934      )cpp",935 936      R"cpp(// Override specifier jumps to overridden method937        class Y { virtual void $decl[[a]]() = 0; };938        class X : Y { void a() ^override {} };939      )cpp",940      R"cpp(// Final specifier jumps to overridden method941        class Y { virtual void $decl[[a]]() = 0; };942        class X : Y { void a() ^final {} };943      )cpp",944 945      R"cpp(// Heuristic resolution of dependent method946        template <typename T>947        struct S {948          void [[bar]]() {}949        };950 951        template <typename T>952        void foo(S<T> arg) {953          arg.ba^r();954        }955      )cpp",956 957      R"cpp(// Heuristic resolution of dependent method via this->958        template <typename T>959        struct S {960          void [[foo]]() {961            this->fo^o();962          }963        };964      )cpp",965 966      R"cpp(// Heuristic resolution of dependent static method967        template <typename T>968        struct S {969          static void [[bar]]() {}970        };971 972        template <typename T>973        void foo() {974          S<T>::ba^r();975        }976      )cpp",977 978      R"cpp(// Heuristic resolution of dependent method979            // invoked via smart pointer980        template <typename> struct S { void [[foo]]() {} };981        template <typename T> struct unique_ptr {982          T* operator->();983        };984        template <typename T>985        void test(unique_ptr<S<T>>& V) {986          V->fo^o();987        }988      )cpp",989 990      R"cpp(// Heuristic resolution of dependent enumerator991        template <typename T>992        struct Foo {993          enum class E { [[A]], B };994          E e = E::A^;995        };996      )cpp",997 998      R"cpp(// Enum base999        typedef int $decl[[MyTypeDef]];1000        enum Foo : My^TypeDef {};1001      )cpp",1002      R"cpp(// Enum base1003        typedef int $decl[[MyTypeDef]];1004        enum Foo : My^TypeDef;1005      )cpp",1006      R"cpp(// Enum base1007        using $decl[[MyTypeDef]] = int;1008        enum Foo : My^TypeDef {};1009      )cpp",1010 1011      R"objc(1012        @protocol Dog;1013        @protocol $decl[[Dog]]1014        - (void)bark;1015        @end1016        id<Do^g> getDoggo() {1017          return 0;1018        }1019      )objc",1020 1021      R"objc(1022        @interface Cat1023        @end1024        @implementation Cat1025        @end1026        @interface $decl[[Cat]] (Exte^nsion)1027        - (void)meow;1028        @end1029        @implementation $def[[Cat]] (Extension)1030        - (void)meow {}1031        @end1032      )objc",1033 1034      R"objc(1035        @class $decl[[Foo]];1036        Fo^o * getFoo() {1037          return 0;1038        }1039      )objc",1040 1041      R"objc(// Prefer interface definition over forward declaration1042        @class Foo;1043        @interface $decl[[Foo]]1044        @end1045        Fo^o * getFoo() {1046          return 0;1047        }1048      )objc",1049 1050      R"objc(1051        @class Foo;1052        @interface $decl[[Foo]]1053        @end1054        @implementation $def[[Foo]]1055        @end1056        Fo^o * getFoo() {1057          return 0;1058        }1059      )objc",1060 1061      R"objc(// Method decl and definition for ObjC class.1062        @interface Cat1063        - (void)$decl[[meow]];1064        @end1065        @implementation Cat1066        - (void)$def[[meow]] {}1067        @end1068        void makeNoise(Cat *kitty) {1069          [kitty me^ow];1070        }1071      )objc",1072 1073      R"objc(// Method decl and definition for ObjC category.1074        @interface Dog1075        @end1076        @interface Dog (Play)1077        - (void)$decl[[runAround]];1078        @end1079        @implementation Dog (Play)1080        - (void)$def[[runAround]] {}1081        @end1082        void play(Dog *dog) {1083          [dog run^Around];1084        }1085      )objc",1086 1087      R"objc(// Method decl and definition for ObjC class extension.1088        @interface Dog1089        @end1090        @interface Dog ()1091        - (void)$decl[[howl]];1092        @end1093        @implementation Dog1094        - (void)$def[[howl]] {}1095        @end1096        void play(Dog *dog) {1097          [dog ho^wl];1098        }1099      )objc",1100      R"cpp(1101        struct PointerIntPairInfo {1102          static void *$decl[[getPointer]](void *Value);1103        };1104 1105        template <typename Info = PointerIntPairInfo> struct PointerIntPair {1106          void *Value;1107          void *getPointer() const { return Info::get^Pointer(Value); }1108        };1109      )cpp",1110      R"cpp(// Deducing this1111        struct S {1112          int bar(this S&);1113        };1114        void foo() {1115          S [[waldo]];1116          int x = wa^ldo.bar();1117        }1118    )cpp"};1119  for (const char *Test : Tests) {1120    Annotations T(Test);1121    std::optional<Range> WantDecl;1122    std::optional<Range> WantDef;1123    if (!T.ranges().empty())1124      WantDecl = WantDef = T.range();1125    if (!T.ranges("decl").empty())1126      WantDecl = T.range("decl");1127    if (!T.ranges("def").empty())1128      WantDef = T.range("def");1129 1130    TestTU TU;1131    TU.Code = std::string(T.code());1132 1133    TU.ExtraArgs.push_back("-xobjective-c++");1134    TU.ExtraArgs.push_back("-std=c++23");1135 1136    auto AST = TU.build();1137    auto Results = locateSymbolAt(AST, T.point());1138 1139    if (!WantDecl) {1140      EXPECT_THAT(Results, IsEmpty()) << Test;1141    } else {1142      ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;1143      EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;1144      EXPECT_TRUE(Results[0].ID) << Test;1145      std::optional<Range> GotDef;1146      if (Results[0].Definition)1147        GotDef = Results[0].Definition->range;1148      EXPECT_EQ(WantDef, GotDef) << Test;1149    }1150  }1151}1152TEST(LocateSymbol, ValidSymbolID) {1153  auto T = Annotations(R"cpp(1154    #define MACRO(x, y) ((x) + (y))1155    int add(int x, int y) { return $MACRO^MACRO(x, y); }1156    int sum = $add^add(1, 2);1157  )cpp");1158 1159  TestTU TU = TestTU::withCode(T.code());1160  auto AST = TU.build();1161  auto Index = TU.index();1162  EXPECT_THAT(locateSymbolAt(AST, T.point("add"), Index.get()),1163              ElementsAre(AllOf(sym("add"),1164                                hasID(getSymbolID(&findDecl(AST, "add"))))));1165  EXPECT_THAT(1166      locateSymbolAt(AST, T.point("MACRO"), Index.get()),1167      ElementsAre(AllOf(sym("MACRO"),1168                        hasID(findSymbol(TU.headerSymbols(), "MACRO").ID))));1169}1170 1171TEST(LocateSymbol, AllMulti) {1172  // Ranges in tests:1173  //   $declN is the declaration location1174  //   $defN is the definition location (if absent, symbol has no definition)1175  //1176  // NOTE:1177  //   N starts at 0.1178  struct ExpectedRanges {1179    Range WantDecl;1180    std::optional<Range> WantDef;1181  };1182  const char *Tests[] = {1183      R"objc(1184        @interface $decl0[[Cat]]1185        @end1186        @implementation $def0[[Cat]]1187        @end1188        @interface $decl1[[Ca^t]] (Extension)1189        - (void)meow;1190        @end1191        @implementation $def1[[Cat]] (Extension)1192        - (void)meow {}1193        @end1194      )objc",1195 1196      R"objc(1197        @interface $decl0[[Cat]]1198        @end1199        @implementation $def0[[Cat]]1200        @end1201        @interface $decl1[[Cat]] (Extension)1202        - (void)meow;1203        @end1204        @implementation $def1[[Ca^t]] (Extension)1205        - (void)meow {}1206        @end1207      )objc",1208 1209      R"objc(1210        @interface $decl0[[Cat]]1211        @end1212        @interface $decl1[[Ca^t]] ()1213        - (void)meow;1214        @end1215        @implementation $def0[[$def1[[Cat]]]]1216        - (void)meow {}1217        @end1218      )objc",1219  };1220  for (const char *Test : Tests) {1221    Annotations T(Test);1222    std::vector<ExpectedRanges> Ranges;1223    for (int Idx = 0; true; Idx++) {1224      bool HasDecl = !T.ranges("decl" + std::to_string(Idx)).empty();1225      bool HasDef = !T.ranges("def" + std::to_string(Idx)).empty();1226      if (!HasDecl && !HasDef)1227        break;1228      ExpectedRanges Range;1229      if (HasDecl)1230        Range.WantDecl = T.range("decl" + std::to_string(Idx));1231      if (HasDef)1232        Range.WantDef = T.range("def" + std::to_string(Idx));1233      Ranges.push_back(Range);1234    }1235 1236    TestTU TU;1237    TU.Code = std::string(T.code());1238    TU.ExtraArgs.push_back("-xobjective-c++");1239 1240    auto AST = TU.build();1241    auto Results = locateSymbolAt(AST, T.point());1242 1243    ASSERT_THAT(Results, ::testing::SizeIs(Ranges.size())) << Test;1244    for (size_t Idx = 0; Idx < Ranges.size(); Idx++) {1245      EXPECT_EQ(Results[Idx].PreferredDeclaration.range, Ranges[Idx].WantDecl)1246          << "($decl" << Idx << ")" << Test;1247      std::optional<Range> GotDef;1248      if (Results[Idx].Definition)1249        GotDef = Results[Idx].Definition->range;1250      EXPECT_EQ(GotDef, Ranges[Idx].WantDef) << "($def" << Idx << ")" << Test;1251    }1252  }1253}1254 1255// LocateSymbol test cases that produce warnings.1256// These are separated out from All so that in All we can assert1257// that there are no diagnostics.1258TEST(LocateSymbol, Warnings) {1259  const char *Tests[] = {1260      R"cpp(// Field, GNU old-style field designator1261        struct Foo { int [[x]]; };1262        int main() {1263          Foo bar = { ^x : 1 };1264        }1265      )cpp",1266 1267      R"cpp(// Macro1268        #define MACRO 01269        #define [[MACRO]] 11270        int main() { return ^MACRO; }1271        #define MACRO 21272        #undef macro1273      )cpp",1274  };1275 1276  for (const char *Test : Tests) {1277    Annotations T(Test);1278    std::optional<Range> WantDecl;1279    std::optional<Range> WantDef;1280    if (!T.ranges().empty())1281      WantDecl = WantDef = T.range();1282    if (!T.ranges("decl").empty())1283      WantDecl = T.range("decl");1284    if (!T.ranges("def").empty())1285      WantDef = T.range("def");1286 1287    TestTU TU;1288    TU.Code = std::string(T.code());1289 1290    auto AST = TU.build();1291    auto Results = locateSymbolAt(AST, T.point());1292 1293    if (!WantDecl) {1294      EXPECT_THAT(Results, IsEmpty()) << Test;1295    } else {1296      ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;1297      EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;1298      std::optional<Range> GotDef;1299      if (Results[0].Definition)1300        GotDef = Results[0].Definition->range;1301      EXPECT_EQ(WantDef, GotDef) << Test;1302    }1303  }1304}1305 1306TEST(LocateSymbol, TextualSmoke) {1307  auto T = Annotations(1308      R"cpp(1309        struct [[MyClass]] {};1310        // Comment mentioning M^yClass1311      )cpp");1312 1313  auto TU = TestTU::withCode(T.code());1314  auto AST = TU.build();1315  auto Index = TU.index();1316  EXPECT_THAT(1317      locateSymbolAt(AST, T.point(), Index.get()),1318      ElementsAre(AllOf(sym("MyClass", T.range(), T.range()),1319                        hasID(getSymbolID(&findDecl(AST, "MyClass"))))));1320}1321 1322TEST(LocateSymbol, Textual) {1323  const char *Tests[] = {1324      R"cpp(// Comment1325        struct [[MyClass]] {};1326        // Comment mentioning M^yClass1327      )cpp",1328      R"cpp(// String1329        struct MyClass {};1330        // Not triggered for string literal tokens.1331        const char* s = "String literal mentioning M^yClass";1332      )cpp",1333      R"cpp(// Ifdef'ed out code1334        struct [[MyClass]] {};1335        #ifdef WALDO1336          M^yClass var;1337        #endif1338      )cpp",1339      R"cpp(// Macro definition1340        struct [[MyClass]] {};1341        #define DECLARE_MYCLASS_OBJ(name) M^yClass name;1342      )cpp",1343      R"cpp(// Invalid code1344        /*error-ok*/1345        int myFunction(int);1346        // Not triggered for token which survived preprocessing.1347        int var = m^yFunction();1348      )cpp"};1349 1350  for (const char *Test : Tests) {1351    Annotations T(Test);1352    std::optional<Range> WantDecl;1353    if (!T.ranges().empty())1354      WantDecl = T.range();1355 1356    auto TU = TestTU::withCode(T.code());1357 1358    auto AST = TU.build();1359    auto Index = TU.index();1360    auto Word = SpelledWord::touching(1361        cantFail(sourceLocationInMainFile(AST.getSourceManager(), T.point())),1362        AST.getTokens(), AST.getLangOpts());1363    if (!Word) {1364      ADD_FAILURE() << "No word touching point!" << Test;1365      continue;1366    }1367    auto Results = locateSymbolTextually(*Word, AST, Index.get(),1368                                         testPath(TU.Filename), ASTNodeKind());1369 1370    if (!WantDecl) {1371      EXPECT_THAT(Results, IsEmpty()) << Test;1372    } else {1373      ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;1374      EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;1375    }1376  }1377} // namespace1378 1379TEST(LocateSymbol, Ambiguous) {1380  auto T = Annotations(R"cpp(1381    struct Foo {1382      Foo();1383      Foo(Foo&&);1384      $ConstructorLoc[[Foo]](const char*);1385    };1386 1387    Foo f();1388 1389    void g(Foo foo);1390 1391    void call() {1392      const char* str = "123";1393      Foo a = $1^str;1394      Foo b = Foo($2^str);1395      Foo c = $3^f();1396      $4^g($5^f());1397      g($6^str);1398      Foo ab$7^c;1399      Foo ab$8^cd("asdf");1400      Foo foox = Fo$9^o("asdf");1401      Foo abcde$10^("asdf");1402      Foo foox2 = Foo$11^("asdf");1403    }1404 1405    template <typename T>1406    struct S {1407      void $NonstaticOverload1[[bar]](int);1408      void $NonstaticOverload2[[bar]](float);1409 1410      static void $StaticOverload1[[baz]](int);1411      static void $StaticOverload2[[baz]](float);1412    };1413 1414    template <typename T, typename U>1415    void dependent_call(S<T> s, U u) {1416      s.ba$12^r(u);1417      S<T>::ba$13^z(u);1418    }1419  )cpp");1420  auto TU = TestTU::withCode(T.code());1421  // FIXME: Go-to-definition in a template requires disabling delayed template1422  // parsing.1423  TU.ExtraArgs.push_back("-fno-delayed-template-parsing");1424  auto AST = TU.build();1425  // Ordered assertions are deliberate: we expect a predictable order.1426  EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(sym("str")));1427  EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(sym("str")));1428  EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(sym("f")));1429  EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(sym("g")));1430  EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(sym("f")));1431  EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(sym("str")));1432  // FIXME: Target the constructor as well.1433  EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(sym("abc")));1434  // FIXME: Target the constructor as well.1435  EXPECT_THAT(locateSymbolAt(AST, T.point("8")), ElementsAre(sym("abcd")));1436  // FIXME: Target the constructor as well.1437  EXPECT_THAT(locateSymbolAt(AST, T.point("9")), ElementsAre(sym("Foo")));1438  EXPECT_THAT(locateSymbolAt(AST, T.point("10")),1439              ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt)));1440  EXPECT_THAT(locateSymbolAt(AST, T.point("11")),1441              ElementsAre(sym("Foo", T.range("ConstructorLoc"), std::nullopt)));1442  // These assertions are unordered because the order comes from1443  // CXXRecordDecl::lookupDependentName() which doesn't appear to provide1444  // an order guarantee.1445  EXPECT_THAT(locateSymbolAt(AST, T.point("12")),1446              UnorderedElementsAre(1447                  sym("bar", T.range("NonstaticOverload1"), std::nullopt),1448                  sym("bar", T.range("NonstaticOverload2"), std::nullopt)));1449  EXPECT_THAT(locateSymbolAt(AST, T.point("13")),1450              UnorderedElementsAre(1451                  sym("baz", T.range("StaticOverload1"), std::nullopt),1452                  sym("baz", T.range("StaticOverload2"), std::nullopt)));1453}1454 1455TEST(LocateSymbol, TextualDependent) {1456  // Put the declarations in the header to make sure we are1457  // finding them via the index heuristic and not the1458  // nearby-ident heuristic.1459  Annotations Header(R"cpp(1460        struct Foo {1461          void $FooLoc[[uniqueMethodName]]();1462        };1463        struct Bar {1464          void $BarLoc[[uniqueMethodName]]();1465        };1466        )cpp");1467  Annotations Source(R"cpp(1468        template <typename T>1469        void f(T t) {1470          t.u^niqueMethodName();1471        }1472      )cpp");1473  TestTU TU;1474  TU.Code = std::string(Source.code());1475  TU.HeaderCode = std::string(Header.code());1476  auto AST = TU.build();1477  auto Index = TU.index();1478  // Need to use locateSymbolAt() since we are testing an1479  // interaction between locateASTReferent() and1480  // locateSymbolNamedTextuallyAt().1481  auto Results = locateSymbolAt(AST, Source.point(), Index.get());1482  EXPECT_THAT(1483      Results,1484      UnorderedElementsAre(1485          sym("uniqueMethodName", Header.range("FooLoc"), std::nullopt),1486          sym("uniqueMethodName", Header.range("BarLoc"), std::nullopt)));1487}1488 1489TEST(LocateSymbol, Alias) {1490  const char *Tests[] = {1491      R"cpp(1492      template <class T> struct function {};1493      template <class T> using [[callback]] = function<T()>;1494 1495      c^allback<int> foo;1496    )cpp",1497 1498      // triggered on non-definition of a renaming alias: should not give any1499      // underlying decls.1500      R"cpp(1501      class Foo {};1502      typedef Foo [[Bar]];1503 1504      B^ar b;1505    )cpp",1506      R"cpp(1507      class Foo {};1508      using [[Bar]] = Foo; // definition1509      Ba^r b;1510    )cpp",1511 1512      // triggered on the underlying decl of a renaming alias.1513      R"cpp(1514      class [[Foo]];1515      using Bar = Fo^o;1516    )cpp",1517 1518      // triggered on definition of a non-renaming alias: should give underlying1519      // decls.1520      R"cpp(1521      namespace ns { class [[Foo]] {}; }1522      using ns::F^oo;1523    )cpp",1524 1525      R"cpp(1526      namespace ns { int [[x]](char); int [[x]](double); }1527      using ns::^x;1528    )cpp",1529 1530      R"cpp(1531      namespace ns { int [[x]](char); int x(double); }1532      using ns::[[x]];1533      int y = ^x('a');1534    )cpp",1535 1536      R"cpp(1537      namespace ns { class [[Foo]] {}; }1538      using ns::[[Foo]];1539      F^oo f;1540    )cpp",1541 1542      // other cases that don't matter much.1543      R"cpp(1544      class Foo {};1545      typedef Foo [[Ba^r]];1546    )cpp",1547      R"cpp(1548      class Foo {};1549      using [[B^ar]] = Foo;1550    )cpp",1551 1552      // Member of dependent base1553      R"cpp(1554      template <typename T>1555      struct Base {1556        void [[waldo]]() {}1557      };1558      template <typename T>1559      struct Derived : Base<T> {1560        using Base<T>::w^aldo;1561      };1562    )cpp",1563  };1564 1565  for (const auto *Case : Tests) {1566    SCOPED_TRACE(Case);1567    auto T = Annotations(Case);1568    auto AST = TestTU::withCode(T.code()).build();1569    EXPECT_THAT(locateSymbolAt(AST, T.point()),1570                UnorderedPointwise(declRange(), T.ranges()));1571  }1572}1573 1574TEST(LocateSymbol, RelPathsInCompileCommand) {1575  // The source is in "/clangd-test/src".1576  // We build in "/clangd-test/build".1577 1578  Annotations SourceAnnotations(R"cpp(1579#include "header_in_preamble.h"1580int [[foo]];1581#include "header_not_in_preamble.h"1582int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;1583)cpp");1584 1585  Annotations HeaderInPreambleAnnotations(R"cpp(1586int [[bar_preamble]];1587)cpp");1588 1589  Annotations HeaderNotInPreambleAnnotations(R"cpp(1590int [[bar_not_preamble]];1591)cpp");1592 1593  // Make the compilation paths appear as ../src/foo.cpp in the compile1594  // commands.1595  SmallString<32> RelPathPrefix("..");1596  llvm::sys::path::append(RelPathPrefix, "src");1597  std::string BuildDir = testPath("build");1598  MockCompilationDatabase CDB(BuildDir, RelPathPrefix);1599 1600  MockFS FS;1601  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());1602 1603  // Fill the filesystem.1604  auto FooCpp = testPath("src/foo.cpp");1605  FS.Files[FooCpp] = "";1606  auto HeaderInPreambleH = testPath("src/header_in_preamble.h");1607  FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());1608  auto HeaderNotInPreambleH = testPath("src/header_not_in_preamble.h");1609  FS.Files[HeaderNotInPreambleH] =1610      std::string(HeaderNotInPreambleAnnotations.code());1611 1612  runAddDocument(Server, FooCpp, SourceAnnotations.code());1613 1614  // Go to a definition in main source file.1615  auto Locations =1616      runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1"));1617  EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";1618  EXPECT_THAT(*Locations, ElementsAre(sym("foo", SourceAnnotations.range(),1619                                          SourceAnnotations.range())));1620 1621  // Go to a definition in header_in_preamble.h.1622  Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2"));1623  EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";1624  EXPECT_THAT(1625      *Locations,1626      ElementsAre(sym("bar_preamble", HeaderInPreambleAnnotations.range(),1627                      HeaderInPreambleAnnotations.range())));1628 1629  // Go to a definition in header_not_in_preamble.h.1630  Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3"));1631  EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";1632  EXPECT_THAT(*Locations,1633              ElementsAre(sym("bar_not_preamble",1634                              HeaderNotInPreambleAnnotations.range(),1635                              HeaderNotInPreambleAnnotations.range())));1636}1637 1638TEST(GoToInclude, All) {1639  MockFS FS;1640  MockCompilationDatabase CDB;1641  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());1642 1643  auto FooCpp = testPath("foo.cpp");1644  const char *SourceContents = R"cpp(1645  #include ^"$2^foo.h$3^"1646  #include "$4^invalid.h"1647  int b = a;1648  // test1649  int foo;1650  #in$5^clude "$6^foo.h"$7^1651  )cpp";1652  Annotations SourceAnnotations(SourceContents);1653  FS.Files[FooCpp] = std::string(SourceAnnotations.code());1654  auto FooH = testPath("foo.h");1655 1656  const char *HeaderContents = R"cpp([[]]#pragma once1657                                     int a;1658                                     )cpp";1659  Annotations HeaderAnnotations(HeaderContents);1660  FS.Files[FooH] = std::string(HeaderAnnotations.code());1661 1662  runAddDocument(Server, FooH, HeaderAnnotations.code());1663  runAddDocument(Server, FooCpp, SourceAnnotations.code());1664 1665  // Test include in preamble.1666  auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point());1667  ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";1668  EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),1669                                          HeaderAnnotations.range())));1670 1671  // Test include in preamble, last char.1672  Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2"));1673  ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";1674  EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),1675                                          HeaderAnnotations.range())));1676 1677  Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3"));1678  ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";1679  EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),1680                                          HeaderAnnotations.range())));1681 1682  // Test include outside of preamble.1683  Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6"));1684  ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";1685  EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),1686                                          HeaderAnnotations.range())));1687 1688  // Test a few positions that do not result in Locations.1689  Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4"));1690  ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";1691  EXPECT_THAT(*Locations, IsEmpty());1692 1693  Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));1694  ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";1695  EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),1696                                          HeaderAnnotations.range())));1697 1698  Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7"));1699  ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";1700  EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),1701                                          HeaderAnnotations.range())));1702 1703  // Objective C #import directive.1704  Annotations ObjC(R"objc(1705  #import "^foo.h"1706  )objc");1707  auto FooM = testPath("foo.m");1708  FS.Files[FooM] = std::string(ObjC.code());1709 1710  runAddDocument(Server, FooM, ObjC.code());1711  Locations = runLocateSymbolAt(Server, FooM, ObjC.point());1712  ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";1713  EXPECT_THAT(*Locations, ElementsAre(sym("foo.h", HeaderAnnotations.range(),1714                                          HeaderAnnotations.range())));1715}1716 1717TEST(LocateSymbol, WithPreamble) {1718  // Test stragety: AST should always use the latest preamble instead of last1719  // good preamble.1720  MockFS FS;1721  MockCompilationDatabase CDB;1722  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());1723 1724  auto FooCpp = testPath("foo.cpp");1725  // The trigger locations must be the same.1726  Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp");1727  Annotations FooWithoutHeader(R"cpp(double    [[fo^o]]();)cpp");1728 1729  FS.Files[FooCpp] = std::string(FooWithHeader.code());1730 1731  auto FooH = testPath("foo.h");1732  Annotations FooHeader(R"cpp([[]])cpp");1733  FS.Files[FooH] = std::string(FooHeader.code());1734 1735  runAddDocument(Server, FooCpp, FooWithHeader.code());1736  // LocateSymbol goes to a #include file: the result comes from the preamble.1737  EXPECT_THAT(1738      cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())),1739      ElementsAre(sym("foo.h", FooHeader.range(), FooHeader.range())));1740 1741  // Only preamble is built, and no AST is built in this request.1742  Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",1743                     WantDiagnostics::No);1744  // We build AST here, and it should use the latest preamble rather than the1745  // stale one.1746  EXPECT_THAT(1747      cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),1748      ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt)));1749 1750  // Reset test environment.1751  runAddDocument(Server, FooCpp, FooWithHeader.code());1752  // Both preamble and AST are built in this request.1753  Server.addDocument(FooCpp, FooWithoutHeader.code(), "null",1754                     WantDiagnostics::Yes);1755  // Use the AST being built in above request.1756  EXPECT_THAT(1757      cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),1758      ElementsAre(sym("foo", FooWithoutHeader.range(), std::nullopt)));1759}1760 1761TEST(LocateSymbol, NearbyTokenSmoke) {1762  auto T = Annotations(R"cpp(1763    // prints e^rr and crashes1764    void die(const char* [[err]]);1765  )cpp");1766  auto AST = TestTU::withCode(T.code()).build();1767  // We don't pass an index, so can't hit index-based fallback.1768  EXPECT_THAT(locateSymbolAt(AST, T.point()),1769              ElementsAre(sym("err", T.range(), T.range())));1770}1771 1772TEST(LocateSymbol, NearbyIdentifier) {1773  const char *Tests[] = {1774      R"cpp(1775      // regular identifiers (won't trigger)1776      int hello;1777      int y = he^llo;1778    )cpp",1779      R"cpp(1780      // disabled preprocessor sections1781      int [[hello]];1782      #if 01783      int y = ^hello;1784      #endif1785    )cpp",1786      R"cpp(1787      // comments1788      // he^llo, world1789      int [[hello]];1790    )cpp",1791      R"cpp(1792      // not triggered by string literals1793      int hello;1794      const char* greeting = "h^ello, world";1795    )cpp",1796 1797      R"cpp(1798      // can refer to macro invocations1799      #define INT int1800      [[INT]] x;1801      // I^NT1802    )cpp",1803 1804      R"cpp(1805      // can refer to macro invocations (even if they expand to nothing)1806      #define EMPTY1807      [[EMPTY]] int x;1808      // E^MPTY1809    )cpp",1810 1811      R"cpp(1812      // prefer nearest occurrence, backwards is worse than forwards1813      int hello;1814      int x = hello;1815      // h^ello1816      int y = [[hello]];1817      int z = hello;1818    )cpp",1819 1820      R"cpp(1821      // short identifiers find near results1822      int [[hi]];1823      // h^i1824    )cpp",1825      R"cpp(1826      // short identifiers don't find far results1827      int hi;1828 1829 1830 1831      // h^i1832 1833 1834 1835 1836      int x = hi;1837    )cpp",1838      R"cpp(1839      // prefer nearest occurrence even if several matched tokens1840      // have the same value of `floor(log2(<token line> - <word line>))`.1841      int hello;1842      int x = hello, y = hello;1843      int z = [[hello]];1844      // h^ello1845    )cpp"};1846  for (const char *Test : Tests) {1847    Annotations T(Test);1848    auto AST = TestTU::withCode(T.code()).build();1849    const auto &SM = AST.getSourceManager();1850    std::optional<Range> Nearby;1851    auto Word =1852        SpelledWord::touching(cantFail(sourceLocationInMainFile(SM, T.point())),1853                              AST.getTokens(), AST.getLangOpts());1854    if (!Word) {1855      ADD_FAILURE() << "No word at point! " << Test;1856      continue;1857    }1858    if (const auto *Tok = findNearbyIdentifier(*Word, AST.getTokens()))1859      Nearby = halfOpenToRange(SM, CharSourceRange::getCharRange(1860                                       Tok->location(), Tok->endLocation()));1861    if (T.ranges().empty())1862      EXPECT_THAT(Nearby, Eq(std::nullopt)) << Test;1863    else1864      EXPECT_EQ(Nearby, T.range()) << Test;1865  }1866}1867 1868TEST(FindImplementations, Inheritance) {1869  llvm::StringRef Test = R"cpp(1870    struct $0^Base {1871      virtual void F$1^oo();1872      void C$4^oncrete();1873    };1874    struct $0[[Child1]] : Base {1875      void $1[[Fo$3^o]]() override;1876      virtual void B$2^ar();1877      void Concrete();  // No implementations for concrete methods.1878    };1879    struct Child2 : Child1 {1880      void $3[[Foo]]() override;1881      void $2[[Bar]]() override;1882    };1883    void FromReference() {1884      $0^Base* B;1885      B->Fo$1^o();1886      B->C$4^oncrete();1887      &Base::Fo$1^o;1888      Child1 * C1;1889      C1->B$2^ar();1890      C1->Fo$3^o();1891    }1892    // CRTP should work.1893    template<typename T>1894    struct $5^TemplateBase {};1895    struct $5[[Child3]] : public TemplateBase<Child3> {};1896 1897    // Local classes.1898    void LocationFunction() {1899      struct $0[[LocalClass1]] : Base {1900        void $1[[Foo]]() override;1901      };1902      struct $6^LocalBase {1903        virtual void $7^Bar();1904      };1905      struct $6[[LocalClass2]]: LocalBase {1906        void $7[[Bar]]() override;1907      };1908    }1909  )cpp";1910 1911  Annotations Code(Test);1912  auto TU = TestTU::withCode(Code.code());1913  auto AST = TU.build();1914  auto Index = TU.index();1915  for (StringRef Label : {"0", "1", "2", "3", "4", "5", "6", "7"}) {1916    for (const auto &Point : Code.points(Label)) {1917      EXPECT_THAT(findImplementations(AST, Point, Index.get()),1918                  UnorderedPointwise(declRange(), Code.ranges(Label)))1919          << Code.code() << " at " << Point << " for Label " << Label;1920    }1921  }1922}1923 1924TEST(FindImplementations, InheritanceObjC) {1925  llvm::StringRef Test = R"objc(1926    @interface $base^Base1927    - (void)fo$foo^o;1928    @end1929    @protocol Protocol1930    - (void)$protocol^protocol;1931    @end1932    @interface $ChildDecl[[Child]] : Base <Protocol>1933    - (void)concrete;1934    - (void)$fooDecl[[foo]];1935    @end1936    @implementation $ChildDef[[Child]]1937    - (void)concrete {}1938    - (void)$fooDef[[foo]] {}1939    - (void)$protocolDef[[protocol]] {}1940    @end1941  )objc";1942 1943  Annotations Code(Test);1944  auto TU = TestTU::withCode(Code.code());1945  TU.ExtraArgs.push_back("-xobjective-c++");1946  auto AST = TU.build();1947  auto Index = TU.index();1948  EXPECT_THAT(findImplementations(AST, Code.point("base"), Index.get()),1949              UnorderedElementsAre(sym("Child", Code.range("ChildDecl"),1950                                       Code.range("ChildDef"))));1951  EXPECT_THAT(findImplementations(AST, Code.point("foo"), Index.get()),1952              UnorderedElementsAre(1953                  sym("foo", Code.range("fooDecl"), Code.range("fooDef"))));1954  EXPECT_THAT(findImplementations(AST, Code.point("protocol"), Index.get()),1955              UnorderedElementsAre(sym("protocol", Code.range("protocolDef"),1956                                       Code.range("protocolDef"))));1957}1958 1959TEST(FindImplementations, CaptureDefinition) {1960  llvm::StringRef Test = R"cpp(1961    struct Base {1962      virtual void F^oo();1963    };1964    struct Child1 : Base {1965      void $Decl[[Foo]]() override;1966    };1967    struct Child2 : Base {1968      void $Child2[[Foo]]() override;1969    };1970    void Child1::$Def[[Foo]]() { /* Definition */ }1971  )cpp";1972  Annotations Code(Test);1973  auto TU = TestTU::withCode(Code.code());1974  auto AST = TU.build();1975  EXPECT_THAT(1976      findImplementations(AST, Code.point(), TU.index().get()),1977      UnorderedElementsAre(sym("Foo", Code.range("Decl"), Code.range("Def")),1978                           sym("Foo", Code.range("Child2"), std::nullopt)))1979      << Test;1980}1981 1982TEST(FindType, All) {1983  Annotations HeaderA(R"cpp(1984    struct $Target[[Target]] { operator int() const; };1985    struct Aggregate { Target a, b; };1986    Target t;1987    Target make();1988 1989    template <typename T> struct $smart_ptr[[smart_ptr]] {1990      T& operator*();1991      T* operator->();1992      T* get();1993    };1994  )cpp");1995  auto TU = TestTU::withHeaderCode(HeaderA.code());1996  for (const llvm::StringRef Case : {1997           "str^uct Target;",1998           "T^arget x;",1999           "Target ^x;",2000           "a^uto x = Target{};",2001           "namespace m { Target tgt; } auto x = m^::tgt;",2002           "Target funcCall(); auto x = ^funcCall();",2003           "Aggregate a = { {}, ^{} };",2004           "Aggregate a = { ^.a=t, };",2005           "struct X { Target a; X() : ^a() {} };",2006           "^using T = Target; ^T foo();",2007           "^template <int> Target foo();",2008           "void x() { try {} ^catch(Target e) {} }",2009           "void x() { ^throw t; }",2010           "int x() { ^return t; }",2011           "void x() { ^switch(t) {} }",2012           "void x() { ^delete (Target*)nullptr; }",2013           "Target& ^tref = t;",2014           "void x() { ^if (t) {} }",2015           "void x() { ^while (t) {} }",2016           "void x() { ^do { } while (t); }",2017           "void x() { ^make(); }",2018           "void x(smart_ptr<Target> &t) { t.^get(); }",2019           "^auto x = []() { return t; };",2020           "Target* ^tptr = &t;",2021           "Target ^tarray[3];",2022       }) {2023    Annotations A(Case);2024    TU.Code = A.code().str();2025    ParsedAST AST = TU.build();2026 2027    ASSERT_GT(A.points().size(), 0u) << Case;2028    for (auto Pos : A.points())2029      EXPECT_THAT(findType(AST, Pos, nullptr),2030                  ElementsAre(2031                    sym("Target", HeaderA.range("Target"), HeaderA.range("Target"))))2032          << Case;2033  }2034 2035  for (const llvm::StringRef Case : {2036           "smart_ptr<Target> ^tsmart;",2037       }) {2038    Annotations A(Case);2039    TU.Code = A.code().str();2040    ParsedAST AST = TU.build();2041 2042    EXPECT_THAT(findType(AST, A.point(), nullptr),2043                UnorderedElementsAre(2044                  sym("Target", HeaderA.range("Target"), HeaderA.range("Target")),2045                  sym("smart_ptr", HeaderA.range("smart_ptr"), HeaderA.range("smart_ptr"))2046                ))2047        << Case;2048  }2049}2050 2051TEST(FindType, Definition) {2052  Annotations A(R"cpp(2053    class $decl[[X]];2054    X *^x;2055    class $def[[X]] {};2056  )cpp");2057  auto TU = TestTU::withCode(A.code().str());2058  ParsedAST AST = TU.build();2059 2060  EXPECT_THAT(findType(AST, A.point(), nullptr),2061              ElementsAre(sym("X", A.range("decl"), A.range("def"))));2062}2063 2064TEST(FindType, Index) {2065  Annotations Def(R"cpp(2066    // This definition is only available through the index.2067    class [[X]] {};2068  )cpp");2069  TestTU DefTU = TestTU::withHeaderCode(Def.code());2070  DefTU.HeaderFilename = "def.h";2071  auto DefIdx = DefTU.index();2072 2073  Annotations A(R"cpp(2074    class [[X]];2075    X *^x;2076  )cpp");2077  auto TU = TestTU::withCode(A.code().str());2078  ParsedAST AST = TU.build();2079 2080  EXPECT_THAT(findType(AST, A.point(), DefIdx.get()),2081              ElementsAre(sym("X", A.range(), Def.range())));2082}2083 2084void checkFindRefs(llvm::StringRef Test, bool UseIndex = false) {2085  Annotations T(Test);2086  auto TU = TestTU::withCode(T.code());2087  TU.ExtraArgs.push_back("-std=c++20");2088  TU.ExtraArgs.push_back("-xobjective-c++");2089 2090  auto AST = TU.build();2091  std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;2092  for (const auto &[R, Context] : T.rangesWithPayload())2093    ExpectedLocations.push_back(2094        AllOf(rangeIs(R), containerIs(Context), attrsAre(0u)));2095  // $def is actually shorthand for both definition and declaration.2096  // If we have cases that are definition-only, we should change this.2097  for (const auto &[R, Context] : T.rangesWithPayload("def"))2098    ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),2099                                      attrsAre(ReferencesResult::Definition |2100                                               ReferencesResult::Declaration)));2101  for (const auto &[R, Context] : T.rangesWithPayload("decl"))2102    ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),2103                                      attrsAre(ReferencesResult::Declaration)));2104  for (const auto &[R, Context] : T.rangesWithPayload("overridedecl"))2105    ExpectedLocations.push_back(AllOf(2106        rangeIs(R), containerIs(Context),2107        attrsAre(ReferencesResult::Declaration | ReferencesResult::Override)));2108  for (const auto &[R, Context] : T.rangesWithPayload("overridedef"))2109    ExpectedLocations.push_back(AllOf(rangeIs(R), containerIs(Context),2110                                      attrsAre(ReferencesResult::Declaration |2111                                               ReferencesResult::Definition |2112                                               ReferencesResult::Override)));2113  for (const auto &P : T.points()) {2114    EXPECT_THAT(findReferences(AST, P, 0, UseIndex ? TU.index().get() : nullptr,2115                               /*AddContext*/ true)2116                    .References,2117                UnorderedElementsAreArray(ExpectedLocations))2118        << "Failed for Refs at " << P << "\n"2119        << Test;2120  }2121}2122 2123TEST(FindReferences, WithinAST) {2124  const char *Tests[] = {2125      R"cpp(// Local variable2126        int main() {2127          int $def(main)[[foo]];2128          $(main)[[^foo]] = 2;2129          int test1 = $(main)[[foo]];2130        }2131      )cpp",2132 2133      R"cpp(// Struct2134        namespace ns1 {2135        struct $def(ns1)[[Foo]] {};2136        } // namespace ns12137        int main() {2138          ns1::$(main)[[Fo^o]]* Params;2139        }2140      )cpp",2141 2142      R"cpp(// Forward declaration2143        class $decl[[Foo]];2144        class $def[[Foo]] {};2145        int main() {2146          $(main)[[Fo^o]] foo;2147        }2148      )cpp",2149 2150      R"cpp(// Function2151        int $def[[foo]](int) { return 0; }2152        int main() {2153          auto *X = &$(main)[[^foo]];2154          $(main)[[foo]](42);2155        }2156      )cpp",2157 2158      R"cpp(// Field2159        struct Foo {2160          int $def(Foo)[[foo]];2161          Foo() : $(Foo::Foo)[[foo]](0) {}2162        };2163        int main() {2164          Foo f;2165          f.$(main)[[f^oo]] = 1;2166        }2167      )cpp",2168 2169      R"cpp(// Method call2170        struct Foo { int $decl(Foo)[[foo]](); };2171        int Foo::$def(Foo)[[foo]]() { return 0; }2172        int main() {2173          Foo f;2174          f.$(main)[[^foo]]();2175        }2176      )cpp",2177 2178      R"cpp(// Constructor2179        struct Foo {2180          $decl(Foo)[[F^oo]](int);2181        };2182        void foo() {2183          Foo f = $(foo)[[Foo]](42);2184        }2185      )cpp",2186 2187      R"cpp(// Typedef2188        typedef int $def[[Foo]];2189        int main() {2190          $(main)[[^Foo]] bar;2191        }2192      )cpp",2193 2194      R"cpp(// Namespace2195        namespace $decl[[ns]] { // FIXME: def?2196        struct Foo {};2197        } // namespace ns2198        int main() { $(main)[[^ns]]::Foo foo; }2199      )cpp",2200 2201      R"cpp(// Macros2202        #define TYPE(X) X2203        #define FOO Foo2204        #define CAT(X, Y) X##Y2205        class $def[[Fo^o]] {};2206        void test() {2207          TYPE($(test)[[Foo]]) foo;2208          $(test)[[FOO]] foo2;2209          TYPE(TYPE($(test)[[Foo]])) foo3;2210          $(test)[[CAT]](Fo, o) foo4;2211        }2212      )cpp",2213 2214      R"cpp(// Macros2215        #define $def[[MA^CRO]](X) (X+1)2216        void test() {2217          int x = $[[MACRO]]($[[MACRO]](1));2218        }2219      )cpp",2220 2221      R"cpp(// Macro outside preamble2222        int breakPreamble;2223        #define $def[[MA^CRO]](X) (X+1)2224        void test() {2225          int x = $[[MACRO]]($[[MACRO]](1));2226        }2227      )cpp",2228 2229      R"cpp(2230        int $def[[v^ar]] = 0;2231        void foo(int s = $(foo)[[var]]);2232      )cpp",2233 2234      R"cpp(2235       template <typename T>2236       class $def[[Fo^o]] {};2237       void func($(func)[[Foo]]<int>);2238      )cpp",2239 2240      R"cpp(2241       template <typename T>2242       class $def[[Foo]] {};2243       void func($(func)[[Fo^o]]<int>);2244      )cpp",2245      R"cpp(// Not touching any identifiers.2246        struct Foo {2247          $def(Foo)[[~]]Foo() {};2248        };2249        void foo() {2250          Foo f;2251          f.$(foo)[[^~]]Foo();2252        }2253      )cpp",2254      R"cpp(// Lambda capture initializer2255        void foo() {2256          int $def(foo)[[w^aldo]] = 42;2257          auto lambda = [x = $(foo)[[waldo]]](){};2258        }2259      )cpp",2260      R"cpp(// Renaming alias2261        template <typename> class Vector {};2262        using $def[[^X]] = Vector<int>;2263        $(x1)[[X]] x1;2264        Vector<int> x2;2265        Vector<double> y;2266      )cpp",2267      R"cpp(// Dependent code2268        template <typename T> void $decl[[foo]](T t);2269        template <typename T> void bar(T t) { $(bar)[[foo]](t); } // foo in bar is uninstantiated.2270        void baz(int x) { $(baz)[[f^oo]](x); }2271      )cpp",2272      R"cpp(2273        namespace ns {2274        struct S{};2275        void $decl(ns)[[foo]](S s);2276        } // namespace ns2277        template <typename T> void foo(T t);2278        // FIXME: Maybe report this foo as a ref to ns::foo (because of ADL)2279        // when bar<ns::S> is instantiated?2280        template <typename T> void bar(T t) { foo(t); }2281        void baz(int x) {2282          ns::S s;2283          bar<ns::S>(s);2284          $(baz)[[f^oo]](s);2285        }2286      )cpp",2287      R"cpp(// unresolved member expression2288        struct Foo {2289          template <typename T> void $decl(Foo)[[b^ar]](T t);2290        };2291        template <typename T> void test(Foo F, T t) {2292          F.$(test)[[bar]](t);2293        }2294      )cpp",2295 2296      // Enum base2297      R"cpp(2298        typedef int $def[[MyTypeD^ef]];2299        enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };2300      )cpp",2301      R"cpp(2302        typedef int $def[[MyType^Def]];2303        enum MyEnum : $(MyEnum)[[MyTypeD^ef]];2304      )cpp",2305      R"cpp(2306        using $def[[MyTypeD^ef]] = int;2307        enum MyEnum : $(MyEnum)[[MyTy^peDef]] { };2308      )cpp",2309      // UDL2310      R"cpp(2311        bool $decl[[operator]]"" _u^dl(unsigned long long value);2312        bool x = $(x)[[1_udl]];2313      )cpp",2314      R"cpp(2315        struct S {2316        public:2317          static void $decl(S)[[operator]] delete(void *);2318          static void deleteObject(S *S) {2319            $(S::deleteObject)[[de^lete]] S;2320          }2321        };2322      )cpp",2323      // Array designators2324      R"cpp(2325        const int $def[[F^oo]] = 0;2326        int Bar[] = {2327          [$(Bar)[[F^oo]]...$(Bar)[[Fo^o]] + 1] = 0,2328          [$(Bar)[[^Foo]] + 2] = 12329        };2330      )cpp"};2331  for (const char *Test : Tests)2332    checkFindRefs(Test);2333}2334 2335TEST(FindReferences, ConceptsWithinAST) {2336  constexpr llvm::StringLiteral Code = R"cpp(2337    template <class T>2338    concept $def[[IsSmal^l]] = sizeof(T) <= 8;2339 2340    template <class T>2341    concept IsSmallPtr = requires(T x) {2342      { *x } -> $(IsSmallPtr)[[IsSmal^l]];2343    };2344 2345    $(i)[[IsSmall]] auto i = 'c';2346    template<$(foo)[[IsSmal^l]] U> void foo();2347    template<class U> void bar() requires $(bar)[[IsSmal^l]]<U>;2348    template<class U> requires $(baz)[[IsSmal^l]]<U> void baz();2349    static_assert([[IsSma^ll]]<char>);2350  )cpp";2351  checkFindRefs(Code);2352}2353 2354TEST(FindReferences, ConceptReq) {2355  constexpr llvm::StringLiteral Code = R"cpp(2356    template <class T>2357    concept $def[[IsSmal^l]] = sizeof(T) <= 8;2358 2359    template <class T>2360    concept IsSmallPtr = requires(T x) {2361      { *x } -> $(IsSmallPtr)[[IsSmal^l]];2362    };2363  )cpp";2364  checkFindRefs(Code);2365}2366 2367TEST(FindReferences, RequiresExprParameters) {2368  constexpr llvm::StringLiteral Code = R"cpp(2369    template <class T>2370    concept IsSmall = sizeof(T) <= 8;2371 2372    template <class T>2373    concept IsSmallPtr = requires(T $def[[^x]]) {2374      { *$(IsSmallPtr)[[^x]] } -> IsSmall;2375    };2376  )cpp";2377  checkFindRefs(Code);2378}2379 2380TEST(FindReferences, IncludeOverrides) {2381  llvm::StringRef Test =2382      R"cpp(2383        class Base {2384        public:2385          virtu^al void $decl(Base)[[f^unc]]() ^= ^0;2386        };2387        class Derived : public Base {2388        public:2389          void $overridedecl(Derived::func)[[func]]() override;2390        };2391        void Derived::$overridedef[[func]]() {}2392        class Derived2 : public Base {2393          void $overridedef(Derived2::func)[[func]]() override {}2394        };2395        void test(Derived* D, Base* B) {2396          D->func();  // No references to the overrides.2397          B->$(test)[[func]]();2398        })cpp";2399  checkFindRefs(Test, /*UseIndex=*/true);2400}2401 2402TEST(FindReferences, IncludeOverridesObjC) {2403  llvm::StringRef Test =2404      R"objc(2405        @interface Base2406        - (void)$decl(Base)[[f^unc]];2407        @end2408        @interface Derived : Base2409        - (void)$overridedecl(Derived::func)[[func]];2410        @end2411        @implementation Derived2412        - (void)$overridedef[[func]] {}2413        @end2414        void test(Derived *derived, Base *base) {2415          [derived func];  // No references to the overrides.2416          [base $(test)[[func]]];2417        })objc";2418  checkFindRefs(Test, /*UseIndex=*/true);2419}2420 2421TEST(FindReferences, RefsToBaseMethod) {2422  llvm::StringRef Test =2423      R"cpp(2424        class BaseBase {2425        public:2426          virtual void $(BaseBase)[[func]]();2427        };2428        class Base : public BaseBase {2429        public:2430          void $(Base)[[func]]() override;2431        };2432        class Derived : public Base {2433        public:2434          void $decl(Derived)[[fu^nc]]() over^ride;2435        };2436        void test(BaseBase* BB, Base* B, Derived* D) {2437          // refs to overridden methods in complete type hierarchy are reported.2438          BB->$(test)[[func]]();2439          B->$(test)[[func]]();2440          D->$(test)[[fu^nc]]();2441        })cpp";2442  checkFindRefs(Test, /*UseIndex=*/true);2443}2444 2445TEST(FindReferences, RefsToBaseMethodObjC) {2446  llvm::StringRef Test =2447      R"objc(2448        @interface BaseBase2449        - (void)$(BaseBase)[[func]];2450        @end2451        @interface Base : BaseBase2452        - (void)$(Base)[[func]];2453        @end2454        @interface Derived : Base2455        - (void)$decl(Derived)[[fu^nc]];2456        @end2457        void test(BaseBase *bb, Base *b, Derived *d) {2458          // refs to overridden methods in complete type hierarchy are reported.2459          [bb $(test)[[func]]];2460          [b $(test)[[func]]];2461          [d $(test)[[fu^nc]]];2462        })objc";2463  checkFindRefs(Test, /*UseIndex=*/true);2464}2465 2466TEST(FindReferences, MainFileReferencesOnly) {2467  llvm::StringRef Test =2468      R"cpp(2469        void test() {2470          int [[fo^o]] = 1;2471          // refs not from main file should not be included.2472          #include "foo.inc"2473        })cpp";2474 2475  Annotations Code(Test);2476  auto TU = TestTU::withCode(Code.code());2477  TU.AdditionalFiles["foo.inc"] = R"cpp(2478      foo = 3;2479    )cpp";2480  auto AST = TU.build();2481 2482  std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;2483  for (const auto &R : Code.ranges())2484    ExpectedLocations.push_back(rangeIs(R));2485  EXPECT_THAT(findReferences(AST, Code.point(), 0).References,2486              ElementsAreArray(ExpectedLocations))2487      << Test;2488}2489 2490TEST(FindReferences, ExplicitSymbols) {2491  const char *Tests[] = {2492      R"cpp(2493      struct Foo { Foo* $decl(Foo)[[self]]() const; };2494      void f() {2495        Foo foo;2496        if (Foo* T = foo.$(f)[[^self]]()) {} // Foo member call expr.2497      }2498      )cpp",2499 2500      R"cpp(2501      struct Foo { Foo(int); };2502      Foo f() {2503        int $def(f)[[b]];2504        return $(f)[[^b]]; // Foo constructor expr.2505      }2506      )cpp",2507 2508      R"cpp(2509      struct Foo {};2510      void g(Foo);2511      Foo $decl[[f]]();2512      void call() {2513        g($(call)[[^f]]());  // Foo constructor expr.2514      }2515      )cpp",2516 2517      R"cpp(2518      void $decl[[foo]](int);2519      void $decl[[foo]](double);2520 2521      namespace ns {2522      using ::$decl(ns)[[fo^o]];2523      }2524      )cpp",2525 2526      R"cpp(2527      struct X {2528        operator bool();2529      };2530 2531      int test() {2532        X $def(test)[[a]];2533        $(test)[[a]].operator bool();2534        if ($(test)[[a^]]) {} // ignore implicit conversion-operator AST node2535        return 0;2536      }2537    )cpp",2538  };2539  for (const char *Test : Tests)2540    checkFindRefs(Test);2541}2542 2543TEST(FindReferences, UsedSymbolsFromInclude) {2544  const char *Tests[] = {2545      R"cpp(   [[#include   ^"bar.h"]]2546        #include <vector>2547        int fstBar = [[bar1]]();2548        int sndBar = [[bar2]]();2549        [[Bar]] bar;2550        int macroBar = [[BAR]];2551        std::vector<int> vec;2552      )cpp",2553 2554      R"cpp([[#in^clude <vector>]]2555        std::[[vector]]<int> vec;2556      )cpp",2557 2558      R"cpp(2559        [[#include ^"udl_header.h"]]2560        auto x = [[1_b]];2561      )cpp",2562  };2563  for (const char *Test : Tests) {2564    Annotations T(Test);2565    auto TU = TestTU::withCode(T.code());2566    TU.ExtraArgs.push_back("-std=c++20");2567    TU.AdditionalFiles["bar.h"] = guard(R"cpp(2568      #define BAR 52569      int bar1();2570      int bar2();2571      class Bar {};2572    )cpp");2573    TU.AdditionalFiles["system/vector"] = guard(R"cpp(2574      namespace std {2575        template<typename>2576        class vector{};2577      }2578    )cpp");2579    TU.AdditionalFiles["udl_header.h"] = guard(R"cpp(2580      bool operator"" _b(unsigned long long value);2581    )cpp");2582    TU.ExtraArgs.push_back("-isystem" + testPath("system"));2583 2584    auto AST = TU.build();2585    std::vector<Matcher<ReferencesResult::Reference>> ExpectedLocations;2586    for (const auto &R : T.ranges())2587      ExpectedLocations.push_back(AllOf(rangeIs(R), attrsAre(0u)));2588    for (const auto &P : T.points())2589      EXPECT_THAT(findReferences(AST, P, 0).References,2590                  UnorderedElementsAreArray(ExpectedLocations))2591          << "Failed for Refs at " << P << "\n"2592          << Test;2593  }2594}2595 2596TEST(FindReferences, NeedsIndexForSymbols) {2597  const char *Header = "int foo();";2598  Annotations Main("int main() { [[f^oo]](); }");2599  TestTU TU;2600  TU.Code = std::string(Main.code());2601  TU.HeaderCode = Header;2602  auto AST = TU.build();2603 2604  // References in main file are returned without index.2605  EXPECT_THAT(2606      findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,2607      ElementsAre(rangeIs(Main.range())));2608  Annotations IndexedMain(R"cpp(2609    int $decl[[foo]]() { return 42; }2610    void bar() { $bar(bar)[[foo]](); }2611    struct S { void bar() { $S(S::bar)[[foo]](); } };2612    namespace N { void bar() { $N(N::bar)[[foo]](); } }2613  )cpp");2614 2615  // References from indexed files are included.2616  TestTU IndexedTU;2617  IndexedTU.Code = std::string(IndexedMain.code());2618  IndexedTU.Filename = "Indexed.cpp";2619  IndexedTU.HeaderCode = Header;2620  EXPECT_THAT(2621      findReferences(AST, Main.point(), 0, IndexedTU.index().get(),2622                     /*AddContext*/ true)2623          .References,2624      ElementsAre(2625          rangeIs(Main.range()),2626          AllOf(rangeIs(IndexedMain.range("decl")),2627                attrsAre(ReferencesResult::Declaration |2628                         ReferencesResult::Definition)),2629          AllOf(rangeIs(IndexedMain.range("bar")), containerIs("bar")),2630          AllOf(rangeIs(IndexedMain.range("S")), containerIs("S::bar")),2631          AllOf(rangeIs(IndexedMain.range("N")), containerIs("N::bar"))));2632  auto LimitRefs =2633      findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());2634  EXPECT_EQ(1u, LimitRefs.References.size());2635  EXPECT_TRUE(LimitRefs.HasMore);2636 2637  // Avoid indexed results for the main file. Use AST for the mainfile.2638  TU.Code = ("\n\n" + Main.code()).str();2639  EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References,2640              ElementsAre(rangeIs(Main.range())));2641}2642 2643TEST(FindReferences, NeedsIndexForMacro) {2644  const char *Header = "#define MACRO(X) (X+1)";2645  Annotations Main(R"cpp(2646    int main() {2647      int a = [[MA^CRO]](1);2648    }2649  )cpp");2650  TestTU TU;2651  TU.Code = std::string(Main.code());2652  TU.HeaderCode = Header;2653  auto AST = TU.build();2654 2655  // References in main file are returned without index.2656  EXPECT_THAT(2657      findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,2658      ElementsAre(rangeIs(Main.range())));2659 2660  Annotations IndexedMain(R"cpp(2661    int indexed_main() {2662      int a = [[MACRO]](1);2663      return 0;2664    }2665  )cpp");2666 2667  // References from indexed files are included.2668  TestTU IndexedTU;2669  IndexedTU.Code = std::string(IndexedMain.code());2670  IndexedTU.Filename = "Indexed.cpp";2671  IndexedTU.HeaderCode = Header;2672  EXPECT_THAT(2673      findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,2674      ElementsAre(rangeIs(Main.range()), rangeIs(IndexedMain.range())));2675  auto LimitRefs =2676      findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());2677  EXPECT_EQ(1u, LimitRefs.References.size());2678  EXPECT_TRUE(LimitRefs.HasMore);2679}2680 2681TEST(FindReferences, NoQueryForLocalSymbols) {2682  struct RecordingIndex : public MemIndex {2683    mutable std::optional<llvm::DenseSet<SymbolID>> RefIDs;2684    bool refs(const RefsRequest &Req,2685              llvm::function_ref<void(const Ref &)>) const override {2686      RefIDs = Req.IDs;2687      return false;2688    }2689  };2690 2691  struct Test {2692    StringRef AnnotatedCode;2693    bool WantQuery;2694  } Tests[] = {2695      {"int ^x;", true},2696      // For now we don't assume header structure which would allow skipping.2697      {"namespace { int ^x; }", true},2698      {"static int ^x;", true},2699      // Anything in a function certainly can't be referenced though.2700      {"void foo() { int ^x; }", false},2701      {"void foo() { struct ^x{}; }", false},2702      {"auto lambda = []{ int ^x; };", false},2703  };2704  for (Test T : Tests) {2705    Annotations File(T.AnnotatedCode);2706    RecordingIndex Rec;2707    auto AST = TestTU::withCode(File.code()).build();2708    findReferences(AST, File.point(), 0, &Rec);2709    if (T.WantQuery)2710      EXPECT_NE(Rec.RefIDs, std::nullopt) << T.AnnotatedCode;2711    else2712      EXPECT_EQ(Rec.RefIDs, std::nullopt) << T.AnnotatedCode;2713  }2714}2715 2716TEST(GetNonLocalDeclRefs, All) {2717  struct Case {2718    llvm::StringRef AnnotatedCode;2719    std::vector<std::string> ExpectedDecls;2720  } Cases[] = {2721      {2722          // VarDecl and ParamVarDecl2723          R"cpp(2724            void bar();2725            void ^foo(int baz) {2726              int x = 10;2727              bar();2728            })cpp",2729          {"bar"},2730      },2731      {2732          // Method from class2733          R"cpp(2734            class Foo { public: void foo(); };2735            class Bar {2736              void foo();2737              void bar();2738            };2739            void Bar::^foo() {2740              Foo f;2741              bar();2742              f.foo();2743            })cpp",2744          {"Bar", "Bar::bar", "Foo", "Foo::foo"},2745      },2746      {2747          // Local types2748          R"cpp(2749            void ^foo() {2750              class Foo { public: void foo() {} };2751              class Bar { public: void bar() {} };2752              Foo f;2753              Bar b;2754              b.bar();2755              f.foo();2756            })cpp",2757          {},2758      },2759      {2760          // Template params2761          R"cpp(2762            template <typename T, template<typename> class Q>2763            void ^foo() {2764              T x;2765              Q<T> y;2766            })cpp",2767          {},2768      },2769  };2770  for (const Case &C : Cases) {2771    Annotations File(C.AnnotatedCode);2772    auto AST = TestTU::withCode(File.code()).build();2773    SourceLocation SL = llvm::cantFail(2774        sourceLocationInMainFile(AST.getSourceManager(), File.point()));2775 2776    const FunctionDecl *FD =2777        llvm::dyn_cast<FunctionDecl>(&findDecl(AST, [SL](const NamedDecl &ND) {2778          return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);2779        }));2780    ASSERT_NE(FD, nullptr);2781 2782    auto NonLocalDeclRefs = getNonLocalDeclRefs(AST, FD);2783    std::vector<std::string> Names;2784    for (const Decl *D : NonLocalDeclRefs) {2785      if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))2786        Names.push_back(ND->getQualifiedNameAsString());2787    }2788    EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))2789        << File.code();2790  }2791}2792 2793TEST(DocumentLinks, All) {2794  Annotations MainCpp(R"cpp(2795      #define HEADER_AA "faa.h"2796      #define HEADER_BB "fbb.h"2797      #define GET_HEADER(X) HEADER_ ## X 2798 2799      #/*comments*/include /*comments*/ $foo[["foo.h"]] //more comments2800      int end_of_preamble = 0;2801      #include $bar[[<bar.h>]]2802      #include $AA[[GET_HEADER]](AA) // Some comment !2803      # /* What about */ \2804      include /* multiple line */ \2805      $BB[[GET_HEADER]]( /* statements ? */ \2806      BB /* :) */ )2807    )cpp");2808 2809  TestTU TU;2810  TU.Code = std::string(MainCpp.code());2811  TU.AdditionalFiles = {2812      {"faa.h", ""}, {"fbb.h", ""}, {"foo.h", ""}, {"bar.h", ""}};2813  TU.ExtraArgs = {"-isystem."};2814  auto AST = TU.build();2815 2816  EXPECT_THAT(2817      clangd::getDocumentLinks(AST),2818      ElementsAre(2819          DocumentLink({MainCpp.range("foo"),2820                        URIForFile::canonicalize(testPath("foo.h"), "")}),2821          DocumentLink({MainCpp.range("bar"),2822                        URIForFile::canonicalize(testPath("bar.h"), "")}),2823          DocumentLink({MainCpp.range("AA"),2824                        URIForFile::canonicalize(testPath("faa.h"), "")}),2825          DocumentLink({MainCpp.range("BB"),2826                        URIForFile::canonicalize(testPath("fbb.h"), "")})));2827}2828 2829} // namespace2830} // namespace clangd2831} // namespace clang2832