brintos

brintos / llvm-project-archived public Read only

0
0
Text · 146.0 KiB · e2bdb0f Raw
4698 lines · cpp
1//===-- CodeCompleteTests.cpp -----------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ASTSignals.h"10#include "Annotations.h"11#include "ClangdServer.h"12#include "CodeComplete.h"13#include "Compiler.h"14#include "Config.h"15#include "Feature.h"16#include "Matchers.h"17#include "Protocol.h"18#include "Quality.h"19#include "SourceCode.h"20#include "SyncAPI.h"21#include "TestFS.h"22#include "TestIndex.h"23#include "TestTU.h"24#include "index/Index.h"25#include "index/MemIndex.h"26#include "index/SymbolOrigin.h"27#include "support/Threading.h"28#include "clang/Sema/CodeCompleteConsumer.h"29#include "clang/Tooling/CompilationDatabase.h"30#include "llvm/ADT/StringRef.h"31#include "llvm/Support/Error.h"32#include "llvm/Support/Path.h"33#include "llvm/Testing/Annotations/Annotations.h"34#include "llvm/Testing/Support/Error.h"35#include "llvm/Testing/Support/SupportHelpers.h"36#include "gmock/gmock.h"37#include "gtest/gtest.h"38#include <condition_variable>39#include <functional>40#include <mutex>41#include <vector>42 43namespace clang {44namespace clangd {45 46namespace {47using ::llvm::Failed;48using ::testing::AllOf;49using ::testing::Contains;50using ::testing::ElementsAre;51using ::testing::Field;52using ::testing::HasSubstr;53using ::testing::IsEmpty;54using ::testing::Not;55using ::testing::UnorderedElementsAre;56using ContextKind = CodeCompletionContext::Kind;57 58// GMock helpers for matching completion items.59MATCHER_P(named, Name, "") { return arg.Name == Name; }60MATCHER_P(mainFileRefs, Refs, "") { return arg.MainFileRefs == Refs; }61MATCHER_P(scopeRefs, Refs, "") { return arg.ScopeRefsInFile == Refs; }62MATCHER_P(nameStartsWith, Prefix, "") {63  return llvm::StringRef(arg.Name).starts_with(Prefix);64}65MATCHER_P(filterText, F, "") { return arg.FilterText == F; }66MATCHER_P(scope, S, "") { return arg.Scope == S; }67MATCHER_P(qualifier, Q, "") { return arg.RequiredQualifier == Q; }68MATCHER_P(labeled, Label, "") {69  return arg.RequiredQualifier + arg.Name + arg.Signature == Label;70}71MATCHER_P(sigHelpLabeled, Label, "") { return arg.label == Label; }72MATCHER_P(kind, K, "") { return arg.Kind == K; }73MATCHER_P(doc, D, "") {74  return arg.Documentation && arg.Documentation->asPlainText() == D;75}76MATCHER_P(returnType, D, "") { return arg.ReturnType == D; }77MATCHER_P(hasInclude, IncludeHeader, "") {78  return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader;79}80MATCHER_P(insertInclude, IncludeHeader, "") {81  return !arg.Includes.empty() && arg.Includes[0].Header == IncludeHeader &&82         bool(arg.Includes[0].Insertion);83}84MATCHER_P(insertIncludeText, InsertedText, "") {85  return !arg.Includes.empty() && arg.Includes[0].Insertion &&86         arg.Includes[0].Insertion->newText == InsertedText;87}88MATCHER(insertInclude, "") {89  return !arg.Includes.empty() && bool(arg.Includes[0].Insertion);90}91MATCHER_P(snippetSuffix, Text, "") { return arg.SnippetSuffix == Text; }92MATCHER_P(origin, OriginSet, "") { return arg.Origin == OriginSet; }93MATCHER_P(signature, S, "") { return arg.Signature == S; }94MATCHER_P(replacesRange, Range, "") {95  return arg.CompletionTokenRange == Range;96}97 98// Shorthand for Contains(named(Name)).99Matcher<const std::vector<CodeCompletion> &> has(std::string Name) {100  return Contains(named(std::move(Name)));101}102Matcher<const std::vector<CodeCompletion> &> has(std::string Name,103                                                 CompletionItemKind K) {104  return Contains(AllOf(named(std::move(Name)), kind(K)));105}106MATCHER(isDocumented, "") { return arg.Documentation.has_value(); }107MATCHER(deprecated, "") { return arg.Deprecated; }108 109std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {110  SymbolSlab::Builder Slab;111  for (const auto &Sym : Symbols)112    Slab.insert(Sym);113  return MemIndex::build(std::move(Slab).build(), RefSlab(), RelationSlab());114}115 116// Runs code completion.117// If IndexSymbols is non-empty, an index will be built and passed to opts.118CodeCompleteResult completions(const TestTU &TU, Position Point,119                               std::vector<Symbol> IndexSymbols = {},120                               clangd::CodeCompleteOptions Opts = {}) {121  std::unique_ptr<SymbolIndex> OverrideIndex;122  if (!IndexSymbols.empty()) {123    assert(!Opts.Index && "both Index and IndexSymbols given!");124    OverrideIndex = memIndex(std::move(IndexSymbols));125    Opts.Index = OverrideIndex.get();126  }127 128  MockFS FS;129  auto Inputs = TU.inputs(FS);130  IgnoreDiagnostics Diags;131  auto CI = buildCompilerInvocation(Inputs, Diags);132  if (!CI) {133    ADD_FAILURE() << "Couldn't build CompilerInvocation";134    return {};135  }136  auto Preamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,137                                /*InMemory=*/true, /*Callback=*/nullptr);138  return codeComplete(testPath(TU.Filename), Point, Preamble.get(), Inputs,139                      Opts);140}141 142// Runs code completion.143CodeCompleteResult completions(llvm::StringRef Text,144                               std::vector<Symbol> IndexSymbols = {},145                               clangd::CodeCompleteOptions Opts = {},146                               PathRef FilePath = "foo.cpp") {147  Annotations Test(Text);148  auto TU = TestTU::withCode(Test.code());149  // To make sure our tests for completiopns inside templates work on Windows.150  TU.Filename = FilePath.str();151  return completions(TU, Test.point(), std::move(IndexSymbols),152                     std::move(Opts));153}154 155// Runs code completion without the clang parser.156CodeCompleteResult completionsNoCompile(llvm::StringRef Text,157                                        std::vector<Symbol> IndexSymbols = {},158                                        clangd::CodeCompleteOptions Opts = {},159                                        PathRef FilePath = "foo.cpp") {160  std::unique_ptr<SymbolIndex> OverrideIndex;161  if (!IndexSymbols.empty()) {162    assert(!Opts.Index && "both Index and IndexSymbols given!");163    OverrideIndex = memIndex(std::move(IndexSymbols));164    Opts.Index = OverrideIndex.get();165  }166 167  MockFS FS;168  Annotations Test(Text);169  ParseInputs ParseInput{tooling::CompileCommand(), &FS, Test.code().str()};170  return codeComplete(FilePath, Test.point(), /*Preamble=*/nullptr, ParseInput,171                      Opts);172}173 174Symbol withReferences(int N, Symbol S) {175  S.References = N;176  return S;177}178 179#if CLANGD_DECISION_FOREST180TEST(DecisionForestRankingModel, NameMatchSanityTest) {181  clangd::CodeCompleteOptions Opts;182  Opts.RankingModel = CodeCompleteOptions::DecisionForest;183  auto Results = completions(184      R"cpp(185struct MemberAccess {186  int ABG();187  int AlphaBetaGamma();188};189int func() { MemberAccess().ABG^ }190)cpp",191      /*IndexSymbols=*/{}, Opts);192  EXPECT_THAT(Results.Completions,193              ElementsAre(named("ABG"), named("AlphaBetaGamma")));194}195 196TEST(DecisionForestRankingModel, ReferencesAffectRanking) {197  clangd::CodeCompleteOptions Opts;198  Opts.RankingModel = CodeCompleteOptions::DecisionForest;199  constexpr int NumReferences = 100000;200  EXPECT_THAT(201      completions("int main() { clang^ }",202                  {ns("clangA"), withReferences(NumReferences, func("clangD"))},203                  Opts)204          .Completions,205      ElementsAre(named("clangD"), named("clangA")));206  EXPECT_THAT(207      completions("int main() { clang^ }",208                  {withReferences(NumReferences, ns("clangA")), func("clangD")},209                  Opts)210          .Completions,211      ElementsAre(named("clangA"), named("clangD")));212}213#endif // CLANGD_DECISION_FOREST214 215TEST(DecisionForestRankingModel, DecisionForestScorerCallbackTest) {216  clangd::CodeCompleteOptions Opts;217  constexpr float MagicNumber = 1234.5678f;218  Opts.RankingModel = CodeCompleteOptions::DecisionForest;219  Opts.DecisionForestScorer = [&](const SymbolQualitySignals &,220                                  const SymbolRelevanceSignals &, float Base) {221    DecisionForestScores Scores;222    Scores.Total = MagicNumber;223    Scores.ExcludingName = MagicNumber;224    return Scores;225  };226  llvm::StringRef Code = "int func() { int xyz; xy^ }";227  auto Results = completions(Code,228                             /*IndexSymbols=*/{}, Opts);229  ASSERT_EQ(Results.Completions.size(), 1u);230  EXPECT_EQ(Results.Completions[0].Score.Total, MagicNumber);231  EXPECT_EQ(Results.Completions[0].Score.ExcludingName, MagicNumber);232 233  // Do not use DecisionForestScorer for heuristics model.234  Opts.RankingModel = CodeCompleteOptions::Heuristics;235  Results = completions(Code,236                        /*IndexSymbols=*/{}, Opts);237  ASSERT_EQ(Results.Completions.size(), 1u);238  EXPECT_NE(Results.Completions[0].Score.Total, MagicNumber);239  EXPECT_NE(Results.Completions[0].Score.ExcludingName, MagicNumber);240}241 242TEST(CompletionTest, Limit) {243  clangd::CodeCompleteOptions Opts;244  Opts.Limit = 2;245  auto Results = completions(R"cpp(246struct ClassWithMembers {247  int AAA();248  int BBB();249  int CCC();250};251 252int main() { ClassWithMembers().^ }253      )cpp",254                             /*IndexSymbols=*/{}, Opts);255 256  EXPECT_TRUE(Results.HasMore);257  EXPECT_THAT(Results.Completions, ElementsAre(named("AAA"), named("BBB")));258}259 260TEST(CompletionTest, Filter) {261  std::string Body = R"cpp(262    #define MotorCar263    int Car;264    struct S {265      int FooBar;266      int FooBaz;267      int Qux;268    };269  )cpp";270 271  // Only items matching the fuzzy query are returned.272  EXPECT_THAT(completions(Body + "int main() { S().Foba^ }").Completions,273              AllOf(has("FooBar"), has("FooBaz"), Not(has("Qux"))));274 275  // Macros require prefix match, either from index or AST.276  Symbol Sym = var("MotorCarIndex");277  Sym.SymInfo.Kind = index::SymbolKind::Macro;278  EXPECT_THAT(279      completions(Body + "int main() { C^ }", {Sym}).Completions,280      AllOf(has("Car"), Not(has("MotorCar")), Not(has("MotorCarIndex"))));281  EXPECT_THAT(completions(Body + "int main() { M^ }", {Sym}).Completions,282              AllOf(has("MotorCar"), has("MotorCarIndex")));283}284 285void testAfterDotCompletion(clangd::CodeCompleteOptions Opts) {286  auto Results = completions(287      R"cpp(288      int global_var;289 290      int global_func();291 292      // Make sure this is not in preamble.293      #define MACRO X294 295      struct GlobalClass {};296 297      struct ClassWithMembers {298        /// doc for method.299        int method();300 301        int field;302      private:303        int private_field;304      };305 306      int test() {307        struct LocalClass {};308 309        /// doc for local_var.310        int local_var;311 312        ClassWithMembers().^313      }314      )cpp",315      {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);316 317  EXPECT_TRUE(Results.RanParser);318  // Class members. The only items that must be present in after-dot319  // completion.320  EXPECT_THAT(Results.Completions,321              AllOf(has("method"), has("field"), Not(has("ClassWithMembers")),322                    Not(has("operator=")), Not(has("~ClassWithMembers"))));323  EXPECT_IFF(Opts.IncludeIneligibleResults, Results.Completions,324             has("private_field"));325  // Global items.326  EXPECT_THAT(327      Results.Completions,328      Not(AnyOf(has("global_var"), has("index_var"), has("global_func"),329                has("global_func()"), has("index_func"), has("GlobalClass"),330                has("IndexClass"), has("MACRO"), has("LocalClass"))));331  // There should be no code patterns (aka snippets) in after-dot332  // completion. At least there aren't any we're aware of.333  EXPECT_THAT(Results.Completions,334              Not(Contains(kind(CompletionItemKind::Snippet))));335  // Check documentation.336  EXPECT_THAT(Results.Completions, Contains(isDocumented()));337}338 339void testGlobalScopeCompletion(clangd::CodeCompleteOptions Opts) {340  auto Results = completions(341      R"cpp(342      int global_var;343      int global_func();344 345      // Make sure this is not in preamble.346      #define MACRO X347 348      struct GlobalClass {};349 350      struct ClassWithMembers {351        /// doc for method.352        int method();353      };354 355      int test() {356        struct LocalClass {};357 358        /// doc for local_var.359        int local_var;360 361        ^362      }363      )cpp",364      {cls("IndexClass"), var("index_var"), func("index_func")}, Opts);365 366  EXPECT_TRUE(Results.RanParser);367  // Class members. Should never be present in global completions.368  EXPECT_THAT(Results.Completions,369              Not(AnyOf(has("method"), has("method()"), has("field"))));370  // Global items.371  EXPECT_THAT(Results.Completions,372              AllOf(has("global_var"), has("index_var"), has("global_func"),373                    has("index_func" /* our fake symbol doesn't include () */),374                    has("GlobalClass"), has("IndexClass")));375  // A macro.376  EXPECT_THAT(Results.Completions, has("MACRO"));377  // Local items. Must be present always.378  EXPECT_THAT(Results.Completions,379              AllOf(has("local_var"), has("LocalClass"),380                    Contains(kind(CompletionItemKind::Snippet))));381  // Check documentation.382  EXPECT_THAT(Results.Completions, Contains(isDocumented()));383}384 385TEST(CompletionTest, CompletionOptions) {386  auto Test = [&](const clangd::CodeCompleteOptions &Opts) {387    testAfterDotCompletion(Opts);388    testGlobalScopeCompletion(Opts);389  };390  // We used to test every combination of options, but that got too slow (2^N).391  auto Flags = {392      &clangd::CodeCompleteOptions::IncludeIneligibleResults,393  };394  // Test default options.395  Test({});396  // Test with one flag flipped.397  for (auto &F : Flags) {398    clangd::CodeCompleteOptions O;399    O.*F ^= true;400    Test(O);401  }402}403 404TEST(CompletionTest, Accessible) {405  auto Internal = completions(R"cpp(406      class Foo {407        public: void pub();408        protected: void prot();409        private: void priv();410      };411      void Foo::pub() { this->^ }412  )cpp");413  EXPECT_THAT(Internal.Completions,414              AllOf(has("priv"), has("prot"), has("pub")));415 416  auto External = completions(R"cpp(417      class Foo {418        public: void pub();419        protected: void prot();420        private: void priv();421      };422      void test() {423        Foo F;424        F.^425      }426  )cpp");427  EXPECT_THAT(External.Completions,428              AllOf(has("pub"), Not(has("prot")), Not(has("priv"))));429 430  auto Results = completions(R"cpp(431      struct Foo {432        public: void pub();433        protected: void prot();434        private: void priv();435      };436      struct Bar : public Foo {437        private: using Foo::pub;438      };439      void test() {440        Bar B;441        B.^442      }443  )cpp");444  EXPECT_THAT(Results.Completions,445              AllOf(Not(has("priv")), Not(has("prot")), Not(has("pub"))));446}447 448TEST(CompletionTest, Qualifiers) {449  auto Results = completions(R"cpp(450      class Foo {451        public: int foo() const;452        int bar() const;453      };454      class Bar : public Foo {455        int foo() const;456      };457      void test() { Bar().^ }458  )cpp");459  EXPECT_THAT(Results.Completions,460              Contains(AllOf(qualifier(""), named("bar"))));461  // Hidden members are not shown.462  EXPECT_THAT(Results.Completions,463              Not(Contains(AllOf(qualifier("Foo::"), named("foo")))));464  // Private members are not shown.465  EXPECT_THAT(Results.Completions,466              Not(Contains(AllOf(qualifier(""), named("foo")))));467}468 469// https://github.com/clangd/clangd/issues/1451470TEST(CompletionTest, QualificationWithInlineNamespace) {471  auto Results = completions(R"cpp(472    namespace a { inline namespace b {} }473    using namespace a::b;474    void f() { Foo^ }475  )cpp",476                             {cls("a::Foo")});477  EXPECT_THAT(Results.Completions,478              UnorderedElementsAre(AllOf(qualifier("a::"), named("Foo"))));479}480 481TEST(CompletionTest, InjectedTypename) {482  // These are suppressed when accessed as a member...483  EXPECT_THAT(completions("struct X{}; void foo(){ X().^ }").Completions,484              Not(has("X")));485  EXPECT_THAT(completions("struct X{ void foo(){ this->^ } };").Completions,486              Not(has("X")));487  // ...but accessible in other, more useful cases.488  EXPECT_THAT(completions("struct X{ void foo(){ ^ } };").Completions,489              has("X"));490  EXPECT_THAT(491      completions("struct Y{}; struct X:Y{ void foo(){ ^ } };").Completions,492      has("Y"));493  EXPECT_THAT(494      completions(495          "template<class> struct Y{}; struct X:Y<int>{ void foo(){ ^ } };")496          .Completions,497      has("Y"));498  // This case is marginal (`using X::X` is useful), we allow it for now.499  EXPECT_THAT(completions("struct X{}; void foo(){ X::^ }").Completions,500              has("X"));501}502 503TEST(CompletionTest, SkipInjectedWhenUnqualified) {504  EXPECT_THAT(completions("struct X { void f() { X^ }};").Completions,505              ElementsAre(named("X"), named("~X")));506}507 508TEST(CompletionTest, Snippets) {509  clangd::CodeCompleteOptions Opts;510  auto Results = completions(511      R"cpp(512      struct fake {513        int a;514        int f(int i, const float f) const;515      };516      int main() {517        fake f;518        f.^519      }520      )cpp",521      /*IndexSymbols=*/{}, Opts);522  EXPECT_THAT(523      Results.Completions,524      HasSubsequence(named("a"),525                     snippetSuffix("(${1:int i}, ${2:const float f})")));526}527 528TEST(CompletionTest, HeuristicsForMemberFunctionCompletion) {529  clangd::CodeCompleteOptions Opts;530  Opts.EnableSnippets = true;531 532  Annotations Code(R"cpp(533      struct Foo {534        static int staticMethod(int);535        int method(int) const;536        template <typename T, typename U, typename V = int>537        T generic(U, V);538        template <typename T, int U>539        static T staticGeneric();540        Foo() {541          this->$canBeCall^542          $canBeCall^543          Foo::$canBeCall^544        }545      };546 547      struct Derived : Foo {548        using Foo::method;549        using Foo::generic;550        Derived() {551          Foo::$canBeCall^552        }553      };554 555      struct OtherClass {556        OtherClass() {557          Foo f;558          Derived d;559          f.$canBeCall^560          ; // Prevent parsing as 'f.f'561          f.Foo::$canBeCall^562          &Foo::$canNotBeCall^563          ;564          d.Foo::$canBeCall^565          ;566          d.Derived::$canBeCall^567        }568      };569 570      int main() {571        Foo f;572        Derived d;573        f.$canBeCall^574        ; // Prevent parsing as 'f.f'575        f.Foo::$canBeCall^576        &Foo::$canNotBeCall^577        ;578        d.Foo::$canBeCall^579        ;580        d.Derived::$canBeCall^581      }582      )cpp");583  auto TU = TestTU::withCode(Code.code());584 585  for (const auto &P : Code.points("canNotBeCall")) {586    auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);587    EXPECT_THAT(Results.Completions,588                Contains(AllOf(named("method"), signature("(int) const"),589                               snippetSuffix(""))));590    // We don't have any arguments to deduce against if this isn't a call.591    // Thus, we should emit these deducible template arguments explicitly.592    EXPECT_THAT(593        Results.Completions,594        Contains(AllOf(named("generic"),595                       signature("<typename T, typename U>(U, V)"),596                       snippetSuffix("<${1:typename T}, ${2:typename U}>"))));597  }598 599  for (const auto &P : Code.points("canBeCall")) {600    auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);601    EXPECT_THAT(Results.Completions,602                Contains(AllOf(named("method"), signature("(int) const"),603                               snippetSuffix("(${1:int})"))));604    EXPECT_THAT(605        Results.Completions,606        Contains(AllOf(named("generic"), signature("<typename T>(U, V)"),607                       snippetSuffix("<${1:typename T}>(${2:U}, ${3:V})"))));608  }609 610  // static method will always keep the snippet611  for (const auto &P : Code.points()) {612    auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);613    EXPECT_THAT(Results.Completions,614                Contains(AllOf(named("staticMethod"), signature("(int)"),615                               snippetSuffix("(${1:int})"))));616    EXPECT_THAT(Results.Completions,617                Contains(AllOf(618                    named("staticGeneric"), signature("<typename T, int U>()"),619                    snippetSuffix("<${1:typename T}, ${2:int U}>()"))));620  }621}622 623TEST(CompletionTest, NoSnippetsInUsings) {624  clangd::CodeCompleteOptions Opts;625  Opts.EnableSnippets = true;626  auto Results = completions(627      R"cpp(628      namespace ns {629        int func(int a, int b);630      }631 632      using ns::^;633      )cpp",634      /*IndexSymbols=*/{}, Opts);635  EXPECT_THAT(Results.Completions,636              ElementsAre(AllOf(named("func"), labeled("func(int a, int b)"),637                                snippetSuffix(""))));638 639  // Check index completions too.640  auto Func = func("ns::func");641  Func.CompletionSnippetSuffix = "(${1:int a}, ${2: int b})";642  Func.Signature = "(int a, int b)";643  Func.ReturnType = "void";644 645  Results = completions(R"cpp(646      namespace ns {}647      using ns::^;648  )cpp",649                        /*IndexSymbols=*/{Func}, Opts);650  EXPECT_THAT(Results.Completions,651              ElementsAre(AllOf(named("func"), labeled("func(int a, int b)"),652                                snippetSuffix(""))));653 654  // Check all-scopes completions too.655  Opts.AllScopes = true;656  Results = completions(R"cpp(657      using ^;658  )cpp",659                        /*IndexSymbols=*/{Func}, Opts);660  EXPECT_THAT(Results.Completions,661              Contains(AllOf(named("func"), labeled("ns::func(int a, int b)"),662                             snippetSuffix(""))));663}664 665TEST(CompletionTest, Kinds) {666  auto Results = completions(667      R"cpp(668          int variable;669          struct Struct {};670          int function();671          // make sure MACRO is not included in preamble.672          #define MACRO 10673          int X = ^674      )cpp",675      {func("indexFunction"), var("indexVariable"), cls("indexClass"),676       macro("indexObjMacro"), macro("indexFuncMacro", "(x, y)")});677  EXPECT_THAT(Results.Completions,678              AllOf(has("function", CompletionItemKind::Function),679                    has("variable", CompletionItemKind::Variable),680                    has("int", CompletionItemKind::Keyword),681                    has("Struct", CompletionItemKind::Struct),682                    has("MACRO", CompletionItemKind::Constant),683                    has("indexFunction", CompletionItemKind::Function),684                    has("indexVariable", CompletionItemKind::Variable),685                    has("indexClass", CompletionItemKind::Class),686                    has("indexObjMacro", CompletionItemKind::Constant),687                    has("indexFuncMacro", CompletionItemKind::Function)));688 689  Results = completions("nam^");690  EXPECT_THAT(Results.Completions,691              has("namespace", CompletionItemKind::Snippet));692 693  // Members of anonymous unions are of kind 'field'.694  Results = completions(695      R"cpp(696        struct X{697            union {698              void *a;699            };700        };701        auto u = X().^702      )cpp");703  EXPECT_THAT(704      Results.Completions,705      UnorderedElementsAre(AllOf(named("a"), kind(CompletionItemKind::Field))));706 707  // Completion kinds for templates should not be unknown.708  Results = completions(709      R"cpp(710        template <class T> struct complete_class {};711        template <class T> void complete_function();712        template <class T> using complete_type_alias = int;713        template <class T> int complete_variable = 10;714 715        struct X {716          template <class T> static int complete_static_member = 10;717 718          static auto x = complete_^719        }720      )cpp");721  EXPECT_THAT(722      Results.Completions,723      UnorderedElementsAre(724          AllOf(named("complete_class"), kind(CompletionItemKind::Class)),725          AllOf(named("complete_function"), kind(CompletionItemKind::Function)),726          AllOf(named("complete_type_alias"),727                kind(CompletionItemKind::Interface)),728          AllOf(named("complete_variable"), kind(CompletionItemKind::Variable)),729          AllOf(named("complete_static_member"),730                kind(CompletionItemKind::Property))));731 732  Results = completions(733      R"cpp(734        enum Color {735          Red736        };737        Color u = ^738      )cpp");739  EXPECT_THAT(740      Results.Completions,741      Contains(AllOf(named("Red"), kind(CompletionItemKind::EnumMember))));742}743 744TEST(CompletionTest, NoDuplicates) {745  auto Results = completions(746      R"cpp(747          class Adapter {748          };749 750          void f() {751            Adapter^752          }753      )cpp",754      {cls("Adapter")});755 756  // Make sure there are no duplicate entries of 'Adapter'.757  EXPECT_THAT(Results.Completions, ElementsAre(named("Adapter")));758}759 760TEST(CompletionTest, ScopedNoIndex) {761  auto Results = completions(762      R"cpp(763          namespace fake { int BigBang, Babble, Box; };764          int main() { fake::ba^ }765      ")cpp");766  // Babble is a better match than BigBang. Box doesn't match at all.767  EXPECT_THAT(Results.Completions,768              ElementsAre(named("Babble"), named("BigBang")));769}770 771TEST(CompletionTest, Scoped) {772  auto Results = completions(773      R"cpp(774          namespace fake { int Babble, Box; };775          int main() { fake::ba^ }776      ")cpp",777      {var("fake::BigBang")});778  EXPECT_THAT(Results.Completions,779              ElementsAre(named("Babble"), named("BigBang")));780}781 782TEST(CompletionTest, ScopedWithFilter) {783  auto Results = completions(784      R"cpp(785          void f() { ns::x^ }786      )cpp",787      {cls("ns::XYZ"), func("ns::foo")});788  EXPECT_THAT(Results.Completions, UnorderedElementsAre(named("XYZ")));789}790 791TEST(CompletionTest, ReferencesAffectRanking) {792  EXPECT_THAT(completions("int main() { abs^ }", {func("absA"), func("absB")})793                  .Completions,794              HasSubsequence(named("absA"), named("absB")));795  EXPECT_THAT(completions("int main() { abs^ }",796                          {func("absA"), withReferences(1000, func("absB"))})797                  .Completions,798              HasSubsequence(named("absB"), named("absA")));799}800 801TEST(CompletionTest, ContextWords) {802  auto Results = completions(R"cpp(803  enum class Color { RED, YELLOW, BLUE };804 805  // (blank lines so the definition above isn't "context")806 807  // "It was a yellow car," he said. "Big yellow car, new."808  auto Finish = Color::^809  )cpp");810  // Yellow would normally sort last (alphabetic).811  // But the recent mention should bump it up.812  ASSERT_THAT(Results.Completions,813              HasSubsequence(named("YELLOW"), named("BLUE")));814}815 816TEST(CompletionTest, GlobalQualified) {817  auto Results = completions(818      R"cpp(819          void f() { ::^ }820      )cpp",821      {cls("XYZ")});822  EXPECT_THAT(Results.Completions,823              AllOf(has("XYZ", CompletionItemKind::Class),824                    has("f", CompletionItemKind::Function)));825}826 827TEST(CompletionTest, FullyQualified) {828  auto Results = completions(829      R"cpp(830          namespace ns { void bar(); }831          void f() { ::ns::^ }832      )cpp",833      {cls("ns::XYZ")});834  EXPECT_THAT(Results.Completions,835              AllOf(has("XYZ", CompletionItemKind::Class),836                    has("bar", CompletionItemKind::Function)));837}838 839TEST(CompletionTest, SemaIndexMerge) {840  auto Results = completions(841      R"cpp(842          namespace ns { int local; void both(); }843          void f() { ::ns::^ }844      )cpp",845      {func("ns::both"), cls("ns::Index")});846  // We get results from both index and sema, with no duplicates.847  EXPECT_THAT(Results.Completions,848              UnorderedElementsAre(849                  AllOf(named("local"), origin(SymbolOrigin::AST)),850                  AllOf(named("Index"), origin(SymbolOrigin::Static)),851                  AllOf(named("both"),852                        origin(SymbolOrigin::AST | SymbolOrigin::Static))));853}854 855TEST(CompletionTest, SemaIndexMergeWithLimit) {856  clangd::CodeCompleteOptions Opts;857  Opts.Limit = 1;858  auto Results = completions(859      R"cpp(860          namespace ns { int local; void both(); }861          void f() { ::ns::^ }862      )cpp",863      {func("ns::both"), cls("ns::Index")}, Opts);864  EXPECT_EQ(Results.Completions.size(), Opts.Limit);865  EXPECT_TRUE(Results.HasMore);866}867 868TEST(CompletionTest, IncludeInsertionPreprocessorIntegrationTests) {869  TestTU TU;870  TU.ExtraArgs.push_back("-I" + testPath("sub"));871  TU.AdditionalFiles["sub/bar.h"] = "";872  auto BarURI = URI::create(testPath("sub/bar.h")).toString();873 874  Symbol Sym = cls("ns::X");875  Sym.CanonicalDeclaration.FileURI = BarURI.c_str();876  Sym.IncludeHeaders.emplace_back(BarURI, 1, Symbol::Include);877  // Shorten include path based on search directory and insert.878  Annotations Test("int main() { ns::^ }");879  TU.Code = Test.code().str();880  auto Results = completions(TU, Test.point(), {Sym});881  EXPECT_THAT(Results.Completions,882              ElementsAre(AllOf(named("X"), insertInclude("\"bar.h\""))));883  // Can be disabled via option.884  CodeCompleteOptions NoInsertion;885  NoInsertion.InsertIncludes = Config::HeaderInsertionPolicy::NeverInsert;886  Results = completions(TU, Test.point(), {Sym}, NoInsertion);887  EXPECT_THAT(Results.Completions,888              ElementsAre(AllOf(named("X"), Not(insertInclude()))));889  // Duplicate based on inclusions in preamble.890  Test = Annotations(R"cpp(891          #include "sub/bar.h"  // not shortest, so should only match resolved.892          int main() { ns::^ }893      )cpp");894  TU.Code = Test.code().str();895  Results = completions(TU, Test.point(), {Sym});896  EXPECT_THAT(Results.Completions, ElementsAre(AllOf(named("X"), labeled("X"),897                                                     Not(insertInclude()))));898}899 900TEST(CompletionTest, NoIncludeInsertionWhenDeclFoundInFile) {901  Symbol SymX = cls("ns::X");902  Symbol SymY = cls("ns::Y");903  std::string BarHeader = testPath("bar.h");904  auto BarURI = URI::create(BarHeader).toString();905  SymX.CanonicalDeclaration.FileURI = BarURI.c_str();906  SymY.CanonicalDeclaration.FileURI = BarURI.c_str();907  SymX.IncludeHeaders.emplace_back("<bar>", 1, Symbol::Include);908  SymY.IncludeHeaders.emplace_back("<bar>", 1, Symbol::Include);909  // Shorten include path based on search directory and insert.910  auto Results = completions(R"cpp(911          namespace ns {912            class X;913            class Y {};914          }915          int main() { ns::^ }916      )cpp",917                             {SymX, SymY});918  EXPECT_THAT(Results.Completions,919              ElementsAre(AllOf(named("X"), Not(insertInclude())),920                          AllOf(named("Y"), Not(insertInclude()))));921}922 923TEST(CompletionTest, IncludeInsertionRespectsQuotedAngledConfig) {924  TestTU TU;925  TU.ExtraArgs.push_back("-I" + testPath("sub"));926  TU.AdditionalFiles["sub/bar.h"] = "";927  auto BarURI = URI::create(testPath("sub/bar.h")).toString();928 929  Symbol Sym = cls("ns::X");930  Sym.CanonicalDeclaration.FileURI = BarURI.c_str();931  Sym.IncludeHeaders.emplace_back(BarURI, 1, Symbol::Include);932  Annotations Test("int main() { ns::^ }");933  TU.Code = Test.code().str();934  auto Results = completions(TU, Test.point(), {Sym});935  // Default for a local path is quoted include936  EXPECT_THAT(Results.Completions,937              ElementsAre(AllOf(named("X"), insertInclude("\"bar.h\""))));938  {939    Config C;940    C.Style.AngledHeaders.push_back(941        [](auto header) { return header.contains("bar.h"); });942    WithContextValue WithCfg(Config::Key, std::move(C));943    Results = completions(TU, Test.point(), {Sym});944    EXPECT_THAT(Results.Completions,945                ElementsAre(AllOf(named("X"), insertInclude("<bar.h>"))));946  }947  {948    Config C;949    C.Style.QuotedHeaders.push_back(950        [](auto header) { return header.contains("bar.h"); });951    WithContextValue WithCfg(Config::Key, std::move(C));952    Results = completions(TU, Test.point(), {Sym});953    EXPECT_THAT(Results.Completions,954                ElementsAre(AllOf(named("X"), insertInclude("\"bar.h\""))));955  }956}957 958TEST(CompletionTest, IndexSuppressesPreambleCompletions) {959  Annotations Test(R"cpp(960      #include "bar.h"961      namespace ns { int local; }962      void f() { ns::^; }963      void f2() { ns::preamble().$2^; }964  )cpp");965  auto TU = TestTU::withCode(Test.code());966  TU.AdditionalFiles["bar.h"] =967      R"cpp(namespace ns { struct preamble { int member; }; })cpp";968 969  clangd::CodeCompleteOptions Opts = {};970  auto I = memIndex({var("ns::index")});971  Opts.Index = I.get();972  auto WithIndex = completions(TU, Test.point(), {}, Opts);973  EXPECT_THAT(WithIndex.Completions,974              UnorderedElementsAre(named("local"), named("index")));975  auto ClassFromPreamble = completions(TU, Test.point("2"), {}, Opts);976  EXPECT_THAT(ClassFromPreamble.Completions, Contains(named("member")));977 978  Opts.Index = nullptr;979  auto WithoutIndex = completions(TU, Test.point(), {}, Opts);980  EXPECT_THAT(WithoutIndex.Completions,981              UnorderedElementsAre(named("local"), named("preamble")));982}983 984// This verifies that we get normal preprocessor completions in the preamble.985// This is a regression test for an old bug: if we override the preamble and986// try to complete inside it, clang kicks our completion point just outside the987// preamble, resulting in always getting top-level completions.988TEST(CompletionTest, CompletionInPreamble) {989  auto Results = completions(R"cpp(990    #ifnd^ef FOO_H_991    #define BAR_H_992    #include <bar.h>993    int foo() {}994    #endif995    )cpp")996                     .Completions;997  EXPECT_THAT(Results, ElementsAre(named("ifndef")));998}999 1000TEST(CompletionTest, CompletionRecoveryASTType) {1001  auto Results = completions(R"cpp(1002    struct S { int member; };1003    S overloaded(int);1004    void foo() {1005      // No overload matches, but we have recovery-expr with the correct type.1006      overloaded().^1007    })cpp")1008                     .Completions;1009  EXPECT_THAT(Results, ElementsAre(named("member")));1010}1011 1012TEST(CompletionTest, DynamicIndexIncludeInsertion) {1013  MockFS FS;1014  MockCompilationDatabase CDB;1015  ClangdServer::Options Opts = ClangdServer::optsForTest();1016  Opts.BuildDynamicSymbolIndex = true;1017  ClangdServer Server(CDB, FS, Opts);1018 1019  FS.Files[testPath("foo_header.h")] = R"cpp(1020    #pragma once1021    struct Foo {1022       // Member doc1023       int foo();1024    };1025  )cpp";1026  const std::string FileContent(R"cpp(1027    #include "foo_header.h"1028    int Foo::foo() {1029      return 42;1030    }1031  )cpp");1032  Server.addDocument(testPath("foo_impl.cpp"), FileContent);1033  // Wait for the dynamic index being built.1034  ASSERT_TRUE(Server.blockUntilIdleForTest());1035 1036  auto File = testPath("foo.cpp");1037  Annotations Test("Foo^ foo;");1038  runAddDocument(Server, File, Test.code());1039  auto CompletionList =1040      llvm::cantFail(runCodeComplete(Server, File, Test.point(), {}));1041 1042  EXPECT_THAT(CompletionList.Completions,1043              ElementsAre(AllOf(named("Foo"), hasInclude("\"foo_header.h\""),1044                                insertInclude())));1045}1046 1047TEST(CompletionTest, DynamicIndexMultiFile) {1048  MockFS FS;1049  MockCompilationDatabase CDB;1050  auto Opts = ClangdServer::optsForTest();1051  Opts.BuildDynamicSymbolIndex = true;1052  ClangdServer Server(CDB, FS, Opts);1053 1054  FS.Files[testPath("foo.h")] = R"cpp(1055      namespace ns { class XYZ {}; void foo(int x) {} }1056  )cpp";1057  runAddDocument(Server, testPath("foo.cpp"), R"cpp(1058      #include "foo.h"1059  )cpp");1060 1061  auto File = testPath("bar.cpp");1062  Annotations Test(R"cpp(1063      namespace ns {1064      class XXX {};1065      /// Doooc1066      void fooooo() {}1067      }1068      void f() { ns::^ }1069  )cpp");1070  runAddDocument(Server, File, Test.code());1071 1072  auto Results = cantFail(runCodeComplete(Server, File, Test.point(), {}));1073  // "XYZ" and "foo" are not included in the file being completed but are still1074  // visible through the index.1075  EXPECT_THAT(Results.Completions, has("XYZ", CompletionItemKind::Class));1076  EXPECT_THAT(Results.Completions, has("foo", CompletionItemKind::Function));1077  EXPECT_THAT(Results.Completions, has("XXX", CompletionItemKind::Class));1078  EXPECT_THAT(Results.Completions,1079              Contains((named("fooooo"), kind(CompletionItemKind::Function),1080                        doc("Doooc"), returnType("void"))));1081}1082 1083TEST(CompletionTest, Documentation) {1084  auto Results = completions(1085      R"cpp(1086      // Non-doxygen comment.1087      __attribute__((annotate("custom_annotation"))) int foo();1088      /// Doxygen comment.1089      /// \param int a1090      int bar(int a);1091      /* Multi-line1092         block comment1093      */1094      int baz();1095 1096      int x = ^1097     )cpp");1098  EXPECT_THAT(1099      Results.Completions,1100      Contains(1101          AllOf(named("foo"),1102                doc("Annotation: custom_annotation\n\nNon-doxygen comment."))));1103  EXPECT_THAT(1104      Results.Completions,1105      Contains(AllOf(named("bar"), doc("Doxygen comment.\n\\param int a"))));1106  EXPECT_THAT(Results.Completions,1107              Contains(AllOf(named("baz"), doc("Multi-line block comment"))));1108}1109 1110TEST(CompletionTest, CommentsFromSystemHeaders) {1111  MockFS FS;1112  MockCompilationDatabase CDB;1113 1114  auto Opts = ClangdServer::optsForTest();1115  Opts.BuildDynamicSymbolIndex = true;1116 1117  ClangdServer Server(CDB, FS, Opts);1118 1119  FS.Files[testPath("foo.h")] = R"cpp(1120    #pragma GCC system_header1121 1122    // This comment should be retained!1123    int foo();1124  )cpp";1125 1126  auto File = testPath("foo.cpp");1127  Annotations Test(R"cpp(1128#include "foo.h"1129int x = foo^1130     )cpp");1131  runAddDocument(Server, File, Test.code());1132  auto CompletionList =1133      llvm::cantFail(runCodeComplete(Server, File, Test.point(), {}));1134 1135  EXPECT_THAT(1136      CompletionList.Completions,1137      Contains(AllOf(named("foo"), doc("This comment should be retained!"))));1138}1139 1140TEST(CompletionTest, CommentsOnMembersFromHeader) {1141  MockFS FS;1142  MockCompilationDatabase CDB;1143 1144  auto Opts = ClangdServer::optsForTest();1145  Opts.BuildDynamicSymbolIndex = true;1146 1147  ClangdServer Server(CDB, FS, Opts);1148 1149  FS.Files[testPath("foo.h")] = R"cpp(1150    struct alpha {1151      /// This is a member field.1152      int gamma;1153 1154      /// This is a member function.1155      int delta();1156    };1157 1158    template <typename T>1159    struct beta {1160      /// This is a member field inside a template.1161      int omega;1162 1163      /// This is a member function inside a template.1164      int epsilon();1165    };1166  )cpp";1167 1168  auto File = testPath("foo.cpp");1169  Annotations Test(R"cpp(1170#include "foo.h"1171alpha a;1172beta<int> b;1173int x = a.$p1^;1174int y = b.$p2^;1175     )cpp");1176  runAddDocument(Server, File, Test.code());1177  auto CompletionList =1178      llvm::cantFail(runCodeComplete(Server, File, Test.point("p1"), {}));1179 1180  EXPECT_THAT(CompletionList.Completions,1181              Contains(AllOf(named("gamma"), doc("This is a member field."))));1182  EXPECT_THAT(1183      CompletionList.Completions,1184      Contains(AllOf(named("delta"), doc("This is a member function."))));1185 1186  CompletionList =1187      llvm::cantFail(runCodeComplete(Server, File, Test.point("p2"), {}));1188 1189  EXPECT_THAT(CompletionList.Completions,1190              Contains(AllOf(named("omega")1191                             /* FIXME: Doc retrieval does not work yet*/)));1192  EXPECT_THAT(1193      CompletionList.Completions,1194      Contains(AllOf(named("epsilon"),1195                     doc("This is a member function inside a template."))));1196}1197 1198TEST(CompletionTest, CommentsOnMembersFromHeaderOverloadBundling) {1199  using testing::AnyOf;1200  MockFS FS;1201  MockCompilationDatabase CDB;1202 1203  auto Opts = ClangdServer::optsForTest();1204  Opts.BuildDynamicSymbolIndex = true;1205 1206  ClangdServer Server(CDB, FS, Opts);1207 1208  FS.Files[testPath("foo.h")] = R"cpp(1209    struct alpha {1210      /// bool overload.1211      int delta(bool b);1212 1213      /// int overload.1214      int delta(int i);1215 1216      void epsilon(long l);1217 1218      /// This one has a comment.1219      void epsilon(int i);1220    };1221  )cpp";1222 1223  auto File = testPath("foo.cpp");1224  Annotations Test(R"cpp(1225#include "foo.h"1226alpha a;1227int x = a.^1228     )cpp");1229  runAddDocument(Server, File, Test.code());1230  clangd::CodeCompleteOptions CCOpts;1231  CCOpts.BundleOverloads = true;1232  auto CompletionList =1233      llvm::cantFail(runCodeComplete(Server, File, Test.point(), CCOpts));1234 1235  EXPECT_THAT(1236      CompletionList.Completions,1237      Contains(AllOf(named("epsilon"), doc("This one has a comment."))));1238  EXPECT_THAT(CompletionList.Completions,1239              Contains(AllOf(named("delta"), AnyOf(doc("bool overload."),1240                                                   doc("int overload.")))));1241}1242 1243TEST(CompletionTest, GlobalCompletionFiltering) {1244 1245  Symbol Class = cls("XYZ");1246  Class.Flags = static_cast<Symbol::SymbolFlag>(1247      Class.Flags & ~(Symbol::IndexedForCodeCompletion));1248  Symbol Func = func("XYZ::foooo");1249  Func.Flags = static_cast<Symbol::SymbolFlag>(1250      Func.Flags & ~(Symbol::IndexedForCodeCompletion));1251 1252  auto Results = completions(R"(//      void f() {1253      XYZ::foooo^1254      })",1255                             {Class, Func});1256  EXPECT_THAT(Results.Completions, IsEmpty());1257}1258 1259TEST(CodeCompleteTest, DisableTypoCorrection) {1260  auto Results = completions(R"cpp(1261     namespace clang { int v; }1262     void f() { clangd::^1263  )cpp");1264  EXPECT_TRUE(Results.Completions.empty());1265}1266 1267TEST(CodeCompleteTest, NoColonColonAtTheEnd) {1268  auto Results = completions(R"cpp(1269    namespace clang { }1270    void f() {1271      clan^1272    }1273  )cpp");1274 1275  EXPECT_THAT(Results.Completions, Contains(labeled("clang")));1276  EXPECT_THAT(Results.Completions, Not(Contains(labeled("clang::"))));1277}1278 1279TEST(CompletionTests, EmptySnippetDoesNotCrash) {1280  // See https://github.com/clangd/clangd/issues/12161281  auto Results = completions(R"cpp(1282        int main() {1283          auto w = [&](auto &&f) { return f(f); };1284          auto f = w([&](auto &&f) {1285            return [&](auto &&n) {1286              if (n == 0) {1287                return 1;1288              }1289              return n * ^(f)(n - 1);1290            };1291          })(10);1292        }1293    )cpp");1294}1295 1296TEST(CompletionTest, Issue1427Crash) {1297  // Need to provide main file signals to ensure that the branch in1298  // SymbolRelevanceSignals::computeASTSignals() that tries to1299  // compute a symbol ID is taken.1300  ASTSignals MainFileSignals;1301  CodeCompleteOptions Opts;1302  Opts.MainFileSignals = &MainFileSignals;1303  completions(R"cpp(1304      auto f = []() {1305        1.0_^1306      };1307    )cpp",1308              {}, Opts);1309}1310 1311TEST(CompletionTest, BacktrackCrashes) {1312  // Sema calls code completion callbacks twice in these cases.1313  auto Results = completions(R"cpp(1314      namespace ns {1315      struct FooBarBaz {};1316      } // namespace ns1317 1318     int foo(ns::FooBar^1319  )cpp");1320 1321  EXPECT_THAT(Results.Completions, ElementsAre(labeled("FooBarBaz")));1322 1323  // Check we don't crash in that case too.1324  completions(R"cpp(1325    struct FooBarBaz {};1326    void test() {1327      if (FooBarBaz * x^) {}1328    }1329)cpp");1330}1331 1332TEST(CompletionTest, CompleteInMacroWithStringification) {1333  auto Results = completions(R"cpp(1334void f(const char *, int x);1335#define F(x) f(#x, x)1336 1337namespace ns {1338int X;1339int Y;1340}  // namespace ns1341 1342int f(int input_num) {1343  F(ns::^)1344}1345)cpp");1346 1347  EXPECT_THAT(Results.Completions,1348              UnorderedElementsAre(named("X"), named("Y")));1349}1350 1351TEST(CompletionTest, CompleteInMacroAndNamespaceWithStringification) {1352  auto Results = completions(R"cpp(1353void f(const char *, int x);1354#define F(x) f(#x, x)1355 1356namespace ns {1357int X;1358 1359int f(int input_num) {1360  F(^)1361}1362}  // namespace ns1363)cpp");1364 1365  EXPECT_THAT(Results.Completions, Contains(named("X")));1366}1367 1368TEST(CompletionTest, IgnoreCompleteInExcludedPPBranchWithRecoveryContext) {1369  auto Results = completions(R"cpp(1370    int bar(int param_in_bar) {1371    }1372 1373    int foo(int param_in_foo) {1374#if 01375  // In recovery mode, "param_in_foo" will also be suggested among many other1376  // unrelated symbols; however, this is really a special case where this works.1377  // If the #if block is outside of the function, "param_in_foo" is still1378  // suggested, but "bar" and "foo" are missing. So the recovery mode doesn't1379  // really provide useful results in excluded branches.1380  par^1381#endif1382    }1383)cpp");1384 1385  EXPECT_TRUE(Results.Completions.empty());1386}1387 1388TEST(CompletionTest, DefaultArgs) {1389  clangd::CodeCompleteOptions Opts;1390  std::string Context = R"cpp(1391    int X(int A = 0);1392    int Y(int A, int B = 0);1393    int Z(int A, int B = 0, int C = 0, int D = 0);1394  )cpp";1395  EXPECT_THAT(completions(Context + "int y = X^", {}, Opts).Completions,1396              UnorderedElementsAre(labeled("X(int A = 0)")));1397  EXPECT_THAT(completions(Context + "int y = Y^", {}, Opts).Completions,1398              UnorderedElementsAre(AllOf(labeled("Y(int A, int B = 0)"),1399                                         snippetSuffix("(${1:int A})"))));1400  EXPECT_THAT(completions(Context + "int y = Z^", {}, Opts).Completions,1401              UnorderedElementsAre(1402                  AllOf(labeled("Z(int A, int B = 0, int C = 0, int D = 0)"),1403                        snippetSuffix("(${1:int A})"))));1404}1405 1406TEST(CompletionTest, NoCrashWithTemplateParamsAndPreferredTypes) {1407  auto Completions = completions(R"cpp(1408template <template <class> class TT> int foo() {1409  int a = ^1410}1411)cpp")1412                         .Completions;1413  EXPECT_THAT(Completions, Contains(named("TT")));1414}1415 1416TEST(CompletionTest, NestedTemplateHeuristics) {1417  auto Completions = completions(R"cpp(1418struct Plain { int xxx; };1419template <typename T> class Templ { Plain ppp; };1420template <typename T> void foo(Templ<T> &t) {1421  // Formally ppp has DependentTy, because Templ may be specialized.1422  // However we sholud be able to see into it using the primary template.1423  t.ppp.^1424}1425)cpp")1426                         .Completions;1427  EXPECT_THAT(Completions, Contains(named("xxx")));1428}1429 1430TEST(CompletionTest, RecordCCResultCallback) {1431  std::vector<CodeCompletion> RecordedCompletions;1432  CodeCompleteOptions Opts;1433  Opts.RecordCCResult = [&RecordedCompletions](const CodeCompletion &CC,1434                                               const SymbolQualitySignals &,1435                                               const SymbolRelevanceSignals &,1436                                               float Score) {1437    RecordedCompletions.push_back(CC);1438  };1439 1440  completions("int xy1, xy2; int a = xy^", /*IndexSymbols=*/{}, Opts);1441  EXPECT_THAT(RecordedCompletions,1442              UnorderedElementsAre(named("xy1"), named("xy2")));1443}1444 1445TEST(CompletionTest, ASTSignals) {1446  struct Completion {1447    std::string Name;1448    unsigned MainFileRefs;1449    unsigned ScopeRefsInFile;1450  };1451  CodeCompleteOptions Opts;1452  std::vector<Completion> RecordedCompletions;1453  Opts.RecordCCResult = [&RecordedCompletions](const CodeCompletion &CC,1454                                               const SymbolQualitySignals &,1455                                               const SymbolRelevanceSignals &R,1456                                               float Score) {1457    RecordedCompletions.push_back({CC.Name, R.MainFileRefs, R.ScopeRefsInFile});1458  };1459  ASTSignals MainFileSignals;1460  MainFileSignals.ReferencedSymbols[var("xy1").ID] = 3;1461  MainFileSignals.ReferencedSymbols[var("xy2").ID] = 1;1462  MainFileSignals.ReferencedSymbols[var("xyindex").ID] = 10;1463  MainFileSignals.RelatedNamespaces["tar::"] = 5;1464  MainFileSignals.RelatedNamespaces["bar::"] = 3;1465  Opts.MainFileSignals = &MainFileSignals;1466  Opts.AllScopes = true;1467  completions(1468      R"cpp(1469      int xy1;1470      int xy2;1471      namespace bar {1472      int xybar = 1;1473      int a = xy^1474      }1475      )cpp",1476      /*IndexSymbols=*/{var("xyindex"), var("tar::xytar"), var("bar::xybar")},1477      Opts);1478  EXPECT_THAT(RecordedCompletions,1479              UnorderedElementsAre(1480                  AllOf(named("xy1"), mainFileRefs(3u), scopeRefs(0u)),1481                  AllOf(named("xy2"), mainFileRefs(1u), scopeRefs(0u)),1482                  AllOf(named("xyindex"), mainFileRefs(10u), scopeRefs(0u)),1483                  AllOf(named("xytar"), mainFileRefs(0u), scopeRefs(5u)),1484                  AllOf(/*both from sema and index*/ named("xybar"),1485                        mainFileRefs(0u), scopeRefs(3u))));1486}1487 1488SignatureHelp1489signatures(llvm::StringRef Text, Position Point,1490           std::vector<Symbol> IndexSymbols = {},1491           MarkupKind DocumentationFormat = MarkupKind::PlainText) {1492  std::unique_ptr<SymbolIndex> Index;1493  if (!IndexSymbols.empty())1494    Index = memIndex(IndexSymbols);1495 1496  auto TU = TestTU::withCode(Text);1497  MockFS FS;1498  auto Inputs = TU.inputs(FS);1499  Inputs.Index = Index.get();1500  IgnoreDiagnostics Diags;1501  auto CI = buildCompilerInvocation(Inputs, Diags);1502  if (!CI) {1503    ADD_FAILURE() << "Couldn't build CompilerInvocation";1504    return {};1505  }1506  auto Preamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,1507                                /*InMemory=*/true, /*Callback=*/nullptr);1508  if (!Preamble) {1509    ADD_FAILURE() << "Couldn't build Preamble";1510    return {};1511  }1512  return signatureHelp(testPath(TU.Filename), Point, *Preamble, Inputs,1513                       DocumentationFormat);1514}1515 1516SignatureHelp1517signatures(llvm::StringRef Text, std::vector<Symbol> IndexSymbols = {},1518           MarkupKind DocumentationFormat = MarkupKind::PlainText) {1519  Annotations Test(Text);1520  return signatures(Test.code(), Test.point(), std::move(IndexSymbols),1521                    DocumentationFormat);1522}1523 1524struct ExpectedParameter {1525  std::string Text;1526  std::pair<unsigned, unsigned> Offsets;1527};1528llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,1529                              const ExpectedParameter &P) {1530  return OS << P.Text;1531}1532MATCHER_P(paramsAre, P, "") {1533  if (P.size() != arg.parameters.size())1534    return false;1535  for (unsigned I = 0; I < P.size(); ++I) {1536    if (P[I].Text != arg.parameters[I].labelString ||1537        P[I].Offsets != arg.parameters[I].labelOffsets)1538      return false;1539  }1540  return true;1541}1542MATCHER_P(sigDoc, doc, "") { return arg.documentation.value == doc; }1543 1544/// \p AnnotatedLabel is a signature label with ranges marking parameters, e.g.1545///    foo([[int p1]], [[double p2]]) -> void1546Matcher<SignatureInformation> sig(llvm::StringRef AnnotatedLabel) {1547  llvm::Annotations A(AnnotatedLabel);1548  std::string Label = std::string(A.code());1549  std::vector<ExpectedParameter> Parameters;1550  for (auto Range : A.ranges()) {1551    Parameters.emplace_back();1552 1553    ExpectedParameter &P = Parameters.back();1554    P.Text = Label.substr(Range.Begin, Range.End - Range.Begin);1555    P.Offsets.first = lspLength(llvm::StringRef(Label).substr(0, Range.Begin));1556    P.Offsets.second = lspLength(llvm::StringRef(Label).substr(1, Range.End));1557  }1558  return AllOf(sigHelpLabeled(Label), paramsAre(Parameters));1559}1560 1561TEST(SignatureHelpTest, Overloads) {1562  auto Results = signatures(R"cpp(1563    void foo(int x, int y);1564    void foo(int x, float y);1565    void foo(float x, int y);1566    void foo(float x, float y);1567    void bar(int x, int y = 0);1568    int main() { foo(^); }1569  )cpp");1570  EXPECT_THAT(Results.signatures,1571              UnorderedElementsAre(sig("foo([[float x]], [[float y]]) -> void"),1572                                   sig("foo([[float x]], [[int y]]) -> void"),1573                                   sig("foo([[int x]], [[float y]]) -> void"),1574                                   sig("foo([[int x]], [[int y]]) -> void")));1575  // We always prefer the first signature.1576  EXPECT_EQ(0, Results.activeSignature);1577  EXPECT_EQ(0, Results.activeParameter);1578}1579 1580TEST(SignatureHelpTest, FunctionPointers) {1581  llvm::StringLiteral Tests[] = {1582      // Variable of function pointer type1583      R"cpp(1584    void (*foo)(int x, int y);1585    int main() { foo(^); }1586  )cpp",1587      // Wrapped in an AttributedType1588      R"cpp(1589    void (__stdcall *foo)(int x, int y);1590    int main() { foo(^); }1591  )cpp",1592      // Another syntax for an AttributedType1593      R"cpp(1594    void (__attribute__(stdcall) *foo)(int x, int y);1595    int main() { foo(^); },1596  )cpp",1597      // Wrapped in a typedef1598      R"cpp(1599    typedef void (*fn)(int x, int y);1600    fn foo;1601    int main() { foo(^); }1602  )cpp",1603      // Wrapped in both a typedef and an AttributedTyped1604      R"cpp(1605    typedef void (__stdcall *fn)(int x, int y);1606    fn foo;1607    int main() { foo(^); }1608  )cpp",1609      // Field of function pointer type1610      R"cpp(1611    struct S {1612      void (*foo)(int x, int y);1613    };1614    S s;1615    int main() { s.foo(^); }1616  )cpp",1617      // Field of function pointer typedef type1618      R"cpp(1619    typedef void (*fn)(int x, int y);1620    struct S {1621      fn foo;1622    };1623    S s;1624    int main() { s.foo(^); }1625  )cpp"};1626  for (auto Test : Tests)1627    EXPECT_THAT(signatures(Test).signatures,1628                UnorderedElementsAre(sig("([[int x]], [[int y]]) -> void")));1629}1630 1631TEST(SignatureHelpTest, Constructors) {1632  std::string Top = R"cpp(1633    struct S {1634      S(int);1635      S(const S &) = delete;1636    };1637  )cpp";1638 1639  auto CheckParenInit = [&](std::string Init) {1640    EXPECT_THAT(signatures(Top + Init).signatures,1641                UnorderedElementsAre(sig("S([[int]])")))1642        << Init;1643  };1644  CheckParenInit("S s(^);");1645  CheckParenInit("auto s = S(^);");1646  CheckParenInit("auto s = new S(^);");1647 1648  auto CheckBracedInit = [&](std::string Init) {1649    EXPECT_THAT(signatures(Top + Init).signatures,1650                UnorderedElementsAre(sig("S{[[int]]}")))1651        << Init;1652  };1653  CheckBracedInit("S s{^};");1654  CheckBracedInit("S s = {^};");1655  CheckBracedInit("auto s = S{^};");1656  // FIXME: doesn't work: no ExpectedType set in ParseCXXNewExpression.1657  // CheckBracedInit("auto s = new S{^};");1658  CheckBracedInit("int x(S); int i = x({^});");1659}1660 1661TEST(SignatureHelpTest, Aggregates) {1662  std::string Top = R"cpp(1663    struct S {1664      int a, b, c, d;1665    };1666  )cpp";1667  auto AggregateSig = sig("S{[[int a]], [[int b]], [[int c]], [[int d]]}");1668  EXPECT_THAT(signatures(Top + "S s{^}").signatures,1669              UnorderedElementsAre(AggregateSig, sig("S{}"),1670                                   sig("S{[[const S &]]}"),1671                                   sig("S{[[S &&]]}")));1672  EXPECT_THAT(signatures(Top + "S s{1,^}").signatures,1673              ElementsAre(AggregateSig));1674  EXPECT_EQ(signatures(Top + "S s{1,^}").activeParameter, 1);1675  EXPECT_THAT(signatures(Top + "S s{.c=3,^}").signatures,1676              ElementsAre(AggregateSig));1677  EXPECT_EQ(signatures(Top + "S s{.c=3,^}").activeParameter, 3);1678}1679 1680TEST(SignatureHelpTest, OverloadInitListRegression) {1681  auto Results = signatures(R"cpp(1682    struct A {int x;};1683    struct B {B(A);};1684    void f();1685    int main() {1686      B b({1});1687      f(^);1688    }1689  )cpp");1690  EXPECT_THAT(Results.signatures, UnorderedElementsAre(sig("f() -> void")));1691}1692 1693TEST(SignatureHelpTest, DefaultArgs) {1694  auto Results = signatures(R"cpp(1695    void bar(int x, int y = 0);1696    void bar(float x = 0, int y = 42);1697    int main() { bar(^1698  )cpp");1699  EXPECT_THAT(Results.signatures,1700              UnorderedElementsAre(1701                  sig("bar([[int x]], [[int y = 0]]) -> void"),1702                  sig("bar([[float x = 0]], [[int y = 42]]) -> void")));1703  EXPECT_EQ(0, Results.activeSignature);1704  EXPECT_EQ(0, Results.activeParameter);1705}1706 1707TEST(SignatureHelpTest, ActiveArg) {1708  auto Results = signatures(R"cpp(1709    int baz(int a, int b, int c);1710    int main() { baz(baz(1,2,3), ^); }1711  )cpp");1712  EXPECT_THAT(Results.signatures,1713              ElementsAre(sig("baz([[int a]], [[int b]], [[int c]]) -> int")));1714  EXPECT_EQ(0, Results.activeSignature);1715  EXPECT_EQ(1, Results.activeParameter);1716}1717 1718TEST(SignatureHelpTest, OpeningParen) {1719  llvm::StringLiteral Tests[] = {1720      // Recursive function call.1721      R"cpp(1722        int foo(int a, int b, int c);1723        int main() {1724          foo(foo $p^( foo(10, 10, 10), ^ )));1725        })cpp",1726      // Functional type cast.1727      R"cpp(1728        struct Foo {1729          Foo(int a, int b, int c);1730        };1731        int main() {1732          Foo $p^( 10, ^ );1733        })cpp",1734      // New expression.1735      R"cpp(1736        struct Foo {1737          Foo(int a, int b, int c);1738        };1739        int main() {1740          new Foo $p^( 10, ^ );1741        })cpp",1742      // Macro expansion.1743      R"cpp(1744        int foo(int a, int b, int c);1745        #define FOO foo(1746 1747        int main() {1748          // Macro expansions.1749          $p^FOO 10, ^ );1750        })cpp",1751      // Macro arguments.1752      R"cpp(1753        int foo(int a, int b, int c);1754        int main() {1755        #define ID(X) X1756          // FIXME: figure out why ID(foo (foo(10), )) doesn't work when preserving1757          // the recovery expression.1758          ID(foo $p^( 10, ^ ))1759        })cpp",1760      // Dependent args.1761      R"cpp(1762        int foo(int a, int b);1763        template <typename T> void bar(T t) {1764          foo$p^(t, ^t);1765        })cpp",1766      // Dependent args on templated func.1767      R"cpp(1768        template <typename T>1769        int foo(T, T);1770        template <typename T> void bar(T t) {1771          foo$p^(t, ^t);1772        })cpp",1773      // Dependent args on member.1774      R"cpp(1775        struct Foo { int foo(int, int); };1776        template <typename T> void bar(T t) {1777          Foo f;1778          f.foo$p^(t, ^t);1779        })cpp",1780      // Dependent args on templated member.1781      R"cpp(1782        struct Foo { template <typename T> int foo(T, T); };1783        template <typename T> void bar(T t) {1784          Foo f;1785          f.foo$p^(t, ^t);1786        })cpp",1787  };1788 1789  for (auto Test : Tests) {1790    Annotations Code(Test);1791    EXPECT_EQ(signatures(Code.code(), Code.point()).argListStart,1792              Code.point("p"))1793        << "Test source:" << Test;1794  }1795}1796 1797TEST(SignatureHelpTest, StalePreamble) {1798  TestTU TU;1799  TU.Code = "";1800  IgnoreDiagnostics Diags;1801  MockFS FS;1802  auto Inputs = TU.inputs(FS);1803  auto CI = buildCompilerInvocation(Inputs, Diags);1804  ASSERT_TRUE(CI);1805  auto EmptyPreamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,1806                                     /*InMemory=*/true, /*Callback=*/nullptr);1807  ASSERT_TRUE(EmptyPreamble);1808 1809  TU.AdditionalFiles["a.h"] = "int foo(int x);";1810  const Annotations Test(R"cpp(1811    #include "a.h"1812    void bar() { foo(^2); })cpp");1813  TU.Code = Test.code().str();1814  auto Results =1815      signatureHelp(testPath(TU.Filename), Test.point(), *EmptyPreamble,1816                    TU.inputs(FS), MarkupKind::PlainText);1817  EXPECT_THAT(Results.signatures, ElementsAre(sig("foo([[int x]]) -> int")));1818  EXPECT_EQ(0, Results.activeSignature);1819  EXPECT_EQ(0, Results.activeParameter);1820}1821 1822class IndexRequestCollector : public SymbolIndex {1823public:1824  IndexRequestCollector(std::vector<Symbol> Syms = {}) : Symbols(Syms) {}1825 1826  bool1827  fuzzyFind(const FuzzyFindRequest &Req,1828            llvm::function_ref<void(const Symbol &)> Callback) const override {1829    std::unique_lock<std::mutex> Lock(Mut);1830    Requests.push_back(Req);1831    ReceivedRequestCV.notify_one();1832    for (const auto &Sym : Symbols)1833      Callback(Sym);1834    return true;1835  }1836 1837  void lookup(const LookupRequest &,1838              llvm::function_ref<void(const Symbol &)>) const override {}1839 1840  bool refs(const RefsRequest &,1841            llvm::function_ref<void(const Ref &)>) const override {1842    return false;1843  }1844 1845  bool containedRefs(1846      const ContainedRefsRequest &,1847      llvm::function_ref<void(const ContainedRefsResult &)>) const override {1848    return false;1849  }1850 1851  void relations(const RelationsRequest &,1852                 llvm::function_ref<void(const SymbolID &, const Symbol &)>)1853      const override {}1854 1855  void1856  reverseRelations(const RelationsRequest &,1857                   llvm::function_ref<void(const SymbolID &, const Symbol &)>)1858      const override {}1859 1860  llvm::unique_function<IndexContents(llvm::StringRef) const>1861  indexedFiles() const override {1862    return [](llvm::StringRef) { return IndexContents::None; };1863  }1864 1865  // This is incorrect, but IndexRequestCollector is not an actual index and it1866  // isn't used in production code.1867  size_t estimateMemoryUsage() const override { return 0; }1868 1869  const std::vector<FuzzyFindRequest> consumeRequests(size_t Num) const {1870    std::unique_lock<std::mutex> Lock(Mut);1871    EXPECT_TRUE(wait(Lock, ReceivedRequestCV, timeoutSeconds(30),1872                     [this, Num] { return Requests.size() == Num; }));1873    auto Reqs = std::move(Requests);1874    Requests = {};1875    return Reqs;1876  }1877 1878private:1879  std::vector<Symbol> Symbols;1880  // We need a mutex to handle async fuzzy find requests.1881  mutable std::condition_variable ReceivedRequestCV;1882  mutable std::mutex Mut;1883  mutable std::vector<FuzzyFindRequest> Requests;1884};1885 1886// Clients have to consume exactly Num requests.1887std::vector<FuzzyFindRequest> captureIndexRequests(llvm::StringRef Code,1888                                                   size_t Num = 1) {1889  clangd::CodeCompleteOptions Opts;1890  IndexRequestCollector Requests;1891  Opts.Index = &Requests;1892  completions(Code, {}, Opts);1893  const auto Reqs = Requests.consumeRequests(Num);1894  EXPECT_EQ(Reqs.size(), Num);1895  return Reqs;1896}1897 1898TEST(CompletionTest, UnqualifiedIdQuery) {1899  auto Requests = captureIndexRequests(R"cpp(1900      namespace std {}1901      using namespace std;1902      namespace ns {1903      void f() {1904        vec^1905      }1906      }1907  )cpp");1908 1909  EXPECT_THAT(Requests,1910              ElementsAre(Field(&FuzzyFindRequest::Scopes,1911                                UnorderedElementsAre("", "ns::", "std::"))));1912}1913 1914TEST(CompletionTest, EnclosingScopeComesFirst) {1915  auto Requests = captureIndexRequests(R"cpp(1916      namespace std {}1917      using namespace std;1918      namespace nx {1919      namespace ns {1920      namespace {1921      void f() {1922        vec^1923      }1924      }1925      }1926      }1927  )cpp");1928 1929  EXPECT_THAT(Requests,1930              ElementsAre(Field(1931                  &FuzzyFindRequest::Scopes,1932                  UnorderedElementsAre("", "std::", "nx::ns::", "nx::"))));1933  EXPECT_EQ(Requests[0].Scopes[0], "nx::ns::");1934}1935 1936TEST(CompletionTest, ResolvedQualifiedIdQuery) {1937  auto Requests = captureIndexRequests(R"cpp(1938      namespace ns1 {}1939      namespace ns2 {} // ignore1940      namespace ns3 { namespace nns3 {} }1941      namespace foo {1942      using namespace ns1;1943      using namespace ns3::nns3;1944      }1945      namespace ns {1946      void f() {1947        foo::^1948      }1949      }1950  )cpp");1951 1952  EXPECT_THAT(Requests,1953              ElementsAre(Field(1954                  &FuzzyFindRequest::Scopes,1955                  UnorderedElementsAre("foo::", "ns1::", "ns3::nns3::"))));1956}1957 1958TEST(CompletionTest, UnresolvedQualifierIdQuery) {1959  auto Requests = captureIndexRequests(R"cpp(1960      namespace a {}1961      using namespace a;1962      namespace ns {1963      void f() {1964      bar::^1965      }1966      } // namespace ns1967  )cpp");1968 1969  EXPECT_THAT(Requests,1970              ElementsAre(Field(1971                  &FuzzyFindRequest::Scopes,1972                  UnorderedElementsAre("a::bar::", "ns::bar::", "bar::"))));1973}1974 1975TEST(CompletionTest, UnresolvedNestedQualifierIdQuery) {1976  auto Requests = captureIndexRequests(R"cpp(1977      namespace a {}1978      using namespace a;1979      namespace ns {1980      void f() {1981      ::a::bar::^1982      }1983      } // namespace ns1984  )cpp");1985 1986  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,1987                                          UnorderedElementsAre("a::bar::"))));1988}1989 1990TEST(CompletionTest, EmptyQualifiedQuery) {1991  auto Requests = captureIndexRequests(R"cpp(1992      namespace ns {1993      void f() {1994      ^1995      }1996      } // namespace ns1997  )cpp");1998 1999  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,2000                                          UnorderedElementsAre("", "ns::"))));2001}2002 2003TEST(CompletionTest, GlobalQualifiedQuery) {2004  auto Requests = captureIndexRequests(R"cpp(2005      namespace ns {2006      void f() {2007      ::^2008      }2009      } // namespace ns2010  )cpp");2011 2012  EXPECT_THAT(Requests, ElementsAre(Field(&FuzzyFindRequest::Scopes,2013                                          UnorderedElementsAre(""))));2014}2015 2016TEST(CompletionTest, NoDuplicatedQueryScopes) {2017  auto Requests = captureIndexRequests(R"cpp(2018      namespace {}2019 2020      namespace na {2021      namespace {}2022      namespace nb {2023      ^2024      } // namespace nb2025      } // namespace na2026  )cpp");2027 2028  EXPECT_THAT(Requests,2029              ElementsAre(Field(&FuzzyFindRequest::Scopes,2030                                UnorderedElementsAre("na::", "na::nb::", ""))));2031}2032 2033TEST(CompletionTest, NoIndexCompletionsInsideClasses) {2034  auto Completions = completions(2035      R"cpp(2036    struct Foo {2037      int SomeNameOfField;2038      typedef int SomeNameOfTypedefField;2039    };2040 2041    Foo::^)cpp",2042      {func("::SomeNameInTheIndex"), func("::Foo::SomeNameInTheIndex")});2043 2044  EXPECT_THAT(Completions.Completions,2045              AllOf(Contains(labeled("SomeNameOfField")),2046                    Contains(labeled("SomeNameOfTypedefField")),2047                    Not(Contains(labeled("SomeNameInTheIndex")))));2048}2049 2050TEST(CompletionTest, NoIndexCompletionsInsideDependentCode) {2051  {2052    auto Completions = completions(2053        R"cpp(2054      template <class T>2055      void foo() {2056        T::^2057      }2058      )cpp",2059        {func("::SomeNameInTheIndex")});2060 2061    EXPECT_THAT(Completions.Completions,2062                Not(Contains(labeled("SomeNameInTheIndex"))));2063  }2064 2065  {2066    auto Completions = completions(2067        R"cpp(2068      template <class T>2069      void foo() {2070        T::template Y<int>::^2071      }2072      )cpp",2073        {func("::SomeNameInTheIndex")});2074 2075    EXPECT_THAT(Completions.Completions,2076                Not(Contains(labeled("SomeNameInTheIndex"))));2077  }2078 2079  {2080    auto Completions = completions(2081        R"cpp(2082      template <class T>2083      void foo() {2084        T::foo::^2085      }2086      )cpp",2087        {func("::SomeNameInTheIndex")});2088 2089    EXPECT_THAT(Completions.Completions,2090                Not(Contains(labeled("SomeNameInTheIndex"))));2091  }2092}2093 2094TEST(CompletionTest, OverloadBundling) {2095  clangd::CodeCompleteOptions Opts;2096  Opts.BundleOverloads = true;2097 2098  std::string Context = R"cpp(2099    struct X {2100      // Overload with int2101      int a(int) __attribute__((deprecated("", "")));2102      // Overload with bool2103      int a(bool);2104      int b(float);2105 2106      X(int);2107      X(float);2108    };2109    int GFuncC(int);2110    int GFuncD(int);2111  )cpp";2112 2113  // Member completions are bundled.2114  EXPECT_THAT(completions(Context + "int y = X().^", {}, Opts).Completions,2115              UnorderedElementsAre(labeled("a(…)"), labeled("b(float)")));2116 2117  // Constructor completions are bundled.2118  EXPECT_THAT(completions(Context + "X z = X^", {}, Opts).Completions,2119              UnorderedElementsAre(labeled("X"), labeled("X(…)")));2120 2121  // Non-member completions are bundled, including index+sema.2122  Symbol NoArgsGFunc = func("GFuncC");2123  EXPECT_THAT(2124      completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,2125      UnorderedElementsAre(labeled("GFuncC(…)"), labeled("GFuncD(int)")));2126 2127  // Differences in header-to-insert suppress bundling.2128  std::string DeclFile = URI::create(testPath("foo")).toString();2129  NoArgsGFunc.CanonicalDeclaration.FileURI = DeclFile.c_str();2130  NoArgsGFunc.IncludeHeaders.emplace_back("<foo>", 1, Symbol::Include);2131  EXPECT_THAT(2132      completions(Context + "int y = GFunc^", {NoArgsGFunc}, Opts).Completions,2133      UnorderedElementsAre(AllOf(named("GFuncC"), insertInclude("<foo>")),2134                           labeled("GFuncC(int)"), labeled("GFuncD(int)")));2135 2136  // Examine a bundled completion in detail.2137  auto A =2138      completions(Context + "int y = X().a^", {}, Opts).Completions.front();2139  EXPECT_EQ(A.Name, "a");2140  EXPECT_EQ(A.Signature, "(…)");2141  EXPECT_EQ(A.BundleSize, 2u);2142  EXPECT_EQ(A.Kind, CompletionItemKind::Method);2143  EXPECT_EQ(A.ReturnType, "int"); // All overloads return int.2144  // For now we just return one of the doc strings arbitrarily.2145  ASSERT_TRUE(A.Documentation);2146  ASSERT_FALSE(A.Deprecated); // Not all overloads deprecated.2147  EXPECT_THAT(2148      A.Documentation->asPlainText(),2149      AnyOf(HasSubstr("Overload with int"), HasSubstr("Overload with bool")));2150  EXPECT_EQ(A.SnippetSuffix, "($0)");2151}2152 2153TEST(CompletionTest, OverloadBundlingSameFileDifferentURI) {2154  clangd::CodeCompleteOptions Opts;2155  Opts.BundleOverloads = true;2156 2157  Symbol SymX = sym("ns::X", index::SymbolKind::Function, "@F@\\0#");2158  Symbol SymY = sym("ns::X", index::SymbolKind::Function, "@F@\\0#I#");2159  std::string BarHeader = testPath("bar.h");2160  auto BarURI = URI::create(BarHeader).toString();2161  SymX.CanonicalDeclaration.FileURI = BarURI.c_str();2162  SymY.CanonicalDeclaration.FileURI = BarURI.c_str();2163  // The include header is different, but really it's the same file.2164  SymX.IncludeHeaders.emplace_back("\"bar.h\"", 1, Symbol::Include);2165  SymY.IncludeHeaders.emplace_back(BarURI.c_str(), 1, Symbol::Include);2166 2167  auto Results = completions("void f() { ::ns::^ }", {SymX, SymY}, Opts);2168  // Expect both results are bundled, despite the different-but-same2169  // IncludeHeader.2170  ASSERT_EQ(1u, Results.Completions.size());2171  const auto &R = Results.Completions.front();2172  EXPECT_EQ("X", R.Name);2173  EXPECT_EQ(2u, R.BundleSize);2174}2175 2176TEST(CompletionTest, DocumentationFromChangedFileCrash) {2177  MockFS FS;2178  auto FooH = testPath("foo.h");2179  auto FooCpp = testPath("foo.cpp");2180  FS.Files[FooH] = R"cpp(2181    // this is my documentation comment.2182    int func();2183  )cpp";2184  FS.Files[FooCpp] = "";2185 2186  MockCompilationDatabase CDB;2187  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());2188 2189  Annotations Source(R"cpp(2190    #include "foo.h"2191    int func() {2192      // This makes sure we have func from header in the AST.2193    }2194    int a = fun^2195  )cpp");2196  Server.addDocument(FooCpp, Source.code(), "null", WantDiagnostics::Yes);2197  // We need to wait for preamble to build.2198  ASSERT_TRUE(Server.blockUntilIdleForTest());2199 2200  // Change the header file. Completion will reuse the old preamble!2201  FS.Files[FooH] = R"cpp(2202    int func();2203  )cpp";2204 2205  clangd::CodeCompleteOptions Opts;2206  CodeCompleteResult Completions =2207      cantFail(runCodeComplete(Server, FooCpp, Source.point(), Opts));2208  // We shouldn't crash. Unfortunately, current workaround is to not produce2209  // comments for symbols from headers.2210  EXPECT_THAT(Completions.Completions,2211              Contains(AllOf(Not(isDocumented()), named("func"))));2212}2213 2214TEST(CompletionTest, NonDocComments) {2215  const char *Text = R"cpp(2216    // We ignore namespace comments, for rationale see CodeCompletionStrings.h.2217    namespace comments_ns {2218    }2219 2220    // ------------------2221    int comments_foo();2222 2223    // A comment and a decl are separated by newlines.2224    // Therefore, the comment shouldn't show up as doc comment.2225 2226    int comments_bar();2227 2228    // this comment should be in the results.2229    int comments_baz();2230 2231 2232    template <class T>2233    struct Struct {2234      int comments_qux();2235      int comments_quux();2236    };2237 2238 2239    // This comment should not be there.2240 2241    template <class T>2242    int Struct<T>::comments_qux() {2243    }2244 2245    // This comment **should** be in results.2246    template <class T>2247    int Struct<T>::comments_quux() {2248      int a = comments^;2249    }2250  )cpp";2251 2252  // We should not get any of those comments in completion.2253  EXPECT_THAT(2254      completions(Text).Completions,2255      UnorderedElementsAre(AllOf(Not(isDocumented()), named("comments_foo")),2256                           AllOf(isDocumented(), named("comments_baz")),2257                           AllOf(isDocumented(), named("comments_quux")),2258                           AllOf(Not(isDocumented()), named("comments_ns")),2259                           // FIXME(ibiryukov): the following items should have2260                           // empty documentation, since they are separated from2261                           // a comment with an empty line. Unfortunately, I2262                           // couldn't make Sema tests pass if we ignore those.2263                           AllOf(isDocumented(), named("comments_bar")),2264                           AllOf(isDocumented(), named("comments_qux"))));2265}2266 2267TEST(CompletionTest, CompleteOnInvalidLine) {2268  auto FooCpp = testPath("foo.cpp");2269 2270  MockCompilationDatabase CDB;2271  MockFS FS;2272  FS.Files[FooCpp] = "// empty file";2273 2274  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());2275  // Run completion outside the file range.2276  Position Pos;2277  Pos.line = 100;2278  Pos.character = 0;2279  EXPECT_THAT_EXPECTED(2280      runCodeComplete(Server, FooCpp, Pos, clangd::CodeCompleteOptions()),2281      Failed());2282}2283 2284TEST(CompletionTest, QualifiedNames) {2285  auto Results = completions(2286      R"cpp(2287          namespace ns { int local; void both(); }2288          void f() { ::ns::^ }2289      )cpp",2290      {func("ns::both"), cls("ns::Index")});2291  // We get results from both index and sema, with no duplicates.2292  EXPECT_THAT(2293      Results.Completions,2294      UnorderedElementsAre(scope("ns::"), scope("ns::"), scope("ns::")));2295}2296 2297TEST(CompletionTest, Render) {2298  CodeCompletion C;2299  C.Name = "x";2300  C.FilterText = "x";2301  C.Signature = "(bool) const";2302  C.SnippetSuffix = "(${0:bool})";2303  C.ReturnType = "int";2304  C.RequiredQualifier = "Foo::";2305  C.Scope = "ns::Foo::";2306  C.Documentation.emplace();2307  C.Documentation->addParagraph().appendText("This is ").appendCode("x()");2308  C.Includes.emplace_back();2309  auto &Include = C.Includes.back();2310  Include.Header = "\"foo.h\"";2311  C.Kind = CompletionItemKind::Method;2312  C.Score.Total = 1.0;2313  C.Score.ExcludingName = .5;2314  C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;2315 2316  CodeCompleteOptions Opts;2317  Opts.IncludeIndicator.Insert = "^";2318  Opts.IncludeIndicator.NoInsert = "";2319  Opts.EnableSnippets = false;2320 2321  auto R = C.render(Opts);2322  EXPECT_EQ(R.label, "Foo::x");2323  EXPECT_EQ(R.labelDetails->detail, "(bool) const");2324  EXPECT_EQ(R.insertText, "Foo::x");2325  EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);2326  EXPECT_EQ(R.filterText, "x");2327  EXPECT_EQ(R.detail, "int");2328  EXPECT_EQ(R.documentation->value, "From \"foo.h\"\n\nThis is x()");2329  EXPECT_THAT(R.additionalTextEdits, IsEmpty());2330  EXPECT_EQ(R.sortText, sortText(1.0, "x"));2331  EXPECT_FALSE(R.deprecated);2332  EXPECT_EQ(R.score, .5f);2333 2334  C.FilterText = "xtra";2335  R = C.render(Opts);2336  EXPECT_EQ(R.filterText, "xtra");2337  EXPECT_EQ(R.sortText, sortText(1.0, "xtra"));2338 2339  Opts.EnableSnippets = true;2340  R = C.render(Opts);2341  EXPECT_EQ(R.insertText, "Foo::x(${0:bool})");2342  EXPECT_EQ(R.insertTextFormat, InsertTextFormat::Snippet);2343 2344  C.SnippetSuffix = "";2345  R = C.render(Opts);2346  EXPECT_EQ(R.insertText, "Foo::x");2347  EXPECT_EQ(R.insertTextFormat, InsertTextFormat::PlainText);2348 2349  Include.Insertion.emplace();2350  R = C.render(Opts);2351  EXPECT_EQ(R.label, "^Foo::x");2352  EXPECT_EQ(R.labelDetails->detail, "(bool) const");2353  EXPECT_THAT(R.additionalTextEdits, Not(IsEmpty()));2354 2355  Opts.ShowOrigins = true;2356  R = C.render(Opts);2357  EXPECT_EQ(R.label, "^[AS]Foo::x");2358  EXPECT_EQ(R.labelDetails->detail, "(bool) const");2359 2360  C.BundleSize = 2;2361  R = C.render(Opts);2362  EXPECT_EQ(R.detail, "[2 overloads]");2363  EXPECT_EQ(R.documentation->value, "From \"foo.h\"\n\nThis is x()");2364 2365  C.Deprecated = true;2366  R = C.render(Opts);2367  EXPECT_TRUE(R.deprecated);2368 2369  Opts.DocumentationFormat = MarkupKind::Markdown;2370  R = C.render(Opts);2371  EXPECT_EQ(R.documentation->value, "From `\"foo.h\"`\n\nThis is `x()`");2372}2373 2374TEST(CompletionTest, IgnoreRecoveryResults) {2375  auto Results = completions(2376      R"cpp(2377          namespace ns { int NotRecovered() { return 0; } }2378          void f() {2379            // Sema enters recovery mode first and then normal mode.2380            if (auto x = ns::NotRecover^)2381          }2382      )cpp");2383  EXPECT_THAT(Results.Completions, UnorderedElementsAre(named("NotRecovered")));2384}2385 2386TEST(CompletionTest, ScopeOfClassFieldInConstructorInitializer) {2387  auto Results = completions(2388      R"cpp(2389        namespace ns {2390          class X { public: X(); int x_; };2391          X::X() : x_^(0) {}2392        }2393      )cpp");2394  EXPECT_THAT(Results.Completions,2395              UnorderedElementsAre(AllOf(scope("ns::X::"), named("x_"))));2396}2397 2398// Like other class members, constructor init lists have to parse what's below,2399// after the completion point.2400// But recovering from an incomplete constructor init list is particularly2401// tricky because the bulk of the list is not surrounded by brackets.2402TEST(CompletionTest, ConstructorInitListIncomplete) {2403  auto Results = completions(2404      R"cpp(2405        namespace ns {2406          struct X {2407            X() : x^2408            int xyz_;2409          };2410        }2411      )cpp");2412  EXPECT_THAT(Results.Completions, ElementsAre(named("xyz_")));2413 2414  Results = completions(2415      R"cpp(2416        int foo();2417 2418        namespace ns {2419          struct X {2420            X() : xyz_(fo^2421            int xyz_;2422          };2423        }2424      )cpp");2425  EXPECT_THAT(Results.Completions, ElementsAre(named("foo")));2426}2427 2428TEST(CompletionTest, CodeCompletionContext) {2429  auto Results = completions(2430      R"cpp(2431        namespace ns {2432          class X { public: X(); int x_; };2433          void f() {2434            X x;2435            x.^;2436          }2437        }2438      )cpp");2439 2440  EXPECT_THAT(Results.Context, CodeCompletionContext::CCC_DotMemberAccess);2441}2442 2443TEST(CompletionTest, FixItForArrowToDot) {2444  MockFS FS;2445  MockCompilationDatabase CDB;2446 2447  CodeCompleteOptions Opts;2448  Opts.IncludeFixIts = true;2449  const char *Code =2450      R"cpp(2451        class Auxilary {2452         public:2453          void AuxFunction();2454        };2455        class ClassWithPtr {2456         public:2457          void MemberFunction();2458          Auxilary* operator->() const;2459          Auxilary* Aux;2460        };2461        void f() {2462          ClassWithPtr x;2463          x[[->]]^;2464        }2465      )cpp";2466  auto Results = completions(Code, {}, Opts);2467  EXPECT_EQ(Results.Completions.size(), 3u);2468 2469  TextEdit ReplacementEdit;2470  ReplacementEdit.range = Annotations(Code).range();2471  ReplacementEdit.newText = ".";2472  for (const auto &C : Results.Completions) {2473    EXPECT_TRUE(C.FixIts.size() == 1u || C.Name == "AuxFunction");2474    if (!C.FixIts.empty()) {2475      EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));2476    }2477  }2478}2479 2480TEST(CompletionTest, FixItForDotToArrow) {2481  CodeCompleteOptions Opts;2482  Opts.IncludeFixIts = true;2483  const char *Code =2484      R"cpp(2485        class Auxilary {2486         public:2487          void AuxFunction();2488        };2489        class ClassWithPtr {2490         public:2491          void MemberFunction();2492          Auxilary* operator->() const;2493          Auxilary* Aux;2494        };2495        void f() {2496          ClassWithPtr x;2497          x[[.]]^;2498        }2499      )cpp";2500  auto Results = completions(Code, {}, Opts);2501  EXPECT_EQ(Results.Completions.size(), 3u);2502 2503  TextEdit ReplacementEdit;2504  ReplacementEdit.range = Annotations(Code).range();2505  ReplacementEdit.newText = "->";2506  for (const auto &C : Results.Completions) {2507    EXPECT_TRUE(C.FixIts.empty() || C.Name == "AuxFunction");2508    if (!C.FixIts.empty()) {2509      EXPECT_THAT(C.FixIts, ElementsAre(ReplacementEdit));2510    }2511  }2512}2513 2514TEST(CompletionTest, RenderWithFixItMerged) {2515  TextEdit FixIt;2516  FixIt.range.end.character = 5;2517  FixIt.newText = "->";2518 2519  CodeCompletion C;2520  C.Name = "x";2521  C.RequiredQualifier = "Foo::";2522  C.FixIts = {FixIt};2523  C.CompletionTokenRange.start.character = 5;2524 2525  CodeCompleteOptions Opts;2526  Opts.IncludeFixIts = true;2527 2528  auto R = C.render(Opts);2529  EXPECT_TRUE(R.textEdit);2530  EXPECT_EQ(R.textEdit->newText, "->Foo::x");2531  EXPECT_TRUE(R.additionalTextEdits.empty());2532}2533 2534TEST(CompletionTest, RenderWithFixItNonMerged) {2535  TextEdit FixIt;2536  FixIt.range.end.character = 4;2537  FixIt.newText = "->";2538 2539  CodeCompletion C;2540  C.Name = "x";2541  C.RequiredQualifier = "Foo::";2542  C.FixIts = {FixIt};2543  C.CompletionTokenRange.start.character = 5;2544 2545  CodeCompleteOptions Opts;2546  Opts.IncludeFixIts = true;2547 2548  auto R = C.render(Opts);2549  EXPECT_TRUE(R.textEdit);2550  EXPECT_EQ(R.textEdit->newText, "Foo::x");2551  EXPECT_THAT(R.additionalTextEdits, UnorderedElementsAre(FixIt));2552}2553 2554TEST(CompletionTest, CompletionTokenRange) {2555  MockFS FS;2556  MockCompilationDatabase CDB;2557  TestTU TU;2558  TU.AdditionalFiles["foo/abc/foo.h"] = "";2559 2560  constexpr const char *TestCodes[] = {2561      R"cpp(2562        class Auxilary {2563         public:2564          void AuxFunction();2565        };2566        void f() {2567          Auxilary x;2568          x.[[Aux]]^;2569        }2570      )cpp",2571      R"cpp(2572        class Auxilary {2573         public:2574          void AuxFunction();2575        };2576        void f() {2577          Auxilary x;2578          x.[[]]^;2579        }2580      )cpp",2581      R"cpp(2582        #include "foo/[[a^/]]foo.h"2583      )cpp",2584      R"cpp(2585        #include "foo/abc/[[fo^o.h"]]2586      )cpp",2587  };2588  for (const auto &Text : TestCodes) {2589    Annotations TestCode(Text);2590    TU.Code = TestCode.code().str();2591    auto Results = completions(TU, TestCode.point());2592    if (Results.Completions.size() != 1) {2593      ADD_FAILURE() << "Results.Completions.size() != 1" << Text;2594      continue;2595    }2596    EXPECT_THAT(Results.Completions.front().CompletionTokenRange,2597                TestCode.range());2598  }2599}2600 2601TEST(SignatureHelpTest, OverloadsOrdering) {2602  const auto Results = signatures(R"cpp(2603    void foo(int x);2604    void foo(int x, float y);2605    void foo(float x, int y);2606    void foo(float x, float y);2607    void foo(int x, int y = 0);2608    int main() { foo(^); }2609  )cpp");2610  EXPECT_THAT(Results.signatures,2611              ElementsAre(sig("foo([[int x]]) -> void"),2612                          sig("foo([[int x]], [[int y = 0]]) -> void"),2613                          sig("foo([[float x]], [[int y]]) -> void"),2614                          sig("foo([[int x]], [[float y]]) -> void"),2615                          sig("foo([[float x]], [[float y]]) -> void")));2616  // We always prefer the first signature.2617  EXPECT_EQ(0, Results.activeSignature);2618  EXPECT_EQ(0, Results.activeParameter);2619}2620 2621TEST(SignatureHelpTest, InstantiatedSignatures) {2622  StringRef Sig0 = R"cpp(2623    template <class T>2624    void foo(T, T, T);2625 2626    int main() {2627      foo<int>(^);2628    }2629  )cpp";2630 2631  EXPECT_THAT(signatures(Sig0).signatures,2632              ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));2633 2634  StringRef Sig1 = R"cpp(2635    template <class T>2636    void foo(T, T, T);2637 2638    int main() {2639      foo(10, ^);2640    })cpp";2641 2642  EXPECT_THAT(signatures(Sig1).signatures,2643              ElementsAre(sig("foo([[T]], [[T]], [[T]]) -> void")));2644 2645  StringRef Sig2 = R"cpp(2646    template <class ...T>2647    void foo(T...);2648 2649    int main() {2650      foo<int>(^);2651    }2652  )cpp";2653 2654  EXPECT_THAT(signatures(Sig2).signatures,2655              ElementsAre(sig("foo([[T...]]) -> void")));2656 2657  // It is debatable whether we should substitute the outer template parameter2658  // ('T') in that case. Currently we don't substitute it in signature help, but2659  // do substitute in code complete.2660  // FIXME: make code complete and signature help consistent, figure out which2661  // way is better.2662  StringRef Sig3 = R"cpp(2663    template <class T>2664    struct X {2665      template <class U>2666      void foo(T, U);2667    };2668 2669    int main() {2670      X<int>().foo<double>(^)2671    }2672  )cpp";2673 2674  EXPECT_THAT(signatures(Sig3).signatures,2675              ElementsAre(sig("foo([[T]], [[U]]) -> void")));2676}2677 2678TEST(SignatureHelpTest, IndexDocumentation) {2679  Symbol Foo0 = sym("foo", index::SymbolKind::Function, "@F@\\0#");2680  Foo0.Documentation = "doc from the index";2681  Symbol Foo1 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#");2682  Foo1.Documentation = "doc from the index";2683  Symbol Foo2 = sym("foo", index::SymbolKind::Function, "@F@\\0#I#I#");2684 2685  StringRef Sig0 = R"cpp(2686    int foo();2687    int foo(double);2688 2689    void test() {2690      foo(^);2691    }2692  )cpp";2693 2694  EXPECT_THAT(2695      signatures(Sig0, {Foo0}).signatures,2696      ElementsAre(AllOf(sig("foo() -> int"), sigDoc("doc from the index")),2697                  AllOf(sig("foo([[double]]) -> int"), sigDoc(""))));2698 2699  StringRef Sig1 = R"cpp(2700    int foo();2701    // Overriden doc from sema2702    int foo(int);2703    // doc from sema2704    int foo(int, int);2705 2706    void test() {2707      foo(^);2708    }2709  )cpp";2710 2711  EXPECT_THAT(2712      signatures(Sig1, {Foo0, Foo1, Foo2}).signatures,2713      ElementsAre(2714          AllOf(sig("foo() -> int"), sigDoc("doc from the index")),2715          AllOf(sig("foo([[int]]) -> int"), sigDoc("Overriden doc from sema")),2716          AllOf(sig("foo([[int]], [[int]]) -> int"), sigDoc("doc from sema"))));2717}2718 2719TEST(SignatureHelpTest, DynamicIndexDocumentation) {2720  MockFS FS;2721  MockCompilationDatabase CDB;2722  ClangdServer::Options Opts = ClangdServer::optsForTest();2723  Opts.BuildDynamicSymbolIndex = true;2724  ClangdServer Server(CDB, FS, Opts);2725 2726  FS.Files[testPath("foo.h")] = R"cpp(2727    struct Foo {2728       // Member doc2729       int foo();2730    };2731  )cpp";2732  Annotations FileContent(R"cpp(2733    #include "foo.h"2734    void test() {2735      Foo f;2736      f.foo(^);2737    }2738  )cpp");2739  auto File = testPath("test.cpp");2740  Server.addDocument(File, FileContent.code());2741  // Wait for the dynamic index being built.2742  ASSERT_TRUE(Server.blockUntilIdleForTest());2743  EXPECT_THAT(llvm::cantFail(runSignatureHelp(Server, File, FileContent.point(),2744                                              MarkupKind::PlainText))2745                  .signatures,2746              ElementsAre(AllOf(sig("foo() -> int"), sigDoc("Member doc"))));2747}2748 2749TEST(CompletionTest, ArgumentListsPolicy) {2750  CodeCompleteOptions Opts;2751  Opts.EnableSnippets = true;2752  Opts.ArgumentLists = Config::ArgumentListsPolicy::Delimiters;2753 2754  {2755    auto Results = completions(2756        R"cpp(2757      void xfoo();2758      void xfoo(int x, int y);2759      void f() { xfo^ })cpp",2760        {}, Opts);2761    EXPECT_THAT(2762        Results.Completions,2763        UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("()")),2764                             AllOf(named("xfoo"), snippetSuffix("($0)"))));2765  }2766  {2767    auto Results = completions(2768        R"cpp(2769      void xbar();2770      void f() { xba^ })cpp",2771        {}, Opts);2772    EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(2773                                         named("xbar"), snippetSuffix("()"))));2774  }2775  {2776    Opts.BundleOverloads = true;2777    auto Results = completions(2778        R"cpp(2779      void xfoo();2780      void xfoo(int x, int y);2781      void f() { xfo^ })cpp",2782        {}, Opts);2783    EXPECT_THAT(2784        Results.Completions,2785        UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("($0)"))));2786  }2787  {2788    auto Results = completions(2789        R"cpp(2790      template <class T, class U>2791      void xfoo(int a, U b);2792      void f() { xfo^ })cpp",2793        {}, Opts);2794    EXPECT_THAT(2795        Results.Completions,2796        UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("<$1>($0)"))));2797  }2798  {2799    auto Results = completions(2800        R"cpp(2801      template <class T>2802      class foo_class{};2803      template <class T>2804      using foo_alias = T**;2805      template <class T>2806      T foo_var = T{};2807      void f() { foo_^ })cpp",2808        {}, Opts);2809    EXPECT_THAT(2810        Results.Completions,2811        UnorderedElementsAre(AllOf(named("foo_class"), snippetSuffix("<$0>")),2812                             AllOf(named("foo_alias"), snippetSuffix("<$0>")),2813                             AllOf(named("foo_var"), snippetSuffix("<$0>"))));2814  }2815  {2816    auto Results = completions(2817        R"cpp(2818      #define FOO(x, y) x##f2819      FO^ )cpp",2820        {}, Opts);2821    EXPECT_THAT(Results.Completions, UnorderedElementsAre(AllOf(2822                                         named("FOO"), snippetSuffix("($0)"))));2823  }2824  {2825    Opts.ArgumentLists = Config::ArgumentListsPolicy::None;2826    auto Results = completions(2827        R"cpp(2828      void xfoo(int x, int y);2829      void f() { xfo^ })cpp",2830        {}, Opts);2831    EXPECT_THAT(Results.Completions,2832                UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix(""))));2833  }2834  {2835    Opts.ArgumentLists = Config::ArgumentListsPolicy::OpenDelimiter;2836    auto Results = completions(2837        R"cpp(2838      void xfoo(int x, int y);2839      void f() { xfo^ })cpp",2840        {}, Opts);2841    EXPECT_THAT(Results.Completions,2842                UnorderedElementsAre(AllOf(named("xfoo"), snippetSuffix("("))));2843  }2844}2845 2846TEST(CompletionTest, SuggestOverrides) {2847  constexpr const char *const Text(R"cpp(2848  class A {2849   public:2850    virtual void vfunc(bool param);2851    virtual void vfunc(bool param, int p);2852    void func(bool param);2853  };2854  class B : public A {2855  virtual void ttt(bool param) const;2856  void vfunc(bool param, int p) override;2857  };2858  class C : public B {2859   public:2860    void vfunc(bool param) override;2861    ^2862  };2863  )cpp");2864  const auto Results = completions(Text);2865  EXPECT_THAT(2866      Results.Completions,2867      AllOf(Contains(AllOf(labeled("void vfunc(bool param, int p) override"),2868                           nameStartsWith("vfunc"))),2869            Contains(AllOf(labeled("void ttt(bool param) const override"),2870                           nameStartsWith("ttt"))),2871            Not(Contains(labeled("void vfunc(bool param) override")))));2872}2873 2874TEST(CompletionTest, OverridesNonIdentName) {2875  // Check the completions call does not crash.2876  completions(R"cpp(2877    struct Base {2878      virtual ~Base() = 0;2879      virtual operator int() = 0;2880      virtual Base& operator+(Base&) = 0;2881    };2882 2883    struct Derived : Base {2884      ^2885    };2886  )cpp");2887}2888 2889TEST(CompletionTest, NoCrashOnMissingNewLineAtEOF) {2890  auto FooCpp = testPath("foo.cpp");2891 2892  MockCompilationDatabase CDB;2893  MockFS FS;2894  Annotations F("#pragma ^ // no new line");2895  FS.Files[FooCpp] = F.code().str();2896  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());2897  runAddDocument(Server, FooCpp, F.code());2898  // Run completion outside the file range.2899  EXPECT_THAT(cantFail(runCodeComplete(Server, FooCpp, F.point(),2900                                       clangd::CodeCompleteOptions()))2901                  .Completions,2902              IsEmpty());2903  EXPECT_THAT(cantFail(runSignatureHelp(Server, FooCpp, F.point(),2904                                        MarkupKind::PlainText))2905                  .signatures,2906              IsEmpty());2907}2908 2909TEST(GuessCompletionPrefix, Filters) {2910  for (llvm::StringRef Case : {2911           "[[scope::]][[ident]]^",2912           "[[]][[]]^",2913           "\n[[]][[]]^",2914           "[[]][[ab]]^",2915           "x.[[]][[ab]]^",2916           "x.[[]][[]]^",2917           "[[x::]][[ab]]^",2918           "[[x::]][[]]^",2919           "[[::x::]][[ab]]^",2920           "some text [[scope::more::]][[identif]]^ier",2921           "some text [[scope::]][[mor]]^e::identifier",2922           "weird case foo::[[::bar::]][[baz]]^",2923           "/* [[]][[]]^ */",2924       }) {2925    Annotations F(Case);2926    auto Offset = cantFail(positionToOffset(F.code(), F.point()));2927    auto ToStringRef = [&](Range R) {2928      return F.code().slice(cantFail(positionToOffset(F.code(), R.start)),2929                            cantFail(positionToOffset(F.code(), R.end)));2930    };2931    auto WantQualifier = ToStringRef(F.ranges()[0]),2932         WantName = ToStringRef(F.ranges()[1]);2933 2934    auto Prefix = guessCompletionPrefix(F.code(), Offset);2935    // Even when components are empty, check their offsets are correct.2936    EXPECT_EQ(WantQualifier, Prefix.Qualifier) << Case;2937    EXPECT_EQ(WantQualifier.begin(), Prefix.Qualifier.begin()) << Case;2938    EXPECT_EQ(WantName, Prefix.Name) << Case;2939    EXPECT_EQ(WantName.begin(), Prefix.Name.begin()) << Case;2940  }2941}2942 2943TEST(CompletionTest, EnableSpeculativeIndexRequest) {2944  MockFS FS;2945  MockCompilationDatabase CDB;2946  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());2947 2948  auto File = testPath("foo.cpp");2949  Annotations Test(R"cpp(2950      namespace ns1 { int abc; }2951      namespace ns2 { int abc; }2952      void f() { ns1::ab$1^; ns1::ab$2^; }2953      void f2() { ns2::ab$3^; }2954  )cpp");2955  runAddDocument(Server, File, Test.code());2956  clangd::CodeCompleteOptions Opts = {};2957 2958  IndexRequestCollector Requests;2959  Opts.Index = &Requests;2960 2961  auto CompleteAtPoint = [&](StringRef P) {2962    auto CCR = cantFail(runCodeComplete(Server, File, Test.point(P), Opts));2963    EXPECT_TRUE(CCR.HasMore);2964  };2965 2966  CompleteAtPoint("1");2967  auto Reqs1 = Requests.consumeRequests(1);2968  ASSERT_EQ(Reqs1.size(), 1u);2969  EXPECT_THAT(Reqs1[0].Scopes, UnorderedElementsAre("ns1::"));2970 2971  CompleteAtPoint("2");2972  auto Reqs2 = Requests.consumeRequests(1);2973  // Speculation succeeded. Used speculative index result.2974  ASSERT_EQ(Reqs2.size(), 1u);2975  EXPECT_EQ(Reqs2[0], Reqs1[0]);2976 2977  CompleteAtPoint("3");2978  // Speculation failed. Sent speculative index request and the new index2979  // request after sema.2980  auto Reqs3 = Requests.consumeRequests(2);2981  ASSERT_EQ(Reqs3.size(), 2u);2982}2983 2984TEST(CompletionTest, InsertTheMostPopularHeader) {2985  std::string DeclFile = URI::create(testPath("foo")).toString();2986  Symbol Sym = func("Func");2987  Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();2988  Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2, Symbol::Include);2989  Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000, Symbol::Include);2990 2991  auto Results = completions("Fun^", {Sym}).Completions;2992  assert(!Results.empty());2993  EXPECT_THAT(Results[0], AllOf(named("Func"), insertInclude("\"bar.h\"")));2994  EXPECT_EQ(Results[0].Includes.size(), 2u);2995}2996 2997TEST(CompletionTest, InsertIncludeOrImport) {2998  std::string DeclFile = URI::create(testPath("foo")).toString();2999  Symbol Sym = func("Func");3000  Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();3001  Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000,3002                                  Symbol::Include | Symbol::Import);3003  CodeCompleteOptions Opts;3004  // Should only take effect in import contexts.3005  Opts.ImportInsertions = true;3006  auto Results = completions("Fun^", {Sym}, Opts).Completions;3007  assert(!Results.empty());3008  EXPECT_THAT(Results[0],3009              AllOf(named("Func"), insertIncludeText("#include \"bar.h\"\n")));3010 3011  ASTSignals Signals;3012  Signals.InsertionDirective = Symbol::IncludeDirective::Import;3013  Opts.MainFileSignals = &Signals;3014  Results = completions("Fun^", {Sym}, Opts, "Foo.m").Completions;3015  assert(!Results.empty());3016  EXPECT_THAT(Results[0],3017              AllOf(named("Func"), insertIncludeText("#import \"bar.h\"\n")));3018 3019  Sym.IncludeHeaders[0].SupportedDirectives = Symbol::Import;3020  Results = completions("Fun^", {Sym}).Completions;3021  assert(!Results.empty());3022  EXPECT_THAT(Results[0], AllOf(named("Func"), Not(insertInclude())));3023}3024 3025TEST(CompletionTest, NoInsertIncludeIfOnePresent) {3026  Annotations Test(R"cpp(3027    #include "foo.h"3028    Fun^3029  )cpp");3030  auto TU = TestTU::withCode(Test.code());3031  TU.AdditionalFiles["foo.h"] = "";3032 3033  std::string DeclFile = URI::create(testPath("foo")).toString();3034  Symbol Sym = func("Func");3035  Sym.CanonicalDeclaration.FileURI = DeclFile.c_str();3036  Sym.IncludeHeaders.emplace_back("\"foo.h\"", 2, Symbol::Include);3037  Sym.IncludeHeaders.emplace_back("\"bar.h\"", 1000, Symbol::Include);3038 3039  EXPECT_THAT(completions(TU, Test.point(), {Sym}).Completions,3040              UnorderedElementsAre(AllOf(named("Func"), hasInclude("\"foo.h\""),3041                                         Not(insertInclude()))));3042}3043 3044TEST(CompletionTest, MergeMacrosFromIndexAndSema) {3045  Symbol Sym;3046  Sym.Name = "Clangd_Macro_Test";3047  Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test");3048  Sym.SymInfo.Kind = index::SymbolKind::Macro;3049  Sym.Flags |= Symbol::IndexedForCodeCompletion;3050  EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})3051                  .Completions,3052              UnorderedElementsAre(named("Clangd_Macro_Test")));3053}3054 3055TEST(CompletionTest, MacroFromPreamble) {3056  Annotations Test(R"cpp(#define CLANGD_PREAMBLE_MAIN x3057 3058          int x = 0;3059          #define CLANGD_MAIN x3060          void f() { CLANGD_^ }3061      )cpp");3062  auto TU = TestTU::withCode(Test.code());3063  TU.HeaderCode = "#define CLANGD_PREAMBLE_HEADER x";3064  auto Results = completions(TU, Test.point(), {func("CLANGD_INDEX")});3065  // We should get results from the main file, including the preamble section.3066  // However no results from included files (the index should cover them).3067  EXPECT_THAT(Results.Completions,3068              UnorderedElementsAre(named("CLANGD_PREAMBLE_MAIN"),3069                                   named("CLANGD_MAIN"),3070                                   named("CLANGD_INDEX")));3071}3072 3073TEST(CompletionTest, DeprecatedResults) {3074  std::string Body = R"cpp(3075    void TestClangd();3076    void TestClangc() __attribute__((deprecated("", "")));3077  )cpp";3078 3079  EXPECT_THAT(3080      completions(Body + "int main() { TestClang^ }").Completions,3081      UnorderedElementsAre(AllOf(named("TestClangd"), Not(deprecated())),3082                           AllOf(named("TestClangc"), deprecated())));3083}3084 3085TEST(SignatureHelpTest, PartialSpec) {3086  const auto Results = signatures(R"cpp(3087      template <typename T> struct Foo {};3088      template <typename T> struct Foo<T*> { Foo(T); };3089      Foo<int*> F(^);)cpp");3090  EXPECT_THAT(Results.signatures, Contains(sig("Foo([[T]])")));3091  EXPECT_EQ(0, Results.activeParameter);3092}3093 3094TEST(SignatureHelpTest, InsideArgument) {3095  {3096    const auto Results = signatures(R"cpp(3097      void foo(int x);3098      void foo(int x, int y);3099      int main() { foo(1+^); }3100    )cpp");3101    EXPECT_THAT(Results.signatures,3102                ElementsAre(sig("foo([[int x]]) -> void"),3103                            sig("foo([[int x]], [[int y]]) -> void")));3104    EXPECT_EQ(0, Results.activeParameter);3105  }3106  {3107    const auto Results = signatures(R"cpp(3108      void foo(int x);3109      void foo(int x, int y);3110      int main() { foo(1^); }3111    )cpp");3112    EXPECT_THAT(Results.signatures,3113                ElementsAre(sig("foo([[int x]]) -> void"),3114                            sig("foo([[int x]], [[int y]]) -> void")));3115    EXPECT_EQ(0, Results.activeParameter);3116  }3117  {3118    const auto Results = signatures(R"cpp(3119      void foo(int x);3120      void foo(int x, int y);3121      int main() { foo(1^0); }3122    )cpp");3123    EXPECT_THAT(Results.signatures,3124                ElementsAre(sig("foo([[int x]]) -> void"),3125                            sig("foo([[int x]], [[int y]]) -> void")));3126    EXPECT_EQ(0, Results.activeParameter);3127  }3128  {3129    const auto Results = signatures(R"cpp(3130      void foo(int x);3131      void foo(int x, int y);3132      int bar(int x, int y);3133      int main() { bar(foo(2, 3^)); }3134    )cpp");3135    EXPECT_THAT(Results.signatures,3136                ElementsAre(sig("foo([[int x]], [[int y]]) -> void")));3137    EXPECT_EQ(1, Results.activeParameter);3138  }3139}3140 3141TEST(SignatureHelpTest, ConstructorInitializeFields) {3142  {3143    const auto Results = signatures(R"cpp(3144      struct A { A(int); };3145      struct B {3146        B() : a_elem(^) {}3147        A a_elem;3148      };3149    )cpp");3150    EXPECT_THAT(Results.signatures,3151                UnorderedElementsAre(sig("A([[int]])"), sig("A([[A &&]])"),3152                                     sig("A([[const A &]])")));3153  }3154  {3155    const auto Results = signatures(R"cpp(3156      struct A { A(int); };3157      struct B {3158        B() : a_elem(^3159        A a_elem;3160      };3161    )cpp");3162    // FIXME: currently the parser skips over the decl of a_elem as part of the3163    // (broken) init list, so we don't get signatures for the first member.3164    EXPECT_THAT(Results.signatures, IsEmpty());3165  }3166  {3167    const auto Results = signatures(R"cpp(3168      struct A { A(int); };3169      struct B {3170        B() : a_elem(^3171        int dummy_elem;3172        A a_elem;3173      };3174    )cpp");3175    EXPECT_THAT(Results.signatures,3176                UnorderedElementsAre(sig("A([[int]])"), sig("A([[A &&]])"),3177                                     sig("A([[const A &]])")));3178  }3179  {3180    const auto Results = signatures(R"cpp(3181      struct A {3182        A(int);3183      };3184      struct C {3185        C(int);3186        C(A);3187      };3188      struct B {3189        B() : c_elem(A(1^)) {}3190        C c_elem;3191      };3192    )cpp");3193    EXPECT_THAT(Results.signatures,3194                UnorderedElementsAre(sig("A([[int]])"), sig("A([[A &&]])"),3195                                     sig("A([[const A &]])")));3196  }3197}3198 3199TEST(SignatureHelpTest, Variadic) {3200  const std::string Header = R"cpp(3201    void fun(int x, ...) {}3202    void test() {)cpp";3203  const std::string ExpectedSig = "fun([[int x]], [[...]]) -> void";3204 3205  {3206    const auto Result = signatures(Header + "fun(^);}");3207    EXPECT_EQ(0, Result.activeParameter);3208    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3209  }3210  {3211    const auto Result = signatures(Header + "fun(1, ^);}");3212    EXPECT_EQ(1, Result.activeParameter);3213    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3214  }3215  {3216    const auto Result = signatures(Header + "fun(1, 2, ^);}");3217    EXPECT_EQ(1, Result.activeParameter);3218    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3219  }3220}3221 3222TEST(SignatureHelpTest, VariadicTemplate) {3223  const std::string Header = R"cpp(3224    template<typename T, typename ...Args>3225    void fun(T t, Args ...args) {}3226    void test() {)cpp";3227  const std::string ExpectedSig = "fun([[T t]], [[Args args...]]) -> void";3228 3229  {3230    const auto Result = signatures(Header + "fun(^);}");3231    EXPECT_EQ(0, Result.activeParameter);3232    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3233  }3234  {3235    const auto Result = signatures(Header + "fun(1, ^);}");3236    EXPECT_EQ(1, Result.activeParameter);3237    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3238  }3239  {3240    const auto Result = signatures(Header + "fun(1, 2, ^);}");3241    EXPECT_EQ(1, Result.activeParameter);3242    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3243  }3244}3245 3246TEST(SignatureHelpTest, VariadicMethod) {3247  const std::string Header = R"cpp(3248  class C {3249    template<typename T, typename ...Args>3250    void fun(T t, Args ...args) {}3251  };3252    void test() {C c; )cpp";3253  const std::string ExpectedSig = "fun([[T t]], [[Args args...]]) -> void";3254 3255  {3256    const auto Result = signatures(Header + "c.fun(^);}");3257    EXPECT_EQ(0, Result.activeParameter);3258    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3259  }3260  {3261    const auto Result = signatures(Header + "c.fun(1, ^);}");3262    EXPECT_EQ(1, Result.activeParameter);3263    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3264  }3265  {3266    const auto Result = signatures(Header + "c.fun(1, 2, ^);}");3267    EXPECT_EQ(1, Result.activeParameter);3268    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3269  }3270}3271 3272TEST(SignatureHelpTest, VariadicType) {3273  const std::string Header = R"cpp(3274  void fun(int x, ...) {}3275  auto get_fun() { return fun; }3276  void test() {3277  )cpp";3278  const std::string ExpectedSig = "([[int]], [[...]]) -> void";3279 3280  {3281    const auto Result = signatures(Header + "get_fun()(^);}");3282    EXPECT_EQ(0, Result.activeParameter);3283    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3284  }3285  {3286    const auto Result = signatures(Header + "get_fun()(1, ^);}");3287    EXPECT_EQ(1, Result.activeParameter);3288    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3289  }3290  {3291    const auto Result = signatures(Header + "get_fun()(1, 2, ^);}");3292    EXPECT_EQ(1, Result.activeParameter);3293    EXPECT_THAT(Result.signatures, UnorderedElementsAre(sig(ExpectedSig)));3294  }3295}3296 3297TEST(SignatureHelpTest, SkipExplicitObjectParameter) {3298  Annotations Code(R"cpp(3299    struct A {3300      void foo(this auto&& self, int arg); 3301      void bar(this A self, int arg);3302    };3303    int main() {3304      A a {};3305      a.foo($c1^);3306      (&A::bar)($c2^);3307      (&A::foo)($c3^);3308    }3309  )cpp");3310 3311  auto TU = TestTU::withCode(Code.code());3312  TU.ExtraArgs = {"-std=c++23"};3313 3314  MockFS FS;3315  auto Inputs = TU.inputs(FS);3316 3317  auto Preamble = TU.preamble();3318  ASSERT_TRUE(Preamble);3319 3320  {3321    const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c1"),3322                                      *Preamble, Inputs, MarkupKind::PlainText);3323 3324    EXPECT_EQ(1U, Result.signatures.size());3325 3326    EXPECT_THAT(Result.signatures[0], AllOf(sig("foo([[int arg]]) -> void")));3327  }3328  {3329    const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c2"),3330                                      *Preamble, Inputs, MarkupKind::PlainText);3331 3332    EXPECT_EQ(1U, Result.signatures.size());3333 3334    EXPECT_THAT(Result.signatures[0], AllOf(sig("([[A]], [[int]]) -> void")));3335  }3336  {3337    // TODO: llvm/llvm-project/1466493338    const auto Result = signatureHelp(testPath(TU.Filename), Code.point("c3"),3339                                      *Preamble, Inputs, MarkupKind::PlainText);3340    // TODO: We expect 1 signature here, with this signature3341    EXPECT_EQ(0U, Result.signatures.size());3342    // EXPECT_THAT(Result.signatures[0], AllOf(sig("([[auto&&]], [[int]]) ->3343    // void")));3344  }3345}3346 3347TEST(CompletionTest, IncludedCompletionKinds) {3348  Annotations Test(R"cpp(#include "^)cpp");3349  auto TU = TestTU::withCode(Test.code());3350  TU.AdditionalFiles["sub/bar.h"] = "";3351  TU.ExtraArgs.push_back("-I" + testPath("sub"));3352 3353  auto Results = completions(TU, Test.point());3354  EXPECT_THAT(Results.Completions,3355              AllOf(has("sub/", CompletionItemKind::Folder),3356                    has("bar.h\"", CompletionItemKind::File)));3357}3358 3359TEST(CompletionTest, NoCrashAtNonAlphaIncludeHeader) {3360  completions(3361      R"cpp(3362        #include "./^"3363      )cpp");3364}3365 3366TEST(CompletionTest, NoAllScopesCompletionWhenQualified) {3367  clangd::CodeCompleteOptions Opts = {};3368  Opts.AllScopes = true;3369 3370  auto Results = completions(3371      R"cpp(3372    void f() { na::Clangd^ }3373  )cpp",3374      {cls("na::ClangdA"), cls("nx::ClangdX"), cls("Clangd3")}, Opts);3375  EXPECT_THAT(Results.Completions,3376              UnorderedElementsAre(3377                  AllOf(qualifier(""), scope("na::"), named("ClangdA"))));3378}3379 3380TEST(CompletionTest, AllScopesCompletion) {3381  clangd::CodeCompleteOptions Opts = {};3382  Opts.AllScopes = true;3383 3384  auto Results = completions(3385      R"cpp(3386    namespace na {3387    void f() { Clangd^ }3388    }3389  )cpp",3390      {cls("nx::Clangd1"), cls("ny::Clangd2"), cls("Clangd3"),3391       cls("na::nb::Clangd4"), enmConstant("na::C::Clangd5")},3392      Opts);3393  EXPECT_THAT(3394      Results.Completions,3395      UnorderedElementsAre(AllOf(qualifier("nx::"), named("Clangd1"),3396                                 kind(CompletionItemKind::Class)),3397                           AllOf(qualifier("ny::"), named("Clangd2"),3398                                 kind(CompletionItemKind::Class)),3399                           AllOf(qualifier(""), scope(""), named("Clangd3"),3400                                 kind(CompletionItemKind::Class)),3401                           AllOf(qualifier("nb::"), named("Clangd4"),3402                                 kind(CompletionItemKind::Class)),3403                           AllOf(qualifier("C::"), named("Clangd5"),3404                                 kind(CompletionItemKind::EnumMember))));3405}3406 3407TEST(CompletionTest, NoCodePatternsIfDisabled) {3408  clangd::CodeCompleteOptions Opts = {};3409  Opts.EnableSnippets = true;3410  Opts.CodePatterns = Config::CodePatternsPolicy::None;3411 3412  auto Results = completions(R"cpp(3413    void function() {3414      /// Trying to trigger "for (init-statement; condition; inc-expression)3415      /// {statements}~" code pattern3416      for^3417    }3418  )cpp",3419                             {}, Opts);3420 3421  EXPECT_THAT(Results.Completions,3422              Not(Contains(kind(CompletionItemKind::Snippet))));3423}3424 3425TEST(CompletionTest, CompleteIncludeIfCodePatternsNone) {3426  clangd::CodeCompleteOptions Opts = {};3427  Opts.EnableSnippets = true;3428  Opts.CodePatterns = Config::CodePatternsPolicy::None;3429 3430  Annotations Test(R"cpp(#include "^)cpp");3431  auto TU = TestTU::withCode(Test.code());3432  TU.AdditionalFiles["foo/bar.h"] = "";3433  TU.ExtraArgs.push_back("-I" + testPath("foo"));3434 3435  auto Results = completions(TU, Test.point(), {}, Opts);3436  EXPECT_THAT(Results.Completions,3437              AllOf(has("foo/", CompletionItemKind::Folder),3438                    has("bar.h\"", CompletionItemKind::File)));3439}3440 3441TEST(CompletionTest, NoQualifierIfShadowed) {3442  clangd::CodeCompleteOptions Opts = {};3443  Opts.AllScopes = true;3444 3445  auto Results = completions(R"cpp(3446    namespace nx { class Clangd1 {}; }3447    using nx::Clangd1;3448    void f() { Clangd^ }3449  )cpp",3450                             {cls("nx::Clangd1"), cls("nx::Clangd2")}, Opts);3451  // Although Clangd1 is from another namespace, Sema tells us it's in-scope and3452  // needs no qualifier.3453  EXPECT_THAT(Results.Completions,3454              UnorderedElementsAre(AllOf(qualifier(""), named("Clangd1")),3455                                   AllOf(qualifier("nx::"), named("Clangd2"))));3456}3457 3458TEST(CompletionTest, NoCompletionsForNewNames) {3459  clangd::CodeCompleteOptions Opts;3460  Opts.AllScopes = true;3461  auto Results = completions(R"cpp(3462      void f() { int n^ }3463    )cpp",3464                             {cls("naber"), cls("nx::naber")}, Opts);3465  EXPECT_THAT(Results.Completions, UnorderedElementsAre());3466}3467 3468TEST(CompletionTest, Lambda) {3469  clangd::CodeCompleteOptions Opts = {};3470 3471  auto Results = completions(R"cpp(3472    void function() {3473      auto Lambda = [](int a, const double &b) {return 1.f;};3474      Lam^3475    }3476  )cpp",3477                             {}, Opts);3478 3479  ASSERT_EQ(Results.Completions.size(), 1u);3480  const auto &A = Results.Completions.front();3481  EXPECT_EQ(A.Name, "Lambda");3482  EXPECT_EQ(A.Signature, "(int a, const double &b) const");3483  EXPECT_EQ(A.Kind, CompletionItemKind::Variable);3484  EXPECT_EQ(A.ReturnType, "float");3485  EXPECT_EQ(A.SnippetSuffix, "(${1:int a}, ${2:const double &b})");3486}3487 3488TEST(CompletionTest, StructuredBinding) {3489  clangd::CodeCompleteOptions Opts = {};3490 3491  auto Results = completions(R"cpp(3492    struct S {3493      using Float = float;3494      int x;3495      Float y;3496    };3497    void function() {3498      const auto &[xxx, yyy] = S{};3499      yyy^3500    }3501  )cpp",3502                             {}, Opts);3503 3504  ASSERT_EQ(Results.Completions.size(), 1u);3505  const auto &A = Results.Completions.front();3506  EXPECT_EQ(A.Name, "yyy");3507  EXPECT_EQ(A.Kind, CompletionItemKind::Variable);3508  EXPECT_EQ(A.ReturnType, "const Float");3509}3510 3511TEST(CompletionTest, ObjectiveCMethodNoArguments) {3512  auto Results = completions(R"objc(3513      @interface Foo3514      @property(nonatomic, setter=setXToIgnoreComplete:) int value;3515      @end3516      Foo *foo = [Foo new]; int y = [foo v^]3517    )objc",3518                             /*IndexSymbols=*/{},3519                             /*Opts=*/{}, "Foo.m");3520 3521  auto C = Results.Completions;3522  EXPECT_THAT(C, ElementsAre(named("value")));3523  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3524  EXPECT_THAT(C, ElementsAre(returnType("int")));3525  EXPECT_THAT(C, ElementsAre(signature("")));3526  EXPECT_THAT(C, ElementsAre(snippetSuffix("")));3527}3528 3529TEST(CompletionTest, ObjectiveCMethodOneArgument) {3530  auto Results = completions(R"objc(3531      @interface Foo3532      - (int)valueForCharacter:(char)c;3533      @end3534      Foo *foo = [Foo new]; int y = [foo v^]3535    )objc",3536                             /*IndexSymbols=*/{},3537                             /*Opts=*/{}, "Foo.m");3538 3539  auto C = Results.Completions;3540  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));3541  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3542  EXPECT_THAT(C, ElementsAre(returnType("int")));3543  EXPECT_THAT(C, ElementsAre(signature("(char)")));3544  EXPECT_THAT(C, ElementsAre(snippetSuffix("${1:(char)}")));3545}3546 3547TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromBeginning) {3548  auto Results = completions(R"objc(3549      @interface Foo3550      + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;3551      @end3552      id val = [Foo foo^]3553    )objc",3554                             /*IndexSymbols=*/{},3555                             /*Opts=*/{}, "Foo.m");3556 3557  auto C = Results.Completions;3558  EXPECT_THAT(C, ElementsAre(named("fooWithValue:")));3559  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3560  EXPECT_THAT(C, ElementsAre(returnType("id")));3561  EXPECT_THAT(C, ElementsAre(signature("(int) fooey:(unsigned int)")));3562  EXPECT_THAT(3563      C, ElementsAre(snippetSuffix("${1:(int)} fooey:${2:(unsigned int)}")));3564}3565 3566TEST(CompletionTest, ObjectiveCMethodTwoArgumentsFromMiddle) {3567  auto Results = completions(R"objc(3568      @interface Foo3569      + (id)fooWithValue:(int)value fooey:(unsigned int)fooey;3570      @end3571      id val = [Foo fooWithValue:10 f^]3572    )objc",3573                             /*IndexSymbols=*/{},3574                             /*Opts=*/{}, "Foo.m");3575 3576  auto C = Results.Completions;3577  EXPECT_THAT(C, ElementsAre(named("fooey:")));3578  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3579  EXPECT_THAT(C, ElementsAre(returnType("id")));3580  EXPECT_THAT(C, ElementsAre(signature("(unsigned int)")));3581  EXPECT_THAT(C, ElementsAre(snippetSuffix("${1:(unsigned int)}")));3582}3583 3584TEST(CompletionTest, ObjectiveCMethodFilterOnEntireSelector) {3585  auto Results = completions(R"objc(3586      @interface Foo3587      + (id)player:(id)player willRun:(id)run;3588      @end3589      id val = [Foo wi^]3590    )objc",3591                             /*IndexSymbols=*/{},3592                             /*Opts=*/{}, "Foo.m");3593 3594  auto C = Results.Completions;3595  EXPECT_THAT(C, ElementsAre(named("player:")));3596  EXPECT_THAT(C, ElementsAre(filterText("player:willRun:")));3597  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3598  EXPECT_THAT(C, ElementsAre(returnType("id")));3599  EXPECT_THAT(C, ElementsAre(signature("(id) willRun:(id)")));3600  EXPECT_THAT(C, ElementsAre(snippetSuffix("${1:(id)} willRun:${2:(id)}")));3601}3602 3603TEST(CompletionTest, ObjectiveCSimpleMethodDeclaration) {3604  auto Results = completions(R"objc(3605      @interface Foo3606      - (void)foo;3607      @end3608      @implementation Foo3609      fo^3610      @end3611    )objc",3612                             /*IndexSymbols=*/{},3613                             /*Opts=*/{}, "Foo.m");3614 3615  auto C = Results.Completions;3616  EXPECT_THAT(C, ElementsAre(named("foo")));3617  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3618  EXPECT_THAT(C, ElementsAre(qualifier("- (void)")));3619}3620 3621TEST(CompletionTest, ObjectiveCMethodDeclaration) {3622  auto Results = completions(R"objc(3623      @interface Foo3624      - (int)valueForCharacter:(char)c secondArgument:(id)object;3625      @end3626      @implementation Foo3627      valueFor^3628      @end3629    )objc",3630                             /*IndexSymbols=*/{},3631                             /*Opts=*/{}, "Foo.m");3632 3633  auto C = Results.Completions;3634  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));3635  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3636  EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));3637  EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));3638}3639 3640TEST(CompletionTest, ObjectiveCMethodDeclarationFilterOnEntireSelector) {3641  auto Results = completions(R"objc(3642      @interface Foo3643      - (int)valueForCharacter:(char)c secondArgument:(id)object;3644      @end3645      @implementation Foo3646      secondArg^3647      @end3648    )objc",3649                             /*IndexSymbols=*/{},3650                             /*Opts=*/{}, "Foo.m");3651 3652  auto C = Results.Completions;3653  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));3654  EXPECT_THAT(C, ElementsAre(filterText("valueForCharacter:secondArgument:")));3655  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3656  EXPECT_THAT(C, ElementsAre(qualifier("- (int)")));3657  EXPECT_THAT(C, ElementsAre(signature("(char)c secondArgument:(id)object")));3658}3659 3660TEST(CompletionTest, ObjectiveCMethodDeclarationPrefixTyped) {3661  auto Results = completions(R"objc(3662      @interface Foo3663      - (int)valueForCharacter:(char)c;3664      @end3665      @implementation Foo3666      - (int)valueFor^3667      @end3668    )objc",3669                             /*IndexSymbols=*/{},3670                             /*Opts=*/{}, "Foo.m");3671 3672  auto C = Results.Completions;3673  EXPECT_THAT(C, ElementsAre(named("valueForCharacter:")));3674  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3675  EXPECT_THAT(C, ElementsAre(signature("(char)c")));3676}3677 3678TEST(CompletionTest, ObjectiveCMethodDeclarationFromMiddle) {3679  auto Results = completions(R"objc(3680      @interface Foo3681      - (int)valueForCharacter:(char)c secondArgument:(id)object;3682      @end3683      @implementation Foo3684      - (int)valueForCharacter:(char)c second^3685      @end3686    )objc",3687                             /*IndexSymbols=*/{},3688                             /*Opts=*/{}, "Foo.m");3689 3690  auto C = Results.Completions;3691  EXPECT_THAT(C, ElementsAre(named("secondArgument:")));3692  EXPECT_THAT(C, ElementsAre(kind(CompletionItemKind::Method)));3693  EXPECT_THAT(C, ElementsAre(signature("(id)object")));3694}3695 3696TEST(CompletionTest, ObjectiveCProtocolFromIndex) {3697  Symbol FoodClass = objcClass("FoodClass");3698  Symbol SymFood = objcProtocol("Food");3699  Symbol SymFooey = objcProtocol("Fooey");3700  auto Results = completions("id<Foo^>", {SymFood, FoodClass, SymFooey},3701                             /*Opts=*/{}, "Foo.m");3702 3703  // Should only give protocols for ObjC protocol completions.3704  EXPECT_THAT(Results.Completions,3705              UnorderedElementsAre(3706                  AllOf(named("Food"), kind(CompletionItemKind::Interface)),3707                  AllOf(named("Fooey"), kind(CompletionItemKind::Interface))));3708 3709  Results = completions("Fo^", {SymFood, FoodClass, SymFooey},3710                        /*Opts=*/{}, "Foo.m");3711  // Shouldn't give protocols for non protocol completions.3712  EXPECT_THAT(3713      Results.Completions,3714      ElementsAre(AllOf(named("FoodClass"), kind(CompletionItemKind::Class))));3715}3716 3717TEST(CompletionTest, ObjectiveCProtocolFromIndexSpeculation) {3718  MockFS FS;3719  MockCompilationDatabase CDB;3720  ClangdServer Server(CDB, FS, ClangdServer::optsForTest());3721 3722  auto File = testPath("Foo.m");3723  Annotations Test(R"cpp(3724      @protocol Food3725      @end3726      id<Foo$1^> foo;3727      Foo$2^ bar;3728  )cpp");3729  runAddDocument(Server, File, Test.code());3730  clangd::CodeCompleteOptions Opts = {};3731 3732  Symbol FoodClass = objcClass("FoodClass");3733  IndexRequestCollector Requests({FoodClass});3734  Opts.Index = &Requests;3735 3736  auto CompleteAtPoint = [&](StringRef P) {3737    return cantFail(runCodeComplete(Server, File, Test.point(P), Opts))3738        .Completions;3739  };3740 3741  auto C = CompleteAtPoint("1");3742  auto Reqs1 = Requests.consumeRequests(1);3743  ASSERT_EQ(Reqs1.size(), 1u);3744  EXPECT_THAT(C, ElementsAre(AllOf(named("Food"),3745                                   kind(CompletionItemKind::Interface))));3746 3747  C = CompleteAtPoint("2");3748  auto Reqs2 = Requests.consumeRequests(1);3749  // Speculation succeeded. Used speculative index result, but filtering now to3750  // now include FoodClass.3751  ASSERT_EQ(Reqs2.size(), 1u);3752  EXPECT_EQ(Reqs2[0], Reqs1[0]);3753  EXPECT_THAT(C, ElementsAre(AllOf(named("FoodClass"),3754                                   kind(CompletionItemKind::Class))));3755}3756 3757TEST(CompletionTest, ObjectiveCCategoryFromIndexIgnored) {3758  Symbol FoodCategory = objcCategory("FoodClass", "Extension");3759  auto Results = completions(R"objc(3760      @interface Foo3761      @end3762      @interface Foo (^)3763      @end3764    )objc",3765                             {FoodCategory},3766                             /*Opts=*/{}, "Foo.m");3767  EXPECT_THAT(Results.Completions, IsEmpty());3768}3769 3770TEST(CompletionTest, ObjectiveCForwardDeclFromIndex) {3771  Symbol FoodClass = objcClass("FoodClass");3772  FoodClass.IncludeHeaders.emplace_back("\"Foo.h\"", 2, Symbol::Import);3773  Symbol SymFood = objcProtocol("Food");3774  auto Results = completions("@class Foo^", {SymFood, FoodClass},3775                             /*Opts=*/{}, "Foo.m");3776 3777  // Should only give class names without any include insertion.3778  EXPECT_THAT(Results.Completions,3779              UnorderedElementsAre(AllOf(named("FoodClass"),3780                                         kind(CompletionItemKind::Class),3781                                         Not(insertInclude()))));3782}3783 3784TEST(CompletionTest, CursorInSnippets) {3785  clangd::CodeCompleteOptions Options;3786  Options.EnableSnippets = true;3787  auto Results = completions(3788      R"cpp(3789    void while_foo(int a, int b);3790    void test() {3791      whil^3792    })cpp",3793      /*IndexSymbols=*/{}, Options);3794 3795  // Last placeholder in code patterns should be $0 to put the cursor there.3796  EXPECT_THAT(Results.Completions,3797              Contains(AllOf(named("while"),3798                             snippetSuffix(" (${1:condition}) {\n$0\n}"))));3799  // However, snippets for functions must *not* end with $0.3800  EXPECT_THAT(Results.Completions,3801              Contains(AllOf(named("while_foo"),3802                             snippetSuffix("(${1:int a}, ${2:int b})"))));3803 3804  Results = completions(R"cpp(3805    struct Base {3806      Base(int a, int b) {}3807    };3808 3809    struct Derived : Base {3810      Derived() : Base^3811    };3812  )cpp",3813                        /*IndexSymbols=*/{}, Options);3814  // Constructors from base classes are a kind of pattern that shouldn't end3815  // with $0.3816  EXPECT_THAT(Results.Completions,3817              Contains(AllOf(named("Base"),3818                             snippetSuffix("(${1:int a}, ${2:int b})"))));3819}3820 3821TEST(CompletionTest, WorksWithNullType) {3822  auto R = completions(R"cpp(3823    int main() {3824      for (auto [loopVar] : y ) { // y has to be unresolved.3825        int z = loopV^;3826      }3827    }3828  )cpp");3829  EXPECT_THAT(R.Completions, ElementsAre(named("loopVar")));3830}3831 3832TEST(CompletionTest, UsingDecl) {3833  const char *Header(R"cpp(3834    void foo(int);3835    namespace std {3836      using ::foo;3837    })cpp");3838  const char *Source(R"cpp(3839    void bar() {3840      std::^;3841    })cpp");3842  auto Index = TestTU::withHeaderCode(Header).index();3843  clangd::CodeCompleteOptions Opts;3844  Opts.Index = Index.get();3845  Opts.AllScopes = true;3846  auto R = completions(Source, {}, Opts);3847  EXPECT_THAT(R.Completions,3848              ElementsAre(AllOf(scope("std::"), named("foo"),3849                                kind(CompletionItemKind::Reference))));3850}3851 3852TEST(CompletionTest, Enums) {3853  const char *Header(R"cpp(3854    namespace ns {3855      enum Unscoped { Clangd1 };3856      class C {3857      enum Unscoped { Clangd2 };3858      };3859      enum class Scoped { Clangd3 };3860    })cpp");3861  const char *Source(R"cpp(3862    void bar() {3863      Clangd^3864    })cpp");3865  auto Index = TestTU::withHeaderCode(Header).index();3866  clangd::CodeCompleteOptions Opts;3867  Opts.Index = Index.get();3868  Opts.AllScopes = true;3869  auto R = completions(Source, {}, Opts);3870  EXPECT_THAT(R.Completions, UnorderedElementsAre(3871                                 AllOf(scope("ns::"), named("Clangd1"),3872                                       kind(CompletionItemKind::EnumMember)),3873                                 AllOf(scope("ns::C::"), named("Clangd2"),3874                                       kind(CompletionItemKind::EnumMember)),3875                                 AllOf(scope("ns::Scoped::"), named("Clangd3"),3876                                       kind(CompletionItemKind::EnumMember))));3877}3878 3879TEST(CompletionTest, ScopeIsUnresolved) {3880  clangd::CodeCompleteOptions Opts = {};3881  Opts.AllScopes = true;3882 3883  auto Results = completions(R"cpp(3884    namespace a {3885    void f() { b::X^ }3886    }3887  )cpp",3888                             {cls("a::b::XYZ")}, Opts);3889  EXPECT_THAT(Results.Completions,3890              UnorderedElementsAre(AllOf(qualifier(""), named("XYZ"))));3891}3892 3893TEST(CompletionTest, NestedScopeIsUnresolved) {3894  clangd::CodeCompleteOptions Opts = {};3895  Opts.AllScopes = true;3896 3897  auto Results = completions(R"cpp(3898    namespace a {3899    namespace b {}3900    void f() { b::c::X^ }3901    }3902  )cpp",3903                             {cls("a::b::c::XYZ")}, Opts);3904  EXPECT_THAT(Results.Completions,3905              UnorderedElementsAre(AllOf(qualifier(""), named("XYZ"))));3906}3907 3908// Clang parser gets confused here and doesn't report the ns:: prefix.3909// Naive behavior is to insert it again. We examine the source and recover.3910TEST(CompletionTest, NamespaceDoubleInsertion) {3911  clangd::CodeCompleteOptions Opts = {};3912 3913  auto Results = completions(R"cpp(3914    namespace foo {3915    namespace ns {}3916    #define M(X) < X3917    M(ns::ABC^3918    }3919  )cpp",3920                             {cls("foo::ns::ABCDE")}, Opts);3921  EXPECT_THAT(Results.Completions,3922              UnorderedElementsAre(AllOf(qualifier(""), named("ABCDE"))));3923}3924 3925TEST(CompletionTest, DerivedMethodsAreAlwaysVisible) {3926  // Despite the fact that base method matches the ref-qualifier better,3927  // completion results should only include the derived method.3928  auto Completions = completions(R"cpp(3929    struct deque_base {3930      float size();3931      double size() const;3932    };3933    struct deque : deque_base {3934        int size() const;3935    };3936 3937    auto x = deque().^3938  )cpp")3939                         .Completions;3940  EXPECT_THAT(Completions,3941              ElementsAre(AllOf(returnType("int"), named("size"))));3942}3943 3944TEST(CompletionTest, NoCrashWithIncompleteLambda) {3945  auto Completions = completions("auto&& x = []{^").Completions;3946  // The completion of x itself can cause a problem: in the code completion3947  // callback, its type is not known, which affects the linkage calculation.3948  // A bad linkage value gets cached, and subsequently updated.3949  EXPECT_THAT(Completions, Contains(named("x")));3950 3951  auto Signatures = signatures("auto x() { x(^").signatures;3952  EXPECT_THAT(Signatures, Contains(sig("x() -> auto")));3953}3954 3955TEST(CompletionTest, DelayedTemplateParsing) {3956  Annotations Test(R"cpp(3957    int xxx;3958    template <typename T> int foo() { return xx^; }3959  )cpp");3960  auto TU = TestTU::withCode(Test.code());3961  // Even though delayed-template-parsing is on, we will disable it to provide3962  // completion in templates.3963  TU.ExtraArgs.push_back("-fdelayed-template-parsing");3964 3965  EXPECT_THAT(completions(TU, Test.point()).Completions,3966              Contains(named("xxx")));3967}3968 3969TEST(CompletionTest, CompletionRange) {3970  const char *WithRange = "auto x = [[abc]]^";3971  auto Completions = completions(WithRange);3972  EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());3973  Completions = completionsNoCompile(WithRange);3974  EXPECT_EQ(Completions.CompletionRange, Annotations(WithRange).range());3975 3976  const char *EmptyRange = "auto x = [[]]^";3977  Completions = completions(EmptyRange);3978  EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());3979  Completions = completionsNoCompile(EmptyRange);3980  EXPECT_EQ(Completions.CompletionRange, Annotations(EmptyRange).range());3981 3982  // Sema doesn't trigger at all here, while the no-sema completion runs3983  // heuristics as normal and reports a range. It'd be nice to be consistent.3984  const char *NoCompletion = "/* foo [[]]^ */";3985  Completions = completions(NoCompletion);3986  EXPECT_EQ(Completions.CompletionRange, std::nullopt);3987  Completions = completionsNoCompile(NoCompletion);3988  EXPECT_EQ(Completions.CompletionRange, Annotations(NoCompletion).range());3989}3990 3991TEST(NoCompileCompletionTest, Basic) {3992  auto Results = completionsNoCompile(R"cpp(3993    void func() {3994      int xyz;3995      int abc;3996      ^3997    }3998  )cpp");3999  EXPECT_FALSE(Results.RanParser);4000  EXPECT_THAT(Results.Completions,4001              UnorderedElementsAre(named("void"), named("func"), named("int"),4002                                   named("xyz"), named("abc")));4003}4004 4005TEST(NoCompileCompletionTest, WithFilter) {4006  auto Results = completionsNoCompile(R"cpp(4007    void func() {4008      int sym1;4009      int sym2;4010      int xyz1;4011      int xyz2;4012      sy^4013    }4014  )cpp");4015  EXPECT_THAT(Results.Completions,4016              UnorderedElementsAre(named("sym1"), named("sym2")));4017}4018 4019TEST(NoCompileCompletionTest, WithIndex) {4020  std::vector<Symbol> Syms = {func("xxx"), func("a::xxx"), func("ns::b::xxx"),4021                              func("c::xxx"), func("ns::d::xxx")};4022  auto Results = completionsNoCompile(4023      R"cpp(4024        // Current-scopes, unqualified completion.4025        using namespace a;4026        namespace ns {4027        using namespace b;4028        void foo() {4029        xx^4030        }4031        }4032      )cpp",4033      Syms);4034  EXPECT_THAT(Results.Completions,4035              UnorderedElementsAre(AllOf(qualifier(""), scope("")),4036                                   AllOf(qualifier(""), scope("a::")),4037                                   AllOf(qualifier(""), scope("ns::b::"))));4038  CodeCompleteOptions Opts;4039  Opts.AllScopes = true;4040  Results = completionsNoCompile(4041      R"cpp(4042        // All-scopes unqualified completion.4043        using namespace a;4044        namespace ns {4045        using namespace b;4046        void foo() {4047        xx^4048        }4049        }4050      )cpp",4051      Syms, Opts);4052  EXPECT_THAT(Results.Completions,4053              UnorderedElementsAre(AllOf(qualifier(""), scope("")),4054                                   AllOf(qualifier(""), scope("a::")),4055                                   AllOf(qualifier(""), scope("ns::b::")),4056                                   AllOf(qualifier("c::"), scope("c::")),4057                                   AllOf(qualifier("d::"), scope("ns::d::"))));4058  Results = completionsNoCompile(4059      R"cpp(4060        // Qualified completion.4061        using namespace a;4062        namespace ns {4063        using namespace b;4064        void foo() {4065        b::xx^4066        }4067        }4068      )cpp",4069      Syms, Opts);4070  EXPECT_THAT(Results.Completions,4071              ElementsAre(AllOf(qualifier(""), scope("ns::b::"))));4072  Results = completionsNoCompile(4073      R"cpp(4074        // Absolutely qualified completion.4075        using namespace a;4076        namespace ns {4077        using namespace b;4078        void foo() {4079        ::a::xx^4080        }4081        }4082      )cpp",4083      Syms, Opts);4084  EXPECT_THAT(Results.Completions,4085              ElementsAre(AllOf(qualifier(""), scope("a::"))));4086}4087 4088TEST(AllowImplicitCompletion, All) {4089  const char *Yes[] = {4090      "foo.^bar",4091      "foo->^bar",4092      "foo::^bar",4093      "  #  include <^foo.h>",4094      "#import <foo/^bar.h>",4095      "#include_next \"^",4096  };4097  const char *No[] = {4098      "foo>^bar",4099      "foo:^bar",4100      "foo\n^bar",4101      "#include <foo.h> //^",4102      "#include \"foo.h\"^",4103      "#error <^",4104      "#<^",4105  };4106  for (const char *Test : Yes) {4107    llvm::Annotations A(Test);4108    EXPECT_TRUE(allowImplicitCompletion(A.code(), A.point())) << Test;4109  }4110  for (const char *Test : No) {4111    llvm::Annotations A(Test);4112    EXPECT_FALSE(allowImplicitCompletion(A.code(), A.point())) << Test;4113  }4114}4115 4116TEST(CompletionTest, FunctionArgsExist) {4117  clangd::CodeCompleteOptions Opts;4118  Opts.EnableSnippets = true;4119  std::string Context = R"cpp(4120    #define MACRO(x)4121    int foo(int A);4122    int bar();4123    struct Object {4124      Object(int B) {}4125    };4126    template <typename T>4127    struct Container {4128      Container(int Size) {}4129    };4130  )cpp";4131  EXPECT_THAT(completions(Context + "int y = fo^", {}, Opts).Completions,4132              UnorderedElementsAre(4133                  AllOf(labeled("foo(int A)"), snippetSuffix("(${1:int A})"))));4134  EXPECT_THAT(4135      completions(Context + "int y = fo^(42)", {}, Opts).Completions,4136      UnorderedElementsAre(AllOf(labeled("foo(int A)"), snippetSuffix(""))));4137  // FIXME(kirillbobyrev): No snippet should be produced here.4138  EXPECT_THAT(completions(Context + "int y = fo^o(42)", {}, Opts).Completions,4139              UnorderedElementsAre(4140                  AllOf(labeled("foo(int A)"), snippetSuffix("(${1:int A})"))));4141  EXPECT_THAT(4142      completions(Context + "int y = ba^", {}, Opts).Completions,4143      UnorderedElementsAre(AllOf(labeled("bar()"), snippetSuffix("()"))));4144  EXPECT_THAT(completions(Context + "int y = ba^()", {}, Opts).Completions,4145              UnorderedElementsAre(AllOf(labeled("bar()"), snippetSuffix(""))));4146  EXPECT_THAT(4147      completions(Context + "Object o = Obj^", {}, Opts).Completions,4148      Contains(AllOf(labeled("Object(int B)"), snippetSuffix("(${1:int B})"),4149                     kind(CompletionItemKind::Constructor))));4150  EXPECT_THAT(completions(Context + "Object o = Obj^()", {}, Opts).Completions,4151              Contains(AllOf(labeled("Object(int B)"), snippetSuffix(""),4152                             kind(CompletionItemKind::Constructor))));4153  EXPECT_THAT(4154      completions(Context + "Container c = Cont^", {}, Opts).Completions,4155      Contains(AllOf(labeled("Container<typename T>(int Size)"),4156                     snippetSuffix("<${1:typename T}>(${2:int Size})"),4157                     kind(CompletionItemKind::Constructor))));4158  EXPECT_THAT(4159      completions(Context + "Container c = Cont^()", {}, Opts).Completions,4160      Contains(AllOf(labeled("Container<typename T>(int Size)"),4161                     snippetSuffix("<${1:typename T}>"),4162                     kind(CompletionItemKind::Constructor))));4163  EXPECT_THAT(4164      completions(Context + "Container c = Cont^<int>()", {}, Opts).Completions,4165      Contains(AllOf(labeled("Container<typename T>(int Size)"),4166                     snippetSuffix(""),4167                     kind(CompletionItemKind::Constructor))));4168  EXPECT_THAT(completions(Context + "MAC^(2)", {}, Opts).Completions,4169              Contains(AllOf(labeled("MACRO(x)"), snippetSuffix(""),4170                             kind(CompletionItemKind::Function))));4171}4172 4173TEST(CompletionTest, FunctionArgsExist_Issue1785) {4174  // This is a scenario where the implementation of our check for4175  // "is there a function argument list right after the cursor"4176  // gave a bogus result.4177  clangd::CodeCompleteOptions Opts;4178  Opts.EnableSnippets = true;4179  // The whitespace in this testcase is important!4180  std::string Code = R"cpp(4181void waldo(int);4182 4183int main()4184{4185  wal^4186 4187 4188  // (    )4189}4190  )cpp";4191  EXPECT_THAT(4192      completions(Code, {}, Opts).Completions,4193      Contains(AllOf(labeled("waldo(int)"), snippetSuffix("(${1:int})"))));4194}4195 4196TEST(CompletionTest, NoCrashDueToMacroOrdering) {4197  EXPECT_THAT(completions(R"cpp(4198    #define ECHO(X) X4199    #define ECHO2(X) ECHO(X)4200    int finish_preamble = EC^HO(2);)cpp")4201                  .Completions,4202              UnorderedElementsAre(labeled("ECHO(X)"), labeled("ECHO2(X)")));4203}4204 4205TEST(CompletionTest, ObjCCategoryDecls) {4206  TestTU TU;4207  TU.ExtraArgs.push_back("-xobjective-c");4208  TU.HeaderCode = R"objc(4209  @interface Foo4210  @end4211 4212  @interface Foo (FooExt1)4213  @end4214 4215  @interface Foo (FooExt2)4216  @end4217 4218  @interface Bar4219  @end4220 4221  @interface Bar (BarExt)4222  @end)objc";4223 4224  {4225    Annotations Test(R"objc(4226  @implementation Foo (^)4227  @end4228  )objc");4229    TU.Code = Test.code().str();4230    auto Results = completions(TU, Test.point());4231    EXPECT_THAT(Results.Completions,4232                UnorderedElementsAre(labeled("FooExt1"), labeled("FooExt2")));4233  }4234  {4235    Annotations Test(R"objc(4236  @interface Foo (^)4237  @end4238  )objc");4239    TU.Code = Test.code().str();4240    auto Results = completions(TU, Test.point());4241    EXPECT_THAT(Results.Completions, UnorderedElementsAre(labeled("BarExt")));4242  }4243}4244 4245TEST(CompletionTest, PreambleCodeComplete) {4246  llvm::StringLiteral Baseline = "\n#define MACRO 12\nint num = MACRO;";4247  llvm::StringLiteral ModifiedCC =4248      "#include \"header.h\"\n#define MACRO 12\nint num = MACRO; int num2 = M^";4249 4250  Annotations Test(ModifiedCC);4251  auto BaselineTU = TestTU::withCode(Baseline);4252  auto ModifiedTU = TestTU::withCode(Test.code());4253 4254  MockFS FS;4255  auto Inputs = ModifiedTU.inputs(FS);4256  auto Result = codeComplete(testPath(ModifiedTU.Filename), Test.point(),4257                             BaselineTU.preamble().get(), Inputs, {});4258  EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));4259}4260 4261TEST(CompletionTest, CommentParamName) {4262  const std::string Code = R"cpp(4263    void fun(int foo, int bar);4264    void overloaded(int param_int);4265    void overloaded(int param_int, int param_other);4266    void overloaded(char param_char);4267    int main() {4268  )cpp";4269 4270  EXPECT_THAT(completions(Code + "fun(/*^").Completions,4271              UnorderedElementsAre(labeled("foo=*/")));4272  EXPECT_THAT(completions(Code + "fun(1, /*^").Completions,4273              UnorderedElementsAre(labeled("bar=*/")));4274  EXPECT_THAT(completions(Code + "/*^").Completions, IsEmpty());4275  // Test de-duplication.4276  EXPECT_THAT(4277      completions(Code + "overloaded(/*^").Completions,4278      UnorderedElementsAre(labeled("param_int=*/"), labeled("param_char=*/")));4279  // Comment already has some text in it.4280  EXPECT_THAT(completions(Code + "fun(/*  ^").Completions,4281              UnorderedElementsAre(labeled("foo=*/")));4282  EXPECT_THAT(completions(Code + "fun(/* f^").Completions,4283              UnorderedElementsAre(labeled("foo=*/")));4284  EXPECT_THAT(completions(Code + "fun(/* x^").Completions, IsEmpty());4285  EXPECT_THAT(completions(Code + "fun(/* f ^").Completions, IsEmpty());4286 4287  // Test ranges4288  {4289    std::string CompletionRangeTest(Code + "fun(/*[[^]]");4290    auto Results = completions(CompletionRangeTest);4291    EXPECT_THAT(Results.CompletionRange,4292                llvm::ValueIs(Annotations(CompletionRangeTest).range()));4293    EXPECT_THAT(4294        Results.Completions,4295        testing::Each(4296            AllOf(replacesRange(Annotations(CompletionRangeTest).range()),4297                  origin(SymbolOrigin::AST), kind(CompletionItemKind::Text))));4298  }4299  {4300    std::string CompletionRangeTest(Code + "fun(/*[[fo^]]");4301    auto Results = completions(CompletionRangeTest);4302    EXPECT_THAT(Results.CompletionRange,4303                llvm::ValueIs(Annotations(CompletionRangeTest).range()));4304    EXPECT_THAT(4305        Results.Completions,4306        testing::Each(4307            AllOf(replacesRange(Annotations(CompletionRangeTest).range()),4308                  origin(SymbolOrigin::AST), kind(CompletionItemKind::Text))));4309  }4310}4311 4312TEST(CompletionTest, Concepts) {4313  Annotations Code(R"cpp(4314    template<class T>4315    concept A = sizeof(T) <= 8;4316 4317    template<$tparam^A U>4318    int foo();4319 4320    template<typename T>4321    int bar(T t) requires $expr^A<int>;4322 4323    template<class T>4324    concept b = $expr^A && $expr^sizeof(T) % 2 == 0 || $expr^A && sizeof(T) == 1;4325 4326    $toplevel^A auto i = 19;4327 4328    template<$toplevel^A auto i> void constrainedNTTP();4329 4330    // FIXME: The first parameter should be dropped in this case.4331    void abbreviated($expr^A auto x) {}4332  )cpp");4333  TestTU TU;4334  TU.Code = Code.code().str();4335  TU.ExtraArgs = {"-std=c++20"};4336 4337  auto Sym = conceptSym("same_as");4338  Sym.Signature = "<typename Tp, typename Up>";4339  Sym.CompletionSnippetSuffix = "<${1:typename Tp}, ${2:typename Up}>";4340  std::vector<Symbol> Syms = {Sym};4341  for (auto P : Code.points("tparam")) {4342    ASSERT_THAT(4343        completions(TU, P, Syms).Completions,4344        AllOf(Contains(AllOf(named("A"), signature(""), snippetSuffix(""))),4345              Contains(AllOf(named("same_as"), signature("<typename Up>"),4346                             snippetSuffix("<${2:typename Up}>"))),4347              Contains(named("class")), Contains(named("typename"))))4348        << "Completing template parameter at position " << P;4349  }4350 4351  for (auto P : Code.points("toplevel")) {4352    EXPECT_THAT(4353        completions(TU, P, Syms).Completions,4354        AllOf(Contains(AllOf(named("A"), signature(""), snippetSuffix(""))),4355              Contains(AllOf(named("same_as"), signature("<typename Up>"),4356                             snippetSuffix("<${2:typename Up}>")))))4357        << "Completing 'requires' expression at position " << P;4358  }4359 4360  for (auto P : Code.points("expr")) {4361    EXPECT_THAT(4362        completions(TU, P, Syms).Completions,4363        AllOf(Contains(AllOf(named("A"), signature("<class T>"),4364                             snippetSuffix("<${1:class T}>"))),4365              Contains(AllOf(4366                  named("same_as"), signature("<typename Tp, typename Up>"),4367                  snippetSuffix("<${1:typename Tp}, ${2:typename Up}>")))))4368        << "Completing 'requires' expression at position " << P;4369  }4370}4371 4372TEST(SignatureHelp, DocFormat) {4373  Annotations Code(R"cpp(4374    // Comment `with` markup.4375    void foo(int);4376    void bar() { foo(^); }4377  )cpp");4378  for (auto DocumentationFormat :4379       {MarkupKind::PlainText, MarkupKind::Markdown}) {4380    auto Sigs = signatures(Code.code(), Code.point(), /*IndexSymbols=*/{},4381                           DocumentationFormat);4382    ASSERT_EQ(Sigs.signatures.size(), 1U);4383    EXPECT_EQ(Sigs.signatures[0].documentation.kind, DocumentationFormat);4384  }4385}4386 4387TEST(SignatureHelp, TemplateArguments) {4388  std::string Top = R"cpp(4389    template <typename T, int> bool foo(char);4390    template <int I, int> bool foo(float);4391  )cpp";4392 4393  auto First = signatures(Top + "bool x = foo<^");4394  EXPECT_THAT(4395      First.signatures,4396      UnorderedElementsAre(sig("foo<[[typename T]], [[int]]>() -> bool"),4397                           sig("foo<[[int I]], [[int]]>() -> bool")));4398  EXPECT_EQ(First.activeParameter, 0);4399 4400  auto Second = signatures(Top + "bool x = foo<1, ^");4401  EXPECT_THAT(Second.signatures,4402              ElementsAre(sig("foo<[[int I]], [[int]]>() -> bool")));4403  EXPECT_EQ(Second.activeParameter, 1);4404}4405 4406TEST(CompletionTest, DoNotCrash) {4407  llvm::StringLiteral Cases[] = {4408      R"cpp(4409    template <typename = int> struct Foo {};4410    auto a = [x(3)](Foo<^>){};4411    )cpp",4412  };4413  for (auto Case : Cases) {4414    SCOPED_TRACE(Case);4415    auto Completions = completions(Case);4416  }4417}4418TEST(CompletionTest, PreambleFromDifferentTarget) {4419  constexpr std::string_view PreambleTarget = "x86_64";4420  constexpr std::string_view Contents =4421      "int foo(int); int num; int num2 = foo(n^";4422 4423  Annotations Test(Contents);4424  auto TU = TestTU::withCode(Test.code());4425  TU.ExtraArgs.emplace_back("-target");4426  TU.ExtraArgs.emplace_back(PreambleTarget);4427  auto Preamble = TU.preamble();4428  ASSERT_TRUE(Preamble);4429  // Switch target to wasm.4430  TU.ExtraArgs.pop_back();4431  TU.ExtraArgs.emplace_back("wasm32");4432 4433  MockFS FS;4434  auto Inputs = TU.inputs(FS);4435  auto Result = codeComplete(testPath(TU.Filename), Test.point(),4436                             Preamble.get(), Inputs, {});4437  auto Signatures =4438      signatureHelp(testPath(TU.Filename), Test.point(), *Preamble, Inputs, {});4439 4440  // Make sure we don't crash.4441  EXPECT_THAT(Result.Completions, Not(testing::IsEmpty()));4442  EXPECT_THAT(Signatures.signatures, Not(testing::IsEmpty()));4443}4444 4445TEST(CompletionTest, SkipExplicitObjectParameter) {4446  Annotations Code(R"cpp(4447    struct A {4448      void foo(this auto&& self, int arg); 4449      void bar(this A self, int arg);4450    };4451 4452    int main() {4453      A a {};4454      a.$c1^;4455      (&A::fo$c2^;4456      (&A::ba$c3^;4457    }4458  )cpp");4459 4460  // TODO: llvm/llvm-project/1466494461  // This is incorrect behavior. Correct Result should be a variant of,4462  // c2: signature = (auto&& self, int arg)4463  //     snippet = (${1: auto&& self}, ${2: int arg})4464  // c3: signature = (A self, int arg)4465  //     snippet = (${1: A self}, ${2: int arg})4466 4467  auto TU = TestTU::withCode(Code.code());4468  TU.ExtraArgs = {"-std=c++23"};4469 4470  auto Preamble = TU.preamble();4471  ASSERT_TRUE(Preamble);4472 4473  CodeCompleteOptions Opts{};4474 4475  MockFS FS;4476  auto Inputs = TU.inputs(FS);4477  {4478    auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),4479                               Preamble.get(), Inputs, Opts);4480 4481    EXPECT_THAT(Result.Completions,4482                UnorderedElementsAre(AllOf(named("foo"), signature("(int arg)"),4483                                           snippetSuffix("(${1:int arg})")),4484                                     AllOf(named("bar"), signature("(int arg)"),4485                                           snippetSuffix("(${1:int arg})"))));4486  }4487  {4488    auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),4489                               Preamble.get(), Inputs, Opts);4490    EXPECT_THAT(4491        Result.Completions,4492        ElementsAre(AllOf(named("foo"), signature("<class self:auto>(int arg)"),4493                          snippetSuffix("<${1:class self:auto}>"))));4494  }4495  {4496    auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),4497                               Preamble.get(), Inputs, Opts);4498    EXPECT_THAT(Result.Completions,4499                ElementsAre(AllOf(named("bar"), signature("(int arg)"),4500                                  snippetSuffix(""))));4501  }4502}4503 4504TEST(CompletionTest, MemberAccessInExplicitObjMemfn) {4505  Annotations Code(R"cpp(4506    struct A {4507      int member {};4508      int memberFnA(int a);4509      int memberFnA(this A&, float a);4510 4511      void foo(this A& self) {4512        // Should not offer any members here, since 4513        // it needs to be referenced through `self`.4514        mem$c1^;4515        // should offer all results4516        self.mem$c2^;4517 4518        [&]() {4519          // should not offer any results4520          mem$c3^;4521        }();4522      }4523    };4524  )cpp");4525 4526  auto TU = TestTU::withCode(Code.code());4527  TU.ExtraArgs = {"-std=c++23"};4528 4529  auto Preamble = TU.preamble();4530  ASSERT_TRUE(Preamble);4531 4532  CodeCompleteOptions Opts{};4533 4534  MockFS FS;4535  auto Inputs = TU.inputs(FS);4536 4537  {4538    auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),4539                               Preamble.get(), Inputs, Opts);4540 4541    EXPECT_THAT(Result.Completions, ElementsAre());4542  }4543  {4544    auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),4545                               Preamble.get(), Inputs, Opts);4546 4547    EXPECT_THAT(4548        Result.Completions,4549        UnorderedElementsAre(named("member"),4550                             AllOf(named("memberFnA"), signature("(int a)"),4551                                   snippetSuffix("(${1:int a})")),4552                             AllOf(named("memberFnA"), signature("(float a)"),4553                                   snippetSuffix("(${1:float a})"))));4554  }4555  {4556    auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),4557                               Preamble.get(), Inputs, Opts);4558 4559    EXPECT_THAT(Result.Completions, ElementsAre());4560  }4561}4562 4563TEST(CompletionTest, ListExplicitObjectOverloads) {4564  Annotations Code(R"cpp(4565    struct S {4566      void foo1(int a);4567      void foo2(int a) const;4568      void foo2(this const S& self, float a);4569      void foo3(this const S& self, int a);4570      void foo4(this S& self, int a);4571    };4572 4573    void S::foo1(int a) {4574      this->$c1^;4575    }4576 4577    void S::foo2(int a) const {4578      this->$c2^;4579    }4580 4581    void S::foo3(this const S& self, int a) {4582      self.$c3^;4583    }4584 4585    void S::foo4(this S& self, int a) {4586      self.$c4^;4587    }4588 4589    void test1(S s) {4590      s.$c5^;4591    }4592 4593    void test2(const S s) {4594      s.$c6^;4595    }4596  )cpp");4597 4598  auto TU = TestTU::withCode(Code.code());4599  TU.ExtraArgs = {"-std=c++23"};4600 4601  auto Preamble = TU.preamble();4602  ASSERT_TRUE(Preamble);4603 4604  CodeCompleteOptions Opts{};4605 4606  MockFS FS;4607  auto Inputs = TU.inputs(FS);4608 4609  {4610    auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),4611                               Preamble.get(), Inputs, Opts);4612    EXPECT_THAT(4613        Result.Completions,4614        UnorderedElementsAre(AllOf(named("foo1"), signature("(int a)"),4615                                   snippetSuffix("(${1:int a})")),4616                             AllOf(named("foo2"), signature("(int a) const"),4617                                   snippetSuffix("(${1:int a})")),4618                             AllOf(named("foo2"), signature("(float a) const"),4619                                   snippetSuffix("(${1:float a})")),4620                             AllOf(named("foo3"), signature("(int a) const"),4621                                   snippetSuffix("(${1:int a})")),4622                             AllOf(named("foo4"), signature("(int a)"),4623                                   snippetSuffix("(${1:int a})"))));4624  }4625  {4626    auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),4627                               Preamble.get(), Inputs, Opts);4628    EXPECT_THAT(4629        Result.Completions,4630        UnorderedElementsAre(AllOf(named("foo2"), signature("(int a) const"),4631                                   snippetSuffix("(${1:int a})")),4632                             AllOf(named("foo2"), signature("(float a) const"),4633                                   snippetSuffix("(${1:float a})")),4634                             AllOf(named("foo3"), signature("(int a) const"),4635                                   snippetSuffix("(${1:int a})"))));4636  }4637  {4638    auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),4639                               Preamble.get(), Inputs, Opts);4640    EXPECT_THAT(4641        Result.Completions,4642        UnorderedElementsAre(AllOf(named("foo2"), signature("(int a) const"),4643                                   snippetSuffix("(${1:int a})")),4644                             AllOf(named("foo2"), signature("(float a) const"),4645                                   snippetSuffix("(${1:float a})")),4646                             AllOf(named("foo3"), signature("(int a) const"),4647                                   snippetSuffix("(${1:int a})"))));4648  }4649  {4650    auto Result = codeComplete(testPath(TU.Filename), Code.point("c4"),4651                               Preamble.get(), Inputs, Opts);4652    EXPECT_THAT(4653        Result.Completions,4654        UnorderedElementsAre(AllOf(named("foo1"), signature("(int a)"),4655                                   snippetSuffix("(${1:int a})")),4656                             AllOf(named("foo2"), signature("(int a) const"),4657                                   snippetSuffix("(${1:int a})")),4658                             AllOf(named("foo2"), signature("(float a) const"),4659                                   snippetSuffix("(${1:float a})")),4660                             AllOf(named("foo3"), signature("(int a) const"),4661                                   snippetSuffix("(${1:int a})")),4662                             AllOf(named("foo4"), signature("(int a)"),4663                                   snippetSuffix("(${1:int a})"))));4664  }4665  {4666    auto Result = codeComplete(testPath(TU.Filename), Code.point("c5"),4667                               Preamble.get(), Inputs, Opts);4668    EXPECT_THAT(4669        Result.Completions,4670        UnorderedElementsAre(AllOf(named("foo1"), signature("(int a)"),4671                                   snippetSuffix("(${1:int a})")),4672                             AllOf(named("foo2"), signature("(int a) const"),4673                                   snippetSuffix("(${1:int a})")),4674                             AllOf(named("foo2"), signature("(float a) const"),4675                                   snippetSuffix("(${1:float a})")),4676                             AllOf(named("foo3"), signature("(int a) const"),4677                                   snippetSuffix("(${1:int a})")),4678                             AllOf(named("foo4"), signature("(int a)"),4679                                   snippetSuffix("(${1:int a})"))));4680  }4681  {4682    auto Result = codeComplete(testPath(TU.Filename), Code.point("c6"),4683                               Preamble.get(), Inputs, Opts);4684    EXPECT_THAT(4685        Result.Completions,4686        UnorderedElementsAre(AllOf(named("foo2"), signature("(int a) const"),4687                                   snippetSuffix("(${1:int a})")),4688                             AllOf(named("foo2"), signature("(float a) const"),4689                                   snippetSuffix("(${1:float a})")),4690                             AllOf(named("foo3"), signature("(int a) const"),4691                                   snippetSuffix("(${1:int a})"))));4692  }4693}4694 4695} // namespace4696} // namespace clangd4697} // namespace clang4698