brintos

brintos / llvm-project-archived public Read only

0
0
Text · 142.4 KiB · eb858ff Raw
5021 lines · cpp
1//===-- HoverTests.cpp ----------------------------------------------------===//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 9#include "AST.h"10#include "Annotations.h"11#include "Config.h"12#include "Hover.h"13#include "Protocol.h"14#include "TestFS.h"15#include "TestIndex.h"16#include "TestTU.h"17#include "index/MemIndex.h"18#include "clang/AST/Attr.h"19#include "clang/Format/Format.h"20#include "clang/Index/IndexSymbol.h"21#include "llvm/ADT/StringRef.h"22#include "llvm/ADT/Twine.h"23 24#include "gtest/gtest.h"25#include <functional>26#include <optional>27#include <string>28#include <vector>29 30namespace clang {31namespace clangd {32namespace {33 34using PassMode = HoverInfo::PassType::PassMode;35 36std::string guard(llvm::StringRef Code) {37  return "#pragma once\n" + Code.str();38}39 40TEST(Hover, Structured) {41  struct {42    const char *const Code;43    const std::function<void(HoverInfo &)> ExpectedBuilder;44  } Cases[] = {45      // Global scope.46      {R"cpp(47          // Best foo ever.48          void [[fo^o]]() {}49          )cpp",50       [](HoverInfo &HI) {51         HI.NamespaceScope = "";52         HI.Name = "foo";53         HI.Kind = index::SymbolKind::Function;54         HI.Documentation = "Best foo ever.";55         HI.Definition = "void foo()";56         HI.ReturnType = "void";57         HI.Type = "void ()";58         HI.Parameters.emplace();59       }},60      // Inside namespace61      {R"cpp(62          namespace ns1 { namespace ns2 {63            /// Best foo ever.64            void [[fo^o]]() {}65          }}66          )cpp",67       [](HoverInfo &HI) {68         HI.NamespaceScope = "ns1::ns2::";69         HI.Name = "foo";70         HI.Kind = index::SymbolKind::Function;71         HI.Documentation = "Best foo ever.";72         HI.Definition = "void foo()";73         HI.ReturnType = "void";74         HI.Type = "void ()";75         HI.Parameters.emplace();76       }},77      // Field78      {R"cpp(79          namespace ns1 { namespace ns2 {80            class Foo {81              char [[b^ar]];82              double y[2];83            };84          }}85          )cpp",86       [](HoverInfo &HI) {87         HI.NamespaceScope = "ns1::ns2::";88         HI.LocalScope = "Foo::";89         HI.Name = "bar";90         HI.Kind = index::SymbolKind::Field;91         HI.Definition = "char bar";92         HI.Type = "char";93         HI.Offset = 0;94         HI.Size = 8;95         HI.Padding = 56;96         HI.Align = 8;97         HI.AccessSpecifier = "private";98       }},99      // Union field100      {R"cpp(101            union Foo {102              char [[b^ar]];103              double y[2];104            };105          )cpp",106       [](HoverInfo &HI) {107         HI.NamespaceScope = "";108         HI.LocalScope = "Foo::";109         HI.Name = "bar";110         HI.Kind = index::SymbolKind::Field;111         HI.Definition = "char bar";112         HI.Type = "char";113         HI.Size = 8;114         HI.Padding = 120;115         HI.Align = 8;116         HI.AccessSpecifier = "public";117       }},118      // Bitfield119      {R"cpp(120            struct Foo {121              int [[^x]] : 1;122              int y : 1;123            };124          )cpp",125       [](HoverInfo &HI) {126         HI.NamespaceScope = "";127         HI.LocalScope = "Foo::";128         HI.Name = "x";129         HI.Kind = index::SymbolKind::Field;130         HI.Definition = "int x : 1";131         HI.Type = "int";132         HI.Offset = 0;133         HI.Size = 1;134         HI.Align = 32;135         HI.AccessSpecifier = "public";136       }},137      // Local to class method.138      {R"cpp(139          namespace ns1 { namespace ns2 {140            struct Foo {141              void foo() {142                int [[b^ar]];143              }144            };145          }}146          )cpp",147       [](HoverInfo &HI) {148         HI.NamespaceScope = "ns1::ns2::";149         HI.LocalScope = "Foo::foo::";150         HI.Name = "bar";151         HI.Kind = index::SymbolKind::Variable;152         HI.Definition = "int bar";153         HI.Type = "int";154       }},155      // Predefined variable156      {R"cpp(157          void foo() {158            [[__f^unc__]];159          }160          )cpp",161       [](HoverInfo &HI) {162         HI.Name = "__func__";163         HI.Kind = index::SymbolKind::Variable;164         HI.Documentation =165             "Name of the current function (predefined variable)";166         HI.Value = "\"foo\"";167         HI.Type = "const char[4]";168       }},169      // Predefined variable (dependent)170      {R"cpp(171          template<int> void foo() {172            [[__f^unc__]];173          }174          )cpp",175       [](HoverInfo &HI) {176         HI.Name = "__func__";177         HI.Kind = index::SymbolKind::Variable;178         HI.Documentation =179             "Name of the current function (predefined variable)";180         HI.Type = "const char[]";181       }},182      // Anon namespace and local scope.183      {R"cpp(184          namespace ns1 { namespace {185            struct {186              char [[b^ar]];187            } T;188          }}189          )cpp",190       [](HoverInfo &HI) {191         HI.NamespaceScope = "ns1::";192         HI.LocalScope = "(anonymous struct)::";193         HI.Name = "bar";194         HI.Kind = index::SymbolKind::Field;195         HI.Definition = "char bar";196         HI.Type = "char";197         HI.Offset = 0;198         HI.Size = 8;199         HI.Align = 8;200         HI.AccessSpecifier = "public";201       }},202      // Struct definition shows size.203      {R"cpp(204          struct [[^X]]{};205          )cpp",206       [](HoverInfo &HI) {207         HI.NamespaceScope = "";208         HI.Name = "X";209         HI.Kind = index::SymbolKind::Struct;210         HI.Definition = "struct X {}";211         HI.Size = 8;212         HI.Align = 8;213       }},214      // Variable with template type215      {R"cpp(216          template <typename T, class... Ts> class Foo { public: Foo(int); };217          Foo<int, char, bool> [[fo^o]] = Foo<int, char, bool>(5);218          )cpp",219       [](HoverInfo &HI) {220         HI.NamespaceScope = "";221         HI.Name = "foo";222         HI.Kind = index::SymbolKind::Variable;223         HI.Definition = "Foo<int, char, bool> foo = Foo<int, char, bool>(5)";224         HI.Type = "Foo<int, char, bool>";225       }},226      // Implicit template instantiation227      {R"cpp(228          template <typename T> class vector{};229          [[vec^tor]]<int> foo;230          )cpp",231       [](HoverInfo &HI) {232         HI.NamespaceScope = "";233         HI.Name = "vector<int>";234         HI.Kind = index::SymbolKind::Class;235         HI.Definition = "template <> class vector<int> {}";236       }},237      // Class template238      {R"cpp(239          template <template<typename, bool...> class C,240                    typename = char,241                    int = 0,242                    bool Q = false,243                    class... Ts> class Foo final {};244          template <template<typename, bool...> class T>245          [[F^oo]]<T> foo;246          )cpp",247       [](HoverInfo &HI) {248         HI.NamespaceScope = "";249         HI.Name = "Foo";250         HI.Kind = index::SymbolKind::Class;251         HI.Definition =252             R"cpp(template <template <typename, bool...> class C, typename = char, int = 0,253          bool Q = false, class... Ts>254class Foo final {})cpp";255         HI.TemplateParameters = {256             {{"template <typename, bool...> class"},257              std::string("C"),258              std::nullopt},259             {{"typename"}, std::nullopt, std::string("char")},260             {{"int"}, std::nullopt, std::string("0")},261             {{"bool"}, std::string("Q"), std::string("false")},262             {{"class..."}, std::string("Ts"), std::nullopt},263         };264       }},265      // Function template266      {R"cpp(267          template <template<typename, bool...> class C,268                    typename = char,269                    int = 0,270                    bool Q = false,271                    class... Ts> void foo();272          template<typename, bool...> class Foo;273 274          void bar() {275            [[fo^o]]<Foo>();276          }277          )cpp",278       [](HoverInfo &HI) {279         HI.NamespaceScope = "";280         HI.Name = "foo";281         HI.Kind = index::SymbolKind::Function;282         HI.Definition = "template <> void foo<Foo, char, 0, false, <>>()";283         HI.ReturnType = "void";284         HI.Type = "void ()";285         HI.Parameters.emplace();286       }},287      // Function decl288      {R"cpp(289          template<typename, bool...> class Foo {};290          Foo<bool, true, false> foo(int, bool T = false);291 292          void bar() {293            [[fo^o]](3);294          }295          )cpp",296       [](HoverInfo &HI) {297         HI.NamespaceScope = "";298         HI.Name = "foo";299         HI.Kind = index::SymbolKind::Function;300         HI.Definition = "Foo<bool, true, false> foo(int, bool T = false)";301         HI.ReturnType = "Foo<bool, true, false>";302         HI.Type = "Foo<bool, true, false> (int, bool)";303         HI.Parameters = {304             {{"int"}, std::nullopt, std::nullopt},305             {{"bool"}, std::string("T"), std::string("false")},306         };307       }},308      // Pointers to lambdas309      {R"cpp(310        void foo() {311          auto lamb = [](int T, bool B) -> bool { return T && B; };312          auto *b = &lamb;313          auto *[[^c]] = &b;314        }315        )cpp",316       [](HoverInfo &HI) {317         HI.NamespaceScope = "";318         HI.LocalScope = "foo::";319         HI.Name = "c";320         HI.Kind = index::SymbolKind::Variable;321         HI.Definition = "auto *c = &b";322         HI.Type = "(lambda) **";323         HI.ReturnType = "bool";324         HI.Parameters = {325             {{"int"}, std::string("T"), std::nullopt},326             {{"bool"}, std::string("B"), std::nullopt},327         };328         return HI;329       }},330      // Lambda parameter with decltype reference331      {R"cpp(332        auto lamb = [](int T, bool B) -> bool { return T && B; };333        void foo(decltype(lamb)& bar) {334          [[ba^r]](0, false);335        }336        )cpp",337       [](HoverInfo &HI) {338         HI.NamespaceScope = "";339         HI.LocalScope = "foo::";340         HI.Name = "bar";341         HI.Kind = index::SymbolKind::Parameter;342         HI.Definition = "decltype(lamb) &bar";343         HI.Type = {"decltype(lamb) &", "(lambda) &"};344         HI.ReturnType = "bool";345         HI.Parameters = {346             {{"int"}, std::string("T"), std::nullopt},347             {{"bool"}, std::string("B"), std::nullopt},348         };349         return HI;350       }},351      // Lambda parameter with decltype352      {R"cpp(353        auto lamb = [](int T, bool B) -> bool { return T && B; };354        void foo(decltype(lamb) bar) {355          [[ba^r]](0, false);356        }357        )cpp",358       [](HoverInfo &HI) {359         HI.NamespaceScope = "";360         HI.LocalScope = "foo::";361         HI.Name = "bar";362         HI.Kind = index::SymbolKind::Parameter;363         HI.Definition = "decltype(lamb) bar";364         HI.Type = "class (lambda)";365         HI.ReturnType = "bool";366         HI.Parameters = {367             {{"int"}, std::string("T"), std::nullopt},368             {{"bool"}, std::string("B"), std::nullopt},369         };370         HI.Value = "false";371         return HI;372       }},373      // Lambda variable374      {R"cpp(375        void foo() {376          int bar = 5;377          auto lamb = [&bar](int T, bool B) -> bool { return T && B && bar; };378          bool res = [[lam^b]](bar, false);379        }380        )cpp",381       [](HoverInfo &HI) {382         HI.NamespaceScope = "";383         HI.LocalScope = "foo::";384         HI.Name = "lamb";385         HI.Kind = index::SymbolKind::Variable;386         HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}";387         HI.Type = "class (lambda)";388         HI.ReturnType = "bool";389         HI.Parameters = {390             {{"int"}, std::string("T"), std::nullopt},391             {{"bool"}, std::string("B"), std::nullopt},392         };393         return HI;394       }},395      // Local variable in lambda396      {R"cpp(397        void foo() {398          auto lamb = []{int [[te^st]];};399        }400        )cpp",401       [](HoverInfo &HI) {402         HI.NamespaceScope = "";403         HI.LocalScope = "foo::(anonymous class)::operator()::";404         HI.Name = "test";405         HI.Kind = index::SymbolKind::Variable;406         HI.Definition = "int test";407         HI.Type = "int";408       }},409      // Partially-specialized class template. (formerly type-parameter-0-0)410      {R"cpp(411        template <typename T> class X;412        template <typename T> class [[^X]]<T*> {};413        )cpp",414       [](HoverInfo &HI) {415         HI.Name = "X<T *>";416         HI.NamespaceScope = "";417         HI.Kind = index::SymbolKind::Class;418         HI.Definition = "template <typename T> class X<T *> {}";419       }},420      // Constructor of partially-specialized class template421      {R"cpp(422          template<typename, typename=void> struct X;423          template<typename T> struct X<T*>{ [[^X]](); };424          )cpp",425       [](HoverInfo &HI) {426         HI.NamespaceScope = "";427         HI.Name = "X";428         HI.LocalScope = "X<T *>::"; // FIXME: X<T *, void>::429         HI.Kind = index::SymbolKind::Constructor;430         HI.Definition = "X()";431         HI.Parameters.emplace();432         HI.AccessSpecifier = "public";433       }},434      {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]()435       [](HoverInfo &HI) {436         HI.NamespaceScope = "";437         HI.Name = "~X";438         HI.LocalScope = "X::";439         HI.Kind = index::SymbolKind::Destructor;440         HI.Definition = "~X()";441         HI.Parameters.emplace();442         HI.AccessSpecifier = "private";443       }},444      {"class X { [[op^erator]] int(); };",445       [](HoverInfo &HI) {446         HI.NamespaceScope = "";447         HI.Name = "operator int";448         HI.LocalScope = "X::";449         HI.Kind = index::SymbolKind::ConversionFunction;450         HI.Definition = "operator int()";451         HI.Parameters.emplace();452         HI.AccessSpecifier = "private";453       }},454      {"class X { operator [[^X]](); };",455       [](HoverInfo &HI) {456         HI.NamespaceScope = "";457         HI.Name = "X";458         HI.Kind = index::SymbolKind::Class;459         HI.Definition = "class X {}";460       }},461 462      // auto on structured bindings463      {R"cpp(464        void foo() {465          struct S { int x; float y; };466          [[au^to]] [x, y] = S();467        }468        )cpp",469       [](HoverInfo &HI) {470         HI.Name = "auto";471         HI.Kind = index::SymbolKind::TypeAlias;472         HI.Definition = "S";473       }},474      // undeduced auto475      {R"cpp(476        template<typename T>477        void foo() {478          [[au^to]] x = T{};479        }480        )cpp",481       [](HoverInfo &HI) {482         HI.Name = "auto";483         HI.Kind = index::SymbolKind::TypeAlias;484         HI.Definition = "T";485       }},486      // constrained auto487      {R"cpp(488        template <class T> concept F = true;489        F [[au^to]] x = 1;490        )cpp",491       [](HoverInfo &HI) {492         HI.Name = "auto";493         HI.Kind = index::SymbolKind::TypeAlias;494         HI.Definition = "int";495       }},496      {R"cpp(497        template <class T> concept F = true;498        [[^F]] auto x = 1;499        )cpp",500       [](HoverInfo &HI) {501         HI.NamespaceScope = "";502         HI.Name = "F";503         HI.Kind = index::SymbolKind::Concept;504         HI.Definition = "template <class T>\nconcept F = true";505       }},506      // auto on lambda507      {R"cpp(508        void foo() {509          [[au^to]] lamb = []{};510        }511        )cpp",512       [](HoverInfo &HI) {513         HI.Name = "auto";514         HI.Kind = index::SymbolKind::TypeAlias;515         HI.Definition = "class(lambda)";516       }},517      // auto on template instantiation518      {R"cpp(519        template<typename T> class Foo{};520        void foo() {521          [[au^to]] x = Foo<int>();522        }523        )cpp",524       [](HoverInfo &HI) {525         HI.Name = "auto";526         HI.Kind = index::SymbolKind::TypeAlias;527         HI.Definition = "Foo<int>";528       }},529      // auto on specialized template530      {R"cpp(531        template<typename T> class Foo{};532        template<> class Foo<int>{};533        void foo() {534          [[au^to]] x = Foo<int>();535        }536        )cpp",537       [](HoverInfo &HI) {538         HI.Name = "auto";539         HI.Kind = index::SymbolKind::TypeAlias;540         HI.Definition = "Foo<int>";541       }},542      // constrained template parameter543      {R"cpp(544        template<class T> concept Fooable = true;545        template<[[Foo^able]] T>546        void bar(T t) {}547        )cpp",548       [](HoverInfo &HI) {549         HI.NamespaceScope = "";550         HI.Name = "Fooable";551         HI.Kind = index::SymbolKind::Concept;552         HI.Definition = "template <class T>\nconcept Fooable = true";553       }},554      {R"cpp(555        template<class T> concept Fooable = true;556        template<Fooable [[T^T]]>557        void bar(TT t) {}558        )cpp",559       [](HoverInfo &HI) {560         HI.Name = "TT";561         HI.Type = "class";562         HI.AccessSpecifier = "public";563         HI.NamespaceScope = "";564         HI.LocalScope = "bar::";565         HI.Kind = index::SymbolKind::TemplateTypeParm;566         HI.Definition = "Fooable TT";567       }},568      {R"cpp(569        template<class T> concept Fooable = true;570        void bar([[Foo^able]] auto t) {}571        )cpp",572       [](HoverInfo &HI) {573         HI.NamespaceScope = "";574         HI.Name = "Fooable";575         HI.Kind = index::SymbolKind::Concept;576         HI.Definition = "template <class T>\nconcept Fooable = true";577       }},578      // concept reference579      {R"cpp(580        template<class T> concept Fooable = true;581        auto X = [[Fooa^ble]]<int>;582        )cpp",583       [](HoverInfo &HI) {584         HI.NamespaceScope = "";585         HI.Name = "Fooable";586         HI.Kind = index::SymbolKind::Concept;587         HI.Definition = "template <class T>\nconcept Fooable = true";588         HI.Value = "true";589       }},590 591      // empty macro592      {R"cpp(593        #define MACRO594        [[MAC^RO]]595        )cpp",596       [](HoverInfo &HI) {597         HI.Name = "MACRO";598         HI.Kind = index::SymbolKind::Macro;599         HI.Definition = "#define MACRO";600       }},601 602      // object-like macro603      {R"cpp(604        #define MACRO 41605        int x = [[MAC^RO]];606        )cpp",607       [](HoverInfo &HI) {608         HI.Name = "MACRO";609         HI.Kind = index::SymbolKind::Macro;610         HI.Value = "41 (0x29)";611         HI.Type = "int";612         HI.Definition = "#define MACRO 41\n\n"613                         "// Expands to\n"614                         "41";615       }},616 617      // function-like macro618      {R"cpp(619        // Best MACRO ever.620        #define MACRO(x,y,z) void foo(x, y, z)621        [[MAC^RO]](int, double d, bool z = false);622        )cpp",623       [](HoverInfo &HI) {624         HI.Name = "MACRO";625         HI.Kind = index::SymbolKind::Macro;626         HI.Definition = "#define MACRO(x, y, z) void foo(x, y, z)\n\n"627                         "// Expands to\n"628                         "void foo(int, double d, bool z = false)";629       }},630 631      // nested macro632      {R"cpp(633        #define STRINGIFY_AUX(s) #s634        #define STRINGIFY(s) STRINGIFY_AUX(s)635        #define DECL_STR(NAME, VALUE) const char *v_##NAME = STRINGIFY(VALUE)636        #define FOO 41637 638        [[DECL^_STR]](foo, FOO);639        )cpp",640       [](HoverInfo &HI) {641         HI.Name = "DECL_STR";642         HI.Kind = index::SymbolKind::Macro;643         HI.Type = HoverInfo::PrintedType("const char *");644         HI.Definition = "#define DECL_STR(NAME, VALUE) const char *v_##NAME = "645                         "STRINGIFY(VALUE)\n\n"646                         "// Expands to\n"647                         "const char *v_foo = \"41\"";648       }},649 650      // constexprs651      {R"cpp(652        constexpr int add(int a, int b) { return a + b; }653        int [[b^ar]] = add(1, 2);654        )cpp",655       [](HoverInfo &HI) {656         HI.Name = "bar";657         HI.Definition = "int bar = add(1, 2)";658         HI.Kind = index::SymbolKind::Variable;659         HI.Type = "int";660         HI.NamespaceScope = "";661         HI.Value = "3";662       }},663      {R"cpp(664        int [[b^ar]] = sizeof(char);665        )cpp",666       [](HoverInfo &HI) {667         HI.Name = "bar";668         HI.Definition = "int bar = sizeof(char)";669         HI.Kind = index::SymbolKind::Variable;670         HI.Type = "int";671         HI.NamespaceScope = "";672         HI.Value = "1";673       }},674      {R"cpp(675        template<int a, int b> struct Add {676          static constexpr int result = a + b;677        };678        int [[ba^r]] = Add<1, 2>::result;679        )cpp",680       [](HoverInfo &HI) {681         HI.Name = "bar";682         HI.Definition = "int bar = Add<1, 2>::result";683         HI.Kind = index::SymbolKind::Variable;684         HI.Type = "int";685         HI.NamespaceScope = "";686         HI.Value = "3";687       }},688      {R"cpp(689        enum Color { RED = -123, GREEN = 5, };690        Color x = [[GR^EEN]];691       )cpp",692       [](HoverInfo &HI) {693         HI.Name = "GREEN";694         HI.NamespaceScope = "";695         HI.LocalScope = "Color::";696         HI.Definition = "GREEN = 5";697         HI.Kind = index::SymbolKind::EnumConstant;698         HI.Type = "enum Color";699         HI.Value = "5"; // Numeric on the enumerator name, no hex as small.700       }},701      {R"cpp(702        enum Color { RED = -123, GREEN = 5, };703        Color x = RED;704        Color y = [[^x]];705       )cpp",706       [](HoverInfo &HI) {707         HI.Name = "x";708         HI.NamespaceScope = "";709         HI.Definition = "Color x = RED";710         HI.Kind = index::SymbolKind::Variable;711         HI.Type = "Color";712         HI.Value = "RED (0xffffff85)"; // Symbolic on an expression.713       }},714      {R"cpp(715        template<int a, int b> struct Add {716          static constexpr int result = a + b;717        };718        int bar = Add<1, 2>::[[resu^lt]];719        )cpp",720       [](HoverInfo &HI) {721         HI.Name = "result";722         HI.Definition = "static constexpr int result = a + b";723         HI.Kind = index::SymbolKind::StaticProperty;724         HI.Type = "const int";725         HI.NamespaceScope = "";726         HI.LocalScope = "Add<1, 2>::";727         HI.Value = "3";728         HI.AccessSpecifier = "public";729       }},730      {R"cpp(731        using my_int = int;732        constexpr my_int answer() { return 40 + 2; }733        int x = [[ans^wer]]();734        )cpp",735       [](HoverInfo &HI) {736         HI.Name = "answer";737         HI.Definition = "constexpr my_int answer()";738         HI.Kind = index::SymbolKind::Function;739         HI.Type = {"my_int ()", "int ()"};740         HI.ReturnType = {"my_int", "int"};741         HI.Parameters.emplace();742         HI.NamespaceScope = "";743         HI.Value = "42 (0x2a)";744       }},745      {R"cpp(746        const char *[[ba^r]] = "1234";747        )cpp",748       [](HoverInfo &HI) {749         HI.Name = "bar";750         HI.Definition = "const char *bar = \"1234\"";751         HI.Kind = index::SymbolKind::Variable;752         HI.Type = "const char *";753         HI.NamespaceScope = "";754         HI.Value = "&\"1234\"[0]";755       }},756      {R"cpp(// Should not crash757        template <typename T>758        struct Tmpl {759          Tmpl(int name);760        };761 762        template <typename A>763        void boom(int name) {764          new Tmpl<A>([[na^me]]);765        })cpp",766       [](HoverInfo &HI) {767         HI.Name = "name";768         HI.Definition = "int name";769         HI.Kind = index::SymbolKind::Parameter;770         HI.Type = "int";771         HI.NamespaceScope = "";772         HI.LocalScope = "boom::";773       }},774      {775          R"cpp(// Should not print inline or anon namespaces.776          namespace ns {777            inline namespace in_ns {778              namespace a {779                namespace {780                  namespace b {781                    inline namespace in_ns2 {782                      class Foo {};783                    } // in_ns2784                  } // b785                } // anon786              } // a787            } // in_ns788          } // ns789          void foo() {790            ns::a::b::[[F^oo]] x;791            (void)x;792          }793          )cpp",794          [](HoverInfo &HI) {795            HI.Name = "Foo";796            HI.Kind = index::SymbolKind::Class;797            HI.NamespaceScope = "ns::a::b::";798            HI.Definition = "class Foo {}";799          }},800      {801          R"cpp(802          template <typename T> class Foo {};803          class X;804          void foo() {805            [[^auto]] x = Foo<X>();806          }807          )cpp",808          [](HoverInfo &HI) {809            HI.Name = "auto";810            HI.Kind = index::SymbolKind::TypeAlias;811            HI.Definition = "Foo<X>";812          }},813      {// Falls back to primary template, when the type is not instantiated.814       R"cpp(815          // comment from primary816          template <typename T> class Foo {};817          // comment from specialization818          template <typename T> class Foo<T*> {};819          void foo() {820            [[Fo^o]]<int*> *x = nullptr;821          }822          )cpp",823       [](HoverInfo &HI) {824         HI.Name = "Foo<int *>";825         HI.Kind = index::SymbolKind::Class;826         HI.NamespaceScope = "";827         HI.Definition = "template <> class Foo<int *>";828         // FIXME: Maybe force instantiation to make use of real template829         // pattern.830         HI.Documentation = "comment from primary";831       }},832      {// Template Type Parameter833       R"cpp(834          template <typename [[^T]] = int> void foo();835          )cpp",836       [](HoverInfo &HI) {837         HI.Name = "T";838         HI.Kind = index::SymbolKind::TemplateTypeParm;839         HI.NamespaceScope = "";840         HI.Definition = "typename T = int";841         HI.LocalScope = "foo::";842         HI.Type = "typename";843         HI.AccessSpecifier = "public";844       }},845      {// TemplateTemplate Type Parameter846       R"cpp(847          template <template<typename> class [[^T]]> void foo();848          )cpp",849       [](HoverInfo &HI) {850         HI.Name = "T";851         HI.Kind = index::SymbolKind::TemplateTemplateParm;852         HI.NamespaceScope = "";853         HI.Definition = "template <typename> class T";854         HI.LocalScope = "foo::";855         HI.Type = "template <typename> class";856         HI.AccessSpecifier = "public";857       }},858      {// NonType Template Parameter859       R"cpp(860          template <int [[^T]] = 5> void foo();861          )cpp",862       [](HoverInfo &HI) {863         HI.Name = "T";864         HI.Kind = index::SymbolKind::NonTypeTemplateParm;865         HI.NamespaceScope = "";866         HI.Definition = "int T = 5";867         HI.LocalScope = "foo::";868         HI.Type = "int";869         HI.AccessSpecifier = "public";870       }},871 872      {// Getter873       R"cpp(874          struct X { int Y; float [[^y]]() { return Y; } };875          )cpp",876       [](HoverInfo &HI) {877         HI.Name = "y";878         HI.Kind = index::SymbolKind::InstanceMethod;879         HI.NamespaceScope = "";880         HI.Definition = "float y()";881         HI.LocalScope = "X::";882         HI.Documentation = "Trivial accessor for `Y`.";883         HI.Type = "float ()";884         HI.ReturnType = "float";885         HI.Parameters.emplace();886         HI.AccessSpecifier = "public";887       }},888      {// Setter889       R"cpp(890          struct X { int Y; void [[^setY]](float v) { Y = v; } };891          )cpp",892       [](HoverInfo &HI) {893         HI.Name = "setY";894         HI.Kind = index::SymbolKind::InstanceMethod;895         HI.NamespaceScope = "";896         HI.Definition = "void setY(float v)";897         HI.LocalScope = "X::";898         HI.Documentation = "Trivial setter for `Y`.";899         HI.Type = "void (float)";900         HI.ReturnType = "void";901         HI.Parameters.emplace();902         HI.Parameters->emplace_back();903         HI.Parameters->back().Type = "float";904         HI.Parameters->back().Name = "v";905         HI.AccessSpecifier = "public";906       }},907      {// Setter (builder)908       R"cpp(909          struct X { int Y; X& [[^setY]](float v) { Y = v; return *this; } };910          )cpp",911       [](HoverInfo &HI) {912         HI.Name = "setY";913         HI.Kind = index::SymbolKind::InstanceMethod;914         HI.NamespaceScope = "";915         HI.Definition = "X &setY(float v)";916         HI.LocalScope = "X::";917         HI.Documentation = "Trivial setter for `Y`.";918         HI.Type = "X &(float)";919         HI.ReturnType = "X &";920         HI.Parameters.emplace();921         HI.Parameters->emplace_back();922         HI.Parameters->back().Type = "float";923         HI.Parameters->back().Name = "v";924         HI.AccessSpecifier = "public";925       }},926      {// Setter (move)927       R"cpp(928          namespace std { template<typename T> T&& move(T&& t); }929          struct X { int Y; void [[^setY]](float v) { Y = std::move(v); } };930          )cpp",931       [](HoverInfo &HI) {932         HI.Name = "setY";933         HI.Kind = index::SymbolKind::InstanceMethod;934         HI.NamespaceScope = "";935         HI.Definition = "void setY(float v)";936         HI.LocalScope = "X::";937         HI.Documentation = "Trivial setter for `Y`.";938         HI.Type = "void (float)";939         HI.ReturnType = "void";940         HI.Parameters.emplace();941         HI.Parameters->emplace_back();942         HI.Parameters->back().Type = "float";943         HI.Parameters->back().Name = "v";944         HI.AccessSpecifier = "public";945       }},946      {// Field type initializer.947       R"cpp(948          struct X { int x = 2; };949          X ^[[x]];950          )cpp",951       [](HoverInfo &HI) {952         HI.Name = "x";953         HI.Kind = index::SymbolKind::Variable;954         HI.NamespaceScope = "";955         HI.Definition = "X x";956         HI.Type = "X";957       }},958      {// Don't crash on null types.959       R"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp",960       [](HoverInfo &HI) {961         HI.Name = "x";962         HI.Kind = index::SymbolKind::Variable;963         HI.NamespaceScope = "";964         HI.Definition = "";965         HI.Type = "NULL TYPE";966         // Bindings are in theory public members of an anonymous struct.967         HI.AccessSpecifier = "public";968       }},969      {// Don't crash on invalid decl with invalid init expr.970       R"cpp(971          Unknown [[^abc]] = invalid;972          // error-ok973          )cpp",974       [](HoverInfo &HI) {975         HI.Name = "abc";976         HI.Kind = index::SymbolKind::Variable;977         HI.NamespaceScope = "";978         HI.Definition = "int abc";979         HI.Type = "int";980         HI.AccessSpecifier = "public";981       }},982      {// Extra info for function call.983       R"cpp(984          void fun(int arg_a, int &arg_b) {};985          void code() {986            int a = 1, b = 2;987            fun(a, [[^b]]);988          }989          )cpp",990       [](HoverInfo &HI) {991         HI.Name = "b";992         HI.Kind = index::SymbolKind::Variable;993         HI.NamespaceScope = "";994         HI.Definition = "int b = 2";995         HI.LocalScope = "code::";996         HI.Value = "2";997         HI.Type = "int";998         HI.CalleeArgInfo.emplace();999         HI.CalleeArgInfo->Name = "arg_b";1000         HI.CalleeArgInfo->Type = "int &";1001         HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};1002       }},1003      {// make_unique-like function call1004       R"cpp(1005          struct Foo {1006            explicit Foo(int arg_a) {}1007          };1008          template<class T, class... Args>1009          T make(Args&&... args)1010          {1011              return T(args...);1012          }1013 1014          void code() {1015            int a = 1;1016            auto foo = make<Foo>([[^a]]);1017          }1018          )cpp",1019       [](HoverInfo &HI) {1020         HI.Name = "a";1021         HI.Kind = index::SymbolKind::Variable;1022         HI.NamespaceScope = "";1023         HI.Definition = "int a = 1";1024         HI.LocalScope = "code::";1025         HI.Value = "1";1026         HI.Type = "int";1027         HI.CalleeArgInfo.emplace();1028         HI.CalleeArgInfo->Name = "arg_a";1029         HI.CalleeArgInfo->Type = "int";1030         HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};1031       }},1032      {1033          R"cpp(1034          void foobar(const float &arg);1035          int main() {1036            int a = 0;1037            foobar([[^a]]);1038          }1039          )cpp",1040          [](HoverInfo &HI) {1041            HI.Name = "a";1042            HI.Kind = index::SymbolKind::Variable;1043            HI.NamespaceScope = "";1044            HI.Definition = "int a = 0";1045            HI.LocalScope = "main::";1046            HI.Value = "0";1047            HI.Type = "int";1048            HI.CalleeArgInfo.emplace();1049            HI.CalleeArgInfo->Name = "arg";1050            HI.CalleeArgInfo->Type = "const float &";1051            HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};1052          }},1053      {1054          R"cpp(1055          struct Foo {1056            explicit Foo(const float& arg) {}1057          };1058          int main() {1059            int a = 0;1060            Foo foo([[^a]]);1061          }1062          )cpp",1063          [](HoverInfo &HI) {1064            HI.Name = "a";1065            HI.Kind = index::SymbolKind::Variable;1066            HI.NamespaceScope = "";1067            HI.Definition = "int a = 0";1068            HI.LocalScope = "main::";1069            HI.Value = "0";1070            HI.Type = "int";1071            HI.CalleeArgInfo.emplace();1072            HI.CalleeArgInfo->Name = "arg";1073            HI.CalleeArgInfo->Type = "const float &";1074            HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};1075          }},1076      {// Literal passed to function call1077       R"cpp(1078          void fun(int arg_a, const int &arg_b) {};1079          void code() {1080            int a = 1;1081            fun(a, [[^2]]);1082          }1083          )cpp",1084       [](HoverInfo &HI) {1085         HI.Name = "literal";1086         HI.Kind = index::SymbolKind::Unknown;1087         HI.CalleeArgInfo.emplace();1088         HI.CalleeArgInfo->Name = "arg_b";1089         HI.CalleeArgInfo->Type = "const int &";1090         HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false};1091       }},1092      {// Expression passed to function call1093       R"cpp(1094          void fun(int arg_a, const int &arg_b) {};1095          void code() {1096            int a = 1;1097            fun(a, 1 [[^+]] 2);1098          }1099          )cpp",1100       [](HoverInfo &HI) {1101         HI.Name = "expression";1102         HI.Kind = index::SymbolKind::Unknown;1103         HI.Type = "int";1104         HI.Value = "3";1105         HI.CalleeArgInfo.emplace();1106         HI.CalleeArgInfo->Name = "arg_b";1107         HI.CalleeArgInfo->Type = "const int &";1108         HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false};1109       }},1110      {1111          R"cpp(1112        int add(int lhs, int rhs);1113        int main() {1114          add(1 [[^+]] 2, 3);1115        }1116        )cpp",1117          [](HoverInfo &HI) {1118            HI.Name = "expression";1119            HI.Kind = index::SymbolKind::Unknown;1120            HI.Type = "int";1121            HI.Value = "3";1122            HI.CalleeArgInfo.emplace();1123            HI.CalleeArgInfo->Name = "lhs";1124            HI.CalleeArgInfo->Type = "int";1125            HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};1126          }},1127      {1128          R"cpp(1129        void foobar(const float &arg);1130        int main() {1131          foobar([[^0]]);1132        }1133        )cpp",1134          [](HoverInfo &HI) {1135            HI.Name = "literal";1136            HI.Kind = index::SymbolKind::Unknown;1137            HI.CalleeArgInfo.emplace();1138            HI.CalleeArgInfo->Name = "arg";1139            HI.CalleeArgInfo->Type = "const float &";1140            HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};1141          }},1142      {// Extra info for method call.1143       R"cpp(1144          class C {1145           public:1146            void fun(int arg_a = 3, int arg_b = 4) {}1147          };1148          void code() {1149            int a = 1, b = 2;1150            C c;1151            c.fun([[^a]], b);1152          }1153          )cpp",1154       [](HoverInfo &HI) {1155         HI.Name = "a";1156         HI.Kind = index::SymbolKind::Variable;1157         HI.NamespaceScope = "";1158         HI.Definition = "int a = 1";1159         HI.LocalScope = "code::";1160         HI.Value = "1";1161         HI.Type = "int";1162         HI.CalleeArgInfo.emplace();1163         HI.CalleeArgInfo->Name = "arg_a";1164         HI.CalleeArgInfo->Type = "int";1165         HI.CalleeArgInfo->Default = "3";1166         HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};1167       }},1168      {1169          R"cpp(1170          struct Foo {1171            Foo(const int &);1172          };1173          void foo(Foo);1174          void bar() {1175            const int x = 0;1176            foo([[^x]]);1177          }1178       )cpp",1179          [](HoverInfo &HI) {1180            HI.Name = "x";1181            HI.Kind = index::SymbolKind::Variable;1182            HI.NamespaceScope = "";1183            HI.Definition = "const int x = 0";1184            HI.LocalScope = "bar::";1185            HI.Value = "0";1186            HI.Type = "const int";1187            HI.CalleeArgInfo.emplace();1188            HI.CalleeArgInfo->Type = "Foo";1189            HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, true};1190          }},1191      {// Dont crash on invalid decl1192       R"cpp(1193        // error-ok1194        struct Foo {1195          Bar [[x^x]];1196        };)cpp",1197       [](HoverInfo &HI) {1198         HI.Name = "xx";1199         HI.Kind = index::SymbolKind::Field;1200         HI.NamespaceScope = "";1201         HI.Definition = "int xx";1202         HI.LocalScope = "Foo::";1203         HI.Type = "int";1204         HI.AccessSpecifier = "public";1205       }},1206      {R"cpp(1207        // error-ok1208        struct Foo {1209          Bar xx;1210          int [[y^y]];1211        };)cpp",1212       [](HoverInfo &HI) {1213         HI.Name = "yy";1214         HI.Kind = index::SymbolKind::Field;1215         HI.NamespaceScope = "";1216         HI.Definition = "int yy";1217         HI.LocalScope = "Foo::";1218         HI.Type = "int";1219         HI.AccessSpecifier = "public";1220       }},1221      {// No crash on InitListExpr.1222       R"cpp(1223          struct Foo {1224            int a[10];1225          };1226          constexpr Foo k2 = {1227            ^[[{]]1} // FIXME: why the hover range is 1 character?1228          };1229         )cpp",1230       [](HoverInfo &HI) {1231         HI.Name = "expression";1232         HI.Kind = index::SymbolKind::Unknown;1233         HI.Type = "int[10]";1234         HI.Value = "{1}";1235       }},1236      {// Var template decl1237       R"cpp(1238          using m_int = int;1239 1240          template <int Size> m_int ^[[arr]][Size];1241         )cpp",1242       [](HoverInfo &HI) {1243         HI.Name = "arr";1244         HI.Kind = index::SymbolKind::Variable;1245         HI.Type = {"m_int[Size]", "int[Size]"};1246         HI.NamespaceScope = "";1247         HI.Definition = "template <int Size> m_int arr[Size]";1248         HI.TemplateParameters = {{{"int"}, {"Size"}, std::nullopt}};1249       }},1250      {// Var template decl specialization1251       R"cpp(1252          using m_int = int;1253 1254          template <int Size> m_int arr[Size];1255 1256          template <> m_int ^[[arr]]<4>[4];1257         )cpp",1258       [](HoverInfo &HI) {1259         HI.Name = "arr<4>";1260         HI.Kind = index::SymbolKind::Variable;1261         HI.Type = {"m_int[4]", "int[4]"};1262         HI.NamespaceScope = "";1263         HI.Definition = "m_int arr[4]";1264       }},1265      {// Canonical type1266       R"cpp(1267          template<typename T>1268          struct TestHover {1269            using Type = T;1270          };1271 1272          void code() {1273            TestHover<int>::Type ^[[a]];1274          }1275         )cpp",1276       [](HoverInfo &HI) {1277         HI.Name = "a";1278         HI.NamespaceScope = "";1279         HI.LocalScope = "code::";1280         HI.Definition = "TestHover<int>::Type a";1281         HI.Kind = index::SymbolKind::Variable;1282         HI.Type = {"TestHover<int>::Type", "int"};1283       }},1284      {// Canonical template type1285       R"cpp(1286          template<typename T>1287          void ^[[foo]](T arg) {}1288         )cpp",1289       [](HoverInfo &HI) {1290         HI.Name = "foo";1291         HI.Kind = index::SymbolKind::Function;1292         HI.NamespaceScope = "";1293         HI.Definition = "template <typename T> void foo(T arg)";1294         HI.Type = "void (T)";1295         HI.ReturnType = "void";1296         HI.Parameters = {{{"T"}, std::string("arg"), std::nullopt}};1297         HI.TemplateParameters = {1298             {{"typename"}, std::string("T"), std::nullopt}};1299       }},1300      {// TypeAlias Template1301       R"cpp(1302          template<typename T>1303          using ^[[alias]] = T;1304         )cpp",1305       [](HoverInfo &HI) {1306         HI.Name = "alias";1307         HI.NamespaceScope = "";1308         HI.LocalScope = "";1309         HI.Kind = index::SymbolKind::TypeAlias;1310         HI.Definition = "template <typename T> using alias = T";1311         HI.Type = "T";1312         HI.TemplateParameters = {1313             {{"typename"}, std::string("T"), std::nullopt}};1314       }},1315      {// TypeAlias Template1316       R"cpp(1317          template<typename T>1318          using A = T;1319 1320          template<typename T>1321          using ^[[AA]] = A<T>;1322         )cpp",1323       [](HoverInfo &HI) {1324         HI.Name = "AA";1325         HI.NamespaceScope = "";1326         HI.LocalScope = "";1327         HI.Kind = index::SymbolKind::TypeAlias;1328         HI.Definition = "template <typename T> using AA = A<T>";1329         HI.Type = {"A<T>", "T"};1330         HI.TemplateParameters = {1331             {{"typename"}, std::string("T"), std::nullopt}};1332       }},1333      {// Constant array1334       R"cpp(1335          using m_int = int;1336 1337          m_int ^[[arr]][10];1338         )cpp",1339       [](HoverInfo &HI) {1340         HI.Name = "arr";1341         HI.NamespaceScope = "";1342         HI.LocalScope = "";1343         HI.Kind = index::SymbolKind::Variable;1344         HI.Definition = "m_int arr[10]";1345         HI.Type = {"m_int[10]", "int[10]"};1346       }},1347      {// Incomplete array1348       R"cpp(1349          using m_int = int;1350 1351          extern m_int ^[[arr]][];1352         )cpp",1353       [](HoverInfo &HI) {1354         HI.Name = "arr";1355         HI.NamespaceScope = "";1356         HI.LocalScope = "";1357         HI.Kind = index::SymbolKind::Variable;1358         HI.Definition = "extern m_int arr[]";1359         HI.Type = {"m_int[]", "int[]"};1360       }},1361      {// Dependent size array1362       R"cpp(1363          using m_int = int;1364 1365          template<int Size>1366          struct Test {1367            m_int ^[[arr]][Size];1368          };1369         )cpp",1370       [](HoverInfo &HI) {1371         HI.Name = "arr";1372         HI.NamespaceScope = "";1373         HI.LocalScope = "Test<Size>::";1374         HI.AccessSpecifier = "public";1375         HI.Kind = index::SymbolKind::Field;1376         HI.Definition = "m_int arr[Size]";1377         HI.Type = {"m_int[Size]", "int[Size]"};1378       }},1379      {// Bitfield offset, size and padding1380       R"cpp(1381            struct Foo {1382              char x;1383              char [[^y]] : 1;1384              int z;1385            };1386          )cpp",1387       [](HoverInfo &HI) {1388         HI.NamespaceScope = "";1389         HI.LocalScope = "Foo::";1390         HI.Name = "y";1391         HI.Kind = index::SymbolKind::Field;1392         HI.Definition = "char y : 1";1393         HI.Type = "char";1394         HI.Offset = 8;1395         HI.Size = 1;1396         HI.Padding = 23;1397         HI.Align = 8;1398         HI.AccessSpecifier = "public";1399       }}};1400  for (const auto &Case : Cases) {1401    SCOPED_TRACE(Case.Code);1402 1403    Annotations T(Case.Code);1404    TestTU TU = TestTU::withCode(T.code());1405    TU.ExtraArgs.push_back("-std=c++20");1406    // Types might be different depending on the target triplet, we chose a1407    // fixed one to make sure tests passes on different platform.1408    TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");1409    auto AST = TU.build();1410    Config Cfg;1411    Cfg.Hover.ShowAKA = true;1412    WithContextValue WithCfg(Config::Key, std::move(Cfg));1413 1414    auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);1415    ASSERT_TRUE(H);1416    HoverInfo Expected;1417    Expected.SymRange = T.range();1418    Case.ExpectedBuilder(Expected);1419 1420    EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);1421    EXPECT_EQ(H->LocalScope, Expected.LocalScope);1422    EXPECT_EQ(H->Name, Expected.Name);1423    EXPECT_EQ(H->Kind, Expected.Kind);1424    EXPECT_EQ(H->Documentation, Expected.Documentation);1425    EXPECT_EQ(H->Definition, Expected.Definition);1426    EXPECT_EQ(H->Type, Expected.Type);1427    EXPECT_EQ(H->ReturnType, Expected.ReturnType);1428    EXPECT_EQ(H->Parameters, Expected.Parameters);1429    EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);1430    EXPECT_EQ(H->SymRange, Expected.SymRange);1431    EXPECT_EQ(H->Value, Expected.Value);1432    EXPECT_EQ(H->Size, Expected.Size);1433    EXPECT_EQ(H->Offset, Expected.Offset);1434    EXPECT_EQ(H->Align, Expected.Align);1435    EXPECT_EQ(H->AccessSpecifier, Expected.AccessSpecifier);1436    EXPECT_EQ(H->CalleeArgInfo, Expected.CalleeArgInfo);1437    EXPECT_EQ(H->CallPassType, Expected.CallPassType);1438  }1439}1440 1441TEST(Hover, DefinitionLanuage) {1442  struct {1443    const char *const Code;1444    const std::string ClangLanguageFlag;1445    const char *const ExpectedDefinitionLanguage;1446  } Cases[] = {{R"cpp(1447          void [[some^Global]]() {}1448          )cpp",1449                "", "cpp"},1450               {R"cpp(1451          void [[some^Global]]() {}1452          )cpp",1453                "-xobjective-c++", "objective-cpp"},1454               {R"cpp(1455          void [[some^Global]]() {}1456          )cpp",1457                "-xobjective-c", "objective-c"}};1458  for (const auto &Case : Cases) {1459    SCOPED_TRACE(Case.Code);1460 1461    Annotations T(Case.Code);1462    TestTU TU = TestTU::withCode(T.code());1463    if (!Case.ClangLanguageFlag.empty())1464      TU.ExtraArgs.push_back(Case.ClangLanguageFlag);1465    auto AST = TU.build();1466 1467    auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);1468    ASSERT_TRUE(H);1469 1470    EXPECT_STREQ(H->DefinitionLanguage, Case.ExpectedDefinitionLanguage);1471  }1472}1473 1474TEST(Hover, CallPassType) {1475  const llvm::StringRef CodePrefix = R"cpp(1476class Base {};1477class Derived : public Base {};1478class CustomClass {1479 public:1480  CustomClass() {}1481  CustomClass(const Base &x) {}1482  CustomClass(int &x) {}1483  CustomClass(float x) {}1484  CustomClass(int x, int y) {}1485};1486 1487void int_by_ref(int &x) {}1488void int_by_const_ref(const int &x) {}1489void int_by_value(int x) {}1490void base_by_ref(Base &x) {}1491void base_by_const_ref(const Base &x) {}1492void base_by_value(Base x) {}1493void float_by_value(float x) {}1494void custom_by_value(CustomClass x) {}1495 1496void fun() {1497  int int_x;1498  int &int_ref = int_x;1499  const int &int_const_ref = int_x;1500  Base base;1501  const Base &base_const_ref = base;1502  Derived derived;1503  float float_x;1504)cpp";1505  const llvm::StringRef CodeSuffix = "}";1506 1507  struct {1508    const char *const Code;1509    HoverInfo::PassType::PassMode PassBy;1510    bool Converted;1511  } Tests[] = {1512      // Integer tests1513      {"int_by_value([[^int_x]]);", PassMode::Value, false},1514      {"int_by_value([[^123]]);", PassMode::Value, false},1515      {"int_by_ref([[^int_x]]);", PassMode::Ref, false},1516      {"int_by_const_ref([[^int_x]]);", PassMode::ConstRef, false},1517      {"int_by_const_ref([[^123]]);", PassMode::ConstRef, false},1518      {"int_by_value([[^int_ref]]);", PassMode::Value, false},1519      {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},1520      {"int_by_const_ref([[^int_ref]]);", PassMode::ConstRef, false},1521      {"int_by_const_ref([[^int_const_ref]]);", PassMode::ConstRef, false},1522      // Custom class tests1523      {"base_by_ref([[^base]]);", PassMode::Ref, false},1524      {"base_by_const_ref([[^base]]);", PassMode::ConstRef, false},1525      {"base_by_const_ref([[^base_const_ref]]);", PassMode::ConstRef, false},1526      {"base_by_value([[^base]]);", PassMode::Value, false},1527      {"base_by_value([[^base_const_ref]]);", PassMode::Value, false},1528      {"base_by_ref([[^derived]]);", PassMode::Ref, false},1529      {"base_by_const_ref([[^derived]]);", PassMode::ConstRef, false},1530      {"base_by_value([[^derived]]);", PassMode::Value, false},1531      // Custom class constructor tests1532      {"CustomClass c1([[^base]]);", PassMode::ConstRef, false},1533      {"auto c2 = new CustomClass([[^base]]);", PassMode::ConstRef, false},1534      {"CustomClass c3([[^int_x]]);", PassMode::Ref, false},1535      {"CustomClass c3(int_x, [[^int_x]]);", PassMode::Value, false},1536      // Converted tests1537      {"float_by_value([[^int_x]]);", PassMode::Value, true},1538      {"float_by_value([[^int_ref]]);", PassMode::Value, true},1539      {"float_by_value([[^int_const_ref]]);", PassMode::Value, true},1540      {"float_by_value([[^123.0f]]);", PassMode::Value, false},1541      {"float_by_value([[^123]]);", PassMode::Value, true},1542      {"custom_by_value([[^int_x]]);", PassMode::Ref, true},1543      {"custom_by_value([[^float_x]]);", PassMode::Value, true},1544      {"custom_by_value([[^base]]);", PassMode::ConstRef, true},1545  };1546  for (const auto &Test : Tests) {1547    SCOPED_TRACE(Test.Code);1548 1549    const auto Code = (CodePrefix + Test.Code + CodeSuffix).str();1550    Annotations T(Code);1551    TestTU TU = TestTU::withCode(T.code());1552    TU.ExtraArgs.push_back("-std=c++17");1553    auto AST = TU.build();1554    auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);1555    ASSERT_TRUE(H);1556    EXPECT_EQ(H->CallPassType->PassBy, Test.PassBy);1557    EXPECT_EQ(H->CallPassType->Converted, Test.Converted);1558  }1559}1560 1561TEST(Hover, NoHover) {1562  llvm::StringRef Tests[] = {1563      "^int main() {}",1564      "void foo() {^}",1565      // FIXME: "decltype(auto)" should be a single hover1566      "decltype(au^to) x = 0;",1567      // FIXME: not supported yet1568      R"cpp(// Lambda auto parameter1569            auto lamb = [](a^uto){};1570          )cpp",1571      R"cpp(// non-named decls don't get hover. Don't crash!1572            ^static_assert(1, "");1573          )cpp",1574      R"cpp(// non-evaluatable expr1575          template <typename T> void foo() {1576            (void)[[size^of]](T);1577          })cpp",1578      R"cpp(// should not crash on invalid semantic form of init-list-expr.1579            /*error-ok*/1580            struct Foo {1581              int xyz = 0;1582            };1583            class Bar {};1584            constexpr Foo s = ^{1585              .xyz = Bar(),1586            };1587          )cpp",1588      // literals1589      "auto x = t^rue;",1590      "auto x = ^(int){42};",1591      "auto x = ^42.;",1592      "auto x = ^42.0i;",1593      "auto x = ^42;",1594      "auto x = ^nullptr;",1595  };1596 1597  for (const auto &Test : Tests) {1598    SCOPED_TRACE(Test);1599 1600    Annotations T(Test);1601    TestTU TU = TestTU::withCode(T.code());1602    TU.ExtraArgs.push_back("-std=c++17");1603    auto AST = TU.build();1604    auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);1605    ASSERT_FALSE(H);1606  }1607}1608 1609TEST(Hover, All) {1610  struct {1611    const char *const Code;1612    const std::function<void(HoverInfo &)> ExpectedBuilder;1613  } Cases[] = {1614      {"auto x = [['^A']]; // character literal",1615       [](HoverInfo &HI) {1616         HI.Name = "expression";1617         HI.Type = "char";1618         HI.Value = "65 (0x41)";1619       }},1620      {"auto s = ^[[\"Hello, world!\"]]; // string literal",1621       [](HoverInfo &HI) {1622         HI.Name = "string-literal";1623         HI.Size = 112;1624         HI.Type = "const char[14]";1625       }},1626      {1627          R"cpp(// Local variable1628            int main() {1629              int bonjour;1630              ^[[bonjour]] = 2;1631              int test1 = bonjour;1632            }1633          )cpp",1634          [](HoverInfo &HI) {1635            HI.Name = "bonjour";1636            HI.Kind = index::SymbolKind::Variable;1637            HI.NamespaceScope = "";1638            HI.LocalScope = "main::";1639            HI.Type = "int";1640            HI.Definition = "int bonjour";1641          }},1642      {1643          R"cpp(// Local variable in method1644            struct s {1645              void method() {1646                int bonjour;1647                ^[[bonjour]] = 2;1648              }1649            };1650          )cpp",1651          [](HoverInfo &HI) {1652            HI.Name = "bonjour";1653            HI.Kind = index::SymbolKind::Variable;1654            HI.NamespaceScope = "";1655            HI.LocalScope = "s::method::";1656            HI.Type = "int";1657            HI.Definition = "int bonjour";1658          }},1659      {1660          R"cpp(// Struct1661            namespace ns1 {1662              struct MyClass {};1663            } // namespace ns11664            int main() {1665              ns1::[[My^Class]]* Params;1666            }1667          )cpp",1668          [](HoverInfo &HI) {1669            HI.Name = "MyClass";1670            HI.Kind = index::SymbolKind::Struct;1671            HI.NamespaceScope = "ns1::";1672            HI.Definition = "struct MyClass {}";1673          }},1674      {1675          R"cpp(// Class1676            namespace ns1 {1677              class MyClass {};1678            } // namespace ns11679            int main() {1680              ns1::[[My^Class]]* Params;1681            }1682          )cpp",1683          [](HoverInfo &HI) {1684            HI.Name = "MyClass";1685            HI.Kind = index::SymbolKind::Class;1686            HI.NamespaceScope = "ns1::";1687            HI.Definition = "class MyClass {}";1688          }},1689      {1690          R"cpp(// Union1691            namespace ns1 {1692              union MyUnion { int x; int y; };1693            } // namespace ns11694            int main() {1695              ns1::[[My^Union]] Params;1696            }1697          )cpp",1698          [](HoverInfo &HI) {1699            HI.Name = "MyUnion";1700            HI.Kind = index::SymbolKind::Union;1701            HI.NamespaceScope = "ns1::";1702            HI.Definition = "union MyUnion {}";1703          }},1704      {1705          R"cpp(// Function definition via pointer1706            void foo(int) {}1707            int main() {1708              auto *X = &^[[foo]];1709            }1710          )cpp",1711          [](HoverInfo &HI) {1712            HI.Name = "foo";1713            HI.Kind = index::SymbolKind::Function;1714            HI.NamespaceScope = "";1715            HI.Type = "void (int)";1716            HI.Definition = "void foo(int)";1717            HI.Documentation = "Function definition via pointer";1718            HI.ReturnType = "void";1719            HI.Parameters = {1720                {{"int"}, std::nullopt, std::nullopt},1721            };1722          }},1723      {1724          R"cpp(// Function declaration via call1725            int foo(int);1726            int main() {1727              return ^[[foo]](42);1728            }1729          )cpp",1730          [](HoverInfo &HI) {1731            HI.Name = "foo";1732            HI.Kind = index::SymbolKind::Function;1733            HI.NamespaceScope = "";1734            HI.Type = "int (int)";1735            HI.Definition = "int foo(int)";1736            HI.Documentation = "Function declaration via call";1737            HI.ReturnType = "int";1738            HI.Parameters = {1739                {{"int"}, std::nullopt, std::nullopt},1740            };1741          }},1742      {1743          R"cpp(// Field1744            struct Foo { int x; };1745            int main() {1746              Foo bar;1747              (void)bar.^[[x]];1748            }1749          )cpp",1750          [](HoverInfo &HI) {1751            HI.Name = "x";1752            HI.Kind = index::SymbolKind::Field;1753            HI.NamespaceScope = "";1754            HI.LocalScope = "Foo::";1755            HI.Type = "int";1756            HI.Definition = "int x";1757          }},1758      {1759          R"cpp(// Field with initialization1760            struct Foo { int x = 5; };1761            int main() {1762              Foo bar;1763              (void)bar.^[[x]];1764            }1765          )cpp",1766          [](HoverInfo &HI) {1767            HI.Name = "x";1768            HI.Kind = index::SymbolKind::Field;1769            HI.NamespaceScope = "";1770            HI.LocalScope = "Foo::";1771            HI.Type = "int";1772            HI.Definition = "int x = 5";1773          }},1774      {1775          R"cpp(// Static field1776            struct Foo { static int x; };1777            int main() {1778              (void)Foo::^[[x]];1779            }1780          )cpp",1781          [](HoverInfo &HI) {1782            HI.Name = "x";1783            HI.Kind = index::SymbolKind::StaticProperty;1784            HI.NamespaceScope = "";1785            HI.LocalScope = "Foo::";1786            HI.Type = "int";1787            HI.Definition = "static int x";1788          }},1789      {1790          R"cpp(// Field, member initializer1791            struct Foo {1792              int x;1793              Foo() : ^[[x]](0) {}1794            };1795          )cpp",1796          [](HoverInfo &HI) {1797            HI.Name = "x";1798            HI.Kind = index::SymbolKind::Field;1799            HI.NamespaceScope = "";1800            HI.LocalScope = "Foo::";1801            HI.Type = "int";1802            HI.Definition = "int x";1803          }},1804      {1805          R"cpp(// Field, GNU old-style field designator1806            struct Foo { int x; };1807            int main() {1808              Foo bar = { ^[[x]] : 1 };1809            }1810          )cpp",1811          [](HoverInfo &HI) {1812            HI.Name = "x";1813            HI.Kind = index::SymbolKind::Field;1814            HI.NamespaceScope = "";1815            HI.LocalScope = "Foo::";1816            HI.Type = "int";1817            HI.Definition = "int x";1818            // FIXME: Initializer for x is a DesignatedInitListExpr, hence it is1819            // of struct type and omitted.1820          }},1821      {1822          R"cpp(// Field, field designator1823            struct Foo { int x; int y; };1824            int main() {1825              Foo bar = { .^[[x]] = 2, .y = 2 };1826            }1827          )cpp",1828          [](HoverInfo &HI) {1829            HI.Name = "x";1830            HI.Kind = index::SymbolKind::Field;1831            HI.NamespaceScope = "";1832            HI.LocalScope = "Foo::";1833            HI.Type = "int";1834            HI.Definition = "int x";1835          }},1836      {1837          R"cpp(// Method call1838            struct Foo { int x(); };1839            int main() {1840              Foo bar;1841              bar.^[[x]]();1842            }1843          )cpp",1844          [](HoverInfo &HI) {1845            HI.Name = "x";1846            HI.Kind = index::SymbolKind::InstanceMethod;1847            HI.NamespaceScope = "";1848            HI.LocalScope = "Foo::";1849            HI.Type = "int ()";1850            HI.Definition = "int x()";1851            HI.ReturnType = "int";1852            HI.Parameters = std::vector<HoverInfo::Param>{};1853          }},1854      {1855          R"cpp(// Static method call1856            struct Foo { static int x(); };1857            int main() {1858              Foo::^[[x]]();1859            }1860          )cpp",1861          [](HoverInfo &HI) {1862            HI.Name = "x";1863            HI.Kind = index::SymbolKind::StaticMethod;1864            HI.NamespaceScope = "";1865            HI.LocalScope = "Foo::";1866            HI.Type = "int ()";1867            HI.Definition = "static int x()";1868            HI.ReturnType = "int";1869            HI.Parameters = std::vector<HoverInfo::Param>{};1870          }},1871      {1872          R"cpp(// Typedef1873            typedef int Foo;1874            int main() {1875              ^[[Foo]] bar;1876            }1877          )cpp",1878          [](HoverInfo &HI) {1879            HI.Name = "Foo";1880            HI.Kind = index::SymbolKind::TypeAlias;1881            HI.NamespaceScope = "";1882            HI.Definition = "typedef int Foo";1883            HI.Type = "int";1884            HI.Documentation = "Typedef";1885          }},1886      {1887          R"cpp(// Typedef with embedded definition1888            typedef struct Bar {} Foo;1889            int main() {1890              ^[[Foo]] bar;1891            }1892          )cpp",1893          [](HoverInfo &HI) {1894            HI.Name = "Foo";1895            HI.Kind = index::SymbolKind::TypeAlias;1896            HI.NamespaceScope = "";1897            HI.Definition = "typedef struct Bar Foo";1898            HI.Type = "struct Bar";1899            HI.Documentation = "Typedef with embedded definition";1900          }},1901      {1902          R"cpp(// Namespace1903            namespace ns {1904            struct Foo { static void bar(); };1905            } // namespace ns1906            int main() { ^[[ns]]::Foo::bar(); }1907          )cpp",1908          [](HoverInfo &HI) {1909            HI.Name = "ns";1910            HI.Kind = index::SymbolKind::Namespace;1911            HI.NamespaceScope = "";1912            HI.Definition = "namespace ns {}";1913          }},1914      {1915          R"cpp(// Anonymous namespace1916            namespace ns {1917              namespace {1918                int foo;1919              } // anonymous namespace1920            } // namespace ns1921            int main() { ns::[[f^oo]]++; }1922          )cpp",1923          [](HoverInfo &HI) {1924            HI.Name = "foo";1925            HI.Kind = index::SymbolKind::Variable;1926            HI.NamespaceScope = "ns::";1927            HI.Type = "int";1928            HI.Definition = "int foo";1929          }},1930      {1931          R"cpp(// Function definition via using declaration1932            namespace ns {1933              void foo();1934            }1935            int main() {1936              using ns::foo;1937              ^[[foo]]();1938            }1939          )cpp",1940          [](HoverInfo &HI) {1941            HI.Name = "foo";1942            HI.Kind = index::SymbolKind::Function;1943            HI.NamespaceScope = "ns::";1944            HI.Type = "void ()";1945            HI.Definition = "void foo()";1946            HI.Documentation = "";1947            HI.ReturnType = "void";1948            HI.Parameters = std::vector<HoverInfo::Param>{};1949          }},1950      {1951          R"cpp( // using declaration and two possible function declarations1952            namespace ns { void foo(int); void foo(char); }1953            using ns::foo;1954            template <typename T> void bar() { [[f^oo]](T{}); }1955          )cpp",1956          [](HoverInfo &HI) {1957            HI.Name = "foo";1958            HI.Kind = index::SymbolKind::Using;1959            HI.NamespaceScope = "";1960            HI.Definition = "using ns::foo";1961          }},1962      {1963          R"cpp(// Macro1964            #define MACRO 01965            int main() { return ^[[MACRO]]; }1966          )cpp",1967          [](HoverInfo &HI) {1968            HI.Name = "MACRO";1969            HI.Value = "0";1970            HI.Type = "int";1971            HI.Kind = index::SymbolKind::Macro;1972            HI.Definition = "#define MACRO 0\n\n"1973                            "// Expands to\n"1974                            "0";1975          }},1976      {1977          R"cpp(// Macro1978            #define MACRO 01979            #define MACRO2 ^[[MACRO]]1980          )cpp",1981          [](HoverInfo &HI) {1982            HI.Name = "MACRO";1983            HI.Kind = index::SymbolKind::Macro;1984            HI.Definition = "#define MACRO 0";1985            // NOTE MACRO doesn't have expansion since it technically isn't1986            // expanded here1987          }},1988      {1989          R"cpp(// Macro1990            #define MACRO {\1991              return 0;\1992            }1993            int main() ^[[MACRO]]1994          )cpp",1995          [](HoverInfo &HI) {1996            HI.Name = "MACRO";1997            HI.Kind = index::SymbolKind::Macro;1998            HI.Definition =1999                R"cpp(#define MACRO                                                                  \2000  {                                                                            \2001    return 0;                                                                  \2002  }2003 2004// Expands to2005{2006  return 0;2007})cpp";2008          }},2009      {2010          R"cpp(// Forward class declaration2011            class Foo;2012            class Foo {};2013            [[F^oo]]* foo();2014          )cpp",2015          [](HoverInfo &HI) {2016            HI.Name = "Foo";2017            HI.Kind = index::SymbolKind::Class;2018            HI.NamespaceScope = "";2019            HI.Definition = "class Foo {}";2020            HI.Documentation = "Forward class declaration";2021          }},2022      {2023          R"cpp(// Function declaration2024            void foo();2025            void g() { [[f^oo]](); }2026            void foo() {}2027          )cpp",2028          [](HoverInfo &HI) {2029            HI.Name = "foo";2030            HI.Kind = index::SymbolKind::Function;2031            HI.NamespaceScope = "";2032            HI.Type = "void ()";2033            HI.Definition = "void foo()";2034            HI.Documentation = "Function declaration";2035            HI.ReturnType = "void";2036            HI.Parameters = std::vector<HoverInfo::Param>{};2037          }},2038      {2039          R"cpp(// Enum declaration2040            enum Hello {2041              ONE, TWO, THREE,2042            };2043            void foo() {2044              [[Hel^lo]] hello = ONE;2045            }2046          )cpp",2047          [](HoverInfo &HI) {2048            HI.Name = "Hello";2049            HI.Kind = index::SymbolKind::Enum;2050            HI.NamespaceScope = "";2051            HI.Definition = "enum Hello {}";2052            HI.Documentation = "Enum declaration";2053          }},2054      {2055          R"cpp(// Enumerator2056            enum Hello {2057              ONE, TWO, THREE,2058            };2059            void foo() {2060              Hello hello = [[O^NE]];2061            }2062          )cpp",2063          [](HoverInfo &HI) {2064            HI.Name = "ONE";2065            HI.Kind = index::SymbolKind::EnumConstant;2066            HI.NamespaceScope = "";2067            HI.LocalScope = "Hello::";2068            HI.Type = "enum Hello";2069            HI.Definition = "ONE";2070            HI.Value = "0";2071          }},2072      {2073          R"cpp(// C++20's using enum2074            enum class Hello {2075              ONE, TWO, THREE,2076            };2077            void foo() {2078              using enum Hello;2079              Hello hello = [[O^NE]];2080            }2081          )cpp",2082          [](HoverInfo &HI) {2083            HI.Name = "ONE";2084            HI.Kind = index::SymbolKind::EnumConstant;2085            HI.NamespaceScope = "";2086            HI.LocalScope = "Hello::";2087            HI.Type = "enum Hello";2088            HI.Definition = "ONE";2089            HI.Value = "0";2090          }},2091      {2092          R"cpp(// Enumerator in anonymous enum2093            enum {2094              ONE, TWO, THREE,2095            };2096            void foo() {2097              int hello = [[O^NE]];2098            }2099          )cpp",2100          [](HoverInfo &HI) {2101            HI.Name = "ONE";2102            HI.Kind = index::SymbolKind::EnumConstant;2103            HI.NamespaceScope = "";2104            // FIXME: This should be `(anon enum)::`2105            HI.LocalScope = "";2106            HI.Type = "enum (unnamed)";2107            HI.Definition = "ONE";2108            HI.Value = "0";2109          }},2110      {2111          R"cpp(// Global variable2112            static int hey = 10;2113            void foo() {2114              [[he^y]]++;2115            }2116          )cpp",2117          [](HoverInfo &HI) {2118            HI.Name = "hey";2119            HI.Kind = index::SymbolKind::Variable;2120            HI.NamespaceScope = "";2121            HI.Type = "int";2122            HI.Definition = "static int hey = 10";2123            HI.Documentation = "Global variable";2124            // FIXME: Value shouldn't be set in this case2125            HI.Value = "10 (0xa)";2126          }},2127      {2128          R"cpp(// Global variable in namespace2129            namespace ns1 {2130              static long long hey = -36637162602497;2131            }2132            void foo() {2133              ns1::[[he^y]]++;2134            }2135          )cpp",2136          [](HoverInfo &HI) {2137            HI.Name = "hey";2138            HI.Kind = index::SymbolKind::Variable;2139            HI.NamespaceScope = "ns1::";2140            HI.Type = "long long";2141            HI.Definition = "static long long hey = -36637162602497";2142            HI.Value = "-36637162602497 (0xffffdeadbeefffff)"; // needs 64 bits2143          }},2144      {2145          R"cpp(// Field in anonymous struct2146            static struct {2147              int hello;2148            } s;2149            void foo() {2150              s.[[he^llo]]++;2151            }2152          )cpp",2153          [](HoverInfo &HI) {2154            HI.Name = "hello";2155            HI.Kind = index::SymbolKind::Field;2156            HI.NamespaceScope = "";2157            HI.LocalScope = "(anonymous struct)::";2158            HI.Type = "int";2159            HI.Definition = "int hello";2160          }},2161      {2162          R"cpp(// Templated function2163            template <typename T>2164            T foo() {2165              return 17;2166            }2167            void g() { auto x = [[f^oo]]<int>(); }2168          )cpp",2169          [](HoverInfo &HI) {2170            HI.Name = "foo";2171            HI.Kind = index::SymbolKind::Function;2172            HI.NamespaceScope = "";2173            HI.Type = "int ()";2174            HI.Definition = "template <> int foo<int>()";2175            HI.Documentation = "Templated function";2176            HI.ReturnType = "int";2177            HI.Parameters = std::vector<HoverInfo::Param>{};2178            // FIXME: We should populate template parameters with arguments in2179            // case of instantiations.2180          }},2181      {2182          R"cpp(// Anonymous union2183            struct outer {2184              union {2185                int abc, def;2186              } v;2187            };2188            void g() { struct outer o; o.v.[[d^ef]]++; }2189          )cpp",2190          [](HoverInfo &HI) {2191            HI.Name = "def";2192            HI.Kind = index::SymbolKind::Field;2193            HI.NamespaceScope = "";2194            HI.LocalScope = "outer::(anonymous union)::";2195            HI.Type = "int";2196            HI.Definition = "int def";2197          }},2198      {2199          R"cpp(// documentation from index2200            int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;2201            void indexSymbol();2202            void g() { [[ind^exSymbol]](); }2203          )cpp",2204          [](HoverInfo &HI) {2205            HI.Name = "indexSymbol";2206            HI.Kind = index::SymbolKind::Function;2207            HI.NamespaceScope = "";2208            HI.Type = "void ()";2209            HI.Definition = "void indexSymbol()";2210            HI.ReturnType = "void";2211            HI.Parameters = std::vector<HoverInfo::Param>{};2212            HI.Documentation = "comment from index";2213          }},2214      {2215          R"cpp(// Simple initialization with auto2216            void foo() {2217              ^[[auto]] i = 1;2218            }2219          )cpp",2220          [](HoverInfo &HI) {2221            HI.Name = "auto";2222            HI.Kind = index::SymbolKind::TypeAlias;2223            HI.Definition = "int";2224          }},2225      {2226          R"cpp(// Simple initialization with const auto2227            void foo() {2228              const ^[[auto]] i = 1;2229            }2230          )cpp",2231          [](HoverInfo &HI) {2232            HI.Name = "auto";2233            HI.Kind = index::SymbolKind::TypeAlias;2234            HI.Definition = "int";2235          }},2236      {2237          R"cpp(// Simple initialization with const auto&2238            void foo() {2239              const ^[[auto]]& i = 1;2240            }2241          )cpp",2242          [](HoverInfo &HI) {2243            HI.Name = "auto";2244            HI.Kind = index::SymbolKind::TypeAlias;2245            HI.Definition = "int";2246          }},2247      {2248          R"cpp(// Simple initialization with auto&2249            void foo() {2250              int x;2251              ^[[auto]]& i = x;2252            }2253          )cpp",2254          [](HoverInfo &HI) {2255            HI.Name = "auto";2256            HI.Kind = index::SymbolKind::TypeAlias;2257            HI.Definition = "int";2258          }},2259      {2260          R"cpp(// Simple initialization with auto*2261            void foo() {2262              int a = 1;2263              ^[[auto]]* i = &a;2264            }2265          )cpp",2266          [](HoverInfo &HI) {2267            HI.Name = "auto";2268            HI.Kind = index::SymbolKind::TypeAlias;2269            HI.Definition = "int";2270          }},2271      {2272          R"cpp(// Simple initialization with auto from pointer2273            void foo() {2274              int a = 1;2275              ^[[auto]] i = &a;2276            }2277          )cpp",2278          [](HoverInfo &HI) {2279            HI.Name = "auto";2280            HI.Kind = index::SymbolKind::TypeAlias;2281            HI.Definition = "int *";2282          }},2283      {2284          R"cpp(// Auto with initializer list.2285            namespace std2286            {2287              template<class _E>2288              class initializer_list { const _E *a, *b; };2289            }2290            void foo() {2291              ^[[auto]] i = {1,2};2292            }2293          )cpp",2294          [](HoverInfo &HI) {2295            HI.Name = "auto";2296            HI.Kind = index::SymbolKind::TypeAlias;2297            HI.Definition = "std::initializer_list<int>";2298          }},2299      {2300          R"cpp(// User defined conversion to auto2301            struct Bar {2302              operator ^[[auto]]() const { return 10; }2303            };2304          )cpp",2305          [](HoverInfo &HI) {2306            HI.Name = "auto";2307            HI.Kind = index::SymbolKind::TypeAlias;2308            HI.Definition = "int";2309          }},2310      {2311          R"cpp(// Simple initialization with decltype(auto)2312            void foo() {2313              ^[[decltype]](auto) i = 1;2314            }2315          )cpp",2316          [](HoverInfo &HI) {2317            HI.Name = "decltype";2318            HI.Kind = index::SymbolKind::TypeAlias;2319            HI.Definition = "int";2320          }},2321      {2322          R"cpp(// Simple initialization with const decltype(auto)2323            void foo() {2324              const int j = 0;2325              ^[[decltype]](auto) i = j;2326            }2327          )cpp",2328          [](HoverInfo &HI) {2329            HI.Name = "decltype";2330            HI.Kind = index::SymbolKind::TypeAlias;2331            HI.Definition = "const int";2332          }},2333      {2334          R"cpp(// Simple initialization with const& decltype(auto)2335            void foo() {2336              int k = 0;2337              const int& j = k;2338              ^[[decltype]](auto) i = j;2339            }2340          )cpp",2341          [](HoverInfo &HI) {2342            HI.Name = "decltype";2343            HI.Kind = index::SymbolKind::TypeAlias;2344            HI.Definition = "const int &";2345          }},2346      {2347          R"cpp(// Simple initialization with & decltype(auto)2348            void foo() {2349              int k = 0;2350              int& j = k;2351              ^[[decltype]](auto) i = j;2352            }2353          )cpp",2354          [](HoverInfo &HI) {2355            HI.Name = "decltype";2356            HI.Kind = index::SymbolKind::TypeAlias;2357            HI.Definition = "int &";2358          }},2359      {2360          R"cpp(// simple trailing return type2361            ^[[auto]] main() -> int {2362              return 0;2363            }2364          )cpp",2365          [](HoverInfo &HI) {2366            HI.Name = "auto";2367            HI.Kind = index::SymbolKind::TypeAlias;2368            HI.Definition = "int";2369          }},2370      {2371          R"cpp(// auto function return with trailing type2372            struct Bar {};2373            ^[[auto]] test() -> decltype(Bar()) {2374              return Bar();2375            }2376          )cpp",2377          [](HoverInfo &HI) {2378            HI.Name = "auto";2379            HI.Kind = index::SymbolKind::TypeAlias;2380            HI.Definition = "Bar";2381            HI.Documentation = "auto function return with trailing type";2382          }},2383      {2384          R"cpp(// trailing return type2385            struct Bar {};2386            auto test() -> ^[[decltype]](Bar()) {2387              return Bar();2388            }2389          )cpp",2390          [](HoverInfo &HI) {2391            HI.Name = "decltype";2392            HI.Kind = index::SymbolKind::TypeAlias;2393            HI.Definition = "Bar";2394            HI.Documentation = "trailing return type";2395          }},2396      {2397          R"cpp(// auto in function return2398            struct Bar {};2399            ^[[auto]] test() {2400              return Bar();2401            }2402          )cpp",2403          [](HoverInfo &HI) {2404            HI.Name = "auto";2405            HI.Kind = index::SymbolKind::TypeAlias;2406            HI.Definition = "Bar";2407            HI.Documentation = "auto in function return";2408          }},2409      {2410          R"cpp(// auto& in function return2411            struct Bar {};2412            ^[[auto]]& test() {2413              static Bar x;2414              return x;2415            }2416          )cpp",2417          [](HoverInfo &HI) {2418            HI.Name = "auto";2419            HI.Kind = index::SymbolKind::TypeAlias;2420            HI.Definition = "Bar";2421            HI.Documentation = "auto& in function return";2422          }},2423      {2424          R"cpp(// auto* in function return2425            struct Bar {};2426            ^[[auto]]* test() {2427              Bar* bar;2428              return bar;2429            }2430          )cpp",2431          [](HoverInfo &HI) {2432            HI.Name = "auto";2433            HI.Kind = index::SymbolKind::TypeAlias;2434            HI.Definition = "Bar";2435            HI.Documentation = "auto* in function return";2436          }},2437      {2438          R"cpp(// const auto& in function return2439            struct Bar {};2440            const ^[[auto]]& test() {2441              static Bar x;2442              return x;2443            }2444          )cpp",2445          [](HoverInfo &HI) {2446            HI.Name = "auto";2447            HI.Kind = index::SymbolKind::TypeAlias;2448            HI.Definition = "Bar";2449            HI.Documentation = "const auto& in function return";2450          }},2451      {2452          R"cpp(// decltype(auto) in function return2453            struct Bar {};2454            ^[[decltype]](auto) test() {2455              return Bar();2456            }2457          )cpp",2458          [](HoverInfo &HI) {2459            HI.Name = "decltype";2460            HI.Kind = index::SymbolKind::TypeAlias;2461            HI.Definition = "Bar";2462            HI.Documentation = "decltype(auto) in function return";2463          }},2464      {2465          R"cpp(// decltype(auto) reference in function return2466            ^[[decltype]](auto) test() {2467              static int a;2468              return (a);2469            }2470          )cpp",2471          [](HoverInfo &HI) {2472            HI.Name = "decltype";2473            HI.Kind = index::SymbolKind::TypeAlias;2474            HI.Definition = "int &";2475          }},2476      {2477          R"cpp(// decltype lvalue reference2478            void foo() {2479              int I = 0;2480              ^[[decltype]](I) J = I;2481            }2482          )cpp",2483          [](HoverInfo &HI) {2484            HI.Name = "decltype";2485            HI.Kind = index::SymbolKind::TypeAlias;2486            HI.Definition = "int";2487          }},2488      {2489          R"cpp(// decltype lvalue reference2490            void foo() {2491              int I= 0;2492              int &K = I;2493              ^[[decltype]](K) J = I;2494            }2495          )cpp",2496          [](HoverInfo &HI) {2497            HI.Name = "decltype";2498            HI.Kind = index::SymbolKind::TypeAlias;2499            HI.Definition = "int &";2500          }},2501      {2502          R"cpp(// decltype lvalue reference parenthesis2503            void foo() {2504              int I = 0;2505              ^[[decltype]]((I)) J = I;2506            }2507          )cpp",2508          [](HoverInfo &HI) {2509            HI.Name = "decltype";2510            HI.Kind = index::SymbolKind::TypeAlias;2511            HI.Definition = "int &";2512          }},2513      {2514          R"cpp(// decltype rvalue reference2515            void foo() {2516              int I = 0;2517              ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);2518            }2519          )cpp",2520          [](HoverInfo &HI) {2521            HI.Name = "decltype";2522            HI.Kind = index::SymbolKind::TypeAlias;2523            HI.Definition = "int &&";2524          }},2525      {2526          R"cpp(// decltype rvalue reference function call2527            int && bar();2528            void foo() {2529              int I = 0;2530              ^[[decltype]](bar()) J = bar();2531            }2532          )cpp",2533          [](HoverInfo &HI) {2534            HI.Name = "decltype";2535            HI.Kind = index::SymbolKind::TypeAlias;2536            HI.Definition = "int &&";2537          }},2538      {2539          R"cpp(// decltype of function with trailing return type.2540            struct Bar {};2541            auto test() -> decltype(Bar()) {2542              return Bar();2543            }2544            void foo() {2545              ^[[decltype]](test()) i = test();2546            }2547          )cpp",2548          [](HoverInfo &HI) {2549            HI.Name = "decltype";2550            HI.Kind = index::SymbolKind::TypeAlias;2551            HI.Definition = "Bar";2552            HI.Documentation =2553                "decltype of function with trailing return type.";2554          }},2555      {2556          R"cpp(// decltype of var with decltype.2557            void foo() {2558              int I = 0;2559              decltype(I) J = I;2560              ^[[decltype]](J) K = J;2561            }2562          )cpp",2563          [](HoverInfo &HI) {2564            HI.Name = "decltype";2565            HI.Kind = index::SymbolKind::TypeAlias;2566            HI.Definition = "int";2567          }},2568      {2569          R"cpp(// decltype of dependent type2570            template <typename T>2571            struct X {2572              using Y = ^[[decltype]](T::Z);2573            };2574          )cpp",2575          [](HoverInfo &HI) {2576            HI.Name = "decltype";2577            HI.Kind = index::SymbolKind::TypeAlias;2578            HI.Definition = "<dependent type>";2579          }},2580      {2581          R"cpp(// More complicated structured types.2582            int bar();2583            ^[[auto]] (*foo)() = bar;2584          )cpp",2585          [](HoverInfo &HI) {2586            HI.Name = "auto";2587            HI.Kind = index::SymbolKind::TypeAlias;2588            HI.Definition = "int";2589          }},2590      {2591          R"cpp(// Should not crash when evaluating the initializer.2592            struct Test {};2593            void test() { Test && [[te^st]] = {}; }2594          )cpp",2595          [](HoverInfo &HI) {2596            HI.Name = "test";2597            HI.Kind = index::SymbolKind::Variable;2598            HI.NamespaceScope = "";2599            HI.LocalScope = "test::";2600            HI.Type = "Test &&";2601            HI.Definition = "Test &&test = {}";2602          }},2603      {2604          R"cpp(// Shouldn't crash when evaluating the initializer.2605            struct Bar {}; // error-ok2606            struct Foo { void foo(Bar x = y); }2607            void Foo::foo(Bar [[^x]]) {})cpp",2608          [](HoverInfo &HI) {2609            HI.Name = "x";2610            HI.Kind = index::SymbolKind::Parameter;2611            HI.NamespaceScope = "";2612            HI.LocalScope = "Foo::foo::";2613            HI.Type = "Bar";2614            HI.Definition = "Bar x = <recovery - expr>()";2615          }},2616      {2617          R"cpp(// auto on alias2618          typedef int int_type;2619          ^[[auto]] x = int_type();2620          )cpp",2621          [](HoverInfo &HI) {2622            HI.Name = "auto";2623            HI.Kind = index::SymbolKind::TypeAlias;2624            HI.Definition = "int_type // aka: int";2625          }},2626      {2627          R"cpp(// auto on alias2628          struct cls {};2629          typedef cls cls_type;2630          ^[[auto]] y = cls_type();2631          )cpp",2632          [](HoverInfo &HI) {2633            HI.Name = "auto";2634            HI.Kind = index::SymbolKind::TypeAlias;2635            HI.Definition = "cls_type // aka: cls";2636            HI.Documentation = "auto on alias";2637          }},2638      {2639          R"cpp(// auto on alias2640          template <class>2641          struct templ {};2642          ^[[auto]] z = templ<int>();2643          )cpp",2644          [](HoverInfo &HI) {2645            HI.Name = "auto";2646            HI.Kind = index::SymbolKind::TypeAlias;2647            HI.Definition = "templ<int>";2648            HI.Documentation = "auto on alias";2649          }},2650      {2651          R"cpp(// Undeduced auto declaration2652            template<typename T>2653            void foo() {2654              ^[[auto]] x = T();2655            }2656          )cpp",2657          [](HoverInfo &HI) {2658            HI.Name = "auto";2659            HI.Kind = index::SymbolKind::TypeAlias;2660            HI.Definition = "T";2661          }},2662      {2663          R"cpp(// Undeduced auto return type2664            template<typename T>2665            ^[[auto]] foo() {2666              return T();2667            }2668          )cpp",2669          [](HoverInfo &HI) {2670            HI.Name = "auto";2671            HI.Kind = index::SymbolKind::TypeAlias;2672            HI.Definition = "/* not deduced */";2673          }},2674      {2675          R"cpp(// Template auto parameter2676            template<[[a^uto]] T>2677              void func() {2678            }2679          )cpp",2680          [](HoverInfo &HI) {2681            // FIXME: not sure this is what we want, but this2682            // is what we currently get with getDeducedType2683            HI.Name = "auto";2684            HI.Kind = index::SymbolKind::TypeAlias;2685            HI.Definition = "/* not deduced */";2686          }},2687      {2688          R"cpp(// Undeduced decltype(auto) return type2689            template<typename T>2690            ^[[decltype]](auto) foo() {2691              return T();2692            }2693          )cpp",2694          [](HoverInfo &HI) {2695            HI.Name = "decltype";2696            HI.Kind = index::SymbolKind::TypeAlias;2697            HI.Definition = "/* not deduced */";2698          }},2699      {2700          R"cpp(// should not crash.2701          template <class T> struct cls {2702            int method();2703          };2704 2705          auto test = cls<int>().[[m^ethod]]();2706          )cpp",2707          [](HoverInfo &HI) {2708            HI.Definition = "int method()";2709            HI.Kind = index::SymbolKind::InstanceMethod;2710            HI.NamespaceScope = "";2711            HI.LocalScope = "cls<int>::";2712            HI.Name = "method";2713            HI.Parameters.emplace();2714            HI.ReturnType = "int";2715            HI.Type = "int ()";2716          }},2717      {2718          R"cpp(// type of nested templates.2719          template <class T> struct cls {};2720          cls<cls<cls<int>>> [[fo^o]];2721          )cpp",2722          [](HoverInfo &HI) {2723            HI.Definition = "cls<cls<cls<int>>> foo";2724            HI.Kind = index::SymbolKind::Variable;2725            HI.NamespaceScope = "";2726            HI.Name = "foo";2727            HI.Type = "cls<cls<cls<int>>>";2728          }},2729      {2730          R"cpp(// type of nested templates.2731          template <class T> struct cls {};2732          [[cl^s]]<cls<cls<int>>> foo;2733          )cpp",2734          [](HoverInfo &HI) {2735            HI.Definition = "template <> struct cls<cls<cls<int>>> {}";2736            HI.Kind = index::SymbolKind::Struct;2737            HI.NamespaceScope = "";2738            HI.Name = "cls<cls<cls<int>>>";2739            HI.Documentation = "type of nested templates.";2740          }},2741      {2742          R"cpp(// type with decltype2743          int a;2744          decltype(a) [[b^]] = a;)cpp",2745          [](HoverInfo &HI) {2746            HI.Definition = "decltype(a) b = a";2747            HI.Kind = index::SymbolKind::Variable;2748            HI.NamespaceScope = "";2749            HI.Name = "b";2750            HI.Type = "int";2751          }},2752      {2753          R"cpp(// type with decltype2754          int a;2755          decltype(a) c;2756          decltype(c) [[b^]] = a;)cpp",2757          [](HoverInfo &HI) {2758            HI.Definition = "decltype(c) b = a";2759            HI.Kind = index::SymbolKind::Variable;2760            HI.NamespaceScope = "";2761            HI.Name = "b";2762            HI.Type = "int";2763          }},2764      {2765          R"cpp(// type with decltype2766          int a;2767          const decltype(a) [[b^]] = a;)cpp",2768          [](HoverInfo &HI) {2769            HI.Definition = "const decltype(a) b = a";2770            HI.Kind = index::SymbolKind::Variable;2771            HI.NamespaceScope = "";2772            HI.Name = "b";2773            HI.Type = "int";2774          }},2775      {2776          R"cpp(// type with decltype2777          int a;2778          auto [[f^oo]](decltype(a) x) -> decltype(a) { return 0; })cpp",2779          [](HoverInfo &HI) {2780            HI.Definition = "auto foo(decltype(a) x) -> decltype(a)";2781            HI.Kind = index::SymbolKind::Function;2782            HI.NamespaceScope = "";2783            HI.Name = "foo";2784            // FIXME: Handle composite types with decltype with a printing2785            // policy.2786            HI.Type = {"auto (decltype(a)) -> decltype(a)",2787                       "auto (int) -> int"};2788            HI.ReturnType = "int";2789            HI.Parameters = {{{"int"}, std::string("x"), std::nullopt}};2790          }},2791      {2792          R"cpp(// sizeof expr2793          void foo() {2794            (void)[[size^of]](char);2795          })cpp",2796          [](HoverInfo &HI) {2797            HI.Name = "expression";2798            HI.Type = {"__size_t", "unsigned long"};2799            HI.Value = "1";2800          }},2801      {2802          R"cpp(// alignof expr2803          void foo() {2804            (void)[[align^of]](char);2805          })cpp",2806          [](HoverInfo &HI) {2807            HI.Name = "expression";2808            HI.Type = {"__size_t", "unsigned long"};2809            HI.Value = "1";2810          }},2811      {2812          R"cpp(2813          template <typename T = int>2814          void foo(const T& = T()) {2815            [[f^oo]]<>(3);2816          })cpp",2817          [](HoverInfo &HI) {2818            HI.Name = "foo";2819            HI.Kind = index::SymbolKind::Function;2820            HI.Type = "void (const int &)";2821            HI.ReturnType = "void";2822            HI.Parameters = {2823                {{"const int &"}, std::nullopt, std::string("T()")}};2824            HI.Definition = "template <> void foo<int>(const int &)";2825            HI.NamespaceScope = "";2826          }},2827      {2828          R"cpp(// should not crash2829           @interface ObjC {2830             char [[da^ta]];2831           }@end2832          )cpp",2833          [](HoverInfo &HI) {2834            HI.Name = "data";2835            HI.Type = "char";2836            HI.Kind = index::SymbolKind::Field;2837            HI.LocalScope = "ObjC::";2838            HI.NamespaceScope = "";2839            HI.Definition = "char data";2840          }},2841      {2842          R"cpp(2843          @interface MYObject2844          @end2845          @interface Interface2846          @property(retain) [[MYOb^ject]] *x;2847          @end2848          )cpp",2849          [](HoverInfo &HI) {2850            HI.Name = "MYObject";2851            HI.Kind = index::SymbolKind::Class;2852            HI.NamespaceScope = "";2853            HI.Definition = "@interface MYObject\n@end";2854          }},2855      {2856          R"cpp(2857          @interface MYObject2858          @end2859          @interface Interface2860          - (void)doWith:([[MYOb^ject]] *)object;2861          @end2862          )cpp",2863          [](HoverInfo &HI) {2864            HI.Name = "MYObject";2865            HI.Kind = index::SymbolKind::Class;2866            HI.NamespaceScope = "";2867            HI.Definition = "@interface MYObject\n@end";2868          }},2869      {2870          R"cpp(// this expr2871          // comment2872          namespace ns {2873            class Foo {2874              Foo* bar() {2875                return [[t^his]];2876              }2877            };2878          }2879          )cpp",2880          [](HoverInfo &HI) {2881            HI.Name = "this";2882            HI.Definition = "ns::Foo *";2883          }},2884      {2885          R"cpp(// this expr for template class2886          namespace ns {2887            template <typename T>2888            class Foo {2889              Foo* bar() const {2890                return [[t^his]];2891              }2892            };2893          }2894          )cpp",2895          [](HoverInfo &HI) {2896            HI.Name = "this";2897            HI.Definition = "const ns::Foo<T> *";2898          }},2899      {2900          R"cpp(// this expr for specialization class2901          namespace ns {2902            template <typename T> class Foo {};2903            template <>2904            struct Foo<int> {2905              Foo* bar() {2906                return [[thi^s]];2907              }2908            };2909          }2910          )cpp",2911          [](HoverInfo &HI) {2912            HI.Name = "this";2913            HI.Definition = "ns::Foo<int> *";2914          }},2915      {2916          R"cpp(// this expr for partial specialization struct2917          namespace ns {2918            template <typename T, typename F> struct Foo {};2919            template <typename F>2920            struct Foo<int, F> {2921              Foo* bar() const {2922                return [[thi^s]];2923              }2924            };2925          }2926          )cpp",2927          [](HoverInfo &HI) {2928            HI.Name = "this";2929            HI.Definition = "const ns::Foo<int, F> *";2930          }},2931      {2932          R"cpp(2933          @interface MYObject2934          @end2935          @interface MYObject (Private)2936          @property(nonatomic, assign) int privateField;2937          @end2938 2939          int someFunction() {2940            MYObject *obj = [MYObject sharedInstance];2941            return obj.[[private^Field]];2942          }2943          )cpp",2944          [](HoverInfo &HI) {2945            HI.Name = "privateField";2946            HI.Kind = index::SymbolKind::InstanceProperty;2947            HI.LocalScope = "MYObject(Private)::";2948            HI.NamespaceScope = "";2949            HI.Definition = "@property(nonatomic, assign, unsafe_unretained, "2950                            "readwrite) int privateField;";2951          }},2952      {2953          R"cpp(2954          @protocol MYProtocol2955          @property(nonatomic, assign) int prop1;2956          @end2957 2958          int someFunction() {2959            id<MYProtocol> obj = 0;2960            return obj.[[pro^p1]];2961          }2962          )cpp",2963          [](HoverInfo &HI) {2964            HI.Name = "prop1";2965            HI.Kind = index::SymbolKind::InstanceProperty;2966            HI.LocalScope = "MYProtocol::";2967            HI.NamespaceScope = "";2968            HI.Definition = "@property(nonatomic, assign, unsafe_unretained, "2969                            "readwrite) int prop1;";2970          }},2971      {2972          R"cpp(2973          @protocol MYProtocol2974          @end2975          @interface MYObject2976          @end2977 2978          @interface MYObject (Ext) <[[MYProt^ocol]]>2979          @end2980          )cpp",2981          [](HoverInfo &HI) {2982            HI.Name = "MYProtocol";2983            HI.Kind = index::SymbolKind::Protocol;2984            HI.NamespaceScope = "";2985            HI.Definition = "@protocol MYProtocol\n@end";2986          }},2987      {R"objc(2988        @interface Foo2989        @end2990 2991        @implementation Foo(Private)2992        + (int)somePrivateMethod {2993          int [[res^ult]] = 2;2994          return result;2995        }2996        @end2997        )objc",2998       [](HoverInfo &HI) {2999         HI.Name = "result";3000         HI.Definition = "int result = 2";3001         HI.Kind = index::SymbolKind::Variable;3002         HI.Type = "int";3003         HI.LocalScope = "+[Foo(Private) somePrivateMethod]::";3004         HI.NamespaceScope = "";3005         HI.Value = "2";3006       }},3007      {R"objc(3008        @interface Foo3009        @end3010 3011        @implementation Foo3012        - (int)variadicArgMethod:(id)first, ... {3013          int [[res^ult]] = 0;3014          return result;3015        }3016        @end3017        )objc",3018       [](HoverInfo &HI) {3019         HI.Name = "result";3020         HI.Definition = "int result = 0";3021         HI.Kind = index::SymbolKind::Variable;3022         HI.Type = "int";3023         HI.LocalScope = "-[Foo variadicArgMethod:, ...]::";3024         HI.NamespaceScope = "";3025         HI.Value = "0";3026       }},3027      // Should not crash.3028      {R"objc(3029        typedef struct MyRect {} MyRect;3030 3031        @interface IFace3032        @property(nonatomic) MyRect frame;3033        @end3034 3035        MyRect foobar() {3036          MyRect mr;3037          return mr;3038        }3039        void test() {3040          IFace *v;3041          v.frame = [[foo^bar]]();3042        }3043        )objc",3044       [](HoverInfo &HI) {3045         HI.Name = "foobar";3046         HI.Kind = index::SymbolKind::Function;3047         HI.NamespaceScope = "";3048         HI.Definition = "MyRect foobar()";3049         HI.Type = {"MyRect ()", "struct MyRect ()"};3050         HI.ReturnType = {"MyRect", "struct MyRect"};3051         HI.Parameters.emplace();3052       }},3053      {R"cpp(3054         void foo(int * __attribute__(([[non^null]], noescape)) );3055         )cpp",3056       [](HoverInfo &HI) {3057         HI.Name = "nonnull";3058         HI.Kind = index::SymbolKind::Unknown; // FIXME: no suitable value3059         HI.Definition = "__attribute__((nonnull))";3060         HI.Documentation = Attr::getDocumentation(attr::NonNull).str();3061       }},3062      {3063          R"cpp(3064          namespace std {3065          struct strong_ordering {3066            int n;3067            constexpr operator int() const { return n; }3068            static const strong_ordering equal, greater, less;3069          };3070          constexpr strong_ordering strong_ordering::equal = {0};3071          constexpr strong_ordering strong_ordering::greater = {1};3072          constexpr strong_ordering strong_ordering::less = {-1};3073          }3074 3075          struct Foo3076          {3077            int x;3078            // Foo spaceship3079            auto operator<=>(const Foo&) const = default;3080          };3081 3082          bool x = Foo(1) [[!^=]] Foo(2);3083         )cpp",3084          [](HoverInfo &HI) {3085            HI.Type = "bool (const Foo &) const noexcept";3086            HI.Value = "true";3087            HI.Name = "operator==";3088            HI.Parameters = {{{"const Foo &"}, std::nullopt, std::nullopt}};3089            HI.ReturnType = "bool";3090            HI.Kind = index::SymbolKind::InstanceMethod;3091            HI.LocalScope = "Foo::";3092            HI.NamespaceScope = "";3093            HI.Definition =3094                "bool operator==(const Foo &) const noexcept = default";3095            HI.Documentation = "";3096          }},3097  };3098 3099  // Create a tiny index, so tests above can verify documentation is fetched.3100  Symbol IndexSym = func("indexSymbol");3101  IndexSym.Documentation = "comment from index";3102  SymbolSlab::Builder Symbols;3103  Symbols.insert(IndexSym);3104  auto Index =3105      MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());3106 3107  for (const auto &Case : Cases) {3108    SCOPED_TRACE(Case.Code);3109 3110    Annotations T(Case.Code);3111    TestTU TU = TestTU::withCode(T.code());3112    TU.ExtraArgs.push_back("-std=c++20");3113    TU.ExtraArgs.push_back("-xobjective-c++");3114 3115    TU.ExtraArgs.push_back("-Wno-gnu-designator");3116    // Types might be different depending on the target triplet, we chose a3117    // fixed one to make sure tests passes on different platform.3118    TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");3119    auto AST = TU.build();3120    Config Cfg;3121    Cfg.Hover.ShowAKA = true;3122    WithContextValue WithCfg(Config::Key, std::move(Cfg));3123    auto H = getHover(AST, T.point(), format::getLLVMStyle(), Index.get());3124    ASSERT_TRUE(H);3125    HoverInfo Expected;3126    Expected.SymRange = T.range();3127    Case.ExpectedBuilder(Expected);3128 3129    SCOPED_TRACE(H->present(MarkupKind::PlainText));3130    EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);3131    EXPECT_EQ(H->LocalScope, Expected.LocalScope);3132    EXPECT_EQ(H->Name, Expected.Name);3133    EXPECT_EQ(H->Kind, Expected.Kind);3134    EXPECT_EQ(H->Documentation, Expected.Documentation);3135    EXPECT_EQ(H->Definition, Expected.Definition);3136    EXPECT_EQ(H->Type, Expected.Type);3137    EXPECT_EQ(H->ReturnType, Expected.ReturnType);3138    EXPECT_EQ(H->Parameters, Expected.Parameters);3139    EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);3140    EXPECT_EQ(H->SymRange, Expected.SymRange);3141    EXPECT_EQ(H->Value, Expected.Value);3142  }3143}3144 3145TEST(Hover, Providers) {3146  struct {3147    const char *Code;3148    const std::function<void(HoverInfo &)> ExpectedBuilder;3149  } Cases[] = {{R"cpp(3150                  struct Foo {};3151                  Foo F = Fo^o{};3152                )cpp",3153                [](HoverInfo &HI) { HI.Provider = ""; }},3154               {R"cpp(3155                  #include "foo.h"3156                  Foo F = Fo^o{};3157                )cpp",3158                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},3159               {R"cpp(3160                  #include "all.h"3161                  Foo F = Fo^o{};3162                )cpp",3163                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},3164               {R"cpp(3165                  #define FOO 53166                  int F = ^FOO;3167                )cpp",3168                [](HoverInfo &HI) { HI.Provider = ""; }},3169               {R"cpp(3170                  #include "foo.h"3171                  int F = ^FOO;3172                )cpp",3173                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},3174               {R"cpp(3175                  #include "all.h"3176                  int F = ^FOO;3177                )cpp",3178                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},3179               {R"cpp(3180                  #include "foo.h"3181                  Foo A;3182                  Foo B;3183                  Foo C = A ^+ B;3184                )cpp",3185                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},3186               // Hover selects the underlying decl of the using decl3187               {R"cpp(3188                  #include "foo.h"3189                  namespace ns {3190                    using ::Foo;3191                  }3192                  ns::F^oo d;3193                )cpp",3194                [](HoverInfo &HI) { HI.Provider = "\"foo.h\""; }},3195                {R"cpp(3196                  namespace foo {};3197                  using namespace fo^o;3198                )cpp",3199                [](HoverInfo &HI) { HI.Provider = ""; }},3200                };3201 3202  for (const auto &Case : Cases) {3203    Annotations Code{Case.Code};3204    SCOPED_TRACE(Code.code());3205 3206    TestTU TU;3207    TU.Filename = "foo.cpp";3208    TU.Code = Code.code();3209    TU.AdditionalFiles["foo.h"] = guard(R"cpp(3210                                          #define FOO 13211                                          class Foo {};3212                                          Foo& operator+(const Foo, const Foo);3213                                        )cpp");3214    TU.AdditionalFiles["all.h"] = guard("#include \"foo.h\"");3215 3216    auto AST = TU.build();3217    auto H = getHover(AST, Code.point(), format::getLLVMStyle(), nullptr);3218    ASSERT_TRUE(H);3219    HoverInfo Expected;3220    Case.ExpectedBuilder(Expected);3221    SCOPED_TRACE(H->present(MarkupKind::Markdown));3222    EXPECT_EQ(H->Provider, Expected.Provider);3223  }3224}3225 3226TEST(Hover, ParseProviderInfo) {3227  HoverInfo HIFoo;3228  HIFoo.Name = "foo";3229  HIFoo.Provider = "\"foo.h\"";3230 3231  HoverInfo HIFooBar;3232  HIFooBar.Name = "foo";3233  HIFooBar.Provider = "<bar.h>";3234  struct Case {3235    HoverInfo HI;3236    llvm::StringRef ExpectedMarkdown;3237  } Cases[] = {{HIFoo, "### `foo`\n\nprovided by `\"foo.h\"`"},3238               {HIFooBar, "### `foo`\n\nprovided by `<bar.h>`"}};3239 3240  for (const auto &Case : Cases)3241    EXPECT_EQ(Case.HI.present(MarkupKind::Markdown), Case.ExpectedMarkdown);3242}3243 3244TEST(Hover, UsedSymbols) {3245  struct {3246    const char *Code;3247    const std::function<void(HoverInfo &)> ExpectedBuilder;3248  } Cases[] = {{R"cpp(3249                  #include ^"bar.h"3250                  int fstBar = bar1();3251                  int another= bar1(0);3252                  int sndBar = bar2();3253                  Bar bar;3254                  int macroBar = BAR;3255                )cpp",3256                [](HoverInfo &HI) {3257                  HI.UsedSymbolNames = {"BAR", "Bar", "bar1", "bar2"};3258                }},3259               {R"cpp(3260                  #in^clude <vector>3261                  std::vector<int> vec;3262                )cpp",3263                [](HoverInfo &HI) { HI.UsedSymbolNames = {"vector"}; }}};3264  for (const auto &Case : Cases) {3265    Annotations Code{Case.Code};3266    SCOPED_TRACE(Code.code());3267 3268    TestTU TU;3269    TU.Filename = "foo.cpp";3270    TU.Code = Code.code();3271    TU.AdditionalFiles["bar.h"] = guard(R"cpp(3272                                          #define BAR 53273                                          int bar1();3274                                          int bar2();3275                                          int bar1(double);3276                                          class Bar {};3277                                        )cpp");3278    TU.AdditionalFiles["system/vector"] = guard(R"cpp(3279      namespace std {3280        template<typename>3281        class vector{};3282      }3283    )cpp");3284    TU.ExtraArgs.push_back("-isystem" + testPath("system"));3285 3286    auto AST = TU.build();3287    auto H = getHover(AST, Code.point(), format::getLLVMStyle(), nullptr);3288    ASSERT_TRUE(H);3289    HoverInfo Expected;3290    Case.ExpectedBuilder(Expected);3291    SCOPED_TRACE(H->present(MarkupKind::Markdown));3292    EXPECT_EQ(H->UsedSymbolNames, Expected.UsedSymbolNames);3293  }3294}3295 3296TEST(Hover, DocsFromIndex) {3297  Annotations T(R"cpp(3298  template <typename T> class X {};3299  void foo() {3300    auto t = X<int>();3301    X^<int> w;3302    (void)w;3303  })cpp");3304 3305  TestTU TU = TestTU::withCode(T.code());3306  auto AST = TU.build();3307  Symbol IndexSym;3308  IndexSym.ID = getSymbolID(&findDecl(AST, "X"));3309  IndexSym.Documentation = "comment from index";3310  SymbolSlab::Builder Symbols;3311  Symbols.insert(IndexSym);3312  auto Index =3313      MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());3314 3315  for (const auto &P : T.points()) {3316    auto H = getHover(AST, P, format::getLLVMStyle(), Index.get());3317    ASSERT_TRUE(H);3318    EXPECT_EQ(H->Documentation, IndexSym.Documentation);3319  }3320}3321 3322TEST(Hover, DocsFromAST) {3323  Annotations T(R"cpp(3324  // doc3325  template <typename T> class X {};3326  // doc3327  template <typename T> void bar() {}3328  // doc3329  template <typename T> T baz;3330  void foo() {3331    au^to t = X<int>();3332    X^<int>();3333    b^ar<int>();3334    au^to T = ba^z<X<int>>;3335    ba^z<int> = 0;3336  })cpp");3337 3338  TestTU TU = TestTU::withCode(T.code());3339  auto AST = TU.build();3340  for (const auto &P : T.points()) {3341    auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);3342    ASSERT_TRUE(H);3343    EXPECT_EQ(H->Documentation, "doc");3344  }3345}3346 3347TEST(Hover, NoCrash) {3348  Annotations T(R"cpp(3349    /* error-ok */3350    template<typename T> T foo(T);3351 3352    // Setter variable heuristic might fail if the callexpr is broken.3353    struct X { int Y; void [[^setY]](float) { Y = foo(undefined); } };)cpp");3354 3355  TestTU TU = TestTU::withCode(T.code());3356  auto AST = TU.build();3357  for (const auto &P : T.points())3358    getHover(AST, P, format::getLLVMStyle(), nullptr);3359}3360 3361TEST(Hover, NoCrashAPInt64) {3362  Annotations T(R"cpp(3363    constexpr unsigned long value = -1; // wrap around3364    void foo() { va^lue; }3365  )cpp");3366  auto AST = TestTU::withCode(T.code()).build();3367  getHover(AST, T.point(), format::getLLVMStyle(), nullptr);3368}3369 3370TEST(Hover, NoCrashInt128) {3371  Annotations T(R"cpp(3372    constexpr __int128_t value = -4;3373    void foo() { va^lue; }3374  )cpp");3375  auto TU = TestTU::withCode(T.code());3376  // Need a triple that support __int128_t.3377  TU.ExtraArgs.push_back("--target=x86_64-pc-linux-gnu");3378  auto AST = TU.build();3379  auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);3380  ASSERT_TRUE(H);3381  EXPECT_EQ(H->Value, "-4 (0xfffffffc)");3382}3383 3384TEST(Hover, DocsFromMostSpecial) {3385  Annotations T(R"cpp(3386  // doc13387  template <typename T> class $doc1^X {};3388  // doc23389  template <> class $doc2^X<int> {};3390  // doc33391  template <typename T> class $doc3^X<T*> {};3392  void foo() {3393    X$doc1^<char>();3394    X$doc2^<int>();3395    X$doc3^<int*>();3396  })cpp");3397 3398  TestTU TU = TestTU::withCode(T.code());3399  auto AST = TU.build();3400  for (const auto *Comment : {"doc1", "doc2", "doc3"}) {3401    for (const auto &P : T.points(Comment)) {3402      auto H = getHover(AST, P, format::getLLVMStyle(), nullptr);3403      ASSERT_TRUE(H);3404      EXPECT_EQ(H->Documentation, Comment);3405    }3406  }3407}3408 3409TEST(Hover, Present) {3410  struct {3411    const std::function<void(HoverInfo &)> Builder;3412    llvm::StringRef ExpectedMarkdownRender;3413    llvm::StringRef ExpectedDoxygenRender;3414  } Cases[] = {3415      {3416          [](HoverInfo &HI) {3417            HI.Kind = index::SymbolKind::Unknown;3418            HI.Name = "X";3419          },3420          R"(X)",3421          R"(### `X`)",3422      },3423      {3424          [](HoverInfo &HI) {3425            HI.Kind = index::SymbolKind::NamespaceAlias;3426            HI.Name = "foo";3427          },3428          R"(namespace-alias foo)",3429          R"(### namespace-alias `foo`)",3430      },3431      {3432          [](HoverInfo &HI) {3433            HI.Kind = index::SymbolKind::Class;3434            HI.Size = 80;3435            HI.TemplateParameters = {3436                {{"typename"}, std::string("T"), std::nullopt},3437                {{"typename"}, std::string("C"), std::string("bool")},3438            };3439            HI.Documentation = "documentation";3440            HI.Definition =3441                "template <typename T, typename C = bool> class Foo {}";3442            HI.Name = "foo";3443            HI.NamespaceScope.emplace();3444          },3445          R"(class foo3446 3447Size: 10 bytes3448 3449documentation3450 3451template <typename T, typename C = bool> class Foo {})",3452          R"(### class3453 3454---3455```cpp3456template <typename T, typename C = bool> class Foo {}3457```3458 3459---3460### Brief3461 3462documentation3463 3464---3465### Template Parameters3466 3467- `typename T`3468- `typename C = bool`3469 3470---3471Size: 10 bytes)",3472      },3473      {3474          [](HoverInfo &HI) {3475            HI.Kind = index::SymbolKind::Function;3476            HI.Name = "foo";3477            HI.Type = {"type", "c_type"};3478            HI.ReturnType = {"ret_type", "can_ret_type"};3479            HI.Parameters.emplace();3480            HoverInfo::Param P;3481            HI.Parameters->push_back(P);3482            P.Type = {"type", "can_type"};3483            HI.Parameters->push_back(P);3484            P.Name = "foo";3485            HI.Parameters->push_back(P);3486            P.Default = "default";3487            HI.Parameters->push_back(P);3488            HI.NamespaceScope = "ns::";3489            HI.Definition = "ret_type foo(params) {}";3490          },3491          "function foo\n"3492          "\n"3493          "→ ret_type (aka can_ret_type)\n\n"3494          "Parameters:\n\n"3495          "- \n"3496          "- type (aka can_type)\n"3497          "- type foo (aka can_type)\n"3498          "- type foo = default (aka can_type)\n"3499          "\n"3500          "// In namespace ns\n"3501          "ret_type foo(params) {}",3502          R"(### function3503 3504---3505```cpp3506// In namespace ns3507ret_type foo(params) {}3508```3509 3510---3511### Parameters3512 3513- 3514- `type (aka can_type)`3515- `type foo (aka can_type)`3516- `type foo = default (aka can_type)`3517 3518---3519### Returns3520 3521`ret_type (aka can_ret_type)`)",3522      },3523      {3524          [](HoverInfo &HI) {3525            HI.Kind = index::SymbolKind::Field;3526            HI.LocalScope = "test::Bar::";3527            HI.Value = "value";3528            HI.Name = "foo";3529            HI.Type = {"type", "can_type"};3530            HI.Definition = "def";3531            HI.Size = 32;3532            HI.Offset = 96;3533            HI.Padding = 32;3534            HI.Align = 32;3535          },3536          R"(field foo3537 3538Type: type (aka can_type)3539 3540Value = value3541 3542Offset: 12 bytes3543 3544Size: 4 bytes (+4 bytes padding), alignment 4 bytes3545 3546// In test::Bar3547def)",3548          R"(### field3549 3550---3551```cpp3552// In test::Bar3553def3554```3555 3556---3557Type: `type (aka can_type)`3558 3559Value = `value`3560 3561Offset: 12 bytes3562 3563Size: 4 bytes (+4 bytes padding), alignment 4 bytes)",3564      },3565      {3566          [](HoverInfo &HI) {3567            HI.Kind = index::SymbolKind::Field;3568            HI.LocalScope = "test::Bar::";3569            HI.Value = "value";3570            HI.Name = "foo";3571            HI.Type = {"type", "can_type"};3572            HI.Definition = "def";3573            HI.Size = 25;3574            HI.Offset = 35;3575            HI.Padding = 4;3576            HI.Align = 64;3577          },3578          R"(field foo3579 3580Type: type (aka can_type)3581 3582Value = value3583 3584Offset: 4 bytes and 3 bits3585 3586Size: 25 bits (+4 bits padding), alignment 8 bytes3587 3588// In test::Bar3589def)",3590          R"(### field3591 3592---3593```cpp3594// In test::Bar3595def3596```3597 3598---3599Type: `type (aka can_type)`3600 3601Value = `value`3602 3603Offset: 4 bytes and 3 bits3604 3605Size: 25 bits (+4 bits padding), alignment 8 bytes)",3606      },3607      {3608          [](HoverInfo &HI) {3609            HI.Kind = index::SymbolKind::Field;3610            HI.AccessSpecifier = "public";3611            HI.Name = "foo";3612            HI.LocalScope = "test::Bar::";3613            HI.Definition = "def";3614          },3615          R"(field foo3616 3617// In test::Bar3618public: def)",3619          R"(### field3620 3621---3622```cpp3623// In test::Bar3624public: def3625```)",3626      },3627      {3628          [](HoverInfo &HI) {3629            HI.Definition = "size_t method()";3630            HI.AccessSpecifier = "protected";3631            HI.Kind = index::SymbolKind::InstanceMethod;3632            HI.NamespaceScope = "";3633            HI.LocalScope = "cls<int>::";3634            HI.Name = "method";3635            HI.Parameters.emplace();3636            HI.ReturnType = {"size_t", "unsigned long"};3637            HI.Type = {"size_t ()", "unsigned long ()"};3638          },3639          R"(instance-method method3640 3641→ size_t (aka unsigned long)3642 3643// In cls<int>3644protected: size_t method())",3645          R"(### instance-method3646 3647---3648```cpp3649// In cls<int>3650protected: size_t method()3651```3652 3653---3654### Returns3655 3656`size_t (aka unsigned long)`)",3657      },3658      {3659          [](HoverInfo &HI) {3660            HI.Definition = "cls(int a, int b = 5)";3661            HI.AccessSpecifier = "public";3662            HI.Kind = index::SymbolKind::Constructor;3663            HI.NamespaceScope = "";3664            HI.LocalScope = "cls";3665            HI.Name = "cls";3666            HI.Parameters.emplace();3667            HI.Parameters->emplace_back();3668            HI.Parameters->back().Type = "int";3669            HI.Parameters->back().Name = "a";3670            HI.Parameters->emplace_back();3671            HI.Parameters->back().Type = "int";3672            HI.Parameters->back().Name = "b";3673            HI.Parameters->back().Default = "5";3674          },3675          R"(constructor cls3676 3677Parameters:3678 3679- int a3680- int b = 53681 3682// In cls3683public: cls(int a, int b = 5))",3684          R"(### constructor3685 3686---3687```cpp3688// In cls3689public: cls(int a, int b = 5)3690```3691 3692---3693### Parameters3694 3695- `int a`3696- `int b = 5`)",3697      },3698      {3699          [](HoverInfo &HI) {3700            HI.Kind = index::SymbolKind::Union;3701            HI.AccessSpecifier = "private";3702            HI.Name = "foo";3703            HI.NamespaceScope = "ns1::";3704            HI.Definition = "union foo {}";3705          },3706          R"(union foo3707 3708// In namespace ns13709private: union foo {})",3710          R"(### union3711 3712---3713```cpp3714// In namespace ns13715private: union foo {}3716```)",3717      },3718      {3719          [](HoverInfo &HI) {3720            HI.Kind = index::SymbolKind::Variable;3721            HI.Name = "foo";3722            HI.Definition = "int foo = 3";3723            HI.LocalScope = "test::Bar::";3724            HI.Value = "3";3725            HI.Type = "int";3726            HI.CalleeArgInfo.emplace();3727            HI.CalleeArgInfo->Name = "arg_a";3728            HI.CalleeArgInfo->Type = "int";3729            HI.CalleeArgInfo->Default = "7";3730            HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};3731          },3732          R"(variable foo3733 3734Type: int3735 3736Value = 33737 3738Passed as arg_a3739 3740// In test::Bar3741int foo = 3)",3742          R"(### variable3743 3744---3745```cpp3746// In test::Bar3747int foo = 33748```3749 3750---3751Type: `int`3752 3753Value = `3`3754 3755Passed as arg_a)",3756      },3757      {3758          [](HoverInfo &HI) {3759            HI.Kind = index::SymbolKind::Variable;3760            HI.Name = "foo";3761            HI.CalleeArgInfo.emplace();3762            HI.CalleeArgInfo->Type = "int";3763            HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};3764          },3765          R"(variable foo3766 3767Passed by value)",3768          R"(### variable `foo`3769 3770---3771Passed by value)",3772      },3773      {3774          [](HoverInfo &HI) {3775            HI.Kind = index::SymbolKind::Variable;3776            HI.Name = "foo";3777            HI.Definition = "int foo = 3";3778            HI.LocalScope = "test::Bar::";3779            HI.Value = "3";3780            HI.Type = "int";3781            HI.CalleeArgInfo.emplace();3782            HI.CalleeArgInfo->Name = "arg_a";3783            HI.CalleeArgInfo->Type = "int";3784            HI.CalleeArgInfo->Default = "7";3785            HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};3786          },3787          R"(variable foo3788 3789Type: int3790 3791Value = 33792 3793Passed by reference as arg_a3794 3795// In test::Bar3796int foo = 3)",3797          R"(### variable3798 3799---3800```cpp3801// In test::Bar3802int foo = 33803```3804 3805---3806Type: `int`3807 3808Value = `3`3809 3810Passed by reference as arg_a)",3811      },3812      {3813          [](HoverInfo &HI) {3814            HI.Kind = index::SymbolKind::Variable;3815            HI.Name = "foo";3816            HI.Definition = "int foo = 3";3817            HI.LocalScope = "test::Bar::";3818            HI.Value = "3";3819            HI.Type = "int";3820            HI.CalleeArgInfo.emplace();3821            HI.CalleeArgInfo->Name = "arg_a";3822            HI.CalleeArgInfo->Type = {"alias_int", "int"};3823            HI.CalleeArgInfo->Default = "7";3824            HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};3825          },3826          R"(variable foo3827 3828Type: int3829 3830Value = 33831 3832Passed as arg_a (converted to alias_int)3833 3834// In test::Bar3835int foo = 3)",3836          R"(### variable3837 3838---3839```cpp3840// In test::Bar3841int foo = 33842```3843 3844---3845Type: `int`3846 3847Value = `3`3848 3849Passed as arg_a (converted to alias_int))",3850      },3851      {3852          [](HoverInfo &HI) {3853            HI.Kind = index::SymbolKind::Macro;3854            HI.Name = "PLUS_ONE";3855            HI.Definition = "#define PLUS_ONE(X) (X+1)\n\n"3856                            "// Expands to\n"3857                            "(1 + 1)";3858          },3859          R"(macro PLUS_ONE3860 3861#define PLUS_ONE(X) (X+1)3862 3863// Expands to3864(1 + 1))",3865          R"(### macro3866 3867---3868```cpp3869#define PLUS_ONE(X) (X+1)3870 3871// Expands to3872(1 + 1)3873```)",3874      },3875      {3876          [](HoverInfo &HI) {3877            HI.Kind = index::SymbolKind::Variable;3878            HI.Name = "foo";3879            HI.Definition = "int foo = 3";3880            HI.LocalScope = "test::Bar::";3881            HI.Value = "3";3882            HI.Type = "int";3883            HI.CalleeArgInfo.emplace();3884            HI.CalleeArgInfo->Name = "arg_a";3885            HI.CalleeArgInfo->Type = "int";3886            HI.CalleeArgInfo->Default = "7";3887            HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, true};3888          },3889          R"(variable foo3890 3891Type: int3892 3893Value = 33894 3895Passed by const reference as arg_a (converted to int)3896 3897// In test::Bar3898int foo = 3)",3899          R"(### variable3900 3901---3902```cpp3903// In test::Bar3904int foo = 33905```3906 3907---3908Type: `int`3909 3910Value = `3`3911 3912Passed by const reference as arg_a (converted to int))",3913      },3914      {3915          [](HoverInfo &HI) {3916            HI.Name = "stdio.h";3917            HI.Definition = "/usr/include/stdio.h";3918            HI.Kind = index::SymbolKind::IncludeDirective;3919          },3920          R"(stdio.h3921 3922/usr/include/stdio.h)",3923          R"(### `stdio.h`3924 3925`/usr/include/stdio.h`)",3926      },3927      {3928          [](HoverInfo &HI) {3929            HI.Name = "foo.h";3930            HI.UsedSymbolNames = {"Foo", "Bar", "Bar"};3931            HI.Kind = index::SymbolKind::IncludeDirective;3932          },3933          R"(foo.h3934 3935provides Foo, Bar, Bar)",3936          R"(### `foo.h`3937 3938---3939provides `Foo`, `Bar`, `Bar`)",3940      },3941      {[](HoverInfo &HI) {3942         HI.Name = "foo.h";3943         HI.UsedSymbolNames = {"Foo", "Bar", "Baz", "Foobar", "Qux", "Quux"};3944         HI.Kind = index::SymbolKind::IncludeDirective;3945       },3946       R"(foo.h3947 3948provides Foo, Bar, Baz, Foobar, Qux and 1 more)",3949       R"(### `foo.h`3950 3951---3952provides `Foo`, `Bar`, `Baz`, `Foobar`, `Qux` and 1 more)"}};3953 3954  for (const auto &C : Cases) {3955    HoverInfo HI;3956    C.Builder(HI);3957    Config Cfg;3958    Cfg.Hover.ShowAKA = true;3959    Cfg.Documentation.CommentFormat = Config::CommentFormatPolicy::Markdown;3960    WithContextValue WithCfg(Config::Key, std::move(Cfg));3961    EXPECT_EQ(HI.present(MarkupKind::PlainText), C.ExpectedMarkdownRender);3962  }3963  for (const auto &C : Cases) {3964    HoverInfo HI;3965    C.Builder(HI);3966    Config Cfg;3967    Cfg.Hover.ShowAKA = true;3968    Cfg.Documentation.CommentFormat = Config::CommentFormatPolicy::Doxygen;3969    WithContextValue WithCfg(Config::Key, std::move(Cfg));3970    EXPECT_EQ(HI.present(MarkupKind::Markdown), C.ExpectedDoxygenRender);3971  }3972}3973 3974TEST(Hover, PresentDocumentation) {3975  struct {3976    const std::function<void(HoverInfo &)> Builder;3977    llvm::StringRef ExpectedMarkdownRender;3978    llvm::StringRef ExpectedDoxygenRender;3979  } Cases[] = {3980      {[](HoverInfo &HI) {3981         HI.Kind = index::SymbolKind::Function;3982         HI.Documentation = "@brief brief doc\n\n"3983                            "longer doc";3984         HI.Definition = "void foo()";3985         HI.Name = "foo";3986       },3987       R"(### function `foo`3988 3989---3990@brief brief doc3991 3992longer doc3993 3994---3995```cpp3996void foo()3997```)",3998       R"(### function3999 4000---4001```cpp4002void foo()4003```4004 4005---4006### Brief4007 4008brief doc4009 4010---4011### Details4012 4013longer doc)"},4014      {[](HoverInfo &HI) {4015         HI.Kind = index::SymbolKind::Function;4016         HI.Documentation = "@brief brief doc\n\n"4017                            "longer doc";4018         HI.Definition = "int foo()";4019         HI.ReturnType = "int";4020         HI.Name = "foo";4021       },4022       R"(### function `foo`4023 4024---4025→ `int`4026 4027@brief brief doc4028 4029longer doc4030 4031---4032```cpp4033int foo()4034```)",4035       R"(### function4036 4037---4038```cpp4039int foo()4040```4041 4042---4043### Brief4044 4045brief doc4046 4047---4048### Returns4049 4050`int`4051 4052---4053### Details4054 4055longer doc)"},4056      {[](HoverInfo &HI) {4057         HI.Kind = index::SymbolKind::Function;4058         HI.Documentation = R"(@brief brief doc4059 4060longer doc4061@note this is a note4062 4063As you see, notes are "inlined".4064@warning this is a warning4065 4066As well as warnings4067@param a this is a param4068@return it returns something4069@retval 0 if successful4070@retval 1 if failed)";4071         HI.Definition = "int foo(int a)";4072         HI.ReturnType = "int";4073         HI.Name = "foo";4074         HI.Parameters.emplace();4075         HI.Parameters->emplace_back();4076         HI.Parameters->back().Type = "int";4077         HI.Parameters->back().Name = "a";4078       },4079       R"(### function `foo`4080 4081---4082→ `int`4083 4084Parameters:4085 4086- `int a`4087 4088@brief brief doc4089 4090longer doc  4091@note this is a note4092 4093As you see, notes are "inlined".  4094@warning this is a warning4095 4096As well as warnings  4097@param a this is a param  4098@return it returns something  4099@retval 0 if successful  4100@retval 1 if failed4101 4102---4103```cpp4104int foo(int a)4105```)",4106       R"(### function4107 4108---4109```cpp4110int foo(int a)4111```4112 4113---4114### Brief4115 4116brief doc4117 4118---4119### Parameters4120 4121- `int a` - this is a param4122 4123---4124### Returns4125 4126`int` - it returns something4127 4128- `0` - if successful4129- `1` - if failed4130 4131---4132### Details4133 4134longer doc4135 4136**Note:**  4137this is a note4138 4139As you see, notes are "inlined".4140 4141**Warning:**  4142this is a warning4143 4144As well as warnings)"},4145      {[](HoverInfo &HI) {4146         HI.Kind = index::SymbolKind::Function;4147         HI.Documentation = "@brief brief doc\n\n"4148                            "longer doc\n@param a this is a param\n@param b "4149                            "does not exist\n@return it returns something";4150         HI.Definition = "int foo(int a)";4151         HI.ReturnType = "int";4152         HI.Name = "foo";4153         HI.Parameters.emplace();4154         HI.Parameters->emplace_back();4155         HI.Parameters->back().Type = "int";4156         HI.Parameters->back().Name = "a";4157       },4158       R"(### function `foo`4159 4160---4161→ `int`4162 4163Parameters:4164 4165- `int a`4166 4167@brief brief doc4168 4169longer doc  4170@param a this is a param  4171@param b does not exist  4172@return it returns something4173 4174---4175```cpp4176int foo(int a)4177```)",4178       R"(### function4179 4180---4181```cpp4182int foo(int a)4183```4184 4185---4186### Brief4187 4188brief doc4189 4190---4191### Parameters4192 4193- `int a` - this is a param4194 4195---4196### Returns4197 4198`int` - it returns something4199 4200---4201### Details4202 4203longer doc)"},4204  };4205 4206  for (const auto &C : Cases) {4207    HoverInfo HI;4208    C.Builder(HI);4209    Config Cfg;4210    Cfg.Hover.ShowAKA = true;4211    Cfg.Documentation.CommentFormat = Config::CommentFormatPolicy::Markdown;4212    WithContextValue WithCfg(Config::Key, std::move(Cfg));4213    EXPECT_EQ(HI.present(MarkupKind::Markdown), C.ExpectedMarkdownRender);4214  }4215  for (const auto &C : Cases) {4216    HoverInfo HI;4217    C.Builder(HI);4218    Config Cfg;4219    Cfg.Hover.ShowAKA = true;4220    Cfg.Documentation.CommentFormat = Config::CommentFormatPolicy::Doxygen;4221    WithContextValue WithCfg(Config::Key, std::move(Cfg));4222    EXPECT_EQ(HI.present(MarkupKind::Markdown), C.ExpectedDoxygenRender);4223  }4224}4225 4226TEST(Hover, ParseDocumentation) {4227  struct Case {4228    llvm::StringRef Documentation;4229    llvm::StringRef ExpectedRenderEscapedMarkdown;4230    llvm::StringRef ExpectedRenderMarkdown;4231    llvm::StringRef ExpectedRenderPlainText;4232  } Cases[] = {{4233                   " \n foo\nbar",4234                   "foo\nbar",4235                   "foo\nbar",4236                   "foo bar",4237               },4238               {4239                   "foo\nbar \n  ",4240                   "foo\nbar",4241                   "foo\nbar",4242                   "foo bar",4243               },4244               {4245                   "foo  \nbar",4246                   "foo  \nbar",4247                   "foo  \nbar",4248                   "foo\nbar",4249               },4250               {4251                   "foo    \nbar",4252                   "foo    \nbar",4253                   "foo    \nbar",4254                   "foo\nbar",4255               },4256               {4257                   "foo\n\n\nbar",4258                   "foo\n\nbar",4259                   "foo\n\nbar",4260                   "foo\n\nbar",4261               },4262               {4263                   "foo\n\n\n\tbar",4264                   "foo\n\n\tbar",4265                   "foo\n\n\tbar",4266                   "foo\n\nbar",4267               },4268               {4269                   "foo\n\n\n    bar",4270                   "foo\n\n    bar",4271                   "foo\n\n    bar",4272                   "foo\n\nbar",4273               },4274               {4275                   "foo\n\n\n   bar",4276                   "foo\n\n   bar",4277                   "foo\n\n   bar",4278                   "foo\n\nbar",4279               },4280               {4281                   "foo\n\n\n bar",4282                   "foo\n\n bar",4283                   "foo\n\n bar",4284                   "foo\n\nbar",4285               },4286               {4287                   "foo\n\n\n\nbar",4288                   "foo\n\nbar",4289                   "foo\n\nbar",4290                   "foo\n\nbar",4291               },4292               {4293                   "foo\n\n\n\n\tbar",4294                   "foo\n\n\tbar",4295                   "foo\n\n\tbar",4296                   "foo\n\nbar",4297               },4298               {4299                   "foo\n\n\n\n    bar",4300                   "foo\n\n    bar",4301                   "foo\n\n    bar",4302                   "foo\n\nbar",4303               },4304               {4305                   "foo\n\n\n\n   bar",4306                   "foo\n\n   bar",4307                   "foo\n\n   bar",4308                   "foo\n\nbar",4309               },4310               {4311                   "foo\n\n\n\n bar",4312                   "foo\n\n bar",4313                   "foo\n\n bar",4314                   "foo\n\nbar",4315               },4316               {4317                   "foo.\nbar",4318                   "foo.  \nbar",4319                   "foo.  \nbar",4320                   "foo.\nbar",4321               },4322               {4323                   "foo. \nbar",4324                   "foo.   \nbar",4325                   "foo.   \nbar",4326                   "foo.\nbar",4327               },4328               {4329                   "foo\n*bar",4330                   "foo  \n\\*bar",4331                   "foo\n*bar",4332                   "foo\n*bar",4333               },4334               {4335                   "foo\nbar",4336                   "foo\nbar",4337                   "foo\nbar",4338                   "foo bar",4339               },4340               {4341                   "Tests primality of `p`.",4342                   "Tests primality of `p`.",4343                   "Tests primality of `p`.",4344                   "Tests primality of `p`.",4345               },4346               {4347                   "'`' should not occur in `Code`",4348                   "'\\`' should not occur in `Code`",4349                   "'`' should not occur in `Code`",4350                   "'`' should not occur in `Code`",4351               },4352               {4353                   "`not\nparsed`",4354                   "\\`not\nparsed\\`",4355                   "`not\nparsed`",4356                   "`not parsed`",4357               },4358               {4359                   R"(@brief this is a typical use case4360@param x this is x4361\param y this is y4362@return something)",4363                   R"(@brief this is a typical use case  4364@param x this is x  4365\\param y this is y  4366@return something)",4367                   R"(@brief this is a typical use case  4368@param x this is x  4369\param y this is y  4370@return something)",4371                   R"(@brief this is a typical use case4372@param x this is x4373\param y this is y4374@return something)",4375               }};4376 4377  for (const auto &C : Cases) {4378    markup::Document Output;4379    parseDocumentation(C.Documentation, Output);4380 4381    EXPECT_EQ(Output.asEscapedMarkdown(), C.ExpectedRenderEscapedMarkdown);4382    EXPECT_EQ(Output.asMarkdown(), C.ExpectedRenderMarkdown);4383    EXPECT_EQ(Output.asPlainText(), C.ExpectedRenderPlainText);4384  }4385}4386 4387// This is a separate test as headings don't create any differences in4388// plaintext mode.4389TEST(Hover, PresentHeadings) {4390  HoverInfo HI;4391  HI.Kind = index::SymbolKind::Variable;4392  HI.Name = "foo";4393 4394  EXPECT_EQ(HI.present(MarkupKind::Markdown), "### variable `foo`");4395}4396 4397// This is a separate test as rulers behave differently in markdown vs4398// plaintext.4399TEST(Hover, PresentRulers) {4400  HoverInfo HI;4401  HI.Kind = index::SymbolKind::Variable;4402  HI.Name = "foo";4403  HI.Value = "val";4404  HI.Definition = "def";4405 4406  llvm::StringRef ExpectedMarkdown = //4407      "### variable `foo`\n"4408      "\n"4409      "---\n"4410      "Value = `val`\n"4411      "\n"4412      "---\n"4413      "```cpp\n"4414      "def\n"4415      "```";4416  EXPECT_EQ(HI.present(MarkupKind::Markdown), ExpectedMarkdown);4417 4418  llvm::StringRef ExpectedDoxygenMarkdown = //4419      "### variable\n"4420      "\n"4421      "---\n"4422      "```cpp\n"4423      "def\n"4424      "```\n\n"4425      "---\n"4426      "Value = `val`";4427  Config Cfg;4428  Cfg.Hover.ShowAKA = true;4429  Cfg.Documentation.CommentFormat = Config::CommentFormatPolicy::Doxygen;4430  WithContextValue WithCfg(Config::Key, std::move(Cfg));4431  EXPECT_EQ(HI.present(MarkupKind::Markdown), ExpectedDoxygenMarkdown);4432 4433  llvm::StringRef ExpectedPlaintext = R"pt(variable foo4434 4435Value = val4436 4437def)pt";4438  EXPECT_EQ(HI.present(MarkupKind::PlainText), ExpectedPlaintext);4439}4440 4441TEST(Hover, SpaceshipTemplateNoCrash) {4442  Annotations T(R"cpp(4443  namespace std {4444  struct strong_ordering {4445    int n;4446    constexpr operator int() const { return n; }4447    static const strong_ordering equal, greater, less;4448  };4449  constexpr strong_ordering strong_ordering::equal = {0};4450  constexpr strong_ordering strong_ordering::greater = {1};4451  constexpr strong_ordering strong_ordering::less = {-1};4452  }4453 4454  template <typename T>4455  struct S {4456    // Foo bar baz4457    friend auto operator<=>(S, S) = default;4458  };4459  static_assert(S<void>() =^= S<void>());4460    )cpp");4461 4462  TestTU TU = TestTU::withCode(T.code());4463  TU.ExtraArgs.push_back("-std=c++20");4464  auto AST = TU.build();4465  auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);4466  EXPECT_EQ(HI->Documentation, "");4467}4468 4469TEST(Hover, ForwardStructNoCrash) {4470  Annotations T(R"cpp(4471  struct Foo;4472  int bar;4473  auto baz = (Fo^o*)&bar;4474    )cpp");4475 4476  TestTU TU = TestTU::withCode(T.code());4477  auto AST = TU.build();4478  auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);4479  ASSERT_TRUE(HI);4480  EXPECT_EQ(*HI->Value, "&bar");4481}4482 4483TEST(Hover, FunctionParameterDefaulValueNotEvaluatedOnInvalidDecls) {4484  struct {4485    const char *const Code;4486    const std::optional<std::string> HoverValue;4487  } Cases[] = {4488      {R"cpp(4489        // error-ok testing behavior on invalid decl4490        class Foo {};4491        void foo(Foo p^aram = nullptr);4492        )cpp",4493       std::nullopt},4494      {R"cpp(4495        class Foo {};4496        void foo(Foo *p^aram = nullptr);4497        )cpp",4498       "nullptr"},4499  };4500 4501  for (const auto &C : Cases) {4502    Annotations T(C.Code);4503    TestTU TU = TestTU::withCode(T.code());4504    auto AST = TU.build();4505    auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);4506    ASSERT_TRUE(HI);4507    ASSERT_EQ(HI->Value, C.HoverValue);4508  }4509}4510 4511TEST(Hover, DisableShowAKA) {4512  Annotations T(R"cpp(4513    using m_int = int;4514    m_int ^[[a]];4515  )cpp");4516 4517  Config Cfg;4518  Cfg.Hover.ShowAKA = false;4519  WithContextValue WithCfg(Config::Key, std::move(Cfg));4520 4521  TestTU TU = TestTU::withCode(T.code());4522  TU.ExtraArgs.push_back("-std=c++17");4523  auto AST = TU.build();4524  auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);4525 4526  ASSERT_TRUE(H);4527  EXPECT_EQ(H->Type, HoverInfo::PrintedType("m_int"));4528}4529 4530TEST(Hover, HideBigInitializers) {4531  Annotations T(R"cpp(4532  #define A(x) x, x, x, x4533  #define B(x) A(A(A(A(x))))4534  int a^rr[] = {B(0)};4535  )cpp");4536 4537  TestTU TU = TestTU::withCode(T.code());4538  auto AST = TU.build();4539  auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);4540 4541  ASSERT_TRUE(H);4542  EXPECT_EQ(H->Definition, "int arr[]");4543}4544 4545#if defined(__aarch64__)4546// FIXME: AARCH64 sanitizer buildbots are broken after 72142fbac4.4547#define PREDEFINEMACROS_TEST(x) DISABLED_##x4548#else4549#define PREDEFINEMACROS_TEST(x) x4550#endif4551 4552TEST(Hover, PREDEFINEMACROS_TEST(GlobalVarEnumeralCastNoCrash)) {4553  Annotations T(R"cpp(4554    using uintptr_t = __UINTPTR_TYPE__;4555    enum Test : uintptr_t {};4556    unsigned global_var;4557    void foo() {4558      Test v^al = static_cast<Test>(reinterpret_cast<uintptr_t>(&global_var));4559    }4560  )cpp");4561 4562  TestTU TU = TestTU::withCode(T.code());4563  TU.PredefineMacros = true;4564  auto AST = TU.build();4565  auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);4566  ASSERT_TRUE(HI);4567  EXPECT_EQ(*HI->Value, "&global_var");4568}4569 4570TEST(Hover, PREDEFINEMACROS_TEST(GlobalVarIntCastNoCrash)) {4571  Annotations T(R"cpp(4572    using uintptr_t = __UINTPTR_TYPE__;4573    unsigned global_var;4574    void foo() {4575      uintptr_t a^ddress = reinterpret_cast<uintptr_t>(&global_var);4576    }4577  )cpp");4578 4579  TestTU TU = TestTU::withCode(T.code());4580  TU.PredefineMacros = true;4581  auto AST = TU.build();4582  auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);4583  ASSERT_TRUE(HI);4584  EXPECT_EQ(*HI->Value, "&global_var");4585}4586 4587TEST(Hover, Typedefs) {4588  Annotations T(R"cpp(4589  template <bool X, typename T, typename F>4590  struct cond { using type = T; };4591  template <typename T, typename F>4592  struct cond<false, T, F> { using type = F; };4593 4594  template <bool X, typename T, typename F>4595  using type = typename cond<X, T, F>::type;4596 4597  void foo() {4598    using f^oo = type<true, int, double>;4599  }4600  )cpp");4601 4602  TestTU TU = TestTU::withCode(T.code());4603  auto AST = TU.build();4604  auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);4605 4606  ASSERT_TRUE(H && H->Type);4607  EXPECT_EQ(H->Type->Type, "int");4608  EXPECT_EQ(H->Definition, "using foo = type<true, int, double>");4609}4610 4611TEST(Hover, EvaluateMacros) {4612  llvm::StringRef PredefinedCXX = R"cpp(4613#define X 424614#define SizeOf sizeof4615#define AlignOf alignof4616#define PLUS_TWO +24617#define TWO 24618 4619using u64 = unsigned long long;4620// calculate (a ** b) % p4621constexpr u64 pow_with_mod(u64 a, u64 b, u64 p) {4622  u64 ret = 1;4623  while (b) {4624    if (b & 1)4625      ret = (ret * a) % p;4626    a = (a * a) % p;4627    b >>= 1;4628  }4629  return ret;4630}4631#define last_n_digit(x, y, n)                                                  \4632  pow_with_mod(x, y, pow_with_mod(10, n, 2147483647))4633#define declare_struct(X, name, value)                                         \4634  struct X {                                                                   \4635    constexpr auto name() { return value; }                                    \4636  }4637#define gnu_statement_expression(value)                                        \4638  ({                                                                           \4639    declare_struct(Widget, getter, value);                                     \4640    Widget().getter();                                                         \4641  })4642#define define_lambda_begin(lambda, ...)                                       \4643  [&](__VA_ARGS__) {4644#define define_lambda_end() }4645 4646#define left_bracket [4647#define right_bracket ]4648#define dg_left_bracket <:4649#define dg_right_bracket :>4650#define array_decl(type, name, size) type name left_bracket size right_bracket4651  )cpp";4652 4653  struct {4654    llvm::StringRef Code;4655    const std::function<void(std::optional<HoverInfo>, size_t /*Id*/)>4656        Validator;4657  } Cases[] = {4658      {4659          /*Code=*/R"cpp(4660            X^;4661          )cpp",4662          /*Validator=*/4663          [](std::optional<HoverInfo> HI, size_t) {4664            EXPECT_EQ(HI->Value, "42 (0x2a)");4665            EXPECT_EQ(HI->Type, HoverInfo::PrintedType("int"));4666          },4667      },4668      {4669          /*Code=*/R"cpp(4670            Size^Of(int);4671          )cpp",4672          /*Validator=*/4673          [](std::optional<HoverInfo> HI, size_t) {4674            EXPECT_TRUE(HI->Value);4675            EXPECT_TRUE(HI->Type);4676            // Don't validate type or value of `sizeof` and `alignof` as we're4677            // getting different values or desugared types on different4678            // platforms. Same as below.4679          },4680      },4681      {4682          /*Code=*/R"cpp(4683          struct Y {4684            int y;4685            double z;4686          };4687          Alig^nOf(Y);4688        )cpp",4689          /*Validator=*/4690          [](std::optional<HoverInfo> HI, size_t) {4691            EXPECT_TRUE(HI->Value);4692            EXPECT_TRUE(HI->Type);4693          },4694      },4695      {4696          /*Code=*/R"cpp(4697          // 2**32 == 42949672964698          last_n_di^git(2, 32, 6);4699        )cpp",4700          /*Validator=*/4701          [](std::optional<HoverInfo> HI, size_t) {4702            EXPECT_EQ(HI->Value, "967296 (0xec280)");4703            EXPECT_EQ(HI->Type, "u64");4704          },4705      },4706      {4707          /*Code=*/R"cpp(4708          gnu_statement_exp^ression(42);4709        )cpp",4710          /*Validator=*/4711          [](std::optional<HoverInfo> HI, size_t) {4712            EXPECT_EQ(HI->Value, "42 (0x2a)");4713            EXPECT_EQ(HI->Type, "int");4714          },4715      },4716      {4717          /*Code=*/R"cpp(4718          40 + PLU^S_TWO;4719        )cpp",4720          /*Validator=*/4721          [](std::optional<HoverInfo> HI, size_t) {4722            EXPECT_EQ(HI->Value, "2");4723            EXPECT_EQ(HI->Type, "int");4724          },4725      },4726      {4727          /*Code=*/R"cpp(4728          40 PLU^S_TWO;4729        )cpp",4730          /*Validator=*/4731          [](std::optional<HoverInfo> HI, size_t) {4732            EXPECT_FALSE(HI->Value) << HI->Value;4733            EXPECT_FALSE(HI->Type) << HI->Type;4734          },4735      },4736      {4737          /*Code=*/R"cpp(4738          40 + TW^O;4739        )cpp",4740          /*Validator=*/4741          [](std::optional<HoverInfo> HI, size_t) {4742            EXPECT_EQ(HI->Value, "2");4743            EXPECT_EQ(HI->Type, "int");4744          },4745      },4746      {4747          /*Code=*/R"cpp(4748          arra^y_decl(int, vector, 10);4749          vector left_b^racket 3 right_b^racket;4750          vector dg_le^ft_bracket 3 dg_righ^t_bracket;4751        )cpp",4752          /*Validator=*/4753          [](std::optional<HoverInfo> HI, size_t Id) {4754            switch (Id) {4755            case 0:4756              EXPECT_EQ(HI->Type, HoverInfo::PrintedType("int[10]"));4757              break;4758            case 1:4759            case 2:4760            case 3:4761            case 4:4762              EXPECT_FALSE(HI->Type) << HI->Type;4763              EXPECT_FALSE(HI->Value) << HI->Value;4764              break;4765            default:4766              ASSERT_TRUE(false) << "Unhandled id: " << Id;4767            }4768          },4769      },4770      {4771          /*Code=*/R"cpp(4772          constexpr auto value = define_lamb^da_begin(lambda, int, char)4773            // Check if the expansion range is right.4774            return ^last_n_digit(10, 3, 3)^;4775          define_lam^bda_end();4776        )cpp",4777          /*Validator=*/4778          [](std::optional<HoverInfo> HI, size_t Id) {4779            switch (Id) {4780            case 0:4781              EXPECT_FALSE(HI->Value);4782              EXPECT_EQ(HI->Type, HoverInfo::PrintedType("const (lambda)"));4783              break;4784            case 1:4785              EXPECT_EQ(HI->Value, "0");4786              EXPECT_EQ(HI->Type, HoverInfo::PrintedType("u64"));4787              break;4788            case 2:4789              EXPECT_FALSE(HI);4790              break;4791            case 3:4792              EXPECT_FALSE(HI->Type) << HI->Type;4793              EXPECT_FALSE(HI->Value) << HI->Value;4794              break;4795            default:4796              ASSERT_TRUE(false) << "Unhandled id: " << Id;4797            }4798          },4799      },4800  };4801 4802  Config Cfg;4803  Cfg.Hover.ShowAKA = false;4804  WithContextValue WithCfg(Config::Key, std::move(Cfg));4805  for (const auto &C : Cases) {4806    Annotations Code(4807        (PredefinedCXX + "void function() {\n" + C.Code + "}\n").str());4808    auto TU = TestTU::withCode(Code.code());4809    TU.ExtraArgs.push_back("-std=c++17");4810    auto AST = TU.build();4811    for (auto [Index, Position] : llvm::enumerate(Code.points())) {4812      C.Validator(getHover(AST, Position, format::getLLVMStyle(), nullptr),4813                  Index);4814    }4815  }4816 4817  Annotations C(R"c(4818    #define alignof _Alignof4819    void foo() {4820      al^ignof(struct { int x; char y[10]; });4821    }4822  )c");4823 4824  auto TU = TestTU::withCode(C.code());4825  TU.Filename = "TestTU.c";4826  TU.ExtraArgs = {4827      "-std=c17",4828  };4829  auto AST = TU.build();4830  auto H = getHover(AST, C.point(), format::getLLVMStyle(), nullptr);4831 4832  ASSERT_TRUE(H);4833  EXPECT_TRUE(H->Value);4834  EXPECT_TRUE(H->Type);4835}4836 4837TEST(Hover, HoverMacroContentsLimit) {4838  const char *const Code =4839      R"cpp(4840          #define C(A) A##A // Concatenate4841          #define E(A) C(A) // Expand4842          #define Z0032 000000000000000000000000000000004843          #define Z0064 E(Z0032)4844          #define Z0128 E(Z0064)4845          #define Z0256 E(Z0128)4846          #define Z0512 E(Z0256)4847          #define Z1024 E(Z0512)4848          #define Z2048 E(Z1024)4849          #define Z4096 E(Z2048) // 4096 zeroes4850          int main() { return [[^Z4096]]; }4851      )cpp";4852 4853  struct {4854    uint32_t MacroContentsLimit;4855    const std::string ExpectedDefinition;4856  } Cases[] = {4857      // With a limit of 2048, the macro expansion should get dropped.4858      {2048, "#define Z4096 E(Z2048)"},4859      // With a limit of 8192, the macro expansion should be fully expanded.4860      {8192, std::string("#define Z4096 E(Z2048)\n\n") +4861                 std::string("// Expands to\n") + std::string(4096, '0')},4862  };4863  for (const auto &Case : Cases) {4864    SCOPED_TRACE(Code);4865 4866    Annotations T(Code);4867    TestTU TU = TestTU::withCode(T.code());4868    auto AST = TU.build();4869    Config Cfg;4870    Cfg.Hover.MacroContentsLimit = Case.MacroContentsLimit;4871    WithContextValue WithCfg(Config::Key, std::move(Cfg));4872    auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);4873    ASSERT_TRUE(H);4874 4875    EXPECT_EQ(H->Definition, Case.ExpectedDefinition);4876  }4877}4878 4879TEST(Hover, FunctionParameters) {4880  struct {4881    const char *const Code;4882    const std::function<void(HoverInfo &)> ExpectedBuilder;4883    std::string ExpectedRender;4884  } Cases[] = {4885      {R"cpp(/// Function doc4886      void foo(int [[^a]]);4887    )cpp",4888       [](HoverInfo &HI) {4889         HI.Name = "a";4890         HI.Kind = index::SymbolKind::Parameter;4891         HI.NamespaceScope = "";4892         HI.LocalScope = "foo::";4893         HI.Type = "int";4894         HI.Definition = "int a";4895         HI.Documentation = "";4896       },4897       "### param\n\n---\n```cpp\n// In foo\nint a\n```\n\n---\nType: `int`"},4898      {R"cpp(/// Function doc4899      /// @param a this is doc for a4900      void foo(int [[^a]]);4901    )cpp",4902       [](HoverInfo &HI) {4903         HI.Name = "a";4904         HI.Kind = index::SymbolKind::Parameter;4905         HI.NamespaceScope = "";4906         HI.LocalScope = "foo::";4907         HI.Type = "int";4908         HI.Definition = "int a";4909         HI.Documentation = "this is doc for a";4910       },4911       "### param\n\n---\n```cpp\n// In foo\nint a\n```\n\n---\nthis is doc "4912       "for a\n\n---\nType: `int`"},4913      {R"cpp(/// Function doc4914      /// @param b this is doc for b4915      void foo(int [[^a]], int b);4916    )cpp",4917       [](HoverInfo &HI) {4918         HI.Name = "a";4919         HI.Kind = index::SymbolKind::Parameter;4920         HI.NamespaceScope = "";4921         HI.LocalScope = "foo::";4922         HI.Type = "int";4923         HI.Definition = "int a";4924         HI.Documentation = "";4925       },4926       "### param\n\n---\n```cpp\n// In foo\nint a\n```\n\n---\nType: `int`"},4927      {R"cpp(/// Function doc4928      /// @param b this is doc for \p b4929      void foo(int a, int [[^b]]);4930    )cpp",4931       [](HoverInfo &HI) {4932         HI.Name = "b";4933         HI.Kind = index::SymbolKind::Parameter;4934         HI.NamespaceScope = "";4935         HI.LocalScope = "foo::";4936         HI.Type = "int";4937         HI.Definition = "int b";4938         HI.Documentation = "this is doc for \\p b";4939       },4940       "### param\n\n---\n```cpp\n// In foo\nint b\n```\n\n---\nthis is doc "4941       "for `b`\n\n---\nType: `int`"},4942      {R"cpp(/// Function doc4943      /// @param b this is doc for \p b4944      template <typename T>4945      void foo(T a, T [[^b]]);4946    )cpp",4947       [](HoverInfo &HI) {4948         HI.Name = "b";4949         HI.Kind = index::SymbolKind::Parameter;4950         HI.NamespaceScope = "";4951         HI.LocalScope = "foo::";4952         HI.Type = "T";4953         HI.Definition = "T b";4954         HI.Documentation = "this is doc for \\p b";4955       },4956       "### param\n\n---\n```cpp\n// In foo\nT b\n```\n\n---\nthis is doc for "4957       "`b`\n\n---\nType: `T`"},4958      {R"cpp(/// Function doc4959      /// @param b this is <b>doc</b> <html-tag attribute/> <another-html-tag attribute="value">for</another-html-tag> \p b4960      void foo(int a, int [[^b]]);4961    )cpp",4962       [](HoverInfo &HI) {4963         HI.Name = "b";4964         HI.Kind = index::SymbolKind::Parameter;4965         HI.NamespaceScope = "";4966         HI.LocalScope = "foo::";4967         HI.Type = "int";4968         HI.Definition = "int b";4969         HI.Documentation =4970             "this is <b>doc</b> <html-tag attribute/> <another-html-tag "4971             "attribute=\"value\">for</another-html-tag> \\p b";4972       },4973       "### param\n\n---\n```cpp\n// In foo\nint b\n```\n\n---\nthis is "4974       "\\<b>doc\\</b> \\<html-tag attribute/> \\<another-html-tag "4975       "attribute=\"value\">for\\</another-html-tag> `b`\n\n---\nType: `int`"},4976  };4977 4978  // Create a tiny index, so tests above can verify documentation is fetched.4979  Symbol IndexSym = func("indexSymbol");4980  IndexSym.Documentation = "comment from index";4981  SymbolSlab::Builder Symbols;4982  Symbols.insert(IndexSym);4983  auto Index =4984      MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());4985 4986  for (const auto &Case : Cases) {4987    SCOPED_TRACE(Case.Code);4988 4989    Annotations T(Case.Code);4990    TestTU TU = TestTU::withCode(T.code());4991    auto AST = TU.build();4992    Config Cfg;4993    Cfg.Hover.ShowAKA = true;4994    Cfg.Documentation.CommentFormat = Config::CommentFormatPolicy::Doxygen;4995    WithContextValue WithCfg(Config::Key, std::move(Cfg));4996    auto H = getHover(AST, T.point(), format::getLLVMStyle(), Index.get());4997    ASSERT_TRUE(H);4998    HoverInfo Expected;4999    Expected.SymRange = T.range();5000    Case.ExpectedBuilder(Expected);5001 5002    EXPECT_EQ(H->present(MarkupKind::Markdown), Case.ExpectedRender);5003    EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);5004    EXPECT_EQ(H->LocalScope, Expected.LocalScope);5005    EXPECT_EQ(H->Name, Expected.Name);5006    EXPECT_EQ(H->Kind, Expected.Kind);5007    EXPECT_EQ(H->Documentation, Expected.Documentation);5008    EXPECT_EQ(H->Definition, Expected.Definition);5009    EXPECT_EQ(H->Type, Expected.Type);5010    EXPECT_EQ(H->ReturnType, Expected.ReturnType);5011    EXPECT_EQ(H->Parameters, Expected.Parameters);5012    EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);5013    EXPECT_EQ(H->SymRange, Expected.SymRange);5014    EXPECT_EQ(H->Value, Expected.Value);5015  }5016}5017 5018} // namespace5019} // namespace clangd5020} // namespace clang5021