NoTrailingCommaInSinglelineFixerTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  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\Basic;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @internal
  16. *
  17. * @covers \PhpCsFixer\Fixer\Basic\NoTrailingCommaInSinglelineFixer
  18. *
  19. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Basic\NoTrailingCommaInSinglelineFixer>
  20. *
  21. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\Basic\NoTrailingCommaInSinglelineFixer
  22. */
  23. final class NoTrailingCommaInSinglelineFixerTest extends AbstractFixerTestCase
  24. {
  25. /**
  26. * @param _AutogeneratedInputConfiguration $configuration
  27. *
  28. * @dataProvider provideFixCases
  29. */
  30. public function testFix(string $expected, ?string $input = null, array $configuration = []): void
  31. {
  32. $this->fixer->configure($configuration);
  33. $this->doTest($expected, $input);
  34. }
  35. /**
  36. * @return iterable<array{string, null|string, 2?: array{elements?: list<string>}}>
  37. */
  38. public static function provideFixCases(): iterable
  39. {
  40. yield [
  41. '<?php [$x, $y] = $a;',
  42. '<?php [$x, $y,] = $a;',
  43. ];
  44. yield 'group_import' => [
  45. '<?php use a\{ClassA, ClassB};',
  46. '<?php use a\{ClassA, ClassB,};',
  47. ];
  48. yield 'lots of nested' => [
  49. '<?php $a = [1,[1,[1,[1,[1,[1,[1,[1]],[1,[1,[1,[1,[1,[1,[1,[1]]]]]]]]]]]]]];',
  50. '<?php $a = [1,[1,[1,[1,[1,[1,[1,[1,],],[1,[1,[1,[1,[1,[1,[1,[1,],],],],],],],],],],],],],];',
  51. ];
  52. yield 'simple var' => [
  53. '<?php $a(1);',
  54. '<?php $a(1,);',
  55. ['elements' => ['arguments']],
  56. ];
  57. yield '&' => [
  58. '<?php $a = &foo($a);',
  59. '<?php $a = &foo($a,);',
  60. ['elements' => ['arguments']],
  61. ];
  62. yield 'open' => [
  63. '<?php foo($a);',
  64. '<?php foo($a,);',
  65. ['elements' => ['arguments']],
  66. ];
  67. yield '=' => [
  68. '<?php $b = foo($a);',
  69. '<?php $b = foo($a,);',
  70. ['elements' => ['arguments']],
  71. ];
  72. yield '.' => [
  73. '<?php $c = $b . foo($a);',
  74. '<?php $c = $b . foo($a,);',
  75. ['elements' => ['arguments']],
  76. ];
  77. yield '(' => [
  78. '<?php (foo($a/* 1X */ /* 2 */ ));',
  79. '<?php (foo($a /* 1X */ , /* 2 */ ));',
  80. ['elements' => ['arguments']],
  81. ];
  82. yield '\\' => [
  83. '<?php \foo($a);',
  84. '<?php \foo($a,);',
  85. ['elements' => ['arguments']],
  86. ];
  87. yield 'A\\' => [
  88. '<?php A\foo($a);',
  89. '<?php A\foo($a,);',
  90. ['elements' => ['arguments']],
  91. ];
  92. yield '\A\\' => [
  93. '<?php \A\foo($a);',
  94. '<?php \A\foo($a,);',
  95. ['elements' => ['arguments']],
  96. ];
  97. yield ';' => [
  98. '<?php ; foo($a);',
  99. '<?php ; foo($a,);',
  100. ['elements' => ['arguments']],
  101. ];
  102. yield '}' => [
  103. '<?php if ($a) { echo 1;} foo($a);',
  104. '<?php if ($a) { echo 1;} foo($a,);',
  105. ['elements' => ['arguments']],
  106. ];
  107. yield 'test method call' => [
  108. '<?php $o->abc($a);',
  109. '<?php $o->abc($a,);',
  110. ['elements' => ['arguments']],
  111. ];
  112. yield 'nested call' => [
  113. '<?php $o->abc($a,foo(1));',
  114. '<?php $o->abc($a,foo(1,));',
  115. ['elements' => ['arguments']],
  116. ];
  117. yield 'wrapped' => [
  118. '<?php echo (new Process())->getOutput(1);',
  119. '<?php echo (new Process())->getOutput(1,);',
  120. ['elements' => ['arguments']],
  121. ];
  122. yield 'dynamic function and method calls' => [
  123. '<?php $b->$a(1); $c("");',
  124. '<?php $b->$a(1,); $c("",);',
  125. ['elements' => ['arguments']],
  126. ];
  127. yield 'static function call' => [
  128. '<?php
  129. unset($foo->bar);
  130. $b = isset($foo->bar);
  131. ',
  132. '<?php
  133. unset($foo->bar,);
  134. $b = isset($foo->bar,);
  135. ',
  136. ['elements' => ['arguments']],
  137. ];
  138. yield 'unset' => [
  139. '<?php A::foo(1);',
  140. '<?php A::foo(1,);',
  141. ['elements' => ['arguments']],
  142. ];
  143. yield 'anonymous_class construction' => [
  144. '<?php new class(1, 2) {};',
  145. '<?php new class(1, 2,) {};',
  146. ['elements' => ['arguments']],
  147. ];
  148. yield 'array/property access call' => [
  149. '<?php
  150. $a = [
  151. "e" => static function(int $a): void{ echo $a;},
  152. "d" => [
  153. [2 => static function(int $a): void{ echo $a;}]
  154. ]
  155. ];
  156. $a["e"](1);
  157. $a["d"][0][2](1);
  158. $z = new class { public static function b(int $a): void {echo $a; }};
  159. $z::b(1);
  160. ${$e}(1);
  161. $$e(2);
  162. $f(0)(1);
  163. $g["e"](1); // foo',
  164. '<?php
  165. $a = [
  166. "e" => static function(int $a): void{ echo $a;},
  167. "d" => [
  168. [2 => static function(int $a): void{ echo $a;}]
  169. ]
  170. ];
  171. $a["e"](1,);
  172. $a["d"][0][2](1,);
  173. $z = new class { public static function b(int $a): void {echo $a; }};
  174. $z::b(1,);
  175. ${$e}(1,);
  176. $$e(2,);
  177. $f(0,)(1,);
  178. $g["e"](1,); // foo',
  179. ['elements' => ['arguments']],
  180. ];
  181. yield 'do not fix' => [
  182. '<?php
  183. function someFunction ($p1){}
  184. function & foo($a,$b): array { return []; }
  185. foo (
  186. 1,
  187. 2,
  188. );
  189. $a = new class (
  190. $a,
  191. ) {};
  192. isset($a, $b);
  193. unset($a,$b);
  194. list($a,$b) = $a;
  195. $a = [1,2,3,];
  196. $a = array(1,2,3,);
  197. function foo1(string $param = null ): void
  198. {
  199. }
  200. ;',
  201. null,
  202. ['elements' => ['arguments']],
  203. ];
  204. yield [
  205. '<?php $x = array();',
  206. null,
  207. ['elements' => ['array']],
  208. ];
  209. yield [
  210. '<?php $x = array("foo");',
  211. null,
  212. ['elements' => ['array']],
  213. ];
  214. yield [
  215. '<?php $x = array("foo");',
  216. '<?php $x = array("foo", );',
  217. ['elements' => ['array']],
  218. ];
  219. yield [
  220. "<?php \$x = array(\n'foo', \n);",
  221. null,
  222. ['elements' => ['array']],
  223. ];
  224. yield [
  225. "<?php \$x = array('foo', \n);",
  226. null,
  227. ['elements' => ['array']],
  228. ];
  229. yield [
  230. "<?php \$x = array(array('foo'), \n);",
  231. "<?php \$x = array(array('foo',), \n);",
  232. ['elements' => ['array']],
  233. ];
  234. yield [
  235. "<?php \$x = array(array('foo',\n), \n);",
  236. null,
  237. ['elements' => ['array']],
  238. ];
  239. yield [
  240. '<?php
  241. $test = array("foo", <<<TWIG
  242. foo
  243. TWIG
  244. , $twig, );',
  245. null,
  246. ['elements' => ['array']],
  247. ];
  248. yield [
  249. '<?php
  250. $test = array(
  251. "foo", <<<TWIG
  252. foo
  253. TWIG
  254. , $twig, );',
  255. null,
  256. ['elements' => ['array']],
  257. ];
  258. yield [
  259. '<?php
  260. $test = array("foo", <<<\'TWIG\'
  261. foo
  262. TWIG
  263. , $twig, );',
  264. null,
  265. ['elements' => ['array']],
  266. ];
  267. yield [
  268. '<?php
  269. $test = array(
  270. "foo", <<<\'TWIG\'
  271. foo
  272. TWIG
  273. , $twig, );',
  274. null,
  275. ['elements' => ['array']],
  276. ];
  277. // Short syntax
  278. yield [
  279. '<?php $x = array([]);',
  280. null,
  281. ['elements' => ['array']],
  282. ];
  283. yield [
  284. '<?php $x = [[]];',
  285. null,
  286. ['elements' => ['array']],
  287. ];
  288. yield [
  289. '<?php $x = ["foo"];',
  290. '<?php $x = ["foo",];',
  291. ['elements' => ['array']],
  292. ];
  293. yield [
  294. '<?php $x = bar(["foo"]);',
  295. '<?php $x = bar(["foo",]);',
  296. ['elements' => ['array']],
  297. ];
  298. yield [
  299. "<?php \$x = bar([['foo'],\n]);",
  300. null,
  301. ['elements' => ['array']],
  302. ];
  303. yield [
  304. "<?php \$x = ['foo', \n];",
  305. null,
  306. ['elements' => ['array']],
  307. ];
  308. yield [
  309. '<?php $x = array([]);',
  310. '<?php $x = array([],);',
  311. ['elements' => ['array']],
  312. ];
  313. yield [
  314. '<?php $x = [[]];',
  315. '<?php $x = [[],];',
  316. ['elements' => ['array']],
  317. ];
  318. yield [
  319. '<?php $x = [$y[""]];',
  320. '<?php $x = [$y[""],];',
  321. ['elements' => ['array']],
  322. ];
  323. yield [
  324. '<?php
  325. $test = ["foo", <<<TWIG
  326. foo
  327. TWIG
  328. , $twig, ];',
  329. null,
  330. ['elements' => ['array']],
  331. ];
  332. yield [
  333. '<?php
  334. $test = [
  335. "foo", <<<TWIG
  336. foo
  337. TWIG
  338. , $twig, ];',
  339. null,
  340. ['elements' => ['array']],
  341. ];
  342. yield [
  343. '<?php
  344. $test = ["foo", <<<\'TWIG\'
  345. foo
  346. TWIG
  347. , $twig, ];',
  348. null,
  349. ['elements' => ['array']],
  350. ];
  351. yield [
  352. '<?php
  353. $test = [
  354. "foo", <<<\'TWIG\'
  355. foo
  356. TWIG
  357. , $twig, ];',
  358. null,
  359. ['elements' => ['array']],
  360. ];
  361. yield [
  362. '<?php $x = array(...$foo);',
  363. '<?php $x = array(...$foo, );',
  364. ['elements' => ['array']],
  365. ];
  366. yield [
  367. '<?php $x = [...$foo];',
  368. '<?php $x = [...$foo, ];',
  369. ['elements' => ['array']],
  370. ];
  371. yield [
  372. '<?php
  373. list($a1, $b) = foo();
  374. list($a2, , $c, $d) = foo();
  375. list($a3, , $c) = foo();
  376. list($a4) = foo();
  377. list($a5 , $b) = foo();
  378. list($a6, /* $b */, $c) = foo();
  379. ',
  380. '<?php
  381. list($a1, $b) = foo();
  382. list($a2, , $c, $d, ) = foo();
  383. list($a3, , $c, , ) = foo();
  384. list($a4, , , , , ) = foo();
  385. list($a5 , $b , ) = foo();
  386. list($a6, /* $b */, $c, ) = foo();
  387. ',
  388. ['elements' => ['array_destructuring']],
  389. ];
  390. yield [
  391. '<?php
  392. list(
  393. $a#
  394. ,#
  395. #
  396. ) = $a;',
  397. null,
  398. ['elements' => ['array_destructuring']],
  399. ];
  400. yield [
  401. '<?php
  402. [$a7, $b] = foo();
  403. [$a8, , $c, $d] = foo();
  404. [$a9, , $c] = foo();
  405. [$a10] = foo();
  406. [$a11 , $b] = foo();
  407. [$a12, /* $b */, $c] = foo();
  408. ',
  409. '<?php
  410. [$a7, $b] = foo();
  411. [$a8, , $c, $d, ] = foo();
  412. [$a9, , $c, , ] = foo();
  413. [$a10, , , , , ] = foo();
  414. [$a11 , $b , ] = foo();
  415. [$a12, /* $b */, $c, ] = foo();
  416. ',
  417. ['elements' => ['array_destructuring']],
  418. ];
  419. }
  420. /**
  421. * @dataProvider provideFix80Cases
  422. *
  423. * @requires PHP 8.0
  424. */
  425. public function testFix80(string $expected, ?string $input = null): void
  426. {
  427. $this->doTest($expected, $input);
  428. }
  429. /**
  430. * @return iterable<array{string}>
  431. */
  432. public static function provideFix80Cases(): iterable
  433. {
  434. yield [
  435. '<?php function foo(
  436. #[MyAttr(1, 2,)] Type $myParam,
  437. ) {}
  438. $foo1b = function() use ($bar, ) {};
  439. ',
  440. ];
  441. }
  442. /**
  443. * @dataProvider provideFix81Cases
  444. *
  445. * @requires PHP 8.1
  446. */
  447. public function testFix81(string $expected, ?string $input = null): void
  448. {
  449. $this->doTest($expected, $input);
  450. }
  451. /**
  452. * @return iterable<array{string, string}>
  453. */
  454. public static function provideFix81Cases(): iterable
  455. {
  456. yield [
  457. '<?php $object?->method(1); strlen(...);',
  458. '<?php $object?->method(1,); strlen(...);',
  459. ];
  460. }
  461. }