NoUselessElseFixerTest.php 28 KB

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