brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.2 KiB · 63c0403 Raw
946 lines · cpp
1//===-- SelectionTests.cpp - ----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#include "Annotations.h"9#include "Selection.h"10#include "SourceCode.h"11#include "TestTU.h"12#include "support/TestTracer.h"13#include "clang/AST/ASTConcept.h"14#include "clang/AST/Decl.h"15#include "llvm/Support/Casting.h"16#include "gmock/gmock.h"17#include "gtest/gtest.h"18 19namespace clang {20namespace clangd {21namespace {22using ::testing::ElementsAreArray;23using ::testing::UnorderedElementsAreArray;24 25// Create a selection tree corresponding to a point or pair of points.26// This uses the precisely-defined createRight semantics. The fuzzier27// createEach is tested separately.28SelectionTree makeSelectionTree(const StringRef MarkedCode, ParsedAST &AST) {29  Annotations Test(MarkedCode);30  switch (Test.points().size()) {31  case 1: { // Point selection.32    unsigned Offset = cantFail(positionToOffset(Test.code(), Test.point()));33    return SelectionTree::createRight(AST.getASTContext(), AST.getTokens(),34                                      Offset, Offset);35  }36  case 2: // Range selection.37    return SelectionTree::createRight(38        AST.getASTContext(), AST.getTokens(),39        cantFail(positionToOffset(Test.code(), Test.points()[0])),40        cantFail(positionToOffset(Test.code(), Test.points()[1])));41  default:42    ADD_FAILURE() << "Expected 1-2 points for selection.\n" << MarkedCode;43    return SelectionTree::createRight(AST.getASTContext(), AST.getTokens(), 0u,44                                      0u);45  }46}47 48Range nodeRange(const SelectionTree::Node *N, ParsedAST &AST) {49  if (!N)50    return Range{};51  const SourceManager &SM = AST.getSourceManager();52  const LangOptions &LangOpts = AST.getLangOpts();53  StringRef Buffer = SM.getBufferData(SM.getMainFileID());54  if (llvm::isa_and_nonnull<TranslationUnitDecl>(N->ASTNode.get<Decl>()))55    return Range{Position{}, offsetToPosition(Buffer, Buffer.size())};56  auto FileRange =57      toHalfOpenFileRange(SM, LangOpts, N->ASTNode.getSourceRange());58  assert(FileRange && "We should be able to get the File Range");59  return Range{60      offsetToPosition(Buffer, SM.getFileOffset(FileRange->getBegin())),61      offsetToPosition(Buffer, SM.getFileOffset(FileRange->getEnd()))};62}63 64std::string nodeKind(const SelectionTree::Node *N) {65  return N ? N->kind() : "<null>";66}67 68std::vector<const SelectionTree::Node *> allNodes(const SelectionTree &T) {69  std::vector<const SelectionTree::Node *> Result = {&T.root()};70  for (unsigned I = 0; I < Result.size(); ++I) {71    const SelectionTree::Node *N = Result[I];72    Result.insert(Result.end(), N->Children.begin(), N->Children.end());73  }74  return Result;75}76 77// Returns true if Common is a descendent of Root.78// Verifies nothing is selected above Common.79bool verifyCommonAncestor(const SelectionTree::Node &Root,80                          const SelectionTree::Node *Common,81                          StringRef MarkedCode) {82  if (&Root == Common)83    return true;84  if (Root.Selected)85    ADD_FAILURE() << "Selected nodes outside common ancestor\n" << MarkedCode;86  bool Seen = false;87  for (const SelectionTree::Node *Child : Root.Children)88    if (verifyCommonAncestor(*Child, Common, MarkedCode)) {89      if (Seen)90        ADD_FAILURE() << "Saw common ancestor twice\n" << MarkedCode;91      Seen = true;92    }93  return Seen;94}95 96TEST(SelectionTest, CommonAncestor) {97  struct Case {98    // Selection is between ^marks^.99    // common ancestor marked with a [[range]].100    const char *Code;101    const char *CommonAncestorKind;102  };103  Case Cases[] = {104      {105          R"cpp(106            template <typename T>107            int x = T::[[^U]]::ccc();108          )cpp",109          "DependentNameTypeLoc",110      },111      {112          R"cpp(113            struct AAA { struct BBB { static int ccc(); };};114            int x = AAA::[[B^B^B]]::ccc();115          )cpp",116          "RecordTypeLoc",117      },118      {119          R"cpp(120            struct AAA { struct BBB { static int ccc(); };};121            int x = AAA::[[B^BB^]]::ccc();122          )cpp",123          "RecordTypeLoc",124      },125      {126          R"cpp(127            struct AAA { struct BBB { static int ccc(); };};128            int x = [[AAA::BBB::c^c^c]]();129          )cpp",130          "DeclRefExpr",131      },132      {133          R"cpp(134            struct AAA { struct BBB { static int ccc(); };};135            int x = [[AAA::BBB::cc^c(^)]];136          )cpp",137          "CallExpr",138      },139 140      {141          R"cpp(142            void foo() { [[if (1^11) { return; } else {^ }]] }143          )cpp",144          "IfStmt",145      },146      {147          R"cpp(148            int x(int);149            #define M(foo) x(foo)150            int a = 42;151            int b = M([[^a]]);152          )cpp",153          "DeclRefExpr",154      },155      {156          R"cpp(157            void foo();158            #define CALL_FUNCTION(X) X()159            void bar() { CALL_FUNCTION([[f^o^o]]); }160          )cpp",161          "DeclRefExpr",162      },163      {164          R"cpp(165            void foo();166            #define CALL_FUNCTION(X) X()167            void bar() { [[CALL_FUNC^TION(fo^o)]]; }168          )cpp",169          "CallExpr",170      },171      {172          R"cpp(173            void foo();174            #define CALL_FUNCTION(X) X()175            void bar() { [[C^ALL_FUNC^TION(foo)]]; }176          )cpp",177          "CallExpr",178      },179      {180          R"cpp(181            void foo();182            #^define CALL_FUNCTION(X) X(^)183            void bar() { CALL_FUNCTION(foo); }184          )cpp",185          nullptr,186      },187      {188          R"cpp(189            void foo();190            #define CALL_FUNCTION(X) X()191            void bar() { CALL_FUNCTION(foo^)^; }192          )cpp",193          nullptr,194      },195      {196          R"cpp(197            namespace ns {198            #if 0199            void fo^o() {}200            #endif201            }202          )cpp",203          nullptr,204      },205      {206          R"cpp(207            #define TARGET void foo()208            [[TAR^GET{ return; }]]209          )cpp",210          "FunctionDecl",211      },212      {213          R"cpp(214            struct S { S(const char*); };215            [[S s ^= "foo"]];216          )cpp",217          // The AST says a CXXConstructExpr covers the = sign in C++14.218          // But we consider CXXConstructExpr to only own brackets.219          // (It's not the interesting constructor anyway, just S(&&)).220          "VarDecl",221      },222      {223          R"cpp(224            struct S { S(const char*); };225            [[S ^s = "foo"]];226          )cpp",227          "VarDecl",228      },229      {230          R"cpp(231            [[^void]] (*S)(int) = nullptr;232          )cpp",233          "BuiltinTypeLoc",234      },235      {236          R"cpp(237            [[void (*S)^(int)]] = nullptr;238          )cpp",239          "FunctionProtoTypeLoc",240      },241      {242          R"cpp(243            [[void (^*S)(int)]] = nullptr;244          )cpp",245          "PointerTypeLoc",246      },247      {248          R"cpp(249            [[void (*^S)(int) = nullptr]];250          )cpp",251          "VarDecl",252      },253      {254          R"cpp(255            [[void ^(*S)(int)]] = nullptr;256          )cpp",257          "ParenTypeLoc",258      },259      {260          R"cpp(261            struct S {262              int foo() const;263              int bar() { return [[f^oo]](); }264            };265          )cpp",266          "MemberExpr", // Not implicit CXXThisExpr, or its implicit cast!267      },268      {269          R"cpp(270            auto lambda = [](const char*){ return 0; };271            int x = lambda([["y^"]]);272          )cpp",273          "StringLiteral", // Not DeclRefExpr to operator()!274      },275      {276          R"cpp(277            struct Foo {};278            struct Bar : [[v^ir^tual private Foo]] {};279          )cpp",280          "CXXBaseSpecifier",281      },282      {283          R"cpp(284            struct Foo {};285            struct Bar : private [[Fo^o]] {};286          )cpp",287          "RecordTypeLoc",288      },289      {290          R"cpp(291            struct Foo {};292            struct Bar : [[Fo^o]] {};293          )cpp",294          "RecordTypeLoc",295      },296 297      // Point selections.298      {"void foo() { [[^foo]](); }", "DeclRefExpr"},299      {"void foo() { [[f^oo]](); }", "DeclRefExpr"},300      {"void foo() { [[fo^o]](); }", "DeclRefExpr"},301      {"void foo() { [[foo^()]]; }", "CallExpr"},302      {"void foo() { [[foo^]] (); }", "DeclRefExpr"},303      {"int bar; void foo() [[{ foo (); }]]^", "CompoundStmt"},304      {"int x = [[42]]^;", "IntegerLiteral"},305 306      // Ignores whitespace, comments, and semicolons in the selection.307      {"void foo() { [[foo^()]]; /*comment*/^}", "CallExpr"},308 309      // Tricky case: FunctionTypeLoc in FunctionDecl has a hole in it.310      {"[[^void]] foo();", "BuiltinTypeLoc"},311      {"[[void foo^()]];", "FunctionProtoTypeLoc"},312      {"[[^void foo^()]];", "FunctionDecl"},313      {"[[void ^foo()]];", "FunctionDecl"},314      // Tricky case: with function attributes, the AttributedTypeLoc's range315      // includes the function name, but we want the name to be associated with316      // the CXXMethodDecl.317      {"struct X { [[const int* ^Get() const <:[clang::lifetimebound]:> "318       "{return nullptr;}]]; };",319       "CXXMethodDecl"},320      // When the cursor is on the attribute itself, we should select the321      // AttributedTypeLoc. Note: Due to a bug or deliberate quirk in the AST322      // modeling of AttributedTypeLoc, its range ends at the attribute name323      // token, not including the closing brackets ":>:>".324      {"struct X { const [[int* Foo() const <:<:clang::life^timebound]]:>:> "325       "{return nullptr;}; };",326       "AttributedTypeLoc"},327      // Tricky case: two VarDecls share a specifier.328      {"[[int ^a]], b;", "VarDecl"},329      {"[[int a, ^b]];", "VarDecl"},330      // Tricky case: CXXConstructExpr wants to claim the whole init range.331      {332          R"cpp(333            struct X { X(int); };334            class Y {335              X x;336              Y() : [[^x(4)]] {}337            };338          )cpp",339          "CXXCtorInitializer", // Not the CXXConstructExpr!340      },341      // Tricky case: anonymous struct is a sibling of the VarDecl.342      {"[[st^ruct {int x;}]] y;", "CXXRecordDecl"},343      {"[[struct {int x;} ^y]];", "VarDecl"},344      {"struct {[[int ^x]];} y;", "FieldDecl"},345 346      // Tricky case: nested ArrayTypeLocs have the same token range.347      {"const int x = 1, y = 2; int array[^[[x]]][10][y];", "DeclRefExpr"},348      {"const int x = 1, y = 2; int array[x][10][^[[y]]];", "DeclRefExpr"},349      {"const int x = 1, y = 2; int array[x][^[[10]]][y];", "IntegerLiteral"},350      {"const int x = 1, y = 2; [[i^nt]] array[x][10][y];", "BuiltinTypeLoc"},351      {"void func(int x) { int v_array[^[[x]]][10]; }", "DeclRefExpr"},352 353      {"int (*getFunc([[do^uble]]))(int);", "BuiltinTypeLoc"},354 355      // Member pointers and pack expansion use declarator syntax, but are356      // restricted so they don't need special casing.357      {"class X{}; [[int X::^*]]y[10];", "MemberPointerTypeLoc"},358      {"template<typename ...T> void foo([[T*^...]]x);",359       "PackExpansionTypeLoc"},360      {"template<typename ...T> void foo([[^T]]*...x);",361       "TemplateTypeParmTypeLoc"},362 363      // FIXME: the AST has no location info for qualifiers.364      {"const [[a^uto]] x = 42;", "AutoTypeLoc"},365      {"co^nst auto x = 42;", nullptr},366 367      {"^", nullptr},368      {"void foo() { [[foo^^]] (); }", "DeclRefExpr"},369 370      // FIXME: Ideally we'd get a declstmt or the VarDecl itself here.371      // This doesn't happen now; the RAV doesn't traverse a node containing ;.372      {"int x = 42;^", nullptr},373 374      // Common ancestor is logically TUDecl, but we never return that.375      {"^int x; int y;^", nullptr},376 377      // Node types that have caused problems in the past.378      {"template <typename T> void foo() { [[^T]] t; }",379       "TemplateTypeParmTypeLoc"},380 381      // No crash382      {383          R"cpp(384            template <class T> struct Foo {};385            template <[[template<class> class /*cursor here*/^U]]>386             struct Foo<U<int>*> {};387          )cpp",388          "TemplateTemplateParmDecl"},389 390      // Foreach has a weird AST, ensure we can select parts of the range init.391      // This used to fail, because the DeclStmt for C claimed the whole range.392      {393          R"cpp(394            struct Str {395              const char *begin();396              const char *end();397            };398            Str makeStr(const char*);399            void loop() {400              for (const char C : [[mak^eStr("foo"^)]])401                ;402            }403          )cpp",404          "CallExpr"},405 406      // User-defined literals are tricky: is 12_i one token or two?407      // For now we treat it as one, and the UserDefinedLiteral as a leaf.408      {409          R"cpp(410            struct Foo{};411            Foo operator""_ud(unsigned long long);412            Foo x = [[^12_ud]];413          )cpp",414          "UserDefinedLiteral"},415 416      {417          R"cpp(418        int a;419        decltype([[^a]] + a) b;420        )cpp",421          "DeclRefExpr"},422      {"[[decltype^(1)]] b;", "DecltypeTypeLoc"}, // Not the VarDecl.423      // decltype(auto) is an AutoTypeLoc!424      {"[[de^cltype(a^uto)]] a = 1;", "AutoTypeLoc"},425 426      // Objective-C nullability attributes.427      {428          R"cpp(429            @interface I{}430            @property(nullable) [[^I]] *x;431            @end432          )cpp",433          "ObjCInterfaceTypeLoc"},434      {435          R"cpp(436            @interface I{}437            - (void)doSomething:(nonnull [[i^d]])argument;438            @end439          )cpp",440          "TypedefTypeLoc"},441 442      // Objective-C OpaqueValueExpr/PseudoObjectExpr has weird ASTs.443      // Need to traverse the contents of the OpaqueValueExpr to the POE,444      // and ensure we traverse only the syntactic form of the PseudoObjectExpr.445      {446          R"cpp(447            @interface I{}448            @property(retain) I*x;449            @property(retain) I*y;450            @end451            void test(I *f) { [[^f]].x.y = 0; }452          )cpp",453          "DeclRefExpr"},454      {455          R"cpp(456            @interface I{}457            @property(retain) I*x;458            @property(retain) I*y;459            @end460            void test(I *f) { [[f.^x]].y = 0; }461          )cpp",462          "ObjCPropertyRefExpr"},463      // Examples with implicit properties.464      {465          R"cpp(466            @interface I{}467            -(int)foo;468            @end469            int test(I *f) { return 42 + [[^f]].foo; }470          )cpp",471          "DeclRefExpr"},472      {473          R"cpp(474            @interface I{}475            -(int)foo;476            @end477            int test(I *f) { return 42 + [[f.^foo]]; }478          )cpp",479          "ObjCPropertyRefExpr"},480      {"struct foo { [[int has^h<:32:>]]; };", "FieldDecl"},481      {"struct foo { [[op^erator int()]]; };", "CXXConversionDecl"},482      {"struct foo { [[^~foo()]]; };", "CXXDestructorDecl"},483      {"struct foo { [[~^foo()]]; };", "CXXDestructorDecl"},484      {"template <class T> struct foo { ~foo<[[^T]]>(){} };",485       "TemplateTypeParmTypeLoc"},486      {"struct foo {}; void bar(foo *f) { [[f->~^foo]](); }", "MemberExpr"},487      {"struct foo { [[fo^o(){}]] };", "CXXConstructorDecl"},488 489      {R"cpp(490        struct S1 { void f(); };491        struct S2 { S1 * operator->(); };492        void test(S2 s2) {493          s2[[-^>]]f();494        }495      )cpp",496       "DeclRefExpr"}, // DeclRefExpr to the "operator->" method.497 498      // Template template argument.499      {R"cpp(500        template <typename> class Vector {};501        template <template <typename> class Container> class A {};502        A<[[V^ector]]> a;503      )cpp",504       "TemplateArgumentLoc"},505 506      // Attributes507      {R"cpp(508        void f(int * __attribute__(([[no^nnull]])) );509      )cpp",510       "NonNullAttr"},511 512      {R"cpp(513        // Digraph syntax for attributes to avoid accidental annotations.514        class <:[gsl::Owner([[in^t]])]:> X{};515      )cpp",516       "BuiltinTypeLoc"},517 518      // This case used to crash - AST has a null Attr519      {R"cpp(520        @interface I521        [[@property(retain, nonnull) <:[My^Object2]:> *x]]; // error-ok522        @end523      )cpp",524       "ObjCPropertyDecl"},525 526      {R"cpp(527        typedef int Foo;528        enum Bar : [[Fo^o]] {};529      )cpp",530       "TypedefTypeLoc"},531      {R"cpp(532        typedef int Foo;533        enum Bar : [[Fo^o]];534      )cpp",535       "TypedefTypeLoc"},536 537      // lambda captured var-decl538      {R"cpp(539        void test(int bar) {540          auto l = [^[[foo = bar]]] { };541        })cpp",542       "VarDecl"},543      {R"cpp(544        /*error-ok*/545        void func() [[{^]])cpp",546       "CompoundStmt"},547      {R"cpp(548        void func() { [[__^func__]]; }549        )cpp",550       "PredefinedExpr"},551 552      // using enum553      {R"cpp(554        namespace ns { enum class A {}; };555        using enum ns::[[^A]];556        )cpp",557       "EnumTypeLoc"},558      {R"cpp(559        namespace ns { enum class A {}; using B = A; };560        using enum ns::[[^B]];561        )cpp",562       "TypedefTypeLoc"},563      {R"cpp(564        namespace ns { enum class A {}; };565        using enum [[^ns::]]A;566        )cpp",567       "NestedNameSpecifierLoc"},568      {R"cpp(569        namespace ns { enum class A {}; };570        [[using ^enum ns::A]];571        )cpp",572       "UsingEnumDecl"},573      {R"cpp(574        namespace ns { enum class A {}; };575        [[^using enum ns::A]];576        )cpp",577       "UsingEnumDecl"},578 579      // concepts580      {R"cpp(581        template <class> concept C = true;582        auto x = [[^C<int>]];583      )cpp",584       "ConceptReference"},585      {R"cpp(586        template <class> concept C = true;587        [[^C]] auto x = 0;588      )cpp",589       "ConceptReference"},590      {R"cpp(591        template <class> concept C = true;592        void foo([[^C]] auto x) {}593      )cpp",594       "ConceptReference"},595      {R"cpp(596        template <class> concept C = true;597        template <[[^C]] x> int i = 0;598      )cpp",599       "ConceptReference"},600      {R"cpp(601        namespace ns { template <class> concept C = true; }602        auto x = [[ns::^C<int>]];603      )cpp",604       "ConceptReference"},605      {R"cpp(606        template <typename T, typename K>607        concept D = true;608        template <typename T> void g(D<[[^T]]> auto abc) {}609      )cpp",610       "TemplateTypeParmTypeLoc"},611  };612 613  for (const Case &C : Cases) {614    trace::TestTracer Tracer;615    Annotations Test(C.Code);616 617    TestTU TU;618    TU.Code = std::string(Test.code());619 620    TU.ExtraArgs.push_back("-xobjective-c++");621    TU.ExtraArgs.push_back("-std=c++20");622 623    auto AST = TU.build();624    auto T = makeSelectionTree(C.Code, AST);625    EXPECT_EQ("TranslationUnitDecl", nodeKind(&T.root())) << C.Code;626 627    if (Test.ranges().empty()) {628      // If no [[range]] is marked in the example, there should be no selection.629      EXPECT_FALSE(T.commonAncestor()) << C.Code << "\n" << T;630      EXPECT_THAT(Tracer.takeMetric("selection_recovery", "C++"),631                  testing::IsEmpty());632    } else {633      // If there is an expected selection, common ancestor should exist634      // with the appropriate node type.635      EXPECT_EQ(C.CommonAncestorKind, nodeKind(T.commonAncestor()))636          << C.Code << "\n"637          << T;638      // Convert the reported common ancestor to a range and verify it.639      EXPECT_EQ(nodeRange(T.commonAncestor(), AST), Test.range())640          << C.Code << "\n"641          << T;642 643      // Check that common ancestor is reachable on exactly one path from root,644      // and no nodes outside it are selected.645      EXPECT_TRUE(verifyCommonAncestor(T.root(), T.commonAncestor(), C.Code))646          << C.Code;647      EXPECT_THAT(Tracer.takeMetric("selection_recovery", "C++"),648                  ElementsAreArray({0}));649    }650  }651}652 653// Regression test: this used to match the injected X, not the outer X.654TEST(SelectionTest, InjectedClassName) {655  const char *Code = "struct ^X { int x; };";656  auto AST = TestTU::withCode(Annotations(Code).code()).build();657  auto T = makeSelectionTree(Code, AST);658  ASSERT_EQ("CXXRecordDecl", nodeKind(T.commonAncestor())) << T;659  auto *D = dyn_cast<CXXRecordDecl>(T.commonAncestor()->ASTNode.get<Decl>());660  EXPECT_FALSE(D->isInjectedClassName());661}662 663TEST(SelectionTree, Metrics) {664  const char *Code = R"cpp(665    // error-ok: testing behavior on recovery expression666    int foo();667    int foo(int, int);668    int x = fo^o(42);669  )cpp";670  auto AST = TestTU::withCode(Annotations(Code).code()).build();671  trace::TestTracer Tracer;672  auto T = makeSelectionTree(Code, AST);673  EXPECT_THAT(Tracer.takeMetric("selection_recovery", "C++"),674              ElementsAreArray({1}));675  EXPECT_THAT(Tracer.takeMetric("selection_recovery_type", "C++"),676              ElementsAreArray({1}));677}678 679// FIXME: Doesn't select the binary operator node in680//          #define FOO(X) X + 1681//          int a, b = [[FOO(a)]];682TEST(SelectionTest, Selected) {683  // Selection with ^marks^.684  // Partially selected nodes marked with a [[range]].685  // Completely selected nodes marked with a $C[[range]].686  const char *Cases[] = {687      R"cpp( int abc, xyz = [[^ab^c]]; )cpp",688      R"cpp( int abc, xyz = [[a^bc^]]; )cpp",689      R"cpp( int abc, xyz = $C[[^abc^]]; )cpp",690      R"cpp(691        void foo() {692          [[if ([[1^11]]) $C[[{693            $C[[return]];694          }]] else [[{^695          }]]]]696          char z;697        }698      )cpp",699      R"cpp(700          template <class T>701          struct unique_ptr {};702          void foo(^$C[[unique_ptr<$C[[unique_ptr<$C[[int]]>]]>]]^ a) {}703      )cpp",704      R"cpp(int a = [[5 >^> 1]];)cpp",705      R"cpp(706        #define ECHO(X) X707        ECHO(EC^HO($C[[int]]) EC^HO(a));708      )cpp",709      R"cpp( $C[[^$C[[int]] a^]]; )cpp",710      R"cpp( $C[[^$C[[int]] a = $C[[5]]^]]; )cpp",711  };712  for (const char *C : Cases) {713    Annotations Test(C);714    auto AST = TestTU::withCode(Test.code()).build();715    auto T = makeSelectionTree(C, AST);716 717    std::vector<Range> Complete, Partial;718    for (const SelectionTree::Node *N : allNodes(T))719      if (N->Selected == SelectionTree::Complete)720        Complete.push_back(nodeRange(N, AST));721      else if (N->Selected == SelectionTree::Partial)722        Partial.push_back(nodeRange(N, AST));723    EXPECT_THAT(Complete, UnorderedElementsAreArray(Test.ranges("C"))) << C;724    EXPECT_THAT(Partial, UnorderedElementsAreArray(Test.ranges())) << C;725  }726}727 728TEST(SelectionTest, PathologicalPreprocessor) {729  const char *Case = R"cpp(730#define MACRO while(1)731    void test() {732#include "Expand.inc"733        br^eak;734    }735  )cpp";736  Annotations Test(Case);737  auto TU = TestTU::withCode(Test.code());738  TU.AdditionalFiles["Expand.inc"] = "MACRO\n";739  auto AST = TU.build();740  EXPECT_THAT(AST.getDiagnostics(), ::testing::IsEmpty());741  auto T = makeSelectionTree(Case, AST);742 743  EXPECT_EQ("BreakStmt", T.commonAncestor()->kind());744  EXPECT_EQ("WhileStmt", T.commonAncestor()->Parent->kind());745}746 747TEST(SelectionTest, IncludedFile) {748  const char *Case = R"cpp(749    void test() {750#include "Exp^and.inc"751        break;752    }753  )cpp";754  Annotations Test(Case);755  auto TU = TestTU::withCode(Test.code());756  TU.AdditionalFiles["Expand.inc"] = "while(1)\n";757  auto AST = TU.build();758  auto T = makeSelectionTree(Case, AST);759 760  EXPECT_EQ(nullptr, T.commonAncestor());761}762 763TEST(SelectionTest, MacroArgExpansion) {764  // If a macro arg is expanded several times, we only consider the first one765  // selected.766  const char *Case = R"cpp(767    int mul(int, int);768    #define SQUARE(X) mul(X, X);769    int nine = SQUARE(^3);770  )cpp";771  Annotations Test(Case);772  auto AST = TestTU::withCode(Test.code()).build();773  auto T = makeSelectionTree(Case, AST);774  EXPECT_EQ("IntegerLiteral", T.commonAncestor()->kind());775  EXPECT_TRUE(T.commonAncestor()->Selected);776 777  // Verify that the common assert() macro doesn't suffer from this.778  // (This is because we don't associate the stringified token with the arg).779  Case = R"cpp(780    void die(const char*);781    #define assert(x) (x ? (void)0 : die(#x))782    void foo() { assert(^42); }783  )cpp";784  Test = Annotations(Case);785  AST = TestTU::withCode(Test.code()).build();786  T = makeSelectionTree(Case, AST);787  EXPECT_EQ("IntegerLiteral", T.commonAncestor()->kind());788 789  // Reduced from private bug involving RETURN_IF_ERROR.790  // Due to >>-splitting and a bug in isBeforeInTranslationUnit, the inner791  // S<int> would claim way too many tokens.792  Case = R"cpp(793    #define ID(x) x794    template <typename T> class S {};795    ID(796      ID(S<S<int>> x);797      int ^y;798    )799  )cpp";800  Test = Annotations(Case);801  AST = TestTU::withCode(Test.code()).build();802  T = makeSelectionTree(Case, AST);803  // not TemplateSpecializationTypeLoc!804  EXPECT_EQ("VarDecl", T.commonAncestor()->kind());805}806 807TEST(SelectionTest, Implicit) {808  const char *Test = R"cpp(809    struct S { S(const char*); };810    int f(S);811    int x = f("^");812  )cpp";813  auto TU = TestTU::withCode(Annotations(Test).code());814  // C++14 AST contains some temporaries that C++17 elides.815  TU.ExtraArgs.push_back("-std=c++17");816  auto AST = TU.build();817  auto T = makeSelectionTree(Test, AST);818 819  const SelectionTree::Node *Str = T.commonAncestor();820  EXPECT_EQ("StringLiteral", nodeKind(Str)) << "Implicit selected?";821  EXPECT_EQ("ImplicitCastExpr", nodeKind(Str->Parent));822  EXPECT_EQ("CXXConstructExpr", nodeKind(Str->Parent->Parent));823  const SelectionTree::Node *ICE = Str->Parent->Parent->Parent;824  EXPECT_EQ("ImplicitCastExpr", nodeKind(ICE));825  EXPECT_EQ("CallExpr", nodeKind(ICE->Parent));826  EXPECT_EQ(Str, &ICE->ignoreImplicit())827      << "Didn't unwrap " << nodeKind(&ICE->ignoreImplicit());828 829  EXPECT_EQ(ICE, &Str->outerImplicit());830}831 832TEST(SelectionTest, CreateAll) {833  llvm::Annotations Test("int$unique^ a=1$ambiguous^+1; $empty^");834  auto AST = TestTU::withCode(Test.code()).build();835  unsigned Seen = 0;836  SelectionTree::createEach(837      AST.getASTContext(), AST.getTokens(), Test.point("ambiguous"),838      Test.point("ambiguous"), [&](SelectionTree T) {839        // Expect to see the right-biased tree first.840        if (Seen == 0) {841          EXPECT_EQ("BinaryOperator", nodeKind(T.commonAncestor()));842        } else if (Seen == 1) {843          EXPECT_EQ("IntegerLiteral", nodeKind(T.commonAncestor()));844        }845        ++Seen;846        return false;847      });848  EXPECT_EQ(2u, Seen);849 850  Seen = 0;851  SelectionTree::createEach(AST.getASTContext(), AST.getTokens(),852                            Test.point("ambiguous"), Test.point("ambiguous"),853                            [&](SelectionTree T) {854                              ++Seen;855                              return true;856                            });857  EXPECT_EQ(1u, Seen) << "Return true --> stop iterating";858 859  Seen = 0;860  SelectionTree::createEach(AST.getASTContext(), AST.getTokens(),861                            Test.point("unique"), Test.point("unique"),862                            [&](SelectionTree T) {863                              ++Seen;864                              return false;865                            });866  EXPECT_EQ(1u, Seen) << "no ambiguity --> only one tree";867 868  Seen = 0;869  SelectionTree::createEach(AST.getASTContext(), AST.getTokens(),870                            Test.point("empty"), Test.point("empty"),871                            [&](SelectionTree T) {872                              EXPECT_FALSE(T.commonAncestor());873                              ++Seen;874                              return false;875                            });876  EXPECT_EQ(1u, Seen) << "empty tree still created";877 878  Seen = 0;879  SelectionTree::createEach(AST.getASTContext(), AST.getTokens(),880                            Test.point("unique"), Test.point("ambiguous"),881                            [&](SelectionTree T) {882                              ++Seen;883                              return false;884                            });885  EXPECT_EQ(1u, Seen) << "one tree for nontrivial selection";886}887 888TEST(SelectionTest, DeclContextIsLexical) {889  llvm::Annotations Test("namespace a { void $1^foo(); } void a::$2^foo();");890  auto AST = TestTU::withCode(Test.code()).build();891  {892    auto ST = SelectionTree::createRight(AST.getASTContext(), AST.getTokens(),893                                         Test.point("1"), Test.point("1"));894    EXPECT_FALSE(ST.commonAncestor()->getDeclContext().isTranslationUnit());895  }896  {897    auto ST = SelectionTree::createRight(AST.getASTContext(), AST.getTokens(),898                                         Test.point("2"), Test.point("2"));899    EXPECT_TRUE(ST.commonAncestor()->getDeclContext().isTranslationUnit());900  }901}902 903TEST(SelectionTest, DeclContextLambda) {904  llvm::Annotations Test(R"cpp(905    void foo();906    auto lambda = [] {907      return $1^foo();908    };909  )cpp");910  auto AST = TestTU::withCode(Test.code()).build();911  auto ST = SelectionTree::createRight(AST.getASTContext(), AST.getTokens(),912                                       Test.point("1"), Test.point("1"));913  EXPECT_TRUE(ST.commonAncestor()->getDeclContext().isFunctionOrMethod());914}915 916TEST(SelectionTest, UsingConcepts) {917  llvm::Annotations Test(R"cpp(918namespace ns {919template <typename T>920concept Foo = true;921}922 923using ns::Foo;924 925template <Fo^o... T, Fo^o auto U>926auto Func(Fo^o auto V) -> Fo^o decltype(auto) {927  Fo^o auto W = V;928  return W;929}930)cpp");931  auto TU = TestTU::withCode(Test.code());932  TU.ExtraArgs.emplace_back("-std=c++2c");933  auto AST = TU.build();934  for (auto Point : Test.points()) {935    auto ST = SelectionTree::createRight(AST.getASTContext(), AST.getTokens(),936                                         Point, Point);937    auto *C = ST.commonAncestor()->ASTNode.get<ConceptReference>();938    EXPECT_TRUE(C && C->getFoundDecl() &&939                C->getFoundDecl()->getKind() == Decl::UsingShadow);940  }941}942 943} // namespace944} // namespace clangd945} // namespace clang946