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 14 namespace clang { 15 namespace format { 16 namespace { 17 18 using 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 call 24 // identifier token to unexpanded token stream is accessible via 25 // getUnexpanded(). 26 class Expansion { 27 public: 28 Expansion(TestLexer &Lex, MacroExpander &Macros) : Lex(Lex), Macros(Macros) {} 29 30 // Appends the token stream obtained from expanding the macro Name given 31 // 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 48 private: 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 91 struct 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 chunk 101 // of tokens, checking that they match the written code. 102 struct 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 131 UnexpandedMap 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 141 class MacroCallReconstructorTest : public testing::Test { 142 public: 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 Result.Tokens.insert(Result.Tokens.end(), Chunk.Tokens.begin(), 169 Chunk.Tokens.end()); 170 assert(!Result.Tokens.empty()); 171 Result.Tokens.back().Children.append(Chunk.Children.begin(), 172 Chunk.Children.end()); 173 } 174 return Result; 175 } 176 177 TokenList lex(StringRef Text) { return uneof(Lex.lex(Text)); } 178 179 Chunk tokens(StringRef Text) { return Chunk(lex(Text)); } 180 181 Chunk children(ArrayRef<UnwrappedLine> Children) { return Chunk(Children); } 182 183 llvm::SpecificBumpPtrAllocator<FormatToken> Allocator; 184 std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers; 185 TestLexer Lex; 186 }; 187 188 bool matchesTokens(const UnwrappedLine &L1, const UnwrappedLine &L2) { 189 if (L1.Level != L2.Level) 190 return false; 191 if (L1.Tokens.size() != L2.Tokens.size()) 192 return false; 193 for (auto L1It = L1.Tokens.begin(), L2It = L2.Tokens.begin(); 194 L1It != L1.Tokens.end(); ++L1It, ++L2It) { 195 if (L1It->Tok != L2It->Tok) 196 return false; 197 if (L1It->Children.size() != L2It->Children.size()) 198 return false; 199 for (auto L1ChildIt = L1It->Children.begin(), 200 L2ChildIt = L2It->Children.begin(); 201 L1ChildIt != L1It->Children.end(); ++L1ChildIt, ++L2ChildIt) { 202 if (!matchesTokens(*L1ChildIt, *L2ChildIt)) 203 return false; 204 } 205 } 206 return true; 207 } 208 MATCHER_P(matchesLine, line, "") { return matchesTokens(arg, line); } 209 210 TEST_F(MacroCallReconstructorTest, Identifier) { 211 auto Macros = createExpander({"X=x"}); 212 Expansion Exp(Lex, *Macros); 213 TokenList Call = Exp.expand("X"); 214 215 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 216 Unexp.addLine(line(Exp.getTokens())); 217 EXPECT_TRUE(Unexp.finished()); 218 Matcher U(Call, Lex); 219 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(line(U.consume("X")))); 220 } 221 222 TEST_F(MacroCallReconstructorTest, EmptyDefinition) { 223 auto Macros = createExpander({"X"}); 224 Expansion Exp(Lex, *Macros); 225 TokenList Call = Exp.expand("X"); 226 227 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 228 Unexp.addLine(line(Exp.getTokens())); 229 EXPECT_TRUE(Unexp.finished()); 230 Matcher U(Call, Lex); 231 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(line(U.consume("X")))); 232 } 233 234 TEST_F(MacroCallReconstructorTest, EmptyExpansion) { 235 auto Macros = createExpander({"A(x)=x"}); 236 Expansion Exp(Lex, *Macros); 237 TokenList Call = Exp.expand("A", {""}); 238 239 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 240 Unexp.addLine(line(Exp.getTokens())); 241 EXPECT_TRUE(Unexp.finished()); 242 Matcher U(Call, Lex); 243 EXPECT_THAT(std::move(Unexp).takeResult(), 244 matchesLine(line(U.consume("A()")))); 245 } 246 247 TEST_F(MacroCallReconstructorTest, NestedLineWithinCall) { 248 auto Macros = createExpander({"C(a)=class X { a; };"}); 249 Expansion Exp(Lex, *Macros); 250 TokenList Call = Exp.expand("C", {"void f()"}); 251 252 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 253 Matcher E(Exp.getTokens(), Lex); 254 Unexp.addLine(line(E.consume("class X {"))); 255 EXPECT_FALSE(Unexp.finished()); 256 Unexp.addLine(line(E.consume("void f();"))); 257 EXPECT_FALSE(Unexp.finished()); 258 Unexp.addLine(line(E.consume("};"))); 259 EXPECT_TRUE(Unexp.finished()); 260 Matcher U(Call, Lex); 261 EXPECT_THAT(std::move(Unexp).takeResult(), 262 matchesLine(line(U.consume("C(void f())")))); 263 } 264 265 TEST_F(MacroCallReconstructorTest, MultipleLinesInNestedMultiParamsExpansion) { 266 auto Macros = createExpander({"C(a, b)=a b", "B(a)={a}"}); 267 Expansion Exp1(Lex, *Macros); 268 TokenList Call1 = Exp1.expand("B", {"b"}); 269 Expansion Exp2(Lex, *Macros); 270 TokenList Call2 = Exp2.expand("C", {uneof(Lex.lex("a")), Exp1.getTokens()}); 271 272 UnexpandedMap Unexpanded = 273 mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded()); 274 MacroCallReconstructor Unexp(0, Unexpanded); 275 Matcher E(Exp2.getTokens(), Lex); 276 Unexp.addLine(line(E.consume("a"))); 277 EXPECT_FALSE(Unexp.finished()); 278 Unexp.addLine(line(E.consume("{"))); 279 EXPECT_FALSE(Unexp.finished()); 280 Unexp.addLine(line(E.consume("b"))); 281 EXPECT_FALSE(Unexp.finished()); 282 Unexp.addLine(line(E.consume("}"))); 283 EXPECT_TRUE(Unexp.finished()); 284 285 Matcher U1(Call1, Lex); 286 auto Middle = U1.consume("B(b)"); 287 Matcher U2(Call2, Lex); 288 auto Chunk1 = U2.consume("C(a, "); 289 auto Chunk2 = U2.consume("{ b }"); 290 auto Chunk3 = U2.consume(")"); 291 292 EXPECT_THAT(std::move(Unexp).takeResult(), 293 matchesLine(line({Chunk1, Middle, Chunk3}))); 294 } 295 296 TEST_F(MacroCallReconstructorTest, StatementSequence) { 297 auto Macros = createExpander({"SEMI=;"}); 298 Expansion Exp(Lex, *Macros); 299 TokenList Call1 = Exp.expand("SEMI"); 300 TokenList Call2 = Exp.expand("SEMI"); 301 TokenList Call3 = Exp.expand("SEMI"); 302 303 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 304 Matcher E(Exp.getTokens(), Lex); 305 Unexp.addLine(line(E.consume(";"))); 306 EXPECT_TRUE(Unexp.finished()); 307 Unexp.addLine(line(E.consume(";"))); 308 EXPECT_TRUE(Unexp.finished()); 309 Unexp.addLine(line(E.consume(";"))); 310 EXPECT_TRUE(Unexp.finished()); 311 Matcher U1(Call1, Lex); 312 Matcher U2(Call2, Lex); 313 Matcher U3(Call3, Lex); 314 EXPECT_THAT(std::move(Unexp).takeResult(), 315 matchesLine(line( 316 {U1.consume("SEMI"), 317 children({line({U2.consume("SEMI"), 318 children({line(U3.consume("SEMI"), 2)})}, 319 1)})}))); 320 } 321 322 TEST_F(MacroCallReconstructorTest, NestedBlock) { 323 auto Macros = createExpander({"ID(x)=x"}); 324 // Test: ID({ ID(a *b); }) 325 // 1. expand ID(a *b) -> a *b 326 Expansion Exp1(Lex, *Macros); 327 TokenList Call1 = Exp1.expand("ID", {"a *b"}); 328 // 2. expand ID({ a *b; }) 329 TokenList Arg; 330 Arg.push_back(Lex.id("{")); 331 Arg.append(Exp1.getTokens().begin(), Exp1.getTokens().end()); 332 Arg.push_back(Lex.id(";")); 333 Arg.push_back(Lex.id("}")); 334 Expansion Exp2(Lex, *Macros); 335 TokenList Call2 = Exp2.expand("ID", {Arg}); 336 337 // Consume as-if formatted: 338 // { 339 // a *b; 340 // } 341 UnexpandedMap Unexpanded = 342 mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded()); 343 MacroCallReconstructor Unexp(0, Unexpanded); 344 Matcher E(Exp2.getTokens(), Lex); 345 Unexp.addLine(line(E.consume("{"))); 346 EXPECT_FALSE(Unexp.finished()); 347 Unexp.addLine(line(E.consume("a *b;"))); 348 EXPECT_FALSE(Unexp.finished()); 349 Unexp.addLine(line(E.consume("}"))); 350 EXPECT_TRUE(Unexp.finished()); 351 352 // Expect lines: 353 // ID({ 354 // ID(a *b); 355 // }) 356 Matcher U1(Call1, Lex); 357 Matcher U2(Call2, Lex); 358 auto Chunk2Start = U2.consume("ID("); 359 auto Chunk2LBrace = U2.consume("{"); 360 U2.consume("a *b"); 361 auto Chunk2Mid = U2.consume(";"); 362 auto Chunk2RBrace = U2.consume("}"); 363 auto Chunk2End = U2.consume(")"); 364 auto Chunk1 = U1.consume("ID(a *b)"); 365 366 auto Expected = line({Chunk2Start, 367 children({ 368 line(Chunk2LBrace, 1), 369 line({Chunk1, Chunk2Mid}, 1), 370 line(Chunk2RBrace, 1), 371 }), 372 Chunk2End}); 373 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 374 } 375 376 TEST_F(MacroCallReconstructorTest, NestedChildBlocks) { 377 auto Macros = createExpander({"ID(x)=x", "CALL(x)=f([] { x })"}); 378 // Test: ID(CALL(CALL(return a * b;))) 379 // 1. expand CALL(return a * b;) 380 Expansion Exp1(Lex, *Macros); 381 TokenList Call1 = Exp1.expand("CALL", {"return a * b;"}); 382 // 2. expand CALL(f([] { return a * b; })) 383 Expansion Exp2(Lex, *Macros); 384 TokenList Call2 = Exp2.expand("CALL", {Exp1.getTokens()}); 385 // 3. expand ID({ f([] { f([] { return a * b; }) }) }) 386 TokenList Arg3; 387 Arg3.push_back(Lex.id("{")); 388 Arg3.append(Exp2.getTokens().begin(), Exp2.getTokens().end()); 389 Arg3.push_back(Lex.id("}")); 390 Expansion Exp3(Lex, *Macros); 391 TokenList Call3 = Exp3.expand("ID", {Arg3}); 392 393 // Consume as-if formatted in three unwrapped lines: 394 // 0: { 395 // 1: f([] { 396 // f([] { 397 // return a * b; 398 // }) 399 // }) 400 // 2: } 401 UnexpandedMap Unexpanded = mergeUnexpanded( 402 Exp1.getUnexpanded(), 403 mergeUnexpanded(Exp2.getUnexpanded(), Exp3.getUnexpanded())); 404 MacroCallReconstructor Unexp(0, Unexpanded); 405 Matcher E(Exp3.getTokens(), Lex); 406 Unexp.addLine(line(E.consume("{"))); 407 Unexp.addLine( 408 line({E.consume("f([] {"), 409 children({line({E.consume("f([] {"), 410 children({line(E.consume("return a * b;"), 3)}), 411 E.consume("})")}, 412 2)}), 413 E.consume("})")}, 414 1)); 415 Unexp.addLine(line(E.consume("}"))); 416 EXPECT_TRUE(Unexp.finished()); 417 418 // Expect lines: 419 // ID( 420 // { 421 // CALL(CALL(return a * b;)) 422 // } 423 // ) 424 Matcher U1(Call1, Lex); 425 Matcher U2(Call2, Lex); 426 Matcher U3(Call3, Lex); 427 auto Chunk3Start = U3.consume("ID("); 428 auto Chunk3LBrace = U3.consume("{"); 429 U3.consume("f([] { f([] { return a * b; }) })"); 430 auto Chunk3RBrace = U3.consume("}"); 431 auto Chunk3End = U3.consume(")"); 432 auto Chunk2Start = U2.consume("CALL("); 433 U2.consume("f([] { return a * b; })"); 434 auto Chunk2End = U2.consume(")"); 435 auto Chunk1 = U1.consume("CALL(return a * b;)"); 436 437 auto Expected = line({ 438 Chunk3Start, 439 children({ 440 line(Chunk3LBrace, 1), 441 line( 442 { 443 Chunk2Start, 444 Chunk1, 445 Chunk2End, 446 }, 447 2), 448 line(Chunk3RBrace, 1), 449 }), 450 Chunk3End, 451 }); 452 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 453 } 454 455 TEST_F(MacroCallReconstructorTest, NestedChildrenMultipleArguments) { 456 auto Macros = createExpander({"CALL(a, b)=f([] { a; b; })"}); 457 Expansion Exp(Lex, *Macros); 458 TokenList Call = Exp.expand("CALL", {std::string("int a"), "int b"}); 459 460 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 461 Matcher E(Exp.getTokens(), Lex); 462 Unexp.addLine(line({ 463 E.consume("f([] {"), 464 children({ 465 line(E.consume("int a;")), 466 line(E.consume("int b;")), 467 }), 468 E.consume("})"), 469 })); 470 EXPECT_TRUE(Unexp.finished()); 471 Matcher U(Call, Lex); 472 auto Expected = line(U.consume("CALL(int a, int b)")); 473 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 474 } 475 476 TEST_F(MacroCallReconstructorTest, ReverseOrderArgumentsInExpansion) { 477 auto Macros = createExpander({"CALL(a, b)=b + a"}); 478 Expansion Exp(Lex, *Macros); 479 TokenList Call = Exp.expand("CALL", {std::string("x"), "y"}); 480 481 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 482 Matcher E(Exp.getTokens(), Lex); 483 Unexp.addLine(line(E.consume("y + x"))); 484 EXPECT_TRUE(Unexp.finished()); 485 Matcher U(Call, Lex); 486 auto Expected = line(U.consume("CALL(x, y)")); 487 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 488 } 489 490 TEST_F(MacroCallReconstructorTest, MultipleToplevelUnwrappedLines) { 491 auto Macros = createExpander({"ID(a, b)=a b"}); 492 Expansion Exp(Lex, *Macros); 493 TokenList Call = Exp.expand("ID", {std::string("x; x"), "y"}); 494 495 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 496 Matcher E(Exp.getTokens(), Lex); 497 Unexp.addLine(line(E.consume("x;"))); 498 Unexp.addLine(line(E.consume("x y"))); 499 EXPECT_TRUE(Unexp.finished()); 500 Matcher U(Call, Lex); 501 auto Expected = line({ 502 U.consume("ID("), 503 children({ 504 line(U.consume("x;"), 1), 505 line(U.consume("x"), 1), 506 }), 507 U.consume(", y)"), 508 }); 509 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 510 } 511 512 TEST_F(MacroCallReconstructorTest, NestedCallsMultipleLines) { 513 auto Macros = createExpander({"ID(x)=x"}); 514 // Test: ID({ID(a * b);}) 515 // 1. expand ID(a * b) 516 Expansion Exp1(Lex, *Macros); 517 TokenList Call1 = Exp1.expand("ID", {"a * b"}); 518 // 2. expand ID({ a * b; }) 519 Expansion Exp2(Lex, *Macros); 520 TokenList Arg2; 521 Arg2.push_back(Lex.id("{")); 522 Arg2.append(Exp1.getTokens().begin(), Exp1.getTokens().end()); 523 Arg2.push_back(Lex.id(";")); 524 Arg2.push_back(Lex.id("}")); 525 TokenList Call2 = Exp2.expand("ID", {Arg2}); 526 527 // Consume as-if formatted in three unwrapped lines: 528 // 0: { 529 // 1: a * b; 530 // 2: } 531 UnexpandedMap Unexpanded = 532 mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded()); 533 MacroCallReconstructor Unexp(0, Unexpanded); 534 Matcher E(Exp2.getTokens(), Lex); 535 Unexp.addLine(line(E.consume("{"))); 536 Unexp.addLine(line(E.consume("a * b;"))); 537 Unexp.addLine(line(E.consume("}"))); 538 EXPECT_TRUE(Unexp.finished()); 539 540 // Expect lines: 541 // ID( 542 // { 543 // ID(a * b); 544 // } 545 // ) 546 Matcher U1(Call1, Lex); 547 Matcher U2(Call2, Lex); 548 auto Chunk2Start = U2.consume("ID("); 549 auto Chunk2LBrace = U2.consume("{"); 550 U2.consume("a * b"); 551 auto Chunk2Semi = U2.consume(";"); 552 auto Chunk2RBrace = U2.consume("}"); 553 auto Chunk2End = U2.consume(")"); 554 auto Chunk1 = U1.consume("ID(a * b)"); 555 556 auto Expected = line({ 557 Chunk2Start, 558 children({ 559 line({Chunk2LBrace}, 1), 560 line({Chunk1, Chunk2Semi}, 1), 561 line({Chunk2RBrace}, 1), 562 }), 563 Chunk2End, 564 }); 565 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 566 } 567 568 TEST_F(MacroCallReconstructorTest, ParentOutsideMacroCall) { 569 auto Macros = createExpander({"ID(a)=a"}); 570 Expansion Exp(Lex, *Macros); 571 TokenList Call = Exp.expand("ID", {std::string("x; y; z;")}); 572 573 auto Prefix = tokens("int a = []() {"); 574 auto Postfix = tokens("}();"); 575 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 576 Matcher E(Exp.getTokens(), Lex); 577 Unexp.addLine(line({ 578 Prefix, 579 children({ 580 line(E.consume("x;")), 581 line(E.consume("y;")), 582 line(E.consume("z;")), 583 }), 584 Postfix, 585 })); 586 EXPECT_TRUE(Unexp.finished()); 587 Matcher U(Call, Lex); 588 auto Expected = line({ 589 Prefix, 590 children({ 591 line( 592 { 593 U.consume("ID("), 594 children({ 595 line(U.consume("x;"), 2), 596 line(U.consume("y;"), 2), 597 line(U.consume("z;"), 2), 598 }), 599 U.consume(")"), 600 }, 601 1), 602 }), 603 Postfix, 604 }); 605 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 606 } 607 608 TEST_F(MacroCallReconstructorTest, ChildrenSplitAcrossArguments) { 609 auto Macros = createExpander({"CALL(a, b)=f([]() a b)"}); 610 Expansion Exp(Lex, *Macros); 611 TokenList Call = Exp.expand("CALL", {std::string("{ a;"), "b; }"}); 612 613 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 614 Matcher E(Exp.getTokens(), Lex); 615 Unexp.addLine(line({ 616 E.consume("f([]() {"), 617 children({ 618 line(E.consume("a;")), 619 line(E.consume("b;")), 620 }), 621 E.consume("})"), 622 })); 623 EXPECT_TRUE(Unexp.finished()); 624 Matcher U(Call, Lex); 625 auto Expected = line({ 626 U.consume("CALL({"), 627 children(line(U.consume("a;"), 1)), 628 U.consume(", b; })"), 629 }); 630 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 631 } 632 633 TEST_F(MacroCallReconstructorTest, ChildrenAfterMacroCall) { 634 auto Macros = createExpander({"CALL(a, b)=f([]() a b"}); 635 Expansion Exp(Lex, *Macros); 636 TokenList Call = Exp.expand("CALL", {std::string("{ a"), "b"}); 637 638 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 639 Matcher E(Exp.getTokens(), Lex); 640 auto Semi = tokens(";"); 641 auto SecondLine = tokens("c d;"); 642 auto ThirdLine = tokens("e f;"); 643 auto Postfix = tokens("})"); 644 Unexp.addLine(line({ 645 E.consume("f([]() {"), 646 children({ 647 line({E.consume("a b"), Semi}), 648 line(SecondLine), 649 line(ThirdLine), 650 }), 651 Postfix, 652 })); 653 EXPECT_TRUE(Unexp.finished()); 654 Matcher U(Call, Lex); 655 auto Expected = line({ 656 U.consume("CALL({"), 657 children(line(U.consume("a"), 1)), 658 U.consume(", b)"), 659 Semi, 660 children(line( 661 { 662 SecondLine, 663 children(line( 664 { 665 ThirdLine, 666 Postfix, 667 }, 668 2)), 669 }, 670 1)), 671 }); 672 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 673 } 674 675 TEST_F(MacroCallReconstructorTest, InvalidCodeSplittingBracesAcrossArgs) { 676 auto Macros = createExpander({"M(a, b, c)=(a) (b) c"}); 677 Expansion Exp(Lex, *Macros); 678 TokenList Call = Exp.expand("M", {std::string("{"), "x", ""}); 679 680 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 681 Matcher E(Exp.getTokens(), Lex); 682 auto Prefix = tokens("({"); 683 Unexp.addLine(line({ 684 Prefix, 685 children({ 686 line({ 687 E.consume("({"), 688 children({line(E.consume(")(x)"))}), 689 }), 690 }), 691 })); 692 EXPECT_TRUE(Unexp.finished()); 693 Matcher U(Call, Lex); 694 auto Expected = line({ 695 Prefix, 696 children({line(U.consume("M({,x,)"), 1)}), 697 }); 698 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 699 } 700 701 TEST_F(MacroCallReconstructorTest, IndentLevelInExpandedCode) { 702 auto Macros = createExpander({"ID(a)=a"}); 703 Expansion Exp(Lex, *Macros); 704 TokenList Call = Exp.expand("ID", {std::string("[] { { x; } }")}); 705 706 MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); 707 Matcher E(Exp.getTokens(), Lex); 708 Unexp.addLine(line({ 709 E.consume("[] {"), 710 children({ 711 line(E.consume("{"), 1), 712 line(E.consume("x;"), 2), 713 line(E.consume("}"), 1), 714 }), 715 E.consume("}"), 716 })); 717 EXPECT_TRUE(Unexp.finished()); 718 Matcher U(Call, Lex); 719 auto Expected = line({ 720 U.consume("ID([] {"), 721 children({ 722 line(U.consume("{"), 1), 723 line(U.consume("x;"), 2), 724 line(U.consume("}"), 1), 725 }), 726 U.consume("})"), 727 }); 728 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected)); 729 } 730 731 } // namespace 732 } // namespace format 733 } // namespace clang 734