BlankLineBeforeStatementFixerTest.php 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696
  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\Whitespace;
  13. use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException;
  14. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  15. use PhpCsFixer\WhitespacesFixerConfig;
  16. /**
  17. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  18. * @author Andreas Möller <am@localheinz.com>
  19. *
  20. * @internal
  21. *
  22. * @covers \PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer
  23. *
  24. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer>
  25. *
  26. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer
  27. */
  28. final class BlankLineBeforeStatementFixerTest extends AbstractFixerTestCase
  29. {
  30. /**
  31. * @dataProvider provideConfigureRejectsInvalidControlStatementCases
  32. *
  33. * @param mixed $controlStatement
  34. */
  35. public function testConfigureRejectsInvalidControlStatement($controlStatement): void
  36. {
  37. $this->expectException(InvalidFixerConfigurationException::class);
  38. $this->fixer->configure([
  39. 'statements' => [$controlStatement],
  40. ]);
  41. }
  42. public static function provideConfigureRejectsInvalidControlStatementCases(): iterable
  43. {
  44. yield 'null' => [null];
  45. yield 'false' => [false];
  46. yield 'true' => [true];
  47. yield 'int' => [0];
  48. yield 'float' => [3.14];
  49. yield 'array' => [[]];
  50. yield 'object' => [new \stdClass()];
  51. yield 'unknown' => ['foo'];
  52. }
  53. /**
  54. * @dataProvider provideFixWithReturnCases
  55. */
  56. public function testFixWithDefaultConfiguration(string $expected, ?string $input = null): void
  57. {
  58. $this->doTest($expected, $input);
  59. }
  60. /**
  61. * @dataProvider provideFixWithBreakCases
  62. */
  63. public function testFixWithBreak(string $expected, ?string $input = null): void
  64. {
  65. $this->fixer->configure([
  66. 'statements' => ['break'],
  67. ]);
  68. $this->doTest($expected, $input);
  69. }
  70. /**
  71. * @return iterable<array{0: string, 1?: string}>
  72. */
  73. public static function provideFixWithBreakCases(): iterable
  74. {
  75. yield [
  76. '<?php
  77. switch ($a) {
  78. case 42:
  79. break;
  80. }',
  81. ];
  82. yield [
  83. '<?php
  84. switch ($a) {
  85. case 42:
  86. $foo = $bar;
  87. break;
  88. }',
  89. '<?php
  90. switch ($a) {
  91. case 42:
  92. $foo = $bar;
  93. break;
  94. }',
  95. ];
  96. yield [
  97. '<?php
  98. while (true) {
  99. if ($foo === $bar) {
  100. break;
  101. }
  102. }',
  103. ];
  104. yield [
  105. '<?php
  106. while (true) {
  107. if ($foo === $bar) {
  108. break 1;
  109. }
  110. }',
  111. ];
  112. yield [
  113. '<?php
  114. while (true) {
  115. if ($foo === $bar) {
  116. echo $baz;
  117. break;
  118. }
  119. }',
  120. '<?php
  121. while (true) {
  122. if ($foo === $bar) {
  123. echo $baz;
  124. break;
  125. }
  126. }',
  127. ];
  128. yield [
  129. '<?php
  130. while (true) {
  131. if ($foo === $bar) {
  132. echo $baz;
  133. break 1;
  134. }
  135. }',
  136. '<?php
  137. while (true) {
  138. if ($foo === $bar) {
  139. echo $baz;
  140. break 1;
  141. }
  142. }',
  143. ];
  144. yield [
  145. '<?php
  146. while (true) {
  147. if ($foo === $bar) {
  148. /** X */
  149. break 1;
  150. }
  151. }',
  152. ];
  153. }
  154. /**
  155. * @dataProvider provideFixWithCaseCases
  156. */
  157. public function testFixWithCase(string $expected, ?string $input = null): void
  158. {
  159. $this->fixer->configure([
  160. 'statements' => ['case'],
  161. ]);
  162. $this->doTest($expected, $input);
  163. }
  164. /**
  165. * @return iterable<array{string, string}>
  166. */
  167. public static function provideFixWithCaseCases(): iterable
  168. {
  169. yield [
  170. '<?php
  171. switch ($a) {
  172. case 1:
  173. return 1;
  174. case 2;
  175. return 2;
  176. case 3:
  177. return 3;
  178. }',
  179. '<?php
  180. switch ($a) {
  181. case 1:
  182. return 1;
  183. case 2;
  184. return 2;
  185. case 3:
  186. return 3;
  187. }',
  188. ];
  189. }
  190. /**
  191. * @dataProvider provideFixWithContinueCases
  192. */
  193. public function testFixWithContinue(string $expected, ?string $input = null): void
  194. {
  195. $this->fixer->configure([
  196. 'statements' => ['continue'],
  197. ]);
  198. $this->doTest($expected, $input);
  199. }
  200. /**
  201. * @return iterable<array{0: string, 1?: string}>
  202. */
  203. public static function provideFixWithContinueCases(): iterable
  204. {
  205. yield [
  206. '<?php
  207. while (true) {
  208. continue;
  209. }',
  210. ];
  211. yield [
  212. '<?php
  213. while (true) {
  214. continue 1;
  215. }',
  216. ];
  217. yield [
  218. '<?php
  219. while (true) {
  220. while (true) {
  221. continue 2;
  222. }
  223. }',
  224. ];
  225. yield [
  226. '<?php
  227. while (true) {
  228. $foo = true;
  229. continue;
  230. }',
  231. '<?php
  232. while (true) {
  233. $foo = true;
  234. continue;
  235. }',
  236. ];
  237. yield [
  238. '<?php
  239. while (true) {
  240. $foo = true;
  241. continue 1;
  242. }',
  243. '<?php
  244. while (true) {
  245. $foo = true;
  246. continue 1;
  247. }',
  248. ];
  249. yield [
  250. '<?php
  251. while (true) {
  252. while (true) {
  253. switch($a) {
  254. case 1:
  255. echo 1;
  256. continue;
  257. }
  258. $foo = true;
  259. continue 2;
  260. }
  261. }',
  262. '<?php
  263. while (true) {
  264. while (true) {
  265. switch($a) {
  266. case 1:
  267. echo 1;
  268. continue;
  269. }
  270. $foo = true;
  271. continue 2;
  272. }
  273. }',
  274. ];
  275. }
  276. /**
  277. * @dataProvider provideFixWithDeclareCases
  278. */
  279. public function testFixWithDeclare(string $expected, ?string $input = null): void
  280. {
  281. $this->fixer->configure([
  282. 'statements' => ['declare'],
  283. ]);
  284. $this->doTest($expected, $input);
  285. }
  286. /**
  287. * @return iterable<array{0: string, 1?: string}>
  288. */
  289. public static function provideFixWithDeclareCases(): iterable
  290. {
  291. yield [
  292. '<?php
  293. declare(ticks=1);',
  294. ];
  295. yield [
  296. '<?php
  297. $foo = "bar";
  298. do {
  299. } while (true);
  300. $foo = "bar";
  301. declare(ticks=1);',
  302. '<?php
  303. $foo = "bar";
  304. do {
  305. } while (true);
  306. $foo = "bar";
  307. declare(ticks=1);',
  308. ];
  309. }
  310. /**
  311. * @dataProvider provideFixWithDefaultCases
  312. */
  313. public function testFixWithDefault(string $expected, ?string $input = null): void
  314. {
  315. $this->fixer->configure([
  316. 'statements' => ['default'],
  317. ]);
  318. $this->doTest($expected, $input);
  319. }
  320. /**
  321. * @return iterable<array{string, string}>
  322. */
  323. public static function provideFixWithDefaultCases(): iterable
  324. {
  325. yield [
  326. '<?php
  327. switch ($a) {
  328. case 1:
  329. return 1;
  330. default:
  331. return 2;
  332. }
  333. switch ($a1) {
  334. default:
  335. return 22;
  336. }',
  337. '<?php
  338. switch ($a) {
  339. case 1:
  340. return 1;
  341. default:
  342. return 2;
  343. }
  344. switch ($a1) {
  345. default:
  346. return 22;
  347. }',
  348. ];
  349. }
  350. /**
  351. * @dataProvider provideFixWithDoCases
  352. */
  353. public function testFixWithDo(string $expected, ?string $input = null): void
  354. {
  355. $this->fixer->configure([
  356. 'statements' => ['do'],
  357. ]);
  358. $this->doTest($expected, $input);
  359. }
  360. /**
  361. * @return iterable<array{0: string, 1?: string}>
  362. */
  363. public static function provideFixWithDoCases(): iterable
  364. {
  365. yield [
  366. '<?php
  367. do {
  368. } while (true);',
  369. ];
  370. yield [
  371. '<?php
  372. $foo = "bar";
  373. do {
  374. } while (true);',
  375. '<?php
  376. $foo = "bar";
  377. do {
  378. } while (true);',
  379. ];
  380. }
  381. /**
  382. * @dataProvider provideFixWithExitCases
  383. */
  384. public function testFixWithExit(string $expected, ?string $input = null): void
  385. {
  386. $this->fixer->configure([
  387. 'statements' => ['exit'],
  388. ]);
  389. $this->doTest($expected, $input);
  390. }
  391. /**
  392. * @return iterable<array{0: string, 1?: string}>
  393. */
  394. public static function provideFixWithExitCases(): iterable
  395. {
  396. yield [
  397. '<?php
  398. if ($foo === $bar) {
  399. exit();
  400. }',
  401. ];
  402. yield [
  403. '<?php
  404. if ($foo === $bar) {
  405. echo $baz;
  406. exit();
  407. }',
  408. '<?php
  409. if ($foo === $bar) {
  410. echo $baz;
  411. exit();
  412. }',
  413. ];
  414. yield [
  415. '<?php
  416. if ($foo === $bar) {
  417. echo $baz;
  418. exit();
  419. }',
  420. ];
  421. yield [
  422. '<?php
  423. mysqli_connect() or exit();',
  424. ];
  425. yield [
  426. '<?php
  427. if ($foo === $bar) {
  428. $bar = 9001;
  429. mysqli_connect() or exit();
  430. }',
  431. ];
  432. }
  433. /**
  434. * @dataProvider provideFixWithForCases
  435. */
  436. public function testFixWithFor(string $expected, ?string $input = null): void
  437. {
  438. $this->fixer->configure([
  439. 'statements' => ['for'],
  440. ]);
  441. $this->doTest($expected, $input);
  442. }
  443. /**
  444. * @return iterable<array{string, string}>
  445. */
  446. public static function provideFixWithForCases(): iterable
  447. {
  448. yield [
  449. '<?php
  450. echo 1;
  451. for(;;){break;}
  452. ',
  453. '<?php
  454. echo 1;
  455. for(;;){break;}
  456. ',
  457. ];
  458. }
  459. /**
  460. * @dataProvider provideFixWithGotoCases
  461. */
  462. public function testFixWithGoto(string $expected, ?string $input = null): void
  463. {
  464. $this->fixer->configure([
  465. 'statements' => ['goto'],
  466. ]);
  467. $this->doTest($expected, $input);
  468. }
  469. /**
  470. * @return iterable<array{0: string, 1?: string}>
  471. */
  472. public static function provideFixWithGotoCases(): iterable
  473. {
  474. yield [
  475. '<?php
  476. a:
  477. if ($foo === $bar) {
  478. goto a;
  479. }',
  480. ];
  481. yield [
  482. '<?php
  483. a:
  484. if ($foo === $bar) {
  485. echo $baz;
  486. goto a;
  487. }',
  488. '<?php
  489. a:
  490. if ($foo === $bar) {
  491. echo $baz;
  492. goto a;
  493. }',
  494. ];
  495. yield [
  496. '<?php
  497. a:
  498. if ($foo === $bar) {
  499. echo $baz;
  500. goto a;
  501. }',
  502. ];
  503. }
  504. /**
  505. * @dataProvider provideFixWithIfCases
  506. */
  507. public function testFixWithIf(string $expected, ?string $input = null): void
  508. {
  509. $this->fixer->configure([
  510. 'statements' => ['if'],
  511. ]);
  512. $this->doTest($expected, $input);
  513. }
  514. /**
  515. * @return iterable<array{0: string, 1?: string}>
  516. */
  517. public static function provideFixWithIfCases(): iterable
  518. {
  519. yield [
  520. '<?php if (true) {
  521. echo $bar;
  522. }',
  523. ];
  524. yield [
  525. '<?php
  526. if (true) {
  527. echo $bar;
  528. }',
  529. ];
  530. yield [
  531. '<?php
  532. $foo = $bar;
  533. if (true) {
  534. echo $bar;
  535. }',
  536. '<?php
  537. $foo = $bar;
  538. if (true) {
  539. echo $bar;
  540. }',
  541. ];
  542. yield [
  543. '<?php
  544. // foo
  545. if ($foo) { }',
  546. ];
  547. }
  548. /**
  549. * @dataProvider provideFixWithForEachCases
  550. */
  551. public function testFixWithForEach(string $expected, ?string $input = null): void
  552. {
  553. $this->fixer->configure([
  554. 'statements' => ['foreach'],
  555. ]);
  556. $this->doTest($expected, $input);
  557. }
  558. /**
  559. * @return iterable<array{string, string}>
  560. */
  561. public static function provideFixWithForEachCases(): iterable
  562. {
  563. yield [
  564. '<?php
  565. echo 1;
  566. foreach($a as $b){break;}
  567. ',
  568. '<?php
  569. echo 1;
  570. foreach($a as $b){break;}
  571. ',
  572. ];
  573. }
  574. /**
  575. * @dataProvider provideFixWithIncludeCases
  576. */
  577. public function testFixWithInclude(string $expected, ?string $input = null): void
  578. {
  579. $this->fixer->configure([
  580. 'statements' => ['include'],
  581. ]);
  582. $this->doTest($expected, $input);
  583. }
  584. /**
  585. * @return iterable<array{0: string, 1?: string}>
  586. */
  587. public static function provideFixWithIncludeCases(): iterable
  588. {
  589. yield [
  590. '<?php
  591. include "foo.php";',
  592. ];
  593. yield [
  594. '<?php
  595. $foo = $bar;
  596. include "foo.php";',
  597. '<?php
  598. $foo = $bar;
  599. include "foo.php";',
  600. ];
  601. }
  602. /**
  603. * @dataProvider provideFixWithIncludeOnceCases
  604. */
  605. public function testFixWithIncludeOnce(string $expected, ?string $input = null): void
  606. {
  607. $this->fixer->configure([
  608. 'statements' => ['include_once'],
  609. ]);
  610. $this->doTest($expected, $input);
  611. }
  612. /**
  613. * @return iterable<array{0: string, 1?: string}>
  614. */
  615. public static function provideFixWithIncludeOnceCases(): iterable
  616. {
  617. yield [
  618. '<?php
  619. include_once "foo.php";',
  620. ];
  621. yield [
  622. '<?php
  623. $foo = $bar;
  624. include_once "foo.php";',
  625. '<?php
  626. $foo = $bar;
  627. include_once "foo.php";',
  628. ];
  629. }
  630. /**
  631. * @dataProvider provideFixWithRequireCases
  632. */
  633. public function testFixWithRequire(string $expected, ?string $input = null): void
  634. {
  635. $this->fixer->configure([
  636. 'statements' => ['require'],
  637. ]);
  638. $this->doTest($expected, $input);
  639. }
  640. /**
  641. * @return iterable<array{0: string, 1?: string}>
  642. */
  643. public static function provideFixWithRequireCases(): iterable
  644. {
  645. yield [
  646. '<?php
  647. require "foo.php";',
  648. ];
  649. yield [
  650. '<?php
  651. $foo = $bar;
  652. require "foo.php";',
  653. '<?php
  654. $foo = $bar;
  655. require "foo.php";',
  656. ];
  657. }
  658. /**
  659. * @dataProvider provideFixWithRequireOnceCases
  660. */
  661. public function testFixWithRequireOnce(string $expected, ?string $input = null): void
  662. {
  663. $this->fixer->configure([
  664. 'statements' => ['require_once'],
  665. ]);
  666. $this->doTest($expected, $input);
  667. }
  668. /**
  669. * @return iterable<array{0: string, 1?: string}>
  670. */
  671. public static function provideFixWithRequireOnceCases(): iterable
  672. {
  673. yield [
  674. '<?php
  675. require_once "foo.php";',
  676. ];
  677. yield [
  678. '<?php
  679. $foo = $bar;
  680. require_once "foo.php";',
  681. '<?php
  682. $foo = $bar;
  683. require_once "foo.php";',
  684. ];
  685. }
  686. /**
  687. * @dataProvider provideFixWithReturnCases
  688. */
  689. public function testFixWithReturn(string $expected, ?string $input = null): void
  690. {
  691. $this->fixer->configure([
  692. 'statements' => ['return'],
  693. ]);
  694. $this->doTest($expected, $input);
  695. }
  696. /**
  697. * @return iterable<int|string, array{0: string, 1?: string}>
  698. */
  699. public static function provideFixWithReturnCases(): iterable
  700. {
  701. yield [
  702. '<?php
  703. if ($a) { /* 1 */ /* 2 */ /* 3 */ // something about $a
  704. return $b;
  705. }
  706. ',
  707. ];
  708. yield [
  709. '<?php
  710. if ($a) { // something about $a
  711. return $b;
  712. }
  713. ',
  714. ];
  715. yield [
  716. '
  717. $a = $a;
  718. return $a;',
  719. ];
  720. yield [
  721. '<?php
  722. $a = $a;
  723. return $a;',
  724. '<?php
  725. $a = $a; return $a;',
  726. ];
  727. yield [
  728. '<?php
  729. $b = $b;
  730. return $b;',
  731. '<?php
  732. $b = $b;return $b;',
  733. ];
  734. yield [
  735. '<?php
  736. $c = $c;
  737. return $c;',
  738. '<?php
  739. $c = $c;
  740. return $c;',
  741. ];
  742. yield [
  743. '<?php
  744. $d = $d;
  745. return $d;',
  746. '<?php
  747. $d = $d;
  748. return $d;',
  749. ];
  750. yield [
  751. '<?php
  752. if (true) {
  753. return 1;
  754. }',
  755. ];
  756. yield [
  757. '<?php
  758. if (true)
  759. return 1;',
  760. ];
  761. yield [
  762. '<?php
  763. if (true) {
  764. return 1;
  765. } else {
  766. return 2;
  767. }',
  768. ];
  769. yield [
  770. '<?php
  771. if (true)
  772. return 1;
  773. else
  774. return 2;',
  775. ];
  776. yield [
  777. '<?php
  778. if (true) {
  779. return 1;
  780. } elseif (false) {
  781. return 2;
  782. }',
  783. ];
  784. yield [
  785. '<?php
  786. if (true)
  787. return 1;
  788. elseif (false)
  789. return 2;',
  790. ];
  791. yield [
  792. '<?php
  793. throw new Exception("return true; //.");',
  794. ];
  795. yield [
  796. '<?php
  797. function foo()
  798. {
  799. // comment
  800. return "foo";
  801. }',
  802. ];
  803. yield [
  804. '<?php
  805. function foo()
  806. {
  807. // comment
  808. return "bar";
  809. }',
  810. ];
  811. yield [
  812. '<?php
  813. function foo()
  814. {
  815. switch ($foo) {
  816. case 2: // comment
  817. return 1;
  818. }
  819. }',
  820. ];
  821. yield 'do not fix when there is empty line between statement and preceding comment' => [
  822. '<?php function foo()
  823. {
  824. bar();
  825. // comment
  826. return 42;
  827. }',
  828. ];
  829. yield 'do not fix when there is empty line between preceding comments' => [
  830. '<?php function foo()
  831. {
  832. bar();
  833. // comment1
  834. // comment2
  835. // comment3
  836. return 42;
  837. }',
  838. ];
  839. }
  840. /**
  841. * @dataProvider provideFixWithReturnAndMessyWhitespacesCases
  842. */
  843. public function testFixWithReturnAndMessyWhitespaces(string $expected, ?string $input = null): void
  844. {
  845. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t", "\r\n"));
  846. $this->doTest($expected, $input);
  847. }
  848. /**
  849. * @return iterable<array{string, string}>
  850. */
  851. public static function provideFixWithReturnAndMessyWhitespacesCases(): iterable
  852. {
  853. yield [
  854. "<?php\r\n\$a = \$a;\r\n\r\nreturn \$a;",
  855. "<?php\r\n\$a = \$a; return \$a;",
  856. ];
  857. yield [
  858. "<?php\r\n\$b = \$b;\r\n\r\nreturn \$b;",
  859. "<?php\r\n\$b = \$b;return \$b;",
  860. ];
  861. yield [
  862. "<?php\r\n\$c = \$c;\r\n\r\nreturn \$c;",
  863. "<?php\r\n\$c = \$c;\r\nreturn \$c;",
  864. ];
  865. }
  866. /**
  867. * @dataProvider provideFixWithSwitchCases
  868. */
  869. public function testFixWithSwitch(string $expected, ?string $input = null): void
  870. {
  871. $this->fixer->configure([
  872. 'statements' => ['switch'],
  873. ]);
  874. $this->doTest($expected, $input);
  875. }
  876. /**
  877. * @return iterable<array{0: string, 1?: string}>
  878. */
  879. public static function provideFixWithSwitchCases(): iterable
  880. {
  881. yield [
  882. '<?php
  883. switch ($a) {
  884. case 42:
  885. break;
  886. }',
  887. ];
  888. yield [
  889. '<?php
  890. $foo = $bar;
  891. switch ($foo) {
  892. case $bar:
  893. break;
  894. }',
  895. '<?php
  896. $foo = $bar;
  897. switch ($foo) {
  898. case $bar:
  899. break;
  900. }',
  901. ];
  902. }
  903. /**
  904. * @dataProvider provideFixWithThrowCases
  905. */
  906. public function testFixWithThrow(string $expected, ?string $input = null): void
  907. {
  908. $this->fixer->configure([
  909. 'statements' => ['throw'],
  910. ]);
  911. $this->doTest($expected, $input);
  912. }
  913. /**
  914. * @return iterable<array{0: string, 1?: string}>
  915. */
  916. public static function provideFixWithThrowCases(): iterable
  917. {
  918. yield [
  919. '<?php
  920. if (false) {
  921. throw new \Exception("Something unexpected happened.");
  922. }',
  923. ];
  924. yield [
  925. '<?php
  926. if (false) {
  927. $log->error("No");
  928. throw new \Exception("Something unexpected happened.");
  929. }',
  930. '<?php
  931. if (false) {
  932. $log->error("No");
  933. throw new \Exception("Something unexpected happened.");
  934. }',
  935. ];
  936. }
  937. /**
  938. * @dataProvider provideFixWithTryCases
  939. */
  940. public function testFixWithTry(string $expected, ?string $input = null): void
  941. {
  942. $this->fixer->configure([
  943. 'statements' => ['try'],
  944. ]);
  945. $this->doTest($expected, $input);
  946. }
  947. /**
  948. * @return iterable<array{0: string, 1?: string}>
  949. */
  950. public static function provideFixWithTryCases(): iterable
  951. {
  952. yield [
  953. '<?php
  954. try {
  955. $transaction->commit();
  956. } catch (\Exception $exception) {
  957. $transaction->rollback();
  958. }',
  959. ];
  960. yield [
  961. '<?php
  962. $foo = $bar;
  963. try {
  964. $transaction->commit();
  965. } catch (\Exception $exception) {
  966. $transaction->rollback();
  967. }',
  968. '<?php
  969. $foo = $bar;
  970. try {
  971. $transaction->commit();
  972. } catch (\Exception $exception) {
  973. $transaction->rollback();
  974. }',
  975. ];
  976. }
  977. /**
  978. * @dataProvider provideFixWithWhileCases
  979. */
  980. public function testFixWithWhile(string $expected, ?string $input = null): void
  981. {
  982. $this->fixer->configure([
  983. 'statements' => ['while'],
  984. ]);
  985. $this->doTest($expected, $input);
  986. }
  987. /**
  988. * @return iterable<array{0: string, 1?: string}>
  989. */
  990. public static function provideFixWithWhileCases(): iterable
  991. {
  992. yield [
  993. '<?php
  994. while (true) {
  995. $worker->work();
  996. }',
  997. ];
  998. yield [
  999. '<?php
  1000. $foo = $bar;
  1001. while (true) {
  1002. $worker->work();
  1003. }',
  1004. '<?php
  1005. $foo = $bar;
  1006. while (true) {
  1007. $worker->work();
  1008. }',
  1009. ];
  1010. yield [
  1011. '<?php
  1012. $foo = $bar;
  1013. do {
  1014. echo 1;
  1015. while($a());
  1016. $worker->work();
  1017. } while (true);',
  1018. '<?php
  1019. $foo = $bar;
  1020. do {
  1021. echo 1;
  1022. while($a());
  1023. $worker->work();
  1024. } while (true);',
  1025. ];
  1026. }
  1027. /**
  1028. * @dataProvider provideFixWithYieldCases
  1029. */
  1030. public function testFixWithYield(string $expected, ?string $input = null): void
  1031. {
  1032. $this->fixer->configure([
  1033. 'statements' => ['yield'],
  1034. ]);
  1035. $this->doTest($expected, $input);
  1036. }
  1037. /**
  1038. * @return iterable<array{0: string, 1?: string}>
  1039. */
  1040. public static function provideFixWithYieldCases(): iterable
  1041. {
  1042. yield [
  1043. '<?php
  1044. function foo() {
  1045. yield $a; /* a *//* b */ /* c */ /* d *//* e *//* etc */
  1046. '.'
  1047. yield $b;
  1048. }',
  1049. '<?php
  1050. function foo() {
  1051. yield $a; /* a *//* b */ /* c */ /* d *//* e *//* etc */ '.'
  1052. yield $b;
  1053. }',
  1054. ];
  1055. yield [
  1056. '<?php
  1057. function foo() {
  1058. yield $a; // test
  1059. yield $b; // test /* A */
  1060. yield $c;
  1061. yield $d;
  1062. yield $e;#
  1063. yield $f;
  1064. /* @var int $g */
  1065. yield $g;
  1066. /* @var int $h */
  1067. yield $i;
  1068. yield $j;
  1069. }',
  1070. '<?php
  1071. function foo() {
  1072. yield $a; // test
  1073. yield $b; // test /* A */
  1074. yield $c;
  1075. yield $d;yield $e;#
  1076. yield $f;
  1077. /* @var int $g */
  1078. yield $g;
  1079. /* @var int $h */
  1080. yield $i;
  1081. yield $j;
  1082. }',
  1083. ];
  1084. yield [
  1085. '<?php
  1086. function foo() {
  1087. yield $a;
  1088. }',
  1089. ];
  1090. yield [
  1091. '<?php
  1092. function foo() {
  1093. yield $a;
  1094. yield $b;
  1095. }',
  1096. '<?php
  1097. function foo() {
  1098. yield $a;
  1099. yield $b;
  1100. }',
  1101. ];
  1102. yield [
  1103. '<?php
  1104. function foo() {
  1105. yield \'b\' => $a;
  1106. yield "a" => $b;
  1107. }',
  1108. '<?php
  1109. function foo() {
  1110. yield \'b\' => $a;
  1111. yield "a" => $b;
  1112. }',
  1113. ];
  1114. yield [
  1115. '<?php
  1116. function foo() {
  1117. $a = $a;
  1118. yield $a;
  1119. }',
  1120. ];
  1121. yield [
  1122. '<?php
  1123. function foo() {
  1124. $a = $a;
  1125. yield $a;
  1126. }',
  1127. '<?php
  1128. function foo() {
  1129. $a = $a;
  1130. yield $a;
  1131. }',
  1132. ];
  1133. yield [
  1134. '<?php function foo() {
  1135. // yield 1
  1136. yield 1;
  1137. // yield 2
  1138. yield 2;
  1139. }',
  1140. '<?php function foo() {
  1141. // yield 1
  1142. yield 1;
  1143. // yield 2
  1144. yield 2;
  1145. }',
  1146. ];
  1147. yield [
  1148. '<?php function foo() {
  1149. yield 1;
  1150. // yield 2
  1151. // or maybe yield 3
  1152. // better compromise
  1153. yield 2.5;
  1154. }',
  1155. '<?php function foo() {
  1156. yield 1;
  1157. // yield 2
  1158. // or maybe yield 3
  1159. // better compromise
  1160. yield 2.5;
  1161. }',
  1162. ];
  1163. }
  1164. /**
  1165. * @dataProvider provideFixWithYieldFromCases
  1166. */
  1167. public function testFixWithYieldFrom(string $expected, ?string $input = null): void
  1168. {
  1169. $this->fixer->configure([
  1170. 'statements' => ['yield_from'],
  1171. ]);
  1172. $this->doTest($expected, $input);
  1173. }
  1174. /**
  1175. * @return iterable<array{0: string, 1?: string}>
  1176. */
  1177. public static function provideFixWithYieldFromCases(): iterable
  1178. {
  1179. yield [
  1180. '<?php
  1181. function foo() {
  1182. yield from $a;
  1183. }',
  1184. ];
  1185. yield [
  1186. '<?php
  1187. function foo() {
  1188. yield from $a;
  1189. yield from $b;
  1190. }',
  1191. '<?php
  1192. function foo() {
  1193. yield from $a;
  1194. yield from $b;
  1195. }',
  1196. ];
  1197. yield [
  1198. '<?php
  1199. function foo() {
  1200. $a = $a;
  1201. yield from $a;
  1202. yield $a;
  1203. yield $b;
  1204. }',
  1205. ];
  1206. yield [
  1207. '<?php
  1208. function foo() {
  1209. $a = $a;
  1210. yield from $a;
  1211. }',
  1212. '<?php
  1213. function foo() {
  1214. $a = $a;
  1215. yield from $a;
  1216. }',
  1217. ];
  1218. }
  1219. /**
  1220. * @dataProvider provideFixWithMultipleConfigStatementsCases
  1221. *
  1222. * @param _AutogeneratedInputConfiguration['statements'] $statements
  1223. */
  1224. public function testFixWithMultipleConfigStatements(array $statements, string $expected, ?string $input = null): void
  1225. {
  1226. $this->fixer->configure(['statements' => $statements]);
  1227. $this->doTest($expected, $input);
  1228. }
  1229. public static function provideFixWithMultipleConfigStatementsCases(): iterable
  1230. {
  1231. $statementsWithoutCaseOrDefault = [
  1232. 'break',
  1233. 'continue',
  1234. 'declare',
  1235. 'do',
  1236. 'for',
  1237. 'foreach',
  1238. 'if',
  1239. 'include',
  1240. 'include_once',
  1241. 'require',
  1242. 'require_once',
  1243. 'return',
  1244. 'switch',
  1245. 'throw',
  1246. 'try',
  1247. 'while',
  1248. ];
  1249. $allStatements = [...$statementsWithoutCaseOrDefault, 'case', 'default'];
  1250. yield [
  1251. $statementsWithoutCaseOrDefault,
  1252. '<?php
  1253. while($a) {
  1254. if ($c) {
  1255. switch ($d) {
  1256. case $e:
  1257. continue 2;
  1258. case 4:
  1259. break;
  1260. case 5:
  1261. return 1;
  1262. default:
  1263. return 0;
  1264. }
  1265. }
  1266. }
  1267. ',
  1268. ];
  1269. yield [
  1270. $allStatements,
  1271. '<?php
  1272. while($a) {
  1273. if ($c) {
  1274. switch ($d) {
  1275. case $e:
  1276. continue 2;
  1277. case 4:
  1278. break;
  1279. case 5:
  1280. return 1;
  1281. default:
  1282. return 0;
  1283. }
  1284. }
  1285. }
  1286. ',
  1287. ];
  1288. yield [
  1289. ['break', 'throw'],
  1290. '<?php
  1291. do {
  1292. echo 0;
  1293. if ($a) {
  1294. echo 1;
  1295. break;
  1296. }
  1297. echo 2;
  1298. throw $f;
  1299. } while(true);',
  1300. '<?php
  1301. do {
  1302. echo 0;
  1303. if ($a) {
  1304. echo 1;
  1305. break;
  1306. }
  1307. echo 2;
  1308. throw $f;
  1309. } while(true);',
  1310. ];
  1311. }
  1312. /**
  1313. * @dataProvider provideFix80Cases
  1314. *
  1315. * @requires PHP 8.0
  1316. */
  1317. public function testFix80(string $expected, ?string $input = null): void
  1318. {
  1319. $this->fixer->configure([
  1320. 'statements' => ['default'],
  1321. ]);
  1322. $this->doTest($expected, $input);
  1323. }
  1324. /**
  1325. * @return iterable<string, array{string}>
  1326. */
  1327. public static function provideFix80Cases(): iterable
  1328. {
  1329. yield 'match' => [
  1330. '<?php
  1331. match ($foo) {
  1332. 1 => "a",
  1333. default => "b"
  1334. };
  1335. match ($foo) {
  1336. 1 => "a1",
  1337. default => "b2"
  1338. };
  1339. ',
  1340. ];
  1341. }
  1342. /**
  1343. * @dataProvider provideFix81Cases
  1344. *
  1345. * @requires PHP 8.1
  1346. */
  1347. public function testFix81(string $expected, ?string $input = null): void
  1348. {
  1349. $this->fixer->configure([
  1350. 'statements' => ['case'],
  1351. ]);
  1352. $this->doTest($expected, $input);
  1353. }
  1354. /**
  1355. * @return iterable<string, array{string, string}>
  1356. */
  1357. public static function provideFix81Cases(): iterable
  1358. {
  1359. yield 'enum' => [
  1360. '<?php
  1361. enum Suit {
  1362. case Hearts;
  1363. case Diamonds;
  1364. case Clubs;
  1365. case Spades;
  1366. }
  1367. enum UserStatus: string {
  1368. case Pending = "P";
  1369. case Active = "A";
  1370. public function label(): string {
  1371. switch ($a) {
  1372. case 1:
  1373. return 1;
  1374. case 2:
  1375. return 2; // do fix
  1376. }
  1377. return "label";
  1378. }
  1379. }
  1380. ',
  1381. '<?php
  1382. enum Suit {
  1383. case Hearts;
  1384. case Diamonds;
  1385. case Clubs;
  1386. case Spades;
  1387. }
  1388. enum UserStatus: string {
  1389. case Pending = "P";
  1390. case Active = "A";
  1391. public function label(): string {
  1392. switch ($a) {
  1393. case 1:
  1394. return 1;
  1395. case 2:
  1396. return 2; // do fix
  1397. }
  1398. return "label";
  1399. }
  1400. }
  1401. ',
  1402. ];
  1403. }
  1404. /**
  1405. * @dataProvider provideFixWithDocCommentCases
  1406. */
  1407. public function testFixWithDocComment(string $expected, ?string $input = null): void
  1408. {
  1409. $this->fixer->configure([
  1410. 'statements' => ['phpdoc'],
  1411. ]);
  1412. $this->doTest($expected, $input);
  1413. }
  1414. /**
  1415. * @return iterable<array{0: string, 1?: string}>
  1416. */
  1417. public static function provideFixWithDocCommentCases(): iterable
  1418. {
  1419. yield [
  1420. '<?php
  1421. /** @var int $foo */
  1422. $foo = 123;
  1423. /** @var float $bar */
  1424. $bar = 45.6;
  1425. /** @var string */
  1426. $baz = "789";
  1427. ',
  1428. '<?php
  1429. /** @var int $foo */
  1430. $foo = 123;
  1431. /** @var float $bar */
  1432. $bar = 45.6;
  1433. /** @var string */
  1434. $baz = "789";
  1435. ',
  1436. ];
  1437. yield [
  1438. '<?php
  1439. /* header */
  1440. /**
  1441. * Class description
  1442. */
  1443. class Foo {
  1444. /** test */
  1445. public function bar() {}
  1446. }
  1447. ',
  1448. ];
  1449. }
  1450. }