MethodArgumentSpaceFixerTest.php 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235
  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. }
  909. /**
  910. * @param array<string, mixed> $config
  911. *
  912. * @dataProvider provideFix2Cases
  913. */
  914. public function testFix2(string $expected, ?string $input = null, array $config = []): void
  915. {
  916. $this->fixer->configure($config);
  917. $this->doTest($expected, $input);
  918. }
  919. public static function provideFix2Cases(): iterable
  920. {
  921. yield [
  922. '<?php function A($c, ...$a){}',
  923. '<?php function A($c ,...$a){}',
  924. ];
  925. yield [
  926. <<<'EXPECTED'
  927. <?php
  928. foo(
  929. <<<'EOD'
  930. bar
  931. EOD,
  932. 'baz'
  933. );
  934. EXPECTED
  935. ,
  936. <<<'INPUT'
  937. <?php
  938. foo(
  939. <<<'EOD'
  940. bar
  941. EOD
  942. ,
  943. 'baz'
  944. );
  945. INPUT
  946. ,
  947. ['after_heredoc' => true],
  948. ];
  949. yield [
  950. <<<'EXPECTED'
  951. <?php
  952. foo(
  953. $bar,
  954. $baz,
  955. );
  956. EXPECTED
  957. ,
  958. null,
  959. ['on_multiline' => 'ensure_fully_multiline'],
  960. ];
  961. yield [
  962. '<?php
  963. functionCall(
  964. 1,
  965. 2,
  966. 3,
  967. );',
  968. '<?php
  969. functionCall(
  970. 1, 2,
  971. 3,
  972. );',
  973. [
  974. 'on_multiline' => 'ensure_fully_multiline',
  975. ],
  976. ];
  977. yield [
  978. '<?php foo(1, 2, 3, );',
  979. '<?php foo(1,2,3,);',
  980. ];
  981. yield [
  982. '<?php
  983. $fn = fn(
  984. $test1,
  985. $test2
  986. ) => null;',
  987. '<?php
  988. $fn = fn(
  989. $test1, $test2
  990. ) => null;',
  991. [
  992. 'on_multiline' => 'ensure_fully_multiline',
  993. ],
  994. ];
  995. }
  996. /**
  997. * @dataProvider provideFix80Cases
  998. *
  999. * @requires PHP 8.0
  1000. */
  1001. public function testFix80(string $expected, ?string $input = null): void
  1002. {
  1003. $this->doTest($expected, $input);
  1004. }
  1005. public static function provideFix80Cases(): iterable
  1006. {
  1007. yield 'multiple attributes' => [
  1008. '<?php
  1009. class MyClass
  1010. {
  1011. public function __construct(
  1012. private string $id,
  1013. #[Foo]
  1014. #[Bar]
  1015. private ?string $name = null,
  1016. ) {}
  1017. }',
  1018. '<?php
  1019. class MyClass
  1020. {
  1021. public function __construct(
  1022. private string $id,
  1023. #[Foo] #[Bar] private ?string $name = null,
  1024. ) {}
  1025. }',
  1026. ];
  1027. yield 'single attribute markup with comma separated list' => [
  1028. '<?php
  1029. class MyClass
  1030. {
  1031. public function __construct(
  1032. private string $id,
  1033. #[Foo, Bar]
  1034. private ?string $name = null,
  1035. ) {}
  1036. }',
  1037. '<?php
  1038. class MyClass
  1039. {
  1040. public function __construct(
  1041. private string $id,
  1042. #[Foo, Bar] private ?string $name = null,
  1043. ) {}
  1044. }',
  1045. ];
  1046. yield 'attributes with arguments' => [
  1047. '<?php
  1048. class MyClass
  1049. {
  1050. public function __construct(
  1051. private string $id,
  1052. #[Foo(value: 1234, otherValue: [1, 2, 3])]
  1053. #[Bar(Bar::BAZ, array(\'[\',\']\'))]
  1054. private ?string $name = null,
  1055. ) {}
  1056. }',
  1057. '<?php
  1058. class MyClass
  1059. {
  1060. public function __construct(
  1061. private string $id,
  1062. #[Foo(value: 1234, otherValue: [1, 2, 3])] #[Bar(Bar::BAZ, array(\'[\',\']\'))] private ?string $name = null,
  1063. ) {}
  1064. }',
  1065. ];
  1066. yield 'fully qualified attributes' => [
  1067. '<?php
  1068. function foo(
  1069. #[\Foo\Bar]
  1070. $bar,
  1071. #[\Foo\Baz]
  1072. $baz,
  1073. #[\Foo\Buzz]
  1074. $buzz
  1075. ) {}',
  1076. '<?php
  1077. function foo(
  1078. #[\Foo\Bar] $bar, #[\Foo\Baz] $baz, #[\Foo\Buzz] $buzz
  1079. ) {}',
  1080. ];
  1081. yield 'multiline attributes' => [
  1082. '<?php
  1083. function foo(
  1084. $foo,
  1085. #[
  1086. Foo\Bar,
  1087. Foo\Baz,
  1088. Foo\Buzz(a: \'astral\', b: 1234),
  1089. ]
  1090. $bar
  1091. ) {}',
  1092. '<?php
  1093. function foo($foo, #[
  1094. Foo\Bar,
  1095. Foo\Baz,
  1096. Foo\Buzz(a: \'astral\', b: 1234),
  1097. ] $bar) {}',
  1098. ];
  1099. }
  1100. /**
  1101. * @dataProvider provideFix81Cases
  1102. *
  1103. * @requires PHP 8.1
  1104. */
  1105. public function testFix81(string $expected, ?string $input = null): void
  1106. {
  1107. $this->doTest($expected, $input);
  1108. }
  1109. public static function provideFix81Cases(): iterable
  1110. {
  1111. yield [
  1112. '<?php
  1113. [Foo::class, \'method\'](
  1114. ...
  1115. ) ?>',
  1116. '<?php
  1117. [Foo::class, \'method\']( ...
  1118. ) ?>',
  1119. ];
  1120. }
  1121. }