MethodArgumentSpaceFixerTest.php 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291
  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\FunctionNotation;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. use PhpCsFixer\WhitespacesFixerConfig;
  15. /**
  16. * @author Kuanhung Chen <ericj.tw@gmail.com>
  17. *
  18. * @internal
  19. *
  20. * @covers \PhpCsFixer\Fixer\FunctionNotation\MethodArgumentSpaceFixer
  21. */
  22. final class MethodArgumentSpaceFixerTest extends AbstractFixerTestCase
  23. {
  24. /**
  25. * @param array<string, mixed> $configuration
  26. *
  27. * @dataProvider provideFixCases
  28. */
  29. public function testFix(string $expected, ?string $input = null, array $configuration = []): void
  30. {
  31. $indent = ' ';
  32. $lineEnding = "\n";
  33. if (str_contains($expected, "\t")) {
  34. $indent = "\t";
  35. } elseif (preg_match('/\n \S/', $expected)) {
  36. $indent = ' ';
  37. }
  38. if (str_contains($expected, "\r")) {
  39. $lineEnding = "\r\n";
  40. }
  41. $this->fixer->configure($configuration);
  42. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig(
  43. $indent,
  44. $lineEnding
  45. ));
  46. $this->doTest($expected, $input);
  47. }
  48. /**
  49. * @param array<string, mixed> $configuration
  50. *
  51. * @dataProvider provideFixCases
  52. */
  53. public function testFixWithDifferentLineEndings(string $expected, ?string $input = null, array $configuration = []): void
  54. {
  55. if (null !== $input) {
  56. $input = str_replace("\n", "\r\n", $input);
  57. }
  58. $this->testFix(
  59. str_replace("\n", "\r\n", $expected),
  60. $input,
  61. $configuration
  62. );
  63. }
  64. public static function provideFixCases(): iterable
  65. {
  66. yield [
  67. '<?php
  68. // space '.'
  69. $var1 = $a->some_method(
  70. $var2
  71. );
  72. // space '.'
  73. $var2 = some_function(
  74. $var2
  75. );
  76. // space '.'
  77. $var2a = $z[1](
  78. $var2a
  79. );
  80. '.'
  81. $var3 = function( $a, $b ) { };
  82. ',
  83. '<?php
  84. // space '.'
  85. $var1 = $a->some_method(
  86. $var2);
  87. // space '.'
  88. $var2 = some_function(
  89. $var2);
  90. // space '.'
  91. $var2a = $z[1](
  92. $var2a
  93. );
  94. '.'
  95. $var3 = function( $a , $b ) { };
  96. ',
  97. [
  98. 'on_multiline' => 'ensure_fully_multiline',
  99. ],
  100. ];
  101. yield 'default' => [
  102. '<?php xyz("", "", "", "");',
  103. '<?php xyz("","","","");',
  104. ];
  105. yield 'test method arguments' => [
  106. '<?php function xyz($a=10, $b=20, $c=30) {}',
  107. '<?php function xyz($a=10,$b=20,$c=30) {}',
  108. ];
  109. yield 'test method arguments with multiple spaces' => [
  110. '<?php function xyz($a=10, $b=20, $c=30) {}',
  111. '<?php function xyz($a=10, $b=20 , $c=30) {}',
  112. ];
  113. yield 'test method arguments with multiple spaces (kmsac)' => [
  114. '<?php function xyz($a=10, $b=20, $c=30) {}',
  115. '<?php function xyz($a=10, $b=20 , $c=30) {}',
  116. ['keep_multiple_spaces_after_comma' => true],
  117. ];
  118. yield 'test method call (I)' => [
  119. '<?php xyz($a=10, $b=20, $c=30);',
  120. '<?php xyz($a=10 ,$b=20,$c=30);',
  121. ];
  122. yield 'test method call (II)' => [
  123. '<?php xyz($a=10, $b=20, $this->foo(), $c=30);',
  124. '<?php xyz($a=10,$b=20 ,$this->foo() ,$c=30);',
  125. ];
  126. yield 'test method call with multiple spaces (I)' => [
  127. '<?php xyz($a=10, $b=20, $c=30);',
  128. '<?php xyz($a=10 , $b=20 , $c=30);',
  129. ];
  130. yield 'test method call with multiple spaces (I) (kmsac)' => [
  131. '<?php xyz($a=10, $b=20, $c=30);',
  132. '<?php xyz($a=10 , $b=20 , $c=30);',
  133. ['keep_multiple_spaces_after_comma' => true],
  134. ];
  135. yield 'test method call with tab' => [
  136. '<?php xyz($a=10, $b=20, $c=30);',
  137. "<?php xyz(\$a=10 , \$b=20 ,\t \$c=30);",
  138. ];
  139. yield 'test method call with tab (kmsac)' => [
  140. "<?php xyz(\$a=10, \$b=20,\t \$c=30);",
  141. "<?php xyz(\$a=10 , \$b=20 ,\t \$c=30);",
  142. ['keep_multiple_spaces_after_comma' => true],
  143. ];
  144. yield 'test method call with multiple spaces (II)' => [
  145. '<?php xyz($a=10, $b=20, $this->foo(), $c=30);',
  146. '<?php xyz($a=10,$b=20 , $this->foo() ,$c=30);',
  147. ];
  148. yield 'test method call with multiple spaces (II) (kmsac)' => [
  149. '<?php xyz($a=10, $b=20, $this->foo(), $c=30);',
  150. '<?php xyz($a=10,$b=20 , $this->foo() ,$c=30);',
  151. ['keep_multiple_spaces_after_comma' => true],
  152. ];
  153. yield 'test named class constructor call' => [
  154. '<?php new Foo($a=10, $b=20, $this->foo(), $c=30);',
  155. '<?php new Foo($a=10,$b=20 ,$this->foo() ,$c=30);',
  156. ];
  157. yield 'test named class constructor call with multiple spaces' => [
  158. '<?php new Foo($a=10, $b=20, $c=30);',
  159. '<?php new Foo($a=10 , $b=20 , $c=30);',
  160. ];
  161. yield 'test named class constructor call with multiple spaces (kmsac)' => [
  162. '<?php new Foo($a=10, $b=20, $c=30);',
  163. '<?php new Foo($a=10 , $b=20 , $c=30);',
  164. ['keep_multiple_spaces_after_comma' => true],
  165. ];
  166. yield 'test anonymous class constructor call' => [
  167. '<?php new class ($a=10, $b=20, $this->foo(), $c=30) {};',
  168. '<?php new class ($a=10,$b=20 ,$this->foo() ,$c=30) {};',
  169. ];
  170. yield 'test anonymous class constructor call with multiple spaces' => [
  171. '<?php new class ($a=10, $b=20, $c=30) extends Foo {};',
  172. '<?php new class ($a=10 , $b=20 , $c=30) extends Foo {};',
  173. ];
  174. yield 'test anonymous class constructor call with multiple spaces (kmsac)' => [
  175. '<?php new class ($a=10, $b=20, $c=30) {};',
  176. '<?php new class ($a=10 , $b=20 , $c=30) {};',
  177. ['keep_multiple_spaces_after_comma' => true],
  178. ];
  179. yield 'test receiving data in list context with omitted values' => [
  180. '<?php list($a, $b, , , $c) = foo();',
  181. '<?php list($a, $b,, ,$c) = foo();',
  182. ];
  183. yield 'test receiving data in list context with omitted values and multiple spaces' => [
  184. '<?php list($a, $b, , , $c) = foo();',
  185. '<?php list($a, $b,, ,$c) = foo();',
  186. ];
  187. yield 'test receiving data in list context with omitted values and multiple spaces (kmsac)' => [
  188. '<?php list($a, $b, , , $c) = foo();',
  189. '<?php list($a, $b,, ,$c) = foo();',
  190. ['keep_multiple_spaces_after_comma' => true],
  191. ];
  192. yield 'skip array' => [
  193. '<?php array(10 , 20 ,30); $foo = [ 10,50 , 60 ] ?>',
  194. ];
  195. yield 'list call with trailing comma' => [
  196. '<?php list($path, $mode, ) = foo();',
  197. '<?php list($path, $mode,) = foo();',
  198. ];
  199. yield 'list call with trailing comma multi line' => [
  200. '<?php
  201. list(
  202. $a,
  203. $b,
  204. ) = foo();
  205. ',
  206. '<?php
  207. list(
  208. $a ,
  209. $b ,
  210. ) = foo();
  211. ',
  212. ];
  213. yield 'inline comments with spaces' => [
  214. '<?php xyz($a=10, /*comment1*/ $b=2000, /*comment2*/ $c=30);',
  215. '<?php xyz($a=10, /*comment1*/ $b=2000,/*comment2*/ $c=30);',
  216. ];
  217. yield 'inline comments with spaces (kmsac)' => [
  218. '<?php xyz($a=10, /*comment1*/ $b=2000, /*comment2*/ $c=30);',
  219. '<?php xyz($a=10, /*comment1*/ $b=2000,/*comment2*/ $c=30);',
  220. ['keep_multiple_spaces_after_comma' => true],
  221. ];
  222. yield 'multi line testing method call' => [
  223. '<?php if (1) {
  224. xyz(
  225. $a=10,
  226. $b=20,
  227. $c=30
  228. );
  229. }',
  230. '<?php if (1) {
  231. xyz(
  232. $a=10 ,
  233. $b=20,
  234. $c=30
  235. );
  236. }',
  237. ];
  238. yield 'multi line anonymous class constructor call' => [
  239. '<?php if (1) {
  240. new class (
  241. $a=10,
  242. $b=20,
  243. $c=30
  244. ) {};
  245. }',
  246. '<?php if (1) {
  247. new class (
  248. $a=10 ,
  249. $b=20,$c=30) {};
  250. }',
  251. ];
  252. yield 'skip arrays but replace arg methods' => [
  253. '<?php fnc(1, array(2, func2(6, 7) ,4), 5);',
  254. '<?php fnc(1,array(2, func2(6, 7) ,4), 5);',
  255. ];
  256. yield 'skip arrays but replace arg methods (kmsac)' => [
  257. '<?php fnc(1, array(2, func2(6, 7) ,4), 5);',
  258. '<?php fnc(1,array(2, func2(6, 7) ,4), 5);',
  259. ['keep_multiple_spaces_after_comma' => true],
  260. ];
  261. yield 'ignore commas inside call argument' => [
  262. '<?php fnc(1, array(2, 3 ,4), 5);',
  263. ];
  264. yield 'skip multi line array' => [
  265. '<?php
  266. array(
  267. 10 ,
  268. 20,
  269. 30
  270. );',
  271. ];
  272. yield 'skip short array' => [
  273. '<?php
  274. $foo = ["a"=>"apple", "b"=>"bed" ,"c"=>"car"];
  275. $bar = ["a" ,"b" ,"c"];
  276. ',
  277. ];
  278. yield 'don\'t change HEREDOC and NOWDOC' => [
  279. "<?php if (1) {
  280. \$this->foo(
  281. <<<EOTXTa
  282. heredoc
  283. EOTXTa
  284. ,
  285. <<<'EOTXTb'
  286. nowdoc
  287. EOTXTb
  288. ,
  289. 'foo'
  290. );
  291. }",
  292. ];
  293. yield 'with_random_comments on_multiline:ignore' => [
  294. '<?php xyz#
  295. (#
  296. ""#
  297. ,#
  298. $a#
  299. );',
  300. null,
  301. ['on_multiline' => 'ignore'],
  302. ];
  303. yield 'with_random_comments on_multiline:ensure_single_line' => [
  304. '<?php xyz#
  305. (#
  306. ""#
  307. ,#
  308. $a#
  309. );',
  310. null,
  311. ['on_multiline' => 'ensure_single_line'],
  312. ];
  313. yield 'with_random_comments on_multiline:ensure_fully_multiline' => [
  314. '<?php xyz#
  315. (#
  316. ""#
  317. ,#
  318. $a#
  319. );',
  320. '<?php xyz#
  321. (#
  322. ""#
  323. ,#
  324. $a#
  325. );',
  326. ['on_multiline' => 'ensure_fully_multiline'],
  327. ];
  328. yield 'test half-multiline function becomes fully-multiline' => [
  329. <<<'EXPECTED'
  330. <?php
  331. functionCall(
  332. 'a',
  333. 'b',
  334. 'c'
  335. );
  336. EXPECTED
  337. ,
  338. <<<'INPUT'
  339. <?php
  340. functionCall(
  341. 'a', 'b',
  342. 'c'
  343. );
  344. INPUT
  345. ,
  346. ];
  347. yield 'test wrongly formatted half-multiline function becomes fully-multiline' => [
  348. '<?php
  349. f(
  350. 1,
  351. 2,
  352. 3
  353. );',
  354. '<?php
  355. f(1,2,
  356. 3);',
  357. ];
  358. yield 'function calls with here doc cannot be anything but multiline' => [
  359. <<<'EXPECTED'
  360. <?php
  361. str_replace(
  362. "\n",
  363. PHP_EOL,
  364. <<<'TEXT'
  365. 1) someFile.php
  366. TEXT
  367. );
  368. EXPECTED
  369. ,
  370. <<<'INPUT'
  371. <?php
  372. str_replace("\n", PHP_EOL, <<<'TEXT'
  373. 1) someFile.php
  374. TEXT
  375. );
  376. INPUT
  377. ,
  378. ];
  379. yield 'test barely multiline function with blank lines becomes fully-multiline' => [
  380. <<<'EXPECTED'
  381. <?php
  382. functionCall(
  383. 'a',
  384. 'b',
  385. 'c'
  386. );
  387. EXPECTED
  388. ,
  389. <<<'INPUT'
  390. <?php
  391. functionCall('a', 'b',
  392. 'c');
  393. INPUT
  394. ,
  395. ];
  396. yield 'test indentation is preserved' => [
  397. <<<'EXPECTED'
  398. <?php
  399. if (true) {
  400. functionCall(
  401. 'a',
  402. 'b',
  403. 'c'
  404. );
  405. }
  406. EXPECTED
  407. ,
  408. <<<'INPUT'
  409. <?php
  410. if (true) {
  411. functionCall(
  412. 'a', 'b',
  413. 'c'
  414. );
  415. }
  416. INPUT
  417. ,
  418. ];
  419. yield 'test multiline array arguments do not trigger multiline' => [
  420. <<<'EXPECTED'
  421. <?php
  422. defraculate(1, array(
  423. 'a',
  424. 'b',
  425. 'c',
  426. ), 42);
  427. EXPECTED
  428. ,
  429. ];
  430. yield 'test multiline function arguments do not trigger multiline' => [
  431. <<<'EXPECTED'
  432. <?php
  433. defraculate(1, function () {
  434. $a = 42;
  435. }, 42);
  436. EXPECTED
  437. ,
  438. ];
  439. yield 'test violation after opening parenthesis' => [
  440. <<<'EXPECTED'
  441. <?php
  442. defraculate(
  443. 1,
  444. 2,
  445. 3
  446. );
  447. EXPECTED
  448. ,
  449. <<<'INPUT'
  450. <?php
  451. defraculate(
  452. 1, 2, 3);
  453. INPUT
  454. ,
  455. ];
  456. yield 'test violation after opening parenthesis, indented with two spaces' => [
  457. <<<'EXPECTED'
  458. <?php
  459. defraculate(
  460. 1,
  461. 2,
  462. 3
  463. );
  464. EXPECTED
  465. ,
  466. <<<'INPUT'
  467. <?php
  468. defraculate(
  469. 1, 2, 3);
  470. INPUT
  471. ,
  472. ];
  473. yield 'test violation after opening parenthesis, indented with tabs' => [
  474. <<<'EXPECTED'
  475. <?php
  476. defraculate(
  477. 1,
  478. 2,
  479. 3
  480. );
  481. EXPECTED
  482. ,
  483. <<<'INPUT'
  484. <?php
  485. defraculate(
  486. 1, 2, 3);
  487. INPUT
  488. ,
  489. ];
  490. yield 'test violation before closing parenthesis' => [
  491. <<<'EXPECTED'
  492. <?php
  493. defraculate(
  494. 1,
  495. 2,
  496. 3
  497. );
  498. EXPECTED
  499. ,
  500. <<<'INPUT'
  501. <?php
  502. defraculate(1, 2, 3
  503. );
  504. INPUT
  505. ,
  506. ];
  507. yield 'test violation before closing parenthesis in nested call' => [
  508. <<<'EXPECTED'
  509. <?php
  510. getSchwifty('rick', defraculate(
  511. 1,
  512. 2,
  513. 3
  514. ), 'morty');
  515. EXPECTED
  516. ,
  517. <<<'INPUT'
  518. <?php
  519. getSchwifty('rick', defraculate(1, 2, 3
  520. ), 'morty');
  521. INPUT
  522. ,
  523. ];
  524. yield 'test with comment between arguments' => [
  525. <<<'EXPECTED'
  526. <?php
  527. functionCall(
  528. 'a', /* comment */
  529. 'b',
  530. 'c'
  531. );
  532. EXPECTED
  533. ,
  534. <<<'INPUT'
  535. <?php
  536. functionCall(
  537. 'a',/* comment */'b',
  538. 'c'
  539. );
  540. INPUT
  541. ,
  542. ];
  543. yield 'test with deeply nested arguments' => [
  544. <<<'EXPECTED'
  545. <?php
  546. foo(
  547. 'a',
  548. 'b',
  549. [
  550. 'c',
  551. 'd', bar('e', 'f'),
  552. baz(
  553. 'g',
  554. ['h',
  555. 'i',
  556. ]
  557. ),
  558. ]
  559. );
  560. EXPECTED
  561. ,
  562. <<<'INPUT'
  563. <?php
  564. foo('a',
  565. 'b',
  566. [
  567. 'c',
  568. 'd', bar('e', 'f'),
  569. baz('g',
  570. ['h',
  571. 'i',
  572. ]),
  573. ]);
  574. INPUT
  575. ,
  576. ];
  577. yield 'multiline string argument' => [
  578. <<<'UNAFFECTED'
  579. <?php
  580. $this->with('<?php
  581. %s
  582. class FooClass
  583. {
  584. }', $comment, false);
  585. UNAFFECTED
  586. ,
  587. ];
  588. yield 'arrays with whitespace inside' => [
  589. <<<'UNAFFECTED'
  590. <?php
  591. $a = array/**/( 1);
  592. $a = array/**/( 12,
  593. 7);
  594. $a = array/***/(123, 7);
  595. $a = array ( 1,
  596. 2);
  597. UNAFFECTED
  598. ,
  599. ];
  600. yield 'test code that should not be affected (because not a function nor a method)' => [
  601. <<<'UNAFFECTED'
  602. <?php
  603. if (true &&
  604. true
  605. ) {
  606. // do whatever
  607. }
  608. UNAFFECTED
  609. ,
  610. ];
  611. yield 'test ungodly code' => [
  612. <<<'EXPECTED'
  613. <?php
  614. $a = function#
  615. (#
  616. #
  617. $a#
  618. #
  619. ,#
  620. #
  621. $b,
  622. $c#
  623. #
  624. )#
  625. use (
  626. $b1,
  627. $c1,
  628. $d1
  629. ) {
  630. };
  631. EXPECTED
  632. ,
  633. <<<'INPUT'
  634. <?php
  635. $a = function#
  636. (#
  637. #
  638. $a#
  639. #
  640. ,#
  641. #
  642. $b,$c#
  643. #
  644. )#
  645. use ($b1,
  646. $c1,$d1) {
  647. };
  648. INPUT
  649. ,
  650. ];
  651. yield 'test list' => [
  652. <<<'UNAFFECTED'
  653. <?php
  654. // no fix
  655. list($a,
  656. $b, $c) = $a;
  657. isset($a,
  658. $b, $c);
  659. unset($a,
  660. $b, $c);
  661. array(1,
  662. 2,3
  663. );
  664. UNAFFECTED
  665. ,
  666. ];
  667. yield 'test function argument with multiline echo in it' => [
  668. <<<'UNAFFECTED'
  669. <?php
  670. call_user_func(function ($arguments) {
  671. echo 'a',
  672. 'b';
  673. }, $argv);
  674. UNAFFECTED
  675. ,
  676. ];
  677. yield 'test function argument with oneline echo in it' => [
  678. <<<'EXPECTED'
  679. <?php
  680. call_user_func(
  681. function ($arguments) {
  682. echo 'a', 'b';
  683. },
  684. $argv
  685. );
  686. EXPECTED
  687. ,
  688. <<<'INPUT'
  689. <?php
  690. call_user_func(function ($arguments) {
  691. echo 'a', 'b';
  692. },
  693. $argv);
  694. INPUT
  695. ,
  696. ];
  697. yield 'ensure_single_line' => [
  698. <<<'EXPECTED'
  699. <?php
  700. function foo($a, $b) {
  701. // foo
  702. }
  703. foo($a, $b);
  704. EXPECTED
  705. ,
  706. <<<'INPUT'
  707. <?php
  708. function foo(
  709. $a,
  710. $b
  711. ) {
  712. // foo
  713. }
  714. foo(
  715. $a,
  716. $b
  717. );
  718. INPUT
  719. ,
  720. ['on_multiline' => 'ensure_single_line'],
  721. ];
  722. yield 'ensure_single_line_with_random_comments' => [
  723. <<<'EXPECTED'
  724. <?php
  725. function foo(/* foo */// bar
  726. $a, /* foo */// bar
  727. $b#foo
  728. ) {
  729. // foo
  730. }
  731. foo(/* foo */// bar
  732. $a, /* foo */// bar
  733. $b#foo
  734. );
  735. EXPECTED
  736. ,
  737. null,
  738. ['on_multiline' => 'ensure_single_line'],
  739. ];
  740. yield 'ensure_single_line_with_consecutive_newlines' => [
  741. <<<'EXPECTED'
  742. <?php
  743. function foo($a, $b) {
  744. // foo
  745. }
  746. foo($a, $b);
  747. EXPECTED
  748. ,
  749. <<<'INPUT'
  750. <?php
  751. function foo(
  752. $a,
  753. $b
  754. ) {
  755. // foo
  756. }
  757. foo(
  758. $a,
  759. $b
  760. );
  761. INPUT
  762. ,
  763. ['on_multiline' => 'ensure_single_line'],
  764. ];
  765. yield 'ensure_single_line_methods' => [
  766. <<<'EXPECTED'
  767. <?php
  768. class Foo {
  769. public static function foo1($a, $b, $c) {}
  770. private function foo2($a, $b, $c) {}
  771. }
  772. EXPECTED
  773. ,
  774. <<<'INPUT'
  775. <?php
  776. class Foo {
  777. public static function foo1(
  778. $a,
  779. $b,
  780. $c
  781. ) {}
  782. private function foo2(
  783. $a,
  784. $b,
  785. $c
  786. ) {}
  787. }
  788. INPUT
  789. ,
  790. ['on_multiline' => 'ensure_single_line'],
  791. ];
  792. yield 'ensure_single_line_methods_in_anonymous_class' => [
  793. <<<'EXPECTED'
  794. <?php
  795. new class {
  796. public static function foo1($a, $b, $c) {}
  797. private function foo2($a, $b, $c) {}
  798. };
  799. EXPECTED
  800. ,
  801. <<<'INPUT'
  802. <?php
  803. new class {
  804. public static function foo1(
  805. $a,
  806. $b,
  807. $c
  808. ) {}
  809. private function foo2(
  810. $a,
  811. $b,
  812. $c
  813. ) {}
  814. };
  815. INPUT
  816. ,
  817. ['on_multiline' => 'ensure_single_line'],
  818. ];
  819. yield 'ensure_single_line_keep_spaces_after_comma' => [
  820. <<<'EXPECTED'
  821. <?php
  822. function foo($a, $b) {
  823. // foo
  824. }
  825. foo($a, $b);
  826. EXPECTED
  827. ,
  828. <<<'INPUT'
  829. <?php
  830. function foo(
  831. $a,
  832. $b
  833. ) {
  834. // foo
  835. }
  836. foo(
  837. $a,
  838. $b
  839. );
  840. INPUT
  841. ,
  842. [
  843. 'on_multiline' => 'ensure_single_line',
  844. 'keep_multiple_spaces_after_comma' => true,
  845. ],
  846. ];
  847. yield 'fix closing parenthesis (without trailing comma)' => [
  848. '<?php
  849. if (true) {
  850. execute(
  851. $foo,
  852. $bar
  853. );
  854. }',
  855. '<?php
  856. if (true) {
  857. execute(
  858. $foo,
  859. $bar
  860. );
  861. }',
  862. [
  863. 'on_multiline' => 'ensure_fully_multiline',
  864. ],
  865. ];
  866. yield 'test anonymous functions' => [
  867. '<?php
  868. $example = function () use ($message1, $message2) {
  869. };',
  870. '<?php
  871. $example = function () use ($message1,$message2) {
  872. };',
  873. ];
  874. yield 'test first element in same line, space before comma and inconsistent indent' => [
  875. '<?php foo(
  876. "aaa
  877. bbb",
  878. $c,
  879. $d,
  880. $e,
  881. $f
  882. );
  883. ',
  884. '<?php foo("aaa
  885. bbb",
  886. $c, $d ,
  887. $e,
  888. $f);
  889. ',
  890. ];
  891. yield 'test first element in same line, space before comma and inconsistent indent with comments' => [
  892. '<?php foo(
  893. "aaa
  894. bbb", // comment1
  895. $c, /** comment2 */
  896. $d,
  897. $e/* comment3 */,
  898. $f
  899. );# comment4
  900. ',
  901. '<?php foo("aaa
  902. bbb", // comment1
  903. $c, /** comment2 */$d ,
  904. $e/* comment3 */,
  905. $f);# comment4
  906. ',
  907. ];
  908. yield [
  909. '<?php
  910. foo(
  911. /* bar */
  912. "baz"
  913. );
  914. ',
  915. '<?php
  916. foo(
  917. /* bar */ "baz"
  918. );
  919. ',
  920. ];
  921. }
  922. /**
  923. * @param array<string, mixed> $config
  924. *
  925. * @dataProvider provideFix2Cases
  926. */
  927. public function testFix2(string $expected, ?string $input = null, array $config = []): void
  928. {
  929. $this->fixer->configure($config);
  930. $this->doTest($expected, $input);
  931. }
  932. public static function provideFix2Cases(): iterable
  933. {
  934. yield [
  935. '<?php function A($c, ...$a){}',
  936. '<?php function A($c ,...$a){}',
  937. ];
  938. yield [
  939. <<<'EXPECTED'
  940. <?php
  941. foo(
  942. <<<'EOD'
  943. bar
  944. EOD,
  945. 'baz'
  946. );
  947. EXPECTED
  948. ,
  949. <<<'INPUT'
  950. <?php
  951. foo(
  952. <<<'EOD'
  953. bar
  954. EOD
  955. ,
  956. 'baz'
  957. );
  958. INPUT
  959. ,
  960. ['after_heredoc' => true],
  961. ];
  962. yield [
  963. <<<'EXPECTED'
  964. <?php
  965. foo(
  966. $bar,
  967. $baz,
  968. );
  969. EXPECTED
  970. ,
  971. null,
  972. ['on_multiline' => 'ensure_fully_multiline'],
  973. ];
  974. yield [
  975. '<?php
  976. functionCall(
  977. 1,
  978. 2,
  979. 3,
  980. );',
  981. '<?php
  982. functionCall(
  983. 1, 2,
  984. 3,
  985. );',
  986. [
  987. 'on_multiline' => 'ensure_fully_multiline',
  988. ],
  989. ];
  990. yield [
  991. '<?php foo(1, 2, 3, );',
  992. '<?php foo(1,2,3,);',
  993. ];
  994. yield [
  995. '<?php
  996. $fn = fn(
  997. $test1,
  998. $test2
  999. ) => null;',
  1000. '<?php
  1001. $fn = fn(
  1002. $test1, $test2
  1003. ) => null;',
  1004. [
  1005. 'on_multiline' => 'ensure_fully_multiline',
  1006. ],
  1007. ];
  1008. }
  1009. /**
  1010. * @param array<string, mixed> $config
  1011. *
  1012. * @dataProvider provideFix80Cases
  1013. *
  1014. * @requires PHP 8.0
  1015. */
  1016. public function testFix80(string $expected, ?string $input = null, array $config = []): void
  1017. {
  1018. $this->fixer->configure($config);
  1019. $this->doTest($expected, $input);
  1020. }
  1021. public static function provideFix80Cases(): iterable
  1022. {
  1023. yield 'multiple attributes' => [
  1024. '<?php
  1025. class MyClass
  1026. {
  1027. public function __construct(
  1028. private string $id,
  1029. #[Foo]
  1030. #[Bar]
  1031. private ?string $name = null,
  1032. ) {}
  1033. }',
  1034. '<?php
  1035. class MyClass
  1036. {
  1037. public function __construct(
  1038. private string $id,
  1039. #[Foo] #[Bar] private ?string $name = null,
  1040. ) {}
  1041. }',
  1042. ];
  1043. yield 'keep attributes as-is' => [
  1044. '<?php
  1045. class MyClass
  1046. {
  1047. public function __construct(
  1048. private string $id,
  1049. #[Foo] #[Bar] private ?string $name = null,
  1050. ) {}
  1051. }',
  1052. null,
  1053. [
  1054. 'attribute_placement' => 'ignore',
  1055. ],
  1056. ];
  1057. yield 'multiple attributes on the same line as argument' => [
  1058. '<?php
  1059. class MyClass
  1060. {
  1061. public function __construct(
  1062. private string $id,
  1063. #[Foo] #[Bar] private ?string $name = null,
  1064. ) {}
  1065. }',
  1066. '<?php
  1067. class MyClass
  1068. {
  1069. public function __construct(
  1070. private string $id,
  1071. #[Foo]
  1072. #[Bar]
  1073. private ?string $name = null,
  1074. ) {}
  1075. }',
  1076. [
  1077. 'attribute_placement' => 'same_line',
  1078. ],
  1079. ];
  1080. yield 'single attribute markup with comma separated list' => [
  1081. '<?php
  1082. class MyClass
  1083. {
  1084. public function __construct(
  1085. private string $id,
  1086. #[Foo, Bar]
  1087. private ?string $name = null,
  1088. ) {}
  1089. }',
  1090. '<?php
  1091. class MyClass
  1092. {
  1093. public function __construct(
  1094. private string $id,
  1095. #[Foo, Bar] private ?string $name = null,
  1096. ) {}
  1097. }',
  1098. ];
  1099. yield 'attributes with arguments' => [
  1100. '<?php
  1101. class MyClass
  1102. {
  1103. public function __construct(
  1104. private string $id,
  1105. #[Foo(value: 1234, otherValue: [1, 2, 3])]
  1106. #[Bar(Bar::BAZ, array(\'[\',\']\'))]
  1107. private ?string $name = null,
  1108. ) {}
  1109. }',
  1110. '<?php
  1111. class MyClass
  1112. {
  1113. public function __construct(
  1114. private string $id,
  1115. #[Foo(value: 1234, otherValue: [1, 2, 3])] #[Bar(Bar::BAZ, array(\'[\',\']\'))] private ?string $name = null,
  1116. ) {}
  1117. }',
  1118. ];
  1119. yield 'fully qualified attributes' => [
  1120. '<?php
  1121. function foo(
  1122. #[\Foo\Bar]
  1123. $bar,
  1124. #[\Foo\Baz]
  1125. $baz,
  1126. #[\Foo\Buzz]
  1127. $buzz
  1128. ) {}',
  1129. '<?php
  1130. function foo(
  1131. #[\Foo\Bar] $bar, #[\Foo\Baz] $baz, #[\Foo\Buzz] $buzz
  1132. ) {}',
  1133. ];
  1134. yield 'multiline attributes' => [
  1135. '<?php
  1136. function foo(
  1137. $foo,
  1138. #[
  1139. Foo\Bar,
  1140. Foo\Baz,
  1141. Foo\Buzz(a: \'astral\', b: 1234),
  1142. ]
  1143. $bar
  1144. ) {}',
  1145. '<?php
  1146. function foo($foo, #[
  1147. Foo\Bar,
  1148. Foo\Baz,
  1149. Foo\Buzz(a: \'astral\', b: 1234),
  1150. ] $bar) {}',
  1151. ];
  1152. }
  1153. /**
  1154. * @dataProvider provideFix81Cases
  1155. *
  1156. * @requires PHP 8.1
  1157. */
  1158. public function testFix81(string $expected, ?string $input = null): void
  1159. {
  1160. $this->doTest($expected, $input);
  1161. }
  1162. public static function provideFix81Cases(): iterable
  1163. {
  1164. yield [
  1165. '<?php
  1166. [Foo::class, \'method\'](
  1167. ...
  1168. ) ?>',
  1169. '<?php
  1170. [Foo::class, \'method\']( ...
  1171. ) ?>',
  1172. ];
  1173. }
  1174. }