brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.6 KiB · 8699752 Raw
733 lines · cpp
1#include "../../lib/Format/Macros.h"2#include "../../lib/Format/UnwrappedLineParser.h"3#include "TestLexer.h"4#include "llvm/ADT/ArrayRef.h"5#include "llvm/ADT/SmallVector.h"6#include "llvm/ADT/StringRef.h"7 8#include "gmock/gmock.h"9#include "gtest/gtest.h"10#include <map>11#include <memory>12#include <vector>13 14namespace clang {15namespace format {16namespace {17 18using UnexpandedMap =19    llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>>;20 21// Keeps track of a sequence of macro expansions.22//23// The expanded tokens are accessible via getTokens(), while a map of macro call24// identifier token to unexpanded token stream is accessible via25// getUnexpanded().26class Expansion {27public:28  Expansion(TestLexer &Lex, MacroExpander &Macros) : Lex(Lex), Macros(Macros) {}29 30  // Appends the token stream obtained from expanding the macro Name given31  // the provided arguments, to be later retrieved with getTokens().32  // Returns the list of tokens making up the unexpanded macro call.33  TokenList expand(StringRef Name,34                   const SmallVector<SmallVector<FormatToken *, 8>, 1> &Args) {35    return expandInternal(Name, Args);36  }37 38  TokenList expand(StringRef Name) { return expandInternal(Name, {}); }39 40  TokenList expand(StringRef Name, const std::vector<std::string> &Args) {41    return expandInternal(Name, lexArgs(Args));42  }43 44  const UnexpandedMap &getUnexpanded() const { return Unexpanded; }45 46  const TokenList &getTokens() const { return Tokens; }47 48private:49  TokenList expandInternal(50      StringRef Name,51      const std::optional<SmallVector<SmallVector<FormatToken *, 8>, 1>>52          &Args) {53    auto *ID = Lex.id(Name);54    auto UnexpandedLine = std::make_unique<UnwrappedLine>();55    UnexpandedLine->Tokens.push_back(ID);56    if (Args && !Args->empty()) {57      UnexpandedLine->Tokens.push_back(Lex.id("("));58      for (auto I = Args->begin(), E = Args->end(); I != E; ++I) {59        if (I != Args->begin())60          UnexpandedLine->Tokens.push_back(Lex.id(","));61        UnexpandedLine->Tokens.insert(UnexpandedLine->Tokens.end(), I->begin(),62                                      I->end());63      }64      UnexpandedLine->Tokens.push_back(Lex.id(")"));65    }66    Unexpanded[ID] = std::move(UnexpandedLine);67 68    auto Expanded = Macros.expand(ID, Args);69    if (Expanded.size() > 1)70      Expanded = uneof(Expanded);71    Tokens.append(Expanded.begin(), Expanded.end());72 73    TokenList UnexpandedTokens;74    for (const UnwrappedLineNode &Node : Unexpanded[ID]->Tokens)75      UnexpandedTokens.push_back(Node.Tok);76    return UnexpandedTokens;77  }78 79  SmallVector<TokenList, 1> lexArgs(const std::vector<std::string> &Args) {80    SmallVector<TokenList, 1> Result;81    for (const auto &Arg : Args)82      Result.push_back(uneof(Lex.lex(Arg)));83    return Result;84  }85  llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>> Unexpanded;86  SmallVector<FormatToken *, 8> Tokens;87  TestLexer &Lex;88  MacroExpander &Macros;89};90 91struct Chunk {92  Chunk(ArrayRef<FormatToken *> Tokens) : Tokens(Tokens) {}93  Chunk(ArrayRef<UnwrappedLine> Children) : Children(Children) {}94  SmallVector<UnwrappedLineNode, 1> Tokens;95  SmallVector<UnwrappedLine, 0> Children;96};97 98// Allows to produce chunks of a token list by typing the code of equal tokens.99//100// Created from a list of tokens, users call "consume" to get the next chunk101// of tokens, checking that they match the written code.102struct Matcher {103  Matcher(const TokenList &Tokens, TestLexer &Lex)104      : Tokens(Tokens), It(this->Tokens.begin()), Lex(Lex) {}105 106  bool tokenMatches(const FormatToken *Left, const FormatToken *Right) {107    if (Left->getType() == Right->getType() &&108        Left->TokenText == Right->TokenText) {109      return true;110    }111    llvm::dbgs() << Left->TokenText << " != " << Right->TokenText << "\n";112    return false;113  }114 115  Chunk consume(StringRef Tokens) {116    TokenList Result;117    for (const FormatToken *Token : uneof(Lex.lex(Tokens))) {118      (void)Token; // Fix unused variable warning when asserts are disabled.119      assert(tokenMatches(*It, Token));120      Result.push_back(*It);121      ++It;122    }123    return Chunk(Result);124  }125 126  TokenList Tokens;127  TokenList::iterator It;128  TestLexer &Lex;129};130 131UnexpandedMap mergeUnexpanded(const UnexpandedMap &M1,132                              const UnexpandedMap &M2) {133  UnexpandedMap Result;134  for (const auto &KV : M1)135    Result[KV.first] = std::make_unique<UnwrappedLine>(*KV.second);136  for (const auto &KV : M2)137    Result[KV.first] = std::make_unique<UnwrappedLine>(*KV.second);138  return Result;139}140 141class MacroCallReconstructorTest : public testing::Test {142public:143  MacroCallReconstructorTest() : Lex(Allocator, Buffers) {}144 145  std::unique_ptr<MacroExpander>146  createExpander(const std::vector<std::string> &MacroDefinitions) {147    return std::make_unique<MacroExpander>(MacroDefinitions,148                                           Lex.SourceMgr.get(), Lex.Style,149                                           Lex.Allocator, Lex.IdentTable);150  }151 152  UnwrappedLine line(ArrayRef<FormatToken *> Tokens, unsigned Level = 0) {153    UnwrappedLine Result;154    Result.Level = Level;155    for (FormatToken *Tok : Tokens)156      Result.Tokens.push_back(UnwrappedLineNode(Tok));157    return Result;158  }159 160  UnwrappedLine line(StringRef Text, unsigned Level = 0) {161    return line({lex(Text)}, Level);162  }163 164  UnwrappedLine line(ArrayRef<Chunk> Chunks, unsigned Level = 0) {165    UnwrappedLine Result;166    Result.Level = Level;167    for (const Chunk &Chunk : Chunks) {168      llvm::append_range(Result.Tokens, Chunk.Tokens);169      assert(!Result.Tokens.empty());170      Result.Tokens.back().Children.append(Chunk.Children.begin(),171                                           Chunk.Children.end());172    }173    return Result;174  }175 176  TokenList lex(StringRef Text) { return uneof(Lex.lex(Text)); }177 178  Chunk tokens(StringRef Text) { return Chunk(lex(Text)); }179 180  Chunk children(ArrayRef<UnwrappedLine> Children) { return Chunk(Children); }181 182  llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;183  std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;184  TestLexer Lex;185};186 187bool matchesTokens(const UnwrappedLine &L1, const UnwrappedLine &L2) {188  if (L1.Level != L2.Level)189    return false;190  if (L1.Tokens.size() != L2.Tokens.size())191    return false;192  for (auto L1It = L1.Tokens.begin(), L2It = L2.Tokens.begin();193       L1It != L1.Tokens.end(); ++L1It, ++L2It) {194    if (L1It->Tok != L2It->Tok)195      return false;196    if (L1It->Children.size() != L2It->Children.size())197      return false;198    for (auto L1ChildIt = L1It->Children.begin(),199              L2ChildIt = L2It->Children.begin();200         L1ChildIt != L1It->Children.end(); ++L1ChildIt, ++L2ChildIt) {201      if (!matchesTokens(*L1ChildIt, *L2ChildIt))202        return false;203    }204  }205  return true;206}207MATCHER_P(matchesLine, line, "") { return matchesTokens(arg, line); }208 209TEST_F(MacroCallReconstructorTest, Identifier) {210  auto Macros = createExpander({"X=x"});211  Expansion Exp(Lex, *Macros);212  TokenList Call = Exp.expand("X");213 214  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());215  Unexp.addLine(line(Exp.getTokens()));216  EXPECT_TRUE(Unexp.finished());217  Matcher U(Call, Lex);218  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(line(U.consume("X"))));219}220 221TEST_F(MacroCallReconstructorTest, EmptyDefinition) {222  auto Macros = createExpander({"X"});223  Expansion Exp(Lex, *Macros);224  TokenList Call = Exp.expand("X");225 226  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());227  Unexp.addLine(line(Exp.getTokens()));228  EXPECT_TRUE(Unexp.finished());229  Matcher U(Call, Lex);230  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(line(U.consume("X"))));231}232 233TEST_F(MacroCallReconstructorTest, EmptyExpansion) {234  auto Macros = createExpander({"A(x)=x"});235  Expansion Exp(Lex, *Macros);236  TokenList Call = Exp.expand("A", {""});237 238  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());239  Unexp.addLine(line(Exp.getTokens()));240  EXPECT_TRUE(Unexp.finished());241  Matcher U(Call, Lex);242  EXPECT_THAT(std::move(Unexp).takeResult(),243              matchesLine(line(U.consume("A()"))));244}245 246TEST_F(MacroCallReconstructorTest, NestedLineWithinCall) {247  auto Macros = createExpander({"C(a)=class X { a; };"});248  Expansion Exp(Lex, *Macros);249  TokenList Call = Exp.expand("C", {"void f()"});250 251  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());252  Matcher E(Exp.getTokens(), Lex);253  Unexp.addLine(line(E.consume("class X {")));254  EXPECT_FALSE(Unexp.finished());255  Unexp.addLine(line(E.consume("void f();")));256  EXPECT_FALSE(Unexp.finished());257  Unexp.addLine(line(E.consume("};")));258  EXPECT_TRUE(Unexp.finished());259  Matcher U(Call, Lex);260  EXPECT_THAT(std::move(Unexp).takeResult(),261              matchesLine(line(U.consume("C(void f())"))));262}263 264TEST_F(MacroCallReconstructorTest, MultipleLinesInNestedMultiParamsExpansion) {265  auto Macros = createExpander({"C(a, b)=a b", "B(a)={a}"});266  Expansion Exp1(Lex, *Macros);267  TokenList Call1 = Exp1.expand("B", {"b"});268  Expansion Exp2(Lex, *Macros);269  TokenList Call2 = Exp2.expand("C", {uneof(Lex.lex("a")), Exp1.getTokens()});270 271  UnexpandedMap Unexpanded =272      mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded());273  MacroCallReconstructor Unexp(0, Unexpanded);274  Matcher E(Exp2.getTokens(), Lex);275  Unexp.addLine(line(E.consume("a")));276  EXPECT_FALSE(Unexp.finished());277  Unexp.addLine(line(E.consume("{")));278  EXPECT_FALSE(Unexp.finished());279  Unexp.addLine(line(E.consume("b")));280  EXPECT_FALSE(Unexp.finished());281  Unexp.addLine(line(E.consume("}")));282  EXPECT_TRUE(Unexp.finished());283 284  Matcher U1(Call1, Lex);285  auto Middle = U1.consume("B(b)");286  Matcher U2(Call2, Lex);287  auto Chunk1 = U2.consume("C(a, ");288  auto Chunk2 = U2.consume("{ b }");289  auto Chunk3 = U2.consume(")");290 291  EXPECT_THAT(std::move(Unexp).takeResult(),292              matchesLine(line({Chunk1, Middle, Chunk3})));293}294 295TEST_F(MacroCallReconstructorTest, StatementSequence) {296  auto Macros = createExpander({"SEMI=;"});297  Expansion Exp(Lex, *Macros);298  TokenList Call1 = Exp.expand("SEMI");299  TokenList Call2 = Exp.expand("SEMI");300  TokenList Call3 = Exp.expand("SEMI");301 302  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());303  Matcher E(Exp.getTokens(), Lex);304  Unexp.addLine(line(E.consume(";")));305  EXPECT_TRUE(Unexp.finished());306  Unexp.addLine(line(E.consume(";")));307  EXPECT_TRUE(Unexp.finished());308  Unexp.addLine(line(E.consume(";")));309  EXPECT_TRUE(Unexp.finished());310  Matcher U1(Call1, Lex);311  Matcher U2(Call2, Lex);312  Matcher U3(Call3, Lex);313  EXPECT_THAT(std::move(Unexp).takeResult(),314              matchesLine(line(315                  {U1.consume("SEMI"),316                   children({line({U2.consume("SEMI"),317                                   children({line(U3.consume("SEMI"), 2)})},318                                  1)})})));319}320 321TEST_F(MacroCallReconstructorTest, NestedBlock) {322  auto Macros = createExpander({"ID(x)=x"});323  // Test: ID({ ID(a *b); })324  // 1. expand ID(a *b) -> a *b325  Expansion Exp1(Lex, *Macros);326  TokenList Call1 = Exp1.expand("ID", {"a *b"});327  // 2. expand ID({ a *b; })328  TokenList Arg;329  Arg.push_back(Lex.id("{"));330  Arg.append(Exp1.getTokens().begin(), Exp1.getTokens().end());331  Arg.push_back(Lex.id(";"));332  Arg.push_back(Lex.id("}"));333  Expansion Exp2(Lex, *Macros);334  TokenList Call2 = Exp2.expand("ID", {Arg});335 336  // Consume as-if formatted:337  // {338  //   a *b;339  // }340  UnexpandedMap Unexpanded =341      mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded());342  MacroCallReconstructor Unexp(0, Unexpanded);343  Matcher E(Exp2.getTokens(), Lex);344  Unexp.addLine(line(E.consume("{")));345  EXPECT_FALSE(Unexp.finished());346  Unexp.addLine(line(E.consume("a *b;")));347  EXPECT_FALSE(Unexp.finished());348  Unexp.addLine(line(E.consume("}")));349  EXPECT_TRUE(Unexp.finished());350 351  // Expect lines:352  // ID({353  //   ID(a *b);354  // })355  Matcher U1(Call1, Lex);356  Matcher U2(Call2, Lex);357  auto Chunk2Start = U2.consume("ID(");358  auto Chunk2LBrace = U2.consume("{");359  U2.consume("a *b");360  auto Chunk2Mid = U2.consume(";");361  auto Chunk2RBrace = U2.consume("}");362  auto Chunk2End = U2.consume(")");363  auto Chunk1 = U1.consume("ID(a *b)");364 365  auto Expected = line({Chunk2Start,366                        children({367                            line(Chunk2LBrace, 1),368                            line({Chunk1, Chunk2Mid}, 1),369                            line(Chunk2RBrace, 1),370                        }),371                        Chunk2End});372  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));373}374 375TEST_F(MacroCallReconstructorTest, NestedChildBlocks) {376  auto Macros = createExpander({"ID(x)=x", "CALL(x)=f([] { x })"});377  // Test: ID(CALL(CALL(return a * b;)))378  // 1. expand CALL(return a * b;)379  Expansion Exp1(Lex, *Macros);380  TokenList Call1 = Exp1.expand("CALL", {"return a * b;"});381  // 2. expand CALL(f([] { return a * b; }))382  Expansion Exp2(Lex, *Macros);383  TokenList Call2 = Exp2.expand("CALL", {Exp1.getTokens()});384  // 3. expand ID({ f([] { f([] { return a * b; }) }) })385  TokenList Arg3;386  Arg3.push_back(Lex.id("{"));387  Arg3.append(Exp2.getTokens().begin(), Exp2.getTokens().end());388  Arg3.push_back(Lex.id("}"));389  Expansion Exp3(Lex, *Macros);390  TokenList Call3 = Exp3.expand("ID", {Arg3});391 392  // Consume as-if formatted in three unwrapped lines:393  // 0: {394  // 1:   f([] {395  //        f([] {396  //          return a * b;397  //        })398  //      })399  // 2: }400  UnexpandedMap Unexpanded = mergeUnexpanded(401      Exp1.getUnexpanded(),402      mergeUnexpanded(Exp2.getUnexpanded(), Exp3.getUnexpanded()));403  MacroCallReconstructor Unexp(0, Unexpanded);404  Matcher E(Exp3.getTokens(), Lex);405  Unexp.addLine(line(E.consume("{")));406  Unexp.addLine(407      line({E.consume("f([] {"),408            children({line({E.consume("f([] {"),409                            children({line(E.consume("return a * b;"), 3)}),410                            E.consume("})")},411                           2)}),412            E.consume("})")},413           1));414  Unexp.addLine(line(E.consume("}")));415  EXPECT_TRUE(Unexp.finished());416 417  // Expect lines:418  // ID(419  //   {420  //   CALL(CALL(return a * b;))421  //   }422  // )423  Matcher U1(Call1, Lex);424  Matcher U2(Call2, Lex);425  Matcher U3(Call3, Lex);426  auto Chunk3Start = U3.consume("ID(");427  auto Chunk3LBrace = U3.consume("{");428  U3.consume("f([] { f([] { return a * b; }) })");429  auto Chunk3RBrace = U3.consume("}");430  auto Chunk3End = U3.consume(")");431  auto Chunk2Start = U2.consume("CALL(");432  U2.consume("f([] { return a * b; })");433  auto Chunk2End = U2.consume(")");434  auto Chunk1 = U1.consume("CALL(return a * b;)");435 436  auto Expected = line({437      Chunk3Start,438      children({439          line(Chunk3LBrace, 1),440          line(441              {442                  Chunk2Start,443                  Chunk1,444                  Chunk2End,445              },446              2),447          line(Chunk3RBrace, 1),448      }),449      Chunk3End,450  });451  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));452}453 454TEST_F(MacroCallReconstructorTest, NestedChildrenMultipleArguments) {455  auto Macros = createExpander({"CALL(a, b)=f([] { a; b; })"});456  Expansion Exp(Lex, *Macros);457  TokenList Call = Exp.expand("CALL", {std::string("int a"), "int b"});458 459  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());460  Matcher E(Exp.getTokens(), Lex);461  Unexp.addLine(line({462      E.consume("f([] {"),463      children({464          line(E.consume("int a;")),465          line(E.consume("int b;")),466      }),467      E.consume("})"),468  }));469  EXPECT_TRUE(Unexp.finished());470  Matcher U(Call, Lex);471  auto Expected = line(U.consume("CALL(int a, int b)"));472  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));473}474 475TEST_F(MacroCallReconstructorTest, ReverseOrderArgumentsInExpansion) {476  auto Macros = createExpander({"CALL(a, b)=b + a"});477  Expansion Exp(Lex, *Macros);478  TokenList Call = Exp.expand("CALL", {std::string("x"), "y"});479 480  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());481  Matcher E(Exp.getTokens(), Lex);482  Unexp.addLine(line(E.consume("y + x")));483  EXPECT_TRUE(Unexp.finished());484  Matcher U(Call, Lex);485  auto Expected = line(U.consume("CALL(x, y)"));486  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));487}488 489TEST_F(MacroCallReconstructorTest, MultipleToplevelUnwrappedLines) {490  auto Macros = createExpander({"ID(a, b)=a b"});491  Expansion Exp(Lex, *Macros);492  TokenList Call = Exp.expand("ID", {std::string("x; x"), "y"});493 494  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());495  Matcher E(Exp.getTokens(), Lex);496  Unexp.addLine(line(E.consume("x;")));497  Unexp.addLine(line(E.consume("x y")));498  EXPECT_TRUE(Unexp.finished());499  Matcher U(Call, Lex);500  auto Expected = line({501      U.consume("ID("),502      children({503          line(U.consume("x;"), 1),504          line(U.consume("x"), 1),505      }),506      U.consume(", y)"),507  });508  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));509}510 511TEST_F(MacroCallReconstructorTest, NestedCallsMultipleLines) {512  auto Macros = createExpander({"ID(x)=x"});513  // Test: ID({ID(a * b);})514  // 1. expand ID(a * b)515  Expansion Exp1(Lex, *Macros);516  TokenList Call1 = Exp1.expand("ID", {"a * b"});517  // 2. expand ID({ a * b; })518  Expansion Exp2(Lex, *Macros);519  TokenList Arg2;520  Arg2.push_back(Lex.id("{"));521  Arg2.append(Exp1.getTokens().begin(), Exp1.getTokens().end());522  Arg2.push_back(Lex.id(";"));523  Arg2.push_back(Lex.id("}"));524  TokenList Call2 = Exp2.expand("ID", {Arg2});525 526  // Consume as-if formatted in three unwrapped lines:527  // 0: {528  // 1:   a * b;529  // 2: }530  UnexpandedMap Unexpanded =531      mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded());532  MacroCallReconstructor Unexp(0, Unexpanded);533  Matcher E(Exp2.getTokens(), Lex);534  Unexp.addLine(line(E.consume("{")));535  Unexp.addLine(line(E.consume("a * b;")));536  Unexp.addLine(line(E.consume("}")));537  EXPECT_TRUE(Unexp.finished());538 539  // Expect lines:540  // ID(541  //     {542  //     ID(a * b);543  //     }544  // )545  Matcher U1(Call1, Lex);546  Matcher U2(Call2, Lex);547  auto Chunk2Start = U2.consume("ID(");548  auto Chunk2LBrace = U2.consume("{");549  U2.consume("a * b");550  auto Chunk2Semi = U2.consume(";");551  auto Chunk2RBrace = U2.consume("}");552  auto Chunk2End = U2.consume(")");553  auto Chunk1 = U1.consume("ID(a * b)");554 555  auto Expected = line({556      Chunk2Start,557      children({558          line({Chunk2LBrace}, 1),559          line({Chunk1, Chunk2Semi}, 1),560          line({Chunk2RBrace}, 1),561      }),562      Chunk2End,563  });564  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));565}566 567TEST_F(MacroCallReconstructorTest, ParentOutsideMacroCall) {568  auto Macros = createExpander({"ID(a)=a"});569  Expansion Exp(Lex, *Macros);570  TokenList Call = Exp.expand("ID", {std::string("x; y; z;")});571 572  auto Prefix = tokens("int a = []() {");573  auto Postfix = tokens("}();");574  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());575  Matcher E(Exp.getTokens(), Lex);576  Unexp.addLine(line({577      Prefix,578      children({579          line(E.consume("x;")),580          line(E.consume("y;")),581          line(E.consume("z;")),582      }),583      Postfix,584  }));585  EXPECT_TRUE(Unexp.finished());586  Matcher U(Call, Lex);587  auto Expected = line({588      Prefix,589      children({590          line(591              {592                  U.consume("ID("),593                  children({594                      line(U.consume("x;"), 2),595                      line(U.consume("y;"), 2),596                      line(U.consume("z;"), 2),597                  }),598                  U.consume(")"),599              },600              1),601      }),602      Postfix,603  });604  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));605}606 607TEST_F(MacroCallReconstructorTest, ChildrenSplitAcrossArguments) {608  auto Macros = createExpander({"CALL(a, b)=f([]() a b)"});609  Expansion Exp(Lex, *Macros);610  TokenList Call = Exp.expand("CALL", {std::string("{ a;"), "b; }"});611 612  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());613  Matcher E(Exp.getTokens(), Lex);614  Unexp.addLine(line({615      E.consume("f([]() {"),616      children({617          line(E.consume("a;")),618          line(E.consume("b;")),619      }),620      E.consume("})"),621  }));622  EXPECT_TRUE(Unexp.finished());623  Matcher U(Call, Lex);624  auto Expected = line({625      U.consume("CALL({"),626      children(line(U.consume("a;"), 1)),627      U.consume(", b; })"),628  });629  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));630}631 632TEST_F(MacroCallReconstructorTest, ChildrenAfterMacroCall) {633  auto Macros = createExpander({"CALL(a, b)=f([]() a b"});634  Expansion Exp(Lex, *Macros);635  TokenList Call = Exp.expand("CALL", {std::string("{ a"), "b"});636 637  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());638  Matcher E(Exp.getTokens(), Lex);639  auto Semi = tokens(";");640  auto SecondLine = tokens("c d;");641  auto ThirdLine = tokens("e f;");642  auto Postfix = tokens("})");643  Unexp.addLine(line({644      E.consume("f([]() {"),645      children({646          line({E.consume("a b"), Semi}),647          line(SecondLine),648          line(ThirdLine),649      }),650      Postfix,651  }));652  EXPECT_TRUE(Unexp.finished());653  Matcher U(Call, Lex);654  auto Expected = line({655      U.consume("CALL({"),656      children(line(U.consume("a"), 1)),657      U.consume(", b)"),658      Semi,659      children(line(660          {661              SecondLine,662              children(line(663                  {664                      ThirdLine,665                      Postfix,666                  },667                  2)),668          },669          1)),670  });671  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));672}673 674TEST_F(MacroCallReconstructorTest, InvalidCodeSplittingBracesAcrossArgs) {675  auto Macros = createExpander({"M(a, b, c)=(a) (b) c"});676  Expansion Exp(Lex, *Macros);677  TokenList Call = Exp.expand("M", {std::string("{"), "x", ""});678 679  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());680  Matcher E(Exp.getTokens(), Lex);681  auto Prefix = tokens("({");682  Unexp.addLine(line({683      Prefix,684      children({685          line({686              E.consume("({"),687              children({line(E.consume(")(x)"))}),688          }),689      }),690  }));691  EXPECT_TRUE(Unexp.finished());692  Matcher U(Call, Lex);693  auto Expected = line({694      Prefix,695      children({line(U.consume("M({,x,)"), 1)}),696  });697  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));698}699 700TEST_F(MacroCallReconstructorTest, IndentLevelInExpandedCode) {701  auto Macros = createExpander({"ID(a)=a"});702  Expansion Exp(Lex, *Macros);703  TokenList Call = Exp.expand("ID", {std::string("[] { { x; } }")});704 705  MacroCallReconstructor Unexp(0, Exp.getUnexpanded());706  Matcher E(Exp.getTokens(), Lex);707  Unexp.addLine(line({708      E.consume("[] {"),709      children({710          line(E.consume("{"), 1),711          line(E.consume("x;"), 2),712          line(E.consume("}"), 1),713      }),714      E.consume("}"),715  }));716  EXPECT_TRUE(Unexp.finished());717  Matcher U(Call, Lex);718  auto Expected = line({719      U.consume("ID([] {"),720      children({721          line(U.consume("{"), 1),722          line(U.consume("x;"), 2),723          line(U.consume("}"), 1),724      }),725      U.consume("})"),726  });727  EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));728}729 730} // namespace731} // namespace format732} // namespace clang733