NoUselessElseFixerTest.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of PHP CS Fixer.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. namespace PhpCsFixer\Tests\Fixer\ControlStructure;
  13. use PhpCsFixer\AbstractNoUselessElseFixer;
  14. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  15. use PhpCsFixer\Tokenizer\Tokens;
  16. /**
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\AbstractNoUselessElseFixer
  20. * @covers \PhpCsFixer\Fixer\ControlStructure\NoUselessElseFixer
  21. *
  22. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\ControlStructure\NoUselessElseFixer>
  23. */
  24. final class NoUselessElseFixerTest extends AbstractFixerTestCase
  25. {
  26. /**
  27. * @dataProvider provideCloseTagCases
  28. */
  29. public function testCloseTag(string $expected, ?string $input = null): void
  30. {
  31. $this->doTest($expected, $input);
  32. }
  33. /**
  34. * @return iterable<array{0: string, 1?: string}>
  35. */
  36. public static function provideCloseTagCases(): iterable
  37. {
  38. yield [
  39. '<?php
  40. if (true) {
  41. $b = $a > 2 ? "" : die
  42. ?>
  43. <?php
  44. } else {
  45. echo 798;
  46. }',
  47. ];
  48. yield [
  49. '<?php
  50. if (true) {
  51. $b = $a > 2 ? "" : die
  52. ?>
  53. <?php ; // useless semicolon case
  54. } else {
  55. echo 798;
  56. }',
  57. ];
  58. yield [
  59. '<?php
  60. if (true) {
  61. if($a) die
  62. ?>
  63. <?php ; // useless semicolon case
  64. } else {
  65. echo 798;
  66. }',
  67. ];
  68. yield [
  69. '<?php
  70. if (true) {
  71. echo 1;
  72. ?>
  73. <?php ; // useless semicolon case
  74. } else {
  75. echo 798;
  76. }',
  77. ];
  78. yield [
  79. '<?php
  80. if (true) {
  81. echo 777;
  82. if(false) die ?>
  83. <?php
  84. } else {
  85. echo 778;
  86. }',
  87. ];
  88. yield [
  89. '<?php
  90. if (true)
  91. echo 3;
  92. else {
  93. ?><?php
  94. echo 4;
  95. }
  96. ',
  97. ];
  98. yield [
  99. '<?php
  100. if (true)
  101. echo 3;
  102. '.'
  103. ?><?php
  104. echo 4;
  105. ',
  106. '<?php
  107. if (true)
  108. echo 3;
  109. else
  110. ?><?php
  111. echo 4;
  112. ',
  113. ];
  114. yield [
  115. '<?php
  116. if (true)
  117. echo 4;
  118. ?><?php echo 5;',
  119. '<?php
  120. if (true)
  121. echo 4;
  122. else?><?php echo 5;',
  123. ];
  124. }
  125. /**
  126. * @dataProvider provideFixIfElseIfElseCases
  127. */
  128. public function testFixIfElseIfElse(string $expected, ?string $input = null): void
  129. {
  130. $this->doTest($expected, $input);
  131. }
  132. /**
  133. * @return iterable<array{0: string, 1?: string}>
  134. */
  135. public static function provideFixIfElseIfElseCases(): iterable
  136. {
  137. $expected =
  138. '<?php
  139. while(true) {
  140. while(true) {
  141. if ($provideFixIfElseIfElseCases) {
  142. return;
  143. } elseif($a1) {
  144. if ($b) {echo 1; die;} echo 552;
  145. return 1;
  146. } elseif($b) {
  147. %s
  148. } '.'
  149. echo 662;
  150. '.'
  151. }
  152. }
  153. ';
  154. $input =
  155. '<?php
  156. while(true) {
  157. while(true) {
  158. if ($provideFixIfElseIfElseCases) {
  159. return;
  160. } elseif($a1) {
  161. if ($b) {echo 1; die;} else {echo 552;}
  162. return 1;
  163. } elseif($b) {
  164. %s
  165. } else {
  166. echo 662;
  167. }
  168. }
  169. }
  170. ';
  171. yield from self::generateCases($expected, $input);
  172. $expected =
  173. '<?php
  174. while(true) {
  175. while(true) {
  176. if($a) {
  177. echo 100;
  178. } elseif($b) {
  179. %s
  180. } else {
  181. echo 3;
  182. }
  183. }
  184. }
  185. ';
  186. yield from self::generateCases($expected);
  187. $expected =
  188. '<?php
  189. while(true) {
  190. while(true) {
  191. if ($a) {
  192. echo 100;
  193. } elseif ($a1) {
  194. echo 99887;
  195. } elseif ($b) {
  196. echo $b+1; //
  197. /* test */
  198. %s
  199. } else {
  200. echo 321;
  201. }
  202. }
  203. }
  204. ';
  205. yield from self::generateCases($expected);
  206. yield [
  207. '<?php
  208. if ($a)
  209. echo 1789;
  210. else if($b)
  211. echo 256;
  212. elseif($c)
  213. echo 3;
  214. if ($a) {
  215. }elseif($d) {
  216. return 1;
  217. }
  218. else
  219. echo 4;
  220. ',
  221. ];
  222. yield [
  223. '<?php
  224. if ($a)
  225. echo 1789;
  226. else if($b) {
  227. echo 256;
  228. } elseif($c) {
  229. echo 3;
  230. if ($d) {
  231. echo 4;
  232. } elseif($e)
  233. return 1;
  234. } else
  235. echo 4;
  236. ',
  237. ];
  238. }
  239. /**
  240. * @dataProvider provideFixIfElseCases
  241. */
  242. public function testFixIfElse(string $expected, ?string $input = null): void
  243. {
  244. $this->doTest($expected, $input);
  245. }
  246. /**
  247. * @return iterable<array{0: string, 1?: string}>
  248. */
  249. public static function provideFixIfElseCases(): iterable
  250. {
  251. $expected = '<?php
  252. while(true) {
  253. while(true) {
  254. if ($a) {
  255. %s
  256. } '.'
  257. echo 1;
  258. '.'
  259. }
  260. }
  261. ';
  262. $input = '<?php
  263. while(true) {
  264. while(true) {
  265. if ($a) {
  266. %s
  267. } else {
  268. echo 1;
  269. }
  270. }
  271. }
  272. ';
  273. yield from self::generateCases($expected, $input);
  274. yield [
  275. '<?php
  276. if ($a) {
  277. GOTO jump;
  278. } '.'
  279. echo 1789;
  280. '.'
  281. jump:
  282. ',
  283. '<?php
  284. if ($a) {
  285. GOTO jump;
  286. } else {
  287. echo 1789;
  288. }
  289. jump:
  290. ',
  291. ];
  292. }
  293. /**
  294. * @dataProvider provideFixNestedIfCases
  295. */
  296. public function testFixNestedIf(string $expected, ?string $input = null): void
  297. {
  298. $this->doTest($expected, $input);
  299. }
  300. /**
  301. * @return iterable<array{string, string}>
  302. */
  303. public static function provideFixNestedIfCases(): iterable
  304. {
  305. yield [
  306. '<?php
  307. if ($x) {
  308. if ($y) {
  309. return 1;
  310. } '.'
  311. return 2;
  312. '.'
  313. } '.'
  314. return 3;
  315. '.'
  316. ',
  317. '<?php
  318. if ($x) {
  319. if ($y) {
  320. return 1;
  321. } else {
  322. return 2;
  323. }
  324. } else {
  325. return 3;
  326. }
  327. ',
  328. ];
  329. }
  330. /**
  331. * @dataProvider provideFixEmptyElseCases
  332. */
  333. public function testFixEmptyElse(string $expected, ?string $input = null): void
  334. {
  335. $this->doTest($expected, $input);
  336. }
  337. /**
  338. * @return iterable<array{string, string}>
  339. */
  340. public static function provideFixEmptyElseCases(): iterable
  341. {
  342. yield [
  343. '<?php
  344. if (false)
  345. echo 1;
  346. '.'
  347. ',
  348. '<?php
  349. if (false)
  350. echo 1;
  351. else{}
  352. ',
  353. ];
  354. yield [
  355. '<?php if($a){}',
  356. '<?php if($a){}else{}',
  357. ];
  358. yield [
  359. '<?php if($a){ $a = ($b); } ',
  360. '<?php if($a){ $a = ($b); } else {}',
  361. ];
  362. yield [
  363. '<?php if ($a) {;} if ($a) {;} /**/ if($a){}',
  364. '<?php if ($a) {;} else {} if ($a) {;} else {/**/} if($a){}else{}',
  365. ];
  366. yield [
  367. '<?php
  368. if /**/($a) /**/{ //
  369. /**/
  370. /**/return/**/1/**/;
  371. //
  372. }/**/ /**/
  373. /**/
  374. //
  375. /**/
  376. ',
  377. '<?php
  378. if /**/($a) /**/{ //
  379. /**/
  380. /**/return/**/1/**/;
  381. //
  382. }/**/ else /**/{
  383. /**/
  384. //
  385. }/**/
  386. ',
  387. ];
  388. yield [
  389. '<?php
  390. if ($a) {
  391. if ($b) {
  392. if ($c) {
  393. } elseif ($d) {
  394. return;
  395. } //
  396. //
  397. return;
  398. } //
  399. //
  400. return;
  401. } //
  402. //
  403. ',
  404. '<?php
  405. if ($a) {
  406. if ($b) {
  407. if ($c) {
  408. } elseif ($d) {
  409. return;
  410. } else {//
  411. }//
  412. return;
  413. } else {//
  414. }//
  415. return;
  416. } else {//
  417. }//
  418. ',
  419. ];
  420. }
  421. /**
  422. * @dataProvider provideNegativeCases
  423. */
  424. public function testNegative(string $expected): void
  425. {
  426. $this->doTest($expected);
  427. }
  428. /**
  429. * @return iterable<array{string}>
  430. */
  431. public static function provideNegativeCases(): iterable
  432. {
  433. yield [
  434. '<?php
  435. if ($a0) {
  436. //
  437. } else {
  438. echo 0;
  439. }
  440. ',
  441. ];
  442. yield [
  443. '<?php
  444. if (false)
  445. echo "a";
  446. else
  447. echo "a";
  448. ',
  449. ];
  450. yield [
  451. '<?php if($a2){;} else {echo 27;}',
  452. ];
  453. yield [
  454. '<?php if ($a3) {test();} else {echo 3;}',
  455. ];
  456. yield [
  457. '<?php if ($a4) {$b = function () {};} else {echo 4;}',
  458. ];
  459. yield [
  460. '<?php if ($a5) {$b = function () use ($a){};} else {echo 5;}',
  461. ];
  462. yield [
  463. '<?php
  464. if ($a) {
  465. if ($b) return;
  466. } else {
  467. echo 1;
  468. }
  469. ',
  470. ];
  471. yield [
  472. '<?php
  473. if ($a) {
  474. if ($b) throw new \Exception();
  475. } else {
  476. echo 1;
  477. }
  478. ',
  479. ];
  480. yield [
  481. '<?php
  482. if ($a) {
  483. if ($b) { throw new \Exception(); }
  484. } else {
  485. echo 1;
  486. }
  487. ',
  488. ];
  489. yield [
  490. '<?php
  491. $a = true; // 6
  492. if (true === $a)
  493. $b = true === $a ? 1 : die;
  494. else
  495. echo 40;
  496. echo "end";
  497. ',
  498. ];
  499. yield [
  500. '<?php
  501. $a = true; // 6
  502. if (true === $a)
  503. $b = true === $a ? 1 : exit(1);
  504. else
  505. echo 40;
  506. echo "end";
  507. ',
  508. ];
  509. yield [
  510. '<?php
  511. $a = true; // 6
  512. if (true === $a)
  513. $b = true === $a ? 1 : exit(1);
  514. else
  515. echo 4;
  516. echo "end";
  517. ',
  518. ];
  519. yield [
  520. '<?php
  521. if (false)
  522. die;
  523. elseif (true)
  524. if(true)echo 777;else die;
  525. else if (true)
  526. die;
  527. elseif (false)
  528. die;
  529. else
  530. echo 7;
  531. ',
  532. ];
  533. yield [
  534. '<?php
  535. $tmp = function($b){$b();};
  536. $a =1;
  537. return $tmp(function () use ($a) {
  538. if ($a) {
  539. $a++;
  540. } else {
  541. $a--;
  542. }
  543. });
  544. ',
  545. ];
  546. yield [
  547. '<?php
  548. $tmp = function($b){$b();};
  549. $a =1;
  550. return $tmp(function () use ($a) {
  551. if ($a) {
  552. $a++;
  553. } elseif($a > 2) {
  554. return 1;
  555. } else {
  556. $a--;
  557. }
  558. });
  559. ',
  560. ];
  561. yield [
  562. '<?php
  563. return function() {
  564. if (false) {
  565. } elseif (3 > 2) {
  566. } else {
  567. echo 1;
  568. }
  569. };',
  570. ];
  571. yield [
  572. '<?php
  573. return function() {
  574. if (false) {
  575. return 1;
  576. } elseif (3 > 2) {
  577. } else {
  578. echo 1;
  579. }
  580. };',
  581. ];
  582. }
  583. /**
  584. * @dataProvider provideNegativePhp80Cases
  585. *
  586. * @requires PHP 8.0
  587. */
  588. public function testNegativePhp80(string $expected): void
  589. {
  590. $this->doTest($expected);
  591. }
  592. /**
  593. * @return iterable<string, array{string}>
  594. */
  595. public static function provideNegativePhp80Cases(): iterable
  596. {
  597. $cases = [
  598. '$bar = $foo1 ?? throw new \Exception($e);',
  599. '$callable = fn() => throw new Exception();',
  600. '$value = $falsableValue ?: throw new InvalidArgumentException();',
  601. '$value = !empty($array)
  602. ? reset($array)
  603. : throw new InvalidArgumentException();',
  604. '$a = $condition && throw new Exception();',
  605. '$a = $condition || throw new Exception();',
  606. '$a = $condition and throw new Exception();',
  607. '$a = $condition or throw new Exception();',
  608. ];
  609. $template = '<?php
  610. if ($foo) {
  611. %s
  612. } else {
  613. echo 123;
  614. }
  615. ';
  616. foreach ($cases as $index => $case) {
  617. yield \sprintf('PHP8 Negative case %d', $index) => [\sprintf($template, $case)];
  618. }
  619. }
  620. /**
  621. * @param list<int> $expected
  622. *
  623. * @dataProvider provideBlockDetectionCases
  624. */
  625. public function testBlockDetection(array $expected, string $source, int $index): void
  626. {
  627. Tokens::clearCache();
  628. $tokens = Tokens::fromCode($source);
  629. $result = \Closure::bind(static fn (AbstractNoUselessElseFixer $fixer): array => $fixer->getPreviousBlock($tokens, $index), null, AbstractNoUselessElseFixer::class)($this->fixer);
  630. self::assertSame($expected, $result);
  631. }
  632. public static function provideBlockDetectionCases(): iterable
  633. {
  634. $source = '<?php
  635. if ($a)
  636. echo 1;
  637. elseif ($a) ///
  638. echo 2;
  639. else if ($b) /**/ echo 3;
  640. else
  641. echo 4;
  642. ';
  643. yield [[2, 11], $source, 13];
  644. yield [[13, 24], $source, 26];
  645. yield [[26, 39], $source, 41];
  646. $source = '<?php
  647. if ($a) {
  648. if ($b) {
  649. }
  650. echo 1;
  651. } elseif (true) {
  652. echo 2;
  653. } else if (false) {
  654. echo 3;
  655. } elseif ($c) {
  656. echo 4;
  657. } else
  658. echo 1;
  659. ';
  660. yield [[2, 25], $source, 27];
  661. yield [[27, 40], $source, 42];
  662. yield [[59, 72], $source, 74];
  663. }
  664. /**
  665. * @dataProvider provideConditionsWithoutBracesCases
  666. */
  667. public function testConditionsWithoutBraces(string $expected, ?string $input = null): void
  668. {
  669. $this->doTest($expected, $input);
  670. }
  671. /**
  672. * @return iterable<array{0: string, 1?: string}>
  673. */
  674. public static function provideConditionsWithoutBracesCases(): iterable
  675. {
  676. $statements = [
  677. 'die;',
  678. 'throw new Exception($i);',
  679. 'while($i < 1) throw/*{}*/new Exception($i);',
  680. 'while($i < 1){throw new Exception($i);}',
  681. 'do{throw new Exception($i);}while($i < 1);',
  682. 'foreach($a as $b)throw new Exception($i);',
  683. 'foreach($a as $b){throw new Exception($i);}',
  684. ];
  685. foreach ($statements as $statement) {
  686. yield from self::generateConditionsWithoutBracesCase($statement);
  687. }
  688. yield [
  689. '<?php
  690. if ($a === false)
  691. {
  692. if ($v) { $ret = "foo"; if($d){return 1;}echo $a;}
  693. }
  694. else
  695. $ret .= $value;
  696. return $ret;',
  697. '<?php
  698. if ($a === false)
  699. {
  700. if ($v) { $ret = "foo"; if($d){return 1;}else{echo $a;}}
  701. }
  702. else
  703. $ret .= $value;
  704. return $ret;',
  705. ];
  706. yield from self::generateConditionsWithoutBracesCase('throw new class extends Exception{};');
  707. yield from self::generateConditionsWithoutBracesCase('throw new class ($a, 9) extends Exception{ public function z($a, $b){ echo 7;} };');
  708. }
  709. /**
  710. * @dataProvider provideConditionsWithoutBraces80Cases
  711. *
  712. * @requires PHP 8.0
  713. */
  714. public function testConditionsWithoutBraces80(string $expected): void
  715. {
  716. $this->doTest($expected);
  717. }
  718. /**
  719. * @return iterable<array{string}>
  720. */
  721. public static function provideConditionsWithoutBraces80Cases(): iterable
  722. {
  723. yield from self::generateConditionsWithoutBracesCase('$b = $a ?? throw new Exception($i);');
  724. }
  725. /**
  726. * @param array<int, bool> $indexes
  727. *
  728. * @dataProvider provideIsInConditionWithoutBracesCases
  729. */
  730. public function testIsInConditionWithoutBraces(array $indexes, string $input): void
  731. {
  732. $tokens = Tokens::fromCode($input);
  733. foreach ($indexes as $index => $expected) {
  734. self::assertSame(
  735. $expected,
  736. \Closure::bind(static fn (AbstractNoUselessElseFixer $fixer): bool => $fixer->isInConditionWithoutBraces($tokens, $index, 0), null, AbstractNoUselessElseFixer::class)($this->fixer),
  737. \sprintf('Failed in condition without braces check for index %d', $index)
  738. );
  739. }
  740. }
  741. public static function provideIsInConditionWithoutBracesCases(): iterable
  742. {
  743. yield [
  744. [
  745. 18 => false, // return
  746. 25 => false, // return
  747. 36 => false, // return
  748. ],
  749. '<?php
  750. if ($x) {
  751. if ($y) {
  752. return 1;
  753. }
  754. return 2;
  755. } else {
  756. return 3;
  757. }
  758. ',
  759. ];
  760. yield [
  761. [
  762. 0 => false,
  763. 29 => false, // throw
  764. ],
  765. '<?php
  766. if ($v) { $ret = "foo"; }
  767. else
  768. if($a){}else{throw new Exception($i);}
  769. ',
  770. ];
  771. yield [
  772. [
  773. 0 => false,
  774. 38 => true, // throw
  775. ],
  776. '<?php
  777. if ($v) { $ret = "foo"; }
  778. else
  779. for($i =0;$i < 1;++$i) throw new Exception($i);
  780. ',
  781. ];
  782. yield [
  783. [
  784. 0 => false,
  785. 26 => true, // throw
  786. 28 => true, // new
  787. 30 => true, // Exception
  788. ],
  789. '<?php
  790. if ($v) { $ret = "foo"; }
  791. else
  792. while(false){throw new Exception($i);}
  793. ',
  794. ];
  795. yield [
  796. [
  797. 0 => false,
  798. 30 => true, // throw
  799. 32 => true, // new
  800. 34 => true, // Exception
  801. ],
  802. '<?php
  803. if ($v) { $ret = "foo"; }
  804. else
  805. foreach($a as $b){throw new Exception($i);}
  806. ',
  807. ];
  808. yield [
  809. [
  810. 0 => false,
  811. 25 => true, // throw
  812. 27 => true, // new
  813. 29 => true, // Exception
  814. ],
  815. '<?php
  816. if ($v) { $ret = "foo"; }
  817. else
  818. while(false)throw new Exception($i);
  819. ',
  820. ];
  821. yield [
  822. [
  823. 26 => true, // throw
  824. ],
  825. '<?php
  826. if ($v) { $ret = "foo"; }
  827. elseif($a)
  828. do{throw new Exception($i);}while(false);
  829. ',
  830. ];
  831. yield [
  832. [
  833. 4 => false, // 1
  834. 13 => true, // if (2nd)
  835. 21 => true, // true
  836. 33 => true, // while
  837. 43 => false, // echo
  838. 45 => false, // 2
  839. 46 => false, // ;
  840. 51 => false, // echo (123)
  841. ],
  842. '<?php
  843. echo 1;
  844. if ($a) if ($a) while(true)echo 1;
  845. elseif($c) while(true){if($d){echo 2;}};
  846. echo 123;
  847. ',
  848. ];
  849. yield [
  850. [
  851. 2 => false, // echo
  852. 13 => true, // echo
  853. 15 => true, // 2
  854. 20 => true, // die
  855. 23 => false, // echo
  856. ],
  857. '<?php
  858. echo 1;
  859. if ($a) echo 2;
  860. else die; echo 3;
  861. ',
  862. ];
  863. yield [
  864. [
  865. 8 => true, // die
  866. 9 => true, // /**/
  867. 15 => true, // die
  868. ],
  869. '<?php
  870. if ($a)
  871. die/**/;
  872. else
  873. /**/die/**/;#
  874. ',
  875. ];
  876. yield [
  877. [
  878. 8 => true, // die
  879. 9 => true, // /**/
  880. 15 => true, // die
  881. ],
  882. '<?php
  883. if ($a)
  884. die/**/;
  885. else
  886. /**/die/**/?>
  887. ',
  888. ];
  889. }
  890. /**
  891. * @return iterable<array{0: non-empty-string, 1?: non-empty-string}>
  892. */
  893. private static function generateConditionsWithoutBracesCase(string $statement): iterable
  894. {
  895. $ifTemplate = '<?php
  896. if ($a === false)
  897. {
  898. if ($v) %s
  899. }
  900. else
  901. $ret .= $value;
  902. return $ret;';
  903. $ifElseIfTemplate = '<?php
  904. if ($a === false)
  905. {
  906. if ($v) { $ret = "foo"; }
  907. elseif($a)
  908. %s
  909. }
  910. else
  911. $ret .= $value;
  912. return $ret;';
  913. $ifElseTemplate = '<?php
  914. if ($a === false)
  915. {
  916. if ($v) { $ret = "foo"; }
  917. else
  918. %s
  919. }
  920. else
  921. $ret .= $value;
  922. return $ret;';
  923. yield [\sprintf($ifTemplate, $statement)];
  924. yield [\sprintf($ifElseTemplate, $statement)];
  925. yield [\sprintf($ifElseIfTemplate, $statement)];
  926. }
  927. /**
  928. * @return iterable<array{0: string, 1?: string}>
  929. */
  930. private static function generateCases(string $expected, ?string $input = null): iterable
  931. {
  932. $cases = [];
  933. foreach ([
  934. 'exit;',
  935. 'exit();',
  936. 'exit(1);',
  937. 'die;',
  938. 'die();',
  939. 'die(1);',
  940. 'break;',
  941. 'break 2;',
  942. 'break (2);',
  943. 'continue;',
  944. 'continue 2;',
  945. 'continue (2);',
  946. 'return;',
  947. 'return 1;',
  948. 'return (1);',
  949. 'return "a";',
  950. 'return 8+2;',
  951. 'return null;',
  952. 'return sum(1+8*6, 2);',
  953. 'throw $e;',
  954. 'throw ($e);',
  955. 'throw new \Exception;',
  956. 'throw new \Exception();',
  957. 'throw new \Exception((string)12+1);',
  958. ] as $case) {
  959. if (null === $input) {
  960. $cases[] = [\sprintf($expected, $case)];
  961. $cases[] = [\sprintf($expected, strtoupper($case))];
  962. if ($case !== strtolower($case)) {
  963. $cases[] = [\sprintf($expected, strtolower($case))];
  964. }
  965. } else {
  966. $cases[] = [\sprintf($expected, $case), \sprintf($input, $case)];
  967. $cases[] = [\sprintf($expected, strtoupper($case)), \sprintf($input, strtoupper($case))];
  968. if ($case !== strtolower($case)) {
  969. $cases[] = [\sprintf($expected, strtolower($case)), \sprintf($input, strtolower($case))];
  970. }
  971. }
  972. }
  973. return $cases;
  974. }
  975. }