NoUnneededControlParenthesesFixerTest.php 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of PHP CS Fixer.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. namespace PhpCsFixer\Tests\Fixer\ControlStructure;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @author Sullivan Senechal <soullivaneuh@gmail.com>
  16. * @author Gregor Harlan <gharlan@web.de>
  17. *
  18. * @internal
  19. *
  20. * @covers \PhpCsFixer\Fixer\ControlStructure\NoUnneededControlParenthesesFixer
  21. */
  22. final class NoUnneededControlParenthesesFixerTest extends AbstractFixerTestCase
  23. {
  24. /**
  25. * @dataProvider provideFixCases
  26. */
  27. public function testFix(string $expected, ?string $input = null): void
  28. {
  29. $this->fixer->configure(
  30. [
  31. 'statements' => [
  32. 'break',
  33. 'clone',
  34. 'continue',
  35. 'echo_print',
  36. 'return',
  37. 'switch_case',
  38. 'yield',
  39. 'yield_from',
  40. 'others',
  41. ],
  42. ],
  43. );
  44. $this->doTest($expected, $input);
  45. }
  46. public static function provideFixCases(): iterable
  47. {
  48. yield [
  49. '<?php while ($x) { while ($y) { break 2; } }',
  50. '<?php while ($x) { while ($y) { break (2); } }',
  51. ];
  52. yield [
  53. '<?php while ($x) { while ($y) { break 2; } }',
  54. '<?php while ($x) { while ($y) { break(2); } }',
  55. ];
  56. yield [
  57. '<?php while ($x) { while ($y) { continue 2; } }',
  58. '<?php while ($x) { while ($y) { continue (2); } }',
  59. ];
  60. yield [
  61. '<?php while ($x) { while ($y) { continue 2; } }',
  62. '<?php while ($x) { while ($y) { continue(2); } }',
  63. ];
  64. yield [
  65. '<?php
  66. $var = clone ($obj1 ?: $obj2);
  67. $var = clone ($obj1 ? $obj1->getSubject() : $obj2);
  68. ',
  69. ];
  70. yield [
  71. '<?php clone $object;',
  72. '<?php clone ($object);',
  73. ];
  74. yield [
  75. '<?php clone new Foo();',
  76. '<?php clone (new Foo());',
  77. ];
  78. yield [
  79. '<?php
  80. foo(clone $a);
  81. foo(clone $a, 1);
  82. $a = $b ? clone $b : $c;
  83. ',
  84. '<?php
  85. foo(clone($a));
  86. foo(clone($a), 1);
  87. $a = $b ? clone($b) : $c;
  88. ',
  89. ];
  90. yield [
  91. '<?php
  92. echo (1 + 2) . $foo;
  93. print (1 + 2) . $foo;
  94. ',
  95. ];
  96. yield [
  97. '<?php echo (1 + 2) * 10, "\n";',
  98. ];
  99. yield [
  100. '<?php echo (1 + 2) * 10, "\n" ?>',
  101. ];
  102. yield [
  103. '<?php echo "foo" ?>',
  104. '<?php echo ("foo") ?>',
  105. ];
  106. yield [
  107. '<?php print "foo" ?>',
  108. '<?php print ("foo") ?>',
  109. ];
  110. yield [
  111. '<?php echo "foo2"; print "foo";',
  112. '<?php echo ("foo2"); print ("foo");',
  113. ];
  114. yield [
  115. '<?php echo "foo"; print "foo1";',
  116. '<?php echo("foo"); print("foo1");',
  117. ];
  118. yield [
  119. '<?php echo 2; print 2;',
  120. '<?php echo(2); print(2);',
  121. ];
  122. yield [
  123. '<?php
  124. echo $a ? $b : $c;
  125. echo ($a ? $b : $c) ? $d : $e;
  126. echo 10 * (2 + 3);
  127. echo ("foo"), ("bar");
  128. echo my_awesome_function("foo");
  129. echo $this->getOutput(1);
  130. ',
  131. '<?php
  132. echo ($a ? $b : $c);
  133. echo ($a ? $b : $c) ? $d : $e;
  134. echo 10 * (2 + 3);
  135. echo ("foo"), ("bar");
  136. echo my_awesome_function("foo");
  137. echo $this->getOutput(1);
  138. ',
  139. ];
  140. yield [
  141. '<?php return (1 + 2) * 10;',
  142. '<?php return ((1 + 2) * 10);',
  143. ];
  144. yield [
  145. '<?php return "prod";',
  146. '<?php return ("prod");',
  147. ];
  148. yield [
  149. '<?php return $x;',
  150. '<?php return($x);',
  151. ];
  152. yield [
  153. '<?php return 2;',
  154. '<?php return(2);',
  155. ];
  156. yield [
  157. '<?php return 2?>',
  158. '<?php return(2)?>',
  159. ];
  160. yield [
  161. '<?php
  162. switch ($a) {
  163. case "prod":
  164. break;
  165. }
  166. ',
  167. ];
  168. yield [
  169. '<?php
  170. switch ($a) {
  171. case "prod":
  172. break;
  173. }
  174. ',
  175. '<?php
  176. switch ($a) {
  177. case ("prod"):
  178. break;
  179. }
  180. ',
  181. 'switch_case',
  182. ];
  183. yield [
  184. '<?php
  185. switch ($a) {
  186. case $x;
  187. }
  188. ',
  189. '<?php
  190. switch ($a) {
  191. case($x);
  192. }
  193. ',
  194. ];
  195. yield [
  196. '<?php
  197. switch ($a) {
  198. case 2;
  199. }
  200. ',
  201. '<?php
  202. switch ($a) {
  203. case(2);
  204. }
  205. ',
  206. ];
  207. yield [
  208. '<?php
  209. $a = 5.1;
  210. $b = 1.0;
  211. switch($a) {
  212. case (int) $a < 1 : {
  213. echo "leave alone";
  214. break;
  215. }
  216. case $a < 2/* test */: {
  217. echo "fix 1";
  218. break;
  219. }
  220. case 3 : {
  221. echo "fix 2";
  222. break;
  223. }
  224. case /**//**/ // test
  225. 4
  226. /**///
  227. /**/: {
  228. echo "fix 3";
  229. break;
  230. }
  231. case ((int)$b) + 4.1: {
  232. echo "fix 4";
  233. break;
  234. }
  235. case ($b + 1) * 2: {
  236. echo "leave alone";
  237. break;
  238. }
  239. }
  240. ',
  241. '<?php
  242. $a = 5.1;
  243. $b = 1.0;
  244. switch($a) {
  245. case (int) $a < 1 : {
  246. echo "leave alone";
  247. break;
  248. }
  249. case ($a < 2)/* test */: {
  250. echo "fix 1";
  251. break;
  252. }
  253. case (3) : {
  254. echo "fix 2";
  255. break;
  256. }
  257. case /**/(/**/ // test
  258. 4
  259. /**/)//
  260. /**/: {
  261. echo "fix 3";
  262. break;
  263. }
  264. case (((int)$b) + 4.1): {
  265. echo "fix 4";
  266. break;
  267. }
  268. case ($b + 1) * 2: {
  269. echo "leave alone";
  270. break;
  271. }
  272. }
  273. ',
  274. 'switch_case',
  275. ];
  276. yield [
  277. '<?php while ($x) { while ($y) { break#
  278. #
  279. 2#
  280. #
  281. ; } }',
  282. '<?php while ($x) { while ($y) { break#
  283. (#
  284. 2#
  285. )#
  286. ; } }',
  287. ];
  288. yield [
  289. '<?php
  290. function foo() { yield "prod"; }
  291. ',
  292. ];
  293. yield [
  294. '<?php
  295. function foo() { yield (1 + 2) * 10; }
  296. ',
  297. ];
  298. yield [
  299. '<?php
  300. function foo() { yield (1 + 2) * 10; }
  301. ',
  302. '<?php
  303. function foo() { yield ((1 + 2) * 10); }
  304. ',
  305. ];
  306. yield [
  307. '<?php
  308. function foo() { yield "prod"; }
  309. ',
  310. '<?php
  311. function foo() { yield ("prod"); }
  312. ',
  313. ];
  314. yield [
  315. '<?php
  316. function foo() { yield 2; }
  317. ',
  318. '<?php
  319. function foo() { yield(2); }
  320. ',
  321. ];
  322. yield [
  323. '<?php
  324. function foo() { $a = (yield $x); }
  325. ',
  326. '<?php
  327. function foo() { $a = (yield($x)); }
  328. ',
  329. ];
  330. yield [
  331. '<?php
  332. $var = clone ($obj1->getSubject() ?? $obj2);
  333. ',
  334. ];
  335. }
  336. /**
  337. * @dataProvider provideFixAllCases
  338. */
  339. public function testFixAll(string $expected, ?string $input = null): void
  340. {
  341. $this->fixer->configure(
  342. [
  343. 'statements' => [
  344. 'break',
  345. 'clone',
  346. 'continue',
  347. 'echo_print',
  348. 'return',
  349. 'switch_case',
  350. 'yield',
  351. 'yield_from',
  352. 'others',
  353. 'negative_instanceof',
  354. ],
  355. ],
  356. );
  357. $this->doTest($expected, $input);
  358. }
  359. public static function provideFixAllCases(): iterable
  360. {
  361. yield '===' => [
  362. '<?php $at = $a === $b;',
  363. '<?php $at = ($a) === ($b);',
  364. ];
  365. yield 'yield/from fun' => [
  366. '<?php
  367. function foo3() { $a = (yield $x); }
  368. function foo4() { yield from (1 + 2) * 10; }
  369. function foo5() { yield from "prod"; }
  370. function foo6() { $a = (yield $x); }
  371. function foo7() { yield from 2; }
  372. function foo8() { $a = (yield from $x); }
  373. ',
  374. '<?php
  375. function foo3() { $a = (yield $x); }
  376. function foo4() { yield from ((1 + 2) * 10); }
  377. function foo5() { yield from ("prod"); }
  378. function foo6() { $a = (yield($x)); }
  379. function foo7() { yield from(2); }
  380. function foo8() { $a = (yield from($x)); }
  381. ',
  382. ];
  383. yield 'clone stuff' => [
  384. '<?php
  385. clone new $f[0];
  386. $a1 = clone new foo;
  387. $a2 = clone new foo();
  388. $a3 = [clone $f];
  389. $a4 = [1, clone $f];
  390. $a5 = [clone $f, 2];
  391. $a6 = [1, clone $f, 2];
  392. $c1 = fn() => clone $z;
  393. for ( clone new Bar(1+2) ; $i < 100; ++$i) {
  394. $i = foo();
  395. }
  396. clone $object2[0]->foo()[2] /* 1 */ ?>',
  397. '<?php
  398. clone (new $f[0]);
  399. $a1 = clone (new foo);
  400. $a2 = clone (new foo());
  401. $a3 = [clone ($f)];
  402. $a4 = [1, clone ($f)];
  403. $a5 = [clone ($f), 2];
  404. $a6 = [1, clone ($f), 2];
  405. $c1 = fn() => clone ($z);
  406. for ( clone(new Bar(1+2) ); $i < 100; ++$i) {
  407. $i = foo();
  408. }
  409. clone ($object2[0]->foo()[2]) /* 1 */ ?>',
  410. ];
  411. yield 'print unary wrapped sequence' => [
  412. '<?php $b7 =[ print !$a ,];',
  413. '<?php $b7 =[ print !($a) ,];',
  414. ];
  415. yield 'print - sequence' => [
  416. '<?php
  417. $b7 =[ print $a, 1];
  418. $b7 =[1, print $a];
  419. ',
  420. '<?php
  421. $b7 =[ print ($a), 1];
  422. $b7 =[1, print ($a)];
  423. ',
  424. ];
  425. yield 'print - wrapped block' => [
  426. '<?php $b7 =[ print $a ];',
  427. '<?php $b7 =[ print ($a) ];',
  428. ];
  429. yield 'print fun' => [
  430. '<?php
  431. for ( print $b+1; foo(); ++$i ) {}
  432. for( print $b+1; foo(); ++$i ) {}
  433. $b1 = $c[print $e+5];
  434. $b2 = [1, print $e++];
  435. $b3 = [print $e+9, 1];
  436. $b4 = [1, 1 + print $e, 1];
  437. $b51 = fn() => print $b."something";
  438. $b52 = fn() => print $b."else";
  439. $b6 = foo(print $a);
  440. $b7 =[ print $a ,];
  441. $b8 =[ print ($a+1) . "1" ,];
  442. ',
  443. '<?php
  444. for ( (print $b+1); foo(); ++$i ) {}
  445. for( print ($b+1); foo(); ++$i ) {}
  446. $b1 = $c[(print $e+5)];
  447. $b2 = [1, (print $e++)];
  448. $b3 = [(print $e+9), 1];
  449. $b4 = [1, (1 + print $e), 1];
  450. $b51 = fn() => (print $b."something");
  451. $b52 = fn() => print ($b."else");
  452. $b6 = foo(print ($a));
  453. $b7 =[ (print ($a)) ,];
  454. $b8 =[ (print ($a+1) . "1") ,];
  455. ',
  456. ];
  457. yield 'simple' => [
  458. '<?php $aw?><?php $av;',
  459. '<?php ($aw)?><?php ($av);',
  460. ];
  461. yield 'simple, echo open tag' => [
  462. '<?= $a;',
  463. '<?= ($a);',
  464. ];
  465. yield '+ (X),' => [
  466. '<?php $bw = [1 + !!$a, 2 + $b,];',
  467. '<?php $bw = [1 + !!($a), 2 + ($b),];',
  468. ];
  469. yield 'op ns' => [
  470. '<?php $aq = A\B::c . $d;',
  471. '<?php $aq = (A\B::c) . $d;',
  472. ];
  473. yield 'wrapped FN' => [
  474. '<?php $fn1 = fn($x) => $x + $y;',
  475. '<?php $fn1 = fn($x) => ($x + $y);',
  476. ];
  477. yield 'wrapped FN 2 with pre and reference' => [
  478. '<?php $fn1 = fn & ($x) => !$x;',
  479. '<?php $fn1 = fn & ($x) => !($x);',
  480. ];
  481. yield 'wrapped FN with `,`' => [
  482. '<?php
  483. $fn1 = array_map(fn() => 1, $array);
  484. $fn2 = array_map($array, fn() => 2);
  485. $fn3 = array_map($array, fn() => 3, $array);
  486. ',
  487. '<?php
  488. $fn1 = array_map(fn() => (1), $array);
  489. $fn2 = array_map($array, fn() => (2));
  490. $fn3 = array_map($array, fn() => (3), $array);
  491. ',
  492. ];
  493. yield 'wrapped FN with return type' => [
  494. '<?php
  495. $fn8 = fn(): int => 123456;
  496. ',
  497. '<?php
  498. $fn8 = fn(): int => (123456);
  499. ',
  500. ];
  501. yield 'wrapped `for` elements' => [
  502. '<?php
  503. for (!$a; $a < 10; ++$a){
  504. echo $a;
  505. }
  506. ',
  507. '<?php
  508. for (!($a); ($a < 10); (++$a)){
  509. echo $a;
  510. }
  511. ',
  512. ];
  513. $statements = [
  514. 'echo',
  515. 'print',
  516. 'return',
  517. 'throw',
  518. 'yield from',
  519. 'yield',
  520. ];
  521. foreach ($statements as $statement) {
  522. yield $statement.', no op, space' => [
  523. '<?php function foo(){ '.$statement.' $e; }',
  524. '<?php function foo(){ '.$statement.' ($e); }',
  525. ];
  526. yield $statement.', wrapped op, no space' => [
  527. '<?php function foo(){;'.$statement.' $e.$f; }',
  528. '<?php function foo(){;'.$statement.'($e.$f); }',
  529. ];
  530. }
  531. yield 'yield wrapped unary' => [
  532. '<?php $a = function($a) {yield ++$a;};',
  533. '<?php $a = function($a) {yield (++$a);};',
  534. ];
  535. $constants = [
  536. '__CLASS__',
  537. '__DIR__',
  538. '__FILE__',
  539. '__FUNCTION__',
  540. '__LINE__',
  541. '__METHOD__',
  542. '__NAMESPACE__',
  543. '__TRAIT__',
  544. ];
  545. foreach ($constants as $constant) {
  546. yield $constant.'+ op' => [
  547. sprintf('<?php $a = %s . $b;', $constant),
  548. sprintf('<?php $a = (%s) . $b;', $constant),
  549. ];
  550. }
  551. yield 'break/continue' => [
  552. '<?php
  553. while(foo() && $f) {
  554. while(bar()) {
  555. if ($a) {
  556. break 2;
  557. } else {
  558. continue 2;
  559. }
  560. }
  561. }
  562. ',
  563. '<?php
  564. while((foo() && $f)) {
  565. while(bar()) {
  566. if ($a) {
  567. break (2);
  568. } else {
  569. continue (2);
  570. }
  571. }
  572. }
  573. ',
  574. ];
  575. yield 'switch case' => [
  576. '<?php switch($a) {
  577. case 1: echo 1;
  578. case !$a; echo 2;
  579. }',
  580. '<?php switch($a) {
  581. case(1): echo 1;
  582. case !($a); echo 2;
  583. }',
  584. ];
  585. yield 'switch case II' => [
  586. '<?php
  587. switch ($x) {
  588. case $a + 1 + 3:
  589. break;
  590. case 1 + $a + 4:
  591. break;
  592. }
  593. ',
  594. '<?php
  595. switch ($x) {
  596. case ($a) + 1 + 3:
  597. break;
  598. case 1 + ($a) + 4:
  599. break;
  600. }
  601. ',
  602. ];
  603. yield 'bin pre bin' => [
  604. '<?php $t = 1+ $i +1;',
  605. '<?php $t = 1+($i)+1;',
  606. ];
  607. yield 'bin, (X))' => [
  608. '<?php $ap = 1 + $a;',
  609. '<?php $ap = 1 + ($a);',
  610. ];
  611. yield 'bin close tag' => [
  612. '<?php $d + 2; ?>',
  613. '<?php ($d) + 2; ?>',
  614. ];
  615. yield 'bin after open echo' => [
  616. '<?= $d - 55;',
  617. '<?= ($d) - 55;',
  618. ];
  619. yield 'more bin + sequences combinations' => [
  620. '<?php
  621. $b1 = [1 + $d];
  622. $b2 = [1 + $d,];
  623. $b3 = [1,1 + $d + 1];
  624. $b4 = [1,1 + $d,];
  625. ',
  626. '<?php
  627. $b1 = [1 + ($d)];
  628. $b2 = [1 + ($d),];
  629. $b3 = [1,1 + ($d) + 1];
  630. $b4 = [1,1 + ($d),];
  631. ',
  632. ];
  633. yield 'bin doggybag' => [
  634. '<?php
  635. while(foo()[1]){bar();}
  636. $aR . "";
  637. $e = [$a] + $b;
  638. $f = [$a] + $b[1];
  639. $a = $b + !$c + $d;
  640. $b = !$a[1]++;
  641. $c = $c + !!!(bool) -$a;
  642. throw $b . "";
  643. ',
  644. '<?php
  645. while((foo())[1]){bar();}
  646. ($aR) . "";
  647. $e = [$a] + ($b);
  648. $f = [$a] + ($b)[1];
  649. $a = $b + !($c) + $d;
  650. $b = !($a)[1]++;
  651. $c = $c + !!!(bool) -($a);
  652. throw($b) . "";
  653. ',
  654. ];
  655. $statements = [
  656. 'while(foo()){echo 1;}',
  657. ';;;;',
  658. 'echo',
  659. 'print',
  660. 'return',
  661. 'throw',
  662. '',
  663. ];
  664. foreach ($statements as $statement) {
  665. yield $statement.' (X) bin' => [
  666. '<?php '.$statement.' $e . "foo";',
  667. '<?php '.$statement.' ($e) . "foo";',
  668. ];
  669. }
  670. yield 'bin after' => [
  671. '<?php
  672. $d * 5;
  673. ; $a - $b;
  674. while(foo() + 1 < 100){} $z - 6 ?>',
  675. '<?php
  676. ($d) * 5;
  677. ; ($a) - $b;
  678. while((foo()) + 1 < 100){} ($z) - 6 ?>',
  679. ];
  680. yield 'bin after throw/return' => [
  681. '<?php
  682. function foo() {
  683. if($b) {
  684. throw $e . "";
  685. }
  686. return ((string)$dd)[1] . "a";
  687. }',
  688. '<?php
  689. function foo() {
  690. if(($b)) {
  691. throw($e) . "";
  692. }
  693. return(((string)$dd)[1] . "a");
  694. }',
  695. ];
  696. yield 'multiple fixes' => [
  697. '<?php
  698. $a = [];
  699. $b = [1, []];
  700. foo();
  701. while(foo()){
  702. $a = foo2();
  703. }
  704. ',
  705. '<?php
  706. $a = ([]);
  707. $b = ([1,([])]);
  708. (foo());
  709. while(foo()){
  710. $a = (foo2());
  711. }
  712. ',
  713. ];
  714. yield 'access' => [
  715. '<?php
  716. $ag = $b->A::$foo;
  717. $a1 = $b->$c[1];
  718. $a2 = $b->c[1][2];
  719. $a3 = $b->$c[1]->$a[2]->${"abc"};
  720. $a4 = $b->$c[1][2]->${"abc"}(22);
  721. $a5 = $o->$foo();
  722. $o->$c[] = 6;
  723. $a7 = $o->$c[8] (7);
  724. $a9 = $o->abc($a);
  725. $a10 = $o->abc($a)[1];
  726. $a11 = $o->{$bar};
  727. $a12 = $o->{$c->d}($e)[1](2){$f}->$c[1]()?>
  728. ',
  729. '<?php
  730. $ag = (($b)->A::$foo);
  731. $a1 = (($b)->$c[1]);
  732. $a2 = (($b)->c[1][2]);
  733. $a3 = (($b)->$c[1]->$a[2]->${"abc"});
  734. $a4 = (($b)->$c[1][2]->${"abc"}(22));
  735. $a5 = (($o)->$foo());
  736. ($o)->$c[] = 6;
  737. $a7 = (($o)->$c[8] (7));
  738. $a9 = (($o)->abc($a));
  739. $a10 = (($o)->abc($a)[1]);
  740. $a11 = (($o)->{$bar});
  741. $a12 = (($o)->{$c->d}($e)[1](2){$f}->$c[1]())?>
  742. ',
  743. ];
  744. yield 'simple unary `!`' => [
  745. '<?php
  746. $a1 = !$foo;
  747. $a2 = +$f;
  748. $a3 = -$f;
  749. $a4 = @bar();
  750. ',
  751. '<?php
  752. $a1 = !($foo);
  753. $a2 = +($f);
  754. $a3 = -($f);
  755. $a4 = @(bar());
  756. ',
  757. ];
  758. yield 'pre op ! function call' => [
  759. '<?php $a9 = !foo($a + 1);',
  760. '<?php $a9 = !(foo($a + 1));',
  761. ];
  762. yield 'multiple pre in wrapped array init' => [
  763. '<?php $d7 = [!!!!!!!$a5];',
  764. '<?php $d7 = [!!!!!!!($a5)];',
  765. ];
  766. yield 'pre op cast' => [
  767. '<?php $a6 = (bool)$foo;',
  768. '<?php $a6 = (bool)($foo);',
  769. ];
  770. yield 'pre op ! wrapped' => [
  771. '<?php if (!$z) {echo 1;}',
  772. '<?php if ((!($z))) {echo 1;}',
  773. ];
  774. yield 'crazy unary' => [
  775. '<?php
  776. $b0 = !!!(bool) $a1;
  777. $b1 = [!!!(bool) $a2,1];
  778. !!!(bool) $a3;
  779. !!!(bool) $a4;
  780. $b = 1 + (!!!!!!!$a5);
  781. $a = !$a[1]++;
  782. while(!!!(bool) $a2[1] ){echo 1;}
  783. $b = @$a[1];
  784. $b = ++$a[1];
  785. ',
  786. '<?php
  787. $b0 = !!!(bool) ($a1);
  788. $b1 = [!!!(bool) ($a2),1];
  789. (!!!(bool) (($a3)));
  790. (!!!(bool) ($a4));
  791. $b = 1 + (!!!!!!!($a5));
  792. $a = !($a)[1]++;
  793. while(!!!(bool) ($a2)[1] ){echo 1;}
  794. $b = @($a)[1];
  795. $b = ++($a)[1];
  796. ',
  797. ];
  798. yield 'logic &&' => [
  799. '<?php $arr = $a && $b;',
  800. '<?php $arr = ($a) && $b;',
  801. ];
  802. yield 'bin before' => [
  803. '<?php
  804. $ax = $d + $a;
  805. $dx = 1 + $z ?>',
  806. '<?php
  807. $ax = $d + ($a);
  808. $dx = 1 + ($z) ?>',
  809. ];
  810. yield 'bin before and after' => [
  811. '<?php
  812. echo 1 + 2 + 3;
  813. echo 1.5 + 2.5 + 3.5;
  814. echo 1 + $obj->value + 3;
  815. echo 1 + Obj::VALUE + 3;
  816. ',
  817. '<?php
  818. echo 1 + (2) + 3;
  819. echo 1.5 + (2.5) + 3.5;
  820. echo 1 + ($obj->value) + 3;
  821. echo 1 + (Obj::VALUE) + 3;
  822. ',
  823. ];
  824. yield 'new class as sequence element' => [
  825. '<?php $a7 = [1, new class($a+$b) {}];',
  826. '<?php $a7 = [1, (new class($a+$b) {})];',
  827. ];
  828. yield 'pre @ sequence' => [
  829. '<?php $a8 = [1, @ ($f.$b)() ];',
  830. '<?php $a8 = [1, @( ($f.$b)() )];',
  831. ];
  832. yield 'inside `{` and `}`' => [
  833. '<?php
  834. while(foo()) { bar(); }
  835. while(bar()){foo1();};
  836. if($a){foo();}
  837. ',
  838. '<?php
  839. while(foo()) { (bar()); }
  840. while(bar()){(foo1());};
  841. if($a){(foo());}
  842. ',
  843. ];
  844. yield 'block type dynamic var brace' => [
  845. '<?php ${$bar};',
  846. '<?php ${($bar)};',
  847. ];
  848. yield 'block type dynamic prop brace' => [
  849. '<?php $foo->{$bar};',
  850. '<?php $foo->{($bar)};',
  851. ];
  852. yield 'anonymous class wrapped init' => [
  853. '<?php $a11 = new class(1){};',
  854. '<?php $a11 = new class((1)){};',
  855. ];
  856. yield 'return, new long array notation, no space' => [
  857. '<?php return array();',
  858. '<?php return(array());',
  859. ];
  860. yield 'block type array square brace' => [
  861. '<?php
  862. echo $a13 = [1];
  863. $bX = [1,];
  864. $b0 = [1, 2, 3,];
  865. $b1 = [$a + 1];
  866. $b2 = [-1 + $a];
  867. $b3 = [2 + $c];
  868. ',
  869. '<?php
  870. echo $a13 = [(1)];
  871. $bX = [(1),];
  872. $b0 = [(1),(2),(3),];
  873. $b1 = [($a) + 1];
  874. $b2 = [-1 + ($a)];
  875. $b3 = [2 + ($c)];
  876. ',
  877. ];
  878. yield 'multiple array construct elements' => [
  879. '<?php echo $a14 = [1, $a(1,$b(3)), 3+4]?>',
  880. '<?php echo $a14 = [(1),($a(1,$b(3))),(3+4)]?>',
  881. ];
  882. yield 'double comma and `)`' => [
  883. '<?php echo sprintf("%d%s", $e, $f);',
  884. '<?php echo sprintf("%d%s", ($e), ($f));',
  885. ];
  886. yield 'two wrapped function calls' => [
  887. '<?php foo(); $ap = foo();',
  888. '<?php (foo()); $ap = (foo());',
  889. ];
  890. yield 'wrapped function call, op + call as arg' => [
  891. '<?php $bk = foo(1 + bar()) ?>',
  892. '<?php $bk = (foo(1 + bar())) ?>',
  893. ];
  894. yield 'wrapped function call, short open, semicolon' => [
  895. '<?= foo1z() ?>',
  896. '<?=(foo1z()) ?>',
  897. ];
  898. yield 'wrapped function call, short open, close tag' => [
  899. '<?= foo2A();',
  900. '<?=( foo2A());',
  901. ];
  902. yield 'wrapped returns' => [
  903. '<?php function A($a) {return 1;}',
  904. '<?php function A($a) {return (1);}',
  905. ];
  906. yield 'wrapped returns ops' => [
  907. '<?php function A($a1,$b2) {return ++$a1+$b2;}',
  908. '<?php function A($a1,$b2) {return (++$a1+$b2);}',
  909. ];
  910. yield 'throws, no space' => [
  911. '<?php throw $z . 2;',
  912. '<?php throw($z . 2);',
  913. ];
  914. yield 'throws + op, wrapped in {}' => [
  915. '<?php if (k()) { throw new $a.$b(1,2); } ?>',
  916. '<?php if (k()) { throw (new $a.$b(1,2)); } ?>',
  917. ];
  918. yield 'dynamic class name op' => [
  919. '<?php $xX = ($d+$e)->test();',
  920. '<?php $xX = (($d+$e))->test();',
  921. ];
  922. yield 'token type changing edge case' => [
  923. '<?php $y1 = (new Foo())->bar;',
  924. '<?php $y1 = ((new Foo()))->bar;',
  925. ];
  926. yield 'brace class instantiation open, double wrapped, no assign' => [
  927. '<?php (new Foo())->bar();',
  928. '<?php (((new Foo())))->bar();',
  929. ];
  930. yield 'brace class instantiation open, multiple wrapped' => [
  931. '<?php $y0 = (new Foo())->bar;',
  932. '<?php $y0 = (((((new Foo())))))->bar;',
  933. ];
  934. yield 'wrapped instance check' => [
  935. '<?php
  936. ; $foo instanceof Foo;
  937. ; $foo() instanceof Foo;
  938. $l1 = $foo instanceof $z;
  939. $l2 = $foo instanceof $z[1];
  940. $l3 = [$foo instanceof $z->a[1]];
  941. $l4 = [1, $foo instanceof $a[1]->$f];
  942. $l5 = [$foo instanceof Foo, 1];
  943. $l6 = [1, $foo instanceof Foo, 1];
  944. $fn1 = fn($x) => $fx instanceof Foo;
  945. for ($foo instanceof Foo ; $i < 1; ++$i) { echo $i; }
  946. class foo {
  947. public function bar() {
  948. self instanceof static;
  949. self instanceof self;
  950. $a instanceof static;
  951. self instanceof $a;
  952. $a instanceof self;
  953. }
  954. }
  955. ',
  956. '<?php
  957. ; ($foo instanceof Foo);
  958. ; ($foo() instanceof Foo);
  959. $l1 = ($foo instanceof $z);
  960. $l2 = ($foo instanceof $z[1]);
  961. $l3 = [($foo instanceof $z->a[1])];
  962. $l4 = [1, ($foo instanceof $a[1]->$f)];
  963. $l5 = [($foo instanceof Foo), 1];
  964. $l6 = [1, ($foo instanceof Foo), 1];
  965. $fn1 = fn($x) => ($fx instanceof Foo);
  966. for (($foo instanceof Foo) ; $i < 1; ++$i) { echo $i; }
  967. class foo {
  968. public function bar() {
  969. (self instanceof static);
  970. (self instanceof self);
  971. ($a instanceof static);
  972. (self instanceof $a);
  973. ($a instanceof self);
  974. }
  975. }
  976. ',
  977. ];
  978. yield 'wrapped negative instanceof' => [
  979. '<?php
  980. !$z instanceof $z[1];
  981. $z2 = !$foo[1]->b(1)[2] instanceof A\Foo;
  982. $z3 = [!$z instanceof Foo\Bar::$a];
  983. $z4 = [1, !$z instanceof Foo\Bar::$a];
  984. $z5 = [!$z instanceof Foo\Bar::$a, 2];
  985. $z6 = [8, !$z instanceof Foo\Bar::$a, 2];
  986. for( !$z instanceof Foo\Bar::$a ; $a < 100; ++$a) {
  987. foo();
  988. }
  989. $c1 = fn() => !$z instanceof $z[1];
  990. if (!$x instanceof $v) {
  991. echo 123;
  992. }
  993. ',
  994. '<?php
  995. !($z instanceof $z[1]);
  996. $z2 = !($foo[1]->b(1)[2] instanceof A\Foo);
  997. $z3 = [!($z instanceof Foo\Bar::$a)];
  998. $z4 = [1, !($z instanceof Foo\Bar::$a)];
  999. $z5 = [!($z instanceof Foo\Bar::$a), 2];
  1000. $z6 = [8, !($z instanceof Foo\Bar::$a), 2];
  1001. for( !($z instanceof Foo\Bar::$a) ; $a < 100; ++$a) {
  1002. foo();
  1003. }
  1004. $c1 = fn() => !($z instanceof $z[1]);
  1005. if (!($x instanceof $v)) {
  1006. echo 123;
  1007. }
  1008. ',
  1009. ];
  1010. yield 'wrapped negative instanceof 2' => [
  1011. '<?php
  1012. class foo {
  1013. public function bar() {
  1014. !self instanceof static;
  1015. !self instanceof self;
  1016. !$a instanceof static;
  1017. !self instanceof $a;
  1018. !$a instanceof self;
  1019. }
  1020. }',
  1021. '<?php
  1022. class foo {
  1023. public function bar() {
  1024. !(self instanceof static);
  1025. !(self instanceof self);
  1026. !($a instanceof static);
  1027. !(self instanceof $a);
  1028. !($a instanceof self);
  1029. }
  1030. }',
  1031. ];
  1032. yield '(x,y' => [
  1033. '<?php $n = ["".foo(1+2),3];',
  1034. '<?php $n = [("".foo(1+2)),3];',
  1035. ];
  1036. yield 'x,y) = ' => [
  1037. '<?php $m = [$x, $y];',
  1038. '<?php $m = [$x,($y)];',
  1039. ];
  1040. yield '(x,y,x)' => [
  1041. '<?php $aj = [1, "".foo(1+2),3];',
  1042. '<?php $aj = [1,("".foo(1+2)),3];',
  1043. ];
  1044. yield 'block type index square brace' => [
  1045. '<?php $n = $foo[1];',
  1046. '<?php $n = $foo[(1)];',
  1047. ];
  1048. yield 'multiple wrapped call' => [
  1049. '<?php
  1050. $u = $z($b);
  1051. $a = bar/*1*/ ($a) /*2*/;',
  1052. '<?php
  1053. $u = $z(($b));
  1054. $a = bar/*1*/ (((($a)))) /*2*/;',
  1055. ];
  1056. yield 'if' => [
  1057. '<?php if ($z) {echo 1;}',
  1058. '<?php if ((($z))) {echo 1;}',
  1059. ];
  1060. yield 'destructuring square brace + comments' => [
  1061. '<?php
  1062. [/*A*/$a/*B*/] = z();
  1063. [/*A*/$a/*B*/, $c] = z();
  1064. ',
  1065. '<?php
  1066. [/*A*/($a)/*B*/] = z();
  1067. [/*A*/($a)/*B*/,($c)] = z();
  1068. ',
  1069. ];
  1070. yield 'multiple fix cases' => [
  1071. '<?php
  1072. $aF=array(1);$a=array(1);$a=array(1);$a=array(1);
  1073. $bF=array(1);$b=array(1);$b=array(1);$b=array(1);
  1074. $cF=array(1);$c=array(1);$c=array(1);$c=array(1);
  1075. ',
  1076. '<?php
  1077. $aF=array((1));$a=array((1));$a=array((1));$a=array((1));
  1078. $bF=array((1));$b=array((1));$b=array((1));$b=array((1));
  1079. $cF=array((1));$c=array((1));$c=array((1));$c=array((1));
  1080. ',
  1081. ];
  1082. yield 'multiple fix cases with space inserts' => [
  1083. '<?php $a=$b. 1 .$c;$a=$b. 1 .$c;$a=$b. 1 .$c;$a=$b. 1 .$c;$a=$b. 1 .$c;$a=$b./*1*/1/*2*/.$c;',
  1084. '<?php $a=$b.(1).$c;$a=$b.(1).$c;$a=$b.(1).$c;$a=$b.(1).$c;$a=$b.(1).$c;$a=$b./*1*/(1)/*2*/.$c;',
  1085. ];
  1086. yield 'empty exit/die' => [
  1087. '<?php exit; die;',
  1088. '<?php exit(); die();',
  1089. ];
  1090. yield 'more space around concat handling' => [
  1091. '<?php
  1092. $s2 = "a". 0.1 . 2 . "b" . "c";
  1093. $f = \'x\' . \'y\' . \'z\';
  1094. ',
  1095. '<?php
  1096. $s2 = "a".(0.1). (2) . ("b") . "c";
  1097. $f = \'x\' . ( \'y\' ) . \'z\';
  1098. ',
  1099. ];
  1100. $assignOperators = [
  1101. 'and equal' => '&=',
  1102. 'coalesce_equal' => '??=',
  1103. 'concat_equal' => '.=',
  1104. 'div equal' => '*=',
  1105. 'minus equal' => '!=',
  1106. 'mod equal' => '+=',
  1107. 'mul equal' => '*=',
  1108. 'or equal' => '+=',
  1109. 'plus equal' => '+=',
  1110. 'pow equal' => '**=',
  1111. 'sl equal' => '<<=',
  1112. 'sr equal' => '>>=',
  1113. 'xor equal' => '^=',
  1114. ];
  1115. foreach ($assignOperators as $assignOperator) {
  1116. yield [
  1117. '<?php $a '.$assignOperator.' $x;',
  1118. '<?php $a '.$assignOperator.' ($x);',
  1119. ];
  1120. }
  1121. yield 'after `}`' => [
  1122. '<?php
  1123. while(foo()){} ++$i;
  1124. for(;;){}++$i;
  1125. foreach ($a as $b){}++$i;
  1126. if (foo()) {}++$i;
  1127. if (foo()) {} else {}++$i;
  1128. if (foo()) {} elseif(bar()) {}++$i;
  1129. switch(foo()){case 1: echo 1;}++$i;
  1130. switch (foo()){
  1131. case 1: {}++$i; break;
  1132. }
  1133. function Bar(): array {
  1134. $i++;
  1135. return [];
  1136. }
  1137. function Foo1(){}++$i;
  1138. function & Foo2(){}++$i;
  1139. class A{}++$i;
  1140. class A1 extends BD{}++$i;
  1141. class A2 extends BD implements CE{}++$i;
  1142. class A3 extends BD implements CE,DE{}++$i;
  1143. interface B{}++$i;
  1144. interface B1 extends A{}++$i;
  1145. interface B2 extends A,B{}++$i;
  1146. trait X{}++$i;
  1147. try{}catch(E $e){}$i++;
  1148. try {} finally {}++$i;
  1149. ',
  1150. '<?php
  1151. while(foo()){} (++$i);
  1152. for(;;){}(++$i);
  1153. foreach ($a as $b){}(++$i);
  1154. if (foo()) {}(++$i);
  1155. if (foo()) {} else {}(++$i);
  1156. if (foo()) {} elseif(bar()) {}(++$i);
  1157. switch(foo()){case 1: echo 1;}(++$i);
  1158. switch (foo()){
  1159. case 1: {}(++$i); break;
  1160. }
  1161. function Bar(): array {
  1162. ($i++);
  1163. return [];
  1164. }
  1165. function Foo1(){}(++$i);
  1166. function & Foo2(){}(++$i);
  1167. class A{}(++$i);
  1168. class A1 extends BD{}(++$i);
  1169. class A2 extends BD implements CE{}(++$i);
  1170. class A3 extends BD implements CE,DE{}(++$i);
  1171. interface B{}(++$i);
  1172. interface B1 extends A{}(++$i);
  1173. interface B2 extends A,B{}(++$i);
  1174. trait X{}(++$i);
  1175. try{}catch(E $e){}($i++);
  1176. try {} finally {}(++$i);
  1177. ',
  1178. ];
  1179. yield 'do not fix' => [
  1180. '<?php
  1181. $b = ($a+=$c);
  1182. foo();
  1183. foo(1);
  1184. foo(1,$a,3);
  1185. foo(1,3,);
  1186. foo($a)->$b;
  1187. ${foo}();
  1188. foo(+ $a, -$b);
  1189. $a[1](2);
  1190. $b = $c();
  1191. $z = foo(1) + 2;
  1192. $a = ${\'foo\'}();
  1193. $b["foo"]($bar);
  1194. namespace\func();
  1195. Y::class();
  1196. $z = (print \'a\') + 2;
  1197. $fn1 = fn($x) => $x + $y;
  1198. $d = function() use ($d) {};
  1199. function provideFixCases(): iterable{}
  1200. $z = function &($x) {++$x;};
  1201. final class Foo { public static function bar() { return new static(); } }
  1202. $a = (print 1) + 1;
  1203. $b = $c(print $e);
  1204. $c = foo(print $e);
  1205. $c2 =[ print !($a + 1) ,];
  1206. $a = ($a && !$c) && $b;
  1207. $a = (1 + foo()) * 2;
  1208. $a = -($f+$a);
  1209. $a = !($f ? $a : $b);
  1210. $a = @( ($f.$b)() . foo() );
  1211. $a = $b ? ($c)($d + 2) : $d;
  1212. $d = ($c && $a ? true : false) ? 1 : 2; // PHP Deprecated: Unparenthesized `a ? b : c ? d : e` is deprecated.
  1213. $z = $b ? ($c)($d + 2) : $d;
  1214. $x = $b ? foo($c)[$a](1) : $d;
  1215. $a = [1,($a.$foo[1])[2]];
  1216. $b = [ $d[4]($a[1].$b) , ];
  1217. $c = [$d[4]($a[1].$b)];
  1218. $a = ($a ? 1 : 2) ? 1 : 2;
  1219. $a = $a ? ($a ? 1 : 2): 2;
  1220. $a = $a ? 1 : ($a ? 1 : 2);
  1221. $a = 1 + ($a + 1) ? 1 : 2;
  1222. $a = $a ? ($a + 1) + 3 : 2;
  1223. $a = $a ? 3 + ($a + 1) : 2;
  1224. $a = $a ? 3 : 1 + ($a + 1);
  1225. $a = $a ? 3 : ($a + 1) + 2;
  1226. $b += ($a+=$c);
  1227. $a = isset( ( (array) $b) [1] );
  1228. $a = ( (array) $b) [1] ;
  1229. exit(4);
  1230. exit (foo()) + 1;
  1231. $a = array();
  1232. $b = new class(){};
  1233. declare(ticks=1);
  1234. $d = empty($e);
  1235. $e = eval($b);
  1236. list($f) = $f;
  1237. try {foo();} catch (E $e){}
  1238. if ($a){ echo 1; } elseif($b) { echo 2; }
  1239. switch($a) {case 1: echo 1;}
  1240. foreach ($a1 as $b){}
  1241. foreach ($a2 as $b => $c){}
  1242. for ($a =0; $a < 1; --$a){}
  1243. while(bar()) {}
  1244. while(!!!(bool) $a1() ){echo 1;}
  1245. while( ($a2)(1) ){echo 1;}
  1246. $d = isset($c);
  1247. $d = isset($c,$a,$z);
  1248. $y = isset($foo) && isset($foo2);
  1249. unset($d);
  1250. unset($d,$e);
  1251. // from https://www.php.net/manual/en/language.operators.precedence.php
  1252. $a = 1;
  1253. echo $a + ($a++); // echo $a + $a++; // may print either 2 or 3
  1254. $i = 1;
  1255. $array[$i] = ($i++); // $array[$i] = $i++; // may set either index 1 or 2
  1256. $t = 1+($i++)+1;
  1257. echo (("x minus one equals " . $x) - 1) . ", or so I hope\n";
  1258. echo "x minus one equals " . ($x-1) . ", or so I hope\n";
  1259. $bool = (true and false);
  1260. $a = ($a instanceof MyClass) && true;
  1261. $a = foo($a instanceof MyClass);
  1262. $a = $a || ($a instanceof MyClass);
  1263. $a = clone ($a)[0];
  1264. // handled by the `include` rule
  1265. require (__DIR__."/foo2.php");
  1266. require_once (__DIR__."/foo.php");
  1267. include ($a);
  1268. include_once ($b);
  1269. // halt compiler
  1270. __halt_compiler();
  1271. ',
  1272. ];
  1273. yield 'do not fix ' => [
  1274. '<?php
  1275. SomeClass::{$method}(
  1276. $variableA,
  1277. $variableB
  1278. );',
  1279. ];
  1280. yield 'do not fix 2' => [
  1281. '<?php SomeClass::{$method}(2) + 1;',
  1282. ];
  1283. yield 'do not fix 3' => [
  1284. '<?php $object::{$method}(...$args);',
  1285. ];
  1286. yield 'alternative syntax is not completely supported' => [
  1287. '<?php if ($a):(++$i); endif;',
  1288. ];
  1289. }
  1290. /**
  1291. * @param array<string, mixed> $config
  1292. *
  1293. * @dataProvider provideWithConfigCases
  1294. */
  1295. public function testWithConfig(array $config, string $expected, string $input): void
  1296. {
  1297. $this->fixer->configure($config);
  1298. $this->doTest($expected, $input);
  1299. $this->fixer->configure(['statements' => []]);
  1300. $this->doTest($input);
  1301. }
  1302. public static function provideWithConfigCases(): iterable
  1303. {
  1304. yield 'config: break' => [
  1305. ['statements' => ['break']],
  1306. '<?php
  1307. while (foo()) {
  1308. while (foo()) {
  1309. break 2;
  1310. }
  1311. }
  1312. ',
  1313. '<?php
  1314. while (foo()) {
  1315. while (foo()) {
  1316. break (2);
  1317. }
  1318. }
  1319. ',
  1320. ];
  1321. yield 'config: clone' => [
  1322. ['statements' => ['clone']],
  1323. '<?php ; clone $f;',
  1324. '<?php ; clone($f);',
  1325. ];
  1326. yield 'config: continue' => [
  1327. ['statements' => ['continue']],
  1328. '<?php
  1329. while (foo()) {
  1330. while (foo()) {
  1331. continue 2;
  1332. }
  1333. }
  1334. ',
  1335. '<?php
  1336. while (foo()) {
  1337. while (foo()) {
  1338. continue (2);
  1339. }
  1340. }
  1341. ',
  1342. ];
  1343. yield 'config: echo_print' => [
  1344. ['statements' => ['echo_print']],
  1345. '<?php
  1346. echo 1; print 2;
  1347. ',
  1348. '<?php
  1349. echo (1); print (2);
  1350. ',
  1351. ];
  1352. yield 'config: return' => [
  1353. ['statements' => ['return']],
  1354. '<?php ; return 999 ?>',
  1355. '<?php ; return (999) ?>',
  1356. ];
  1357. yield 'config: switch_case' => [
  1358. ['statements' => ['switch_case']],
  1359. '<?php
  1360. switch ($a) {
  1361. case 22: echo 1;
  1362. }
  1363. ',
  1364. '<?php
  1365. switch ($a) {
  1366. case (22): echo 1;
  1367. }
  1368. ',
  1369. ];
  1370. yield 'config: yield' => [
  1371. ['statements' => ['yield']],
  1372. '<?php function foo() { yield "prod"; }',
  1373. '<?php function foo() { yield ("prod"); }',
  1374. ];
  1375. yield 'config: yield_from' => [
  1376. ['statements' => ['yield_from']],
  1377. '<?php function foo() { ; yield from $a; }',
  1378. '<?php function foo() { ; yield from ($a); }',
  1379. ];
  1380. yield 'config: negative_instanceof' => [
  1381. ['statements' => ['negative_instanceof']],
  1382. '<?php !$foo instanceof $b;',
  1383. '<?php !($foo instanceof $b);',
  1384. ];
  1385. yield 'config: others' => [
  1386. ['statements' => ['others']],
  1387. '<?php ; ++$v[1];',
  1388. '<?php ; ++($v)[1];',
  1389. ];
  1390. }
  1391. /**
  1392. * @dataProvider providePrePhp8Cases
  1393. *
  1394. * @requires PHP <8.0
  1395. */
  1396. public function testPrePhp8(string $expected, string $input): void
  1397. {
  1398. $this->fixer->configure(
  1399. [
  1400. 'statements' => [
  1401. 'break',
  1402. 'clone',
  1403. 'continue',
  1404. 'echo_print',
  1405. 'return',
  1406. 'switch_case',
  1407. 'yield',
  1408. 'yield_from',
  1409. 'others',
  1410. ],
  1411. ],
  1412. );
  1413. $this->doTest($expected, $input);
  1414. }
  1415. public static function providePrePhp8Cases(): iterable
  1416. {
  1417. yield 'block type array index curly brace' => [
  1418. '<?php echo $a12 = $a{1};',
  1419. '<?php echo $a12 = $a{(1)};',
  1420. ];
  1421. yield 'PHP8 bin doggybag' => [
  1422. '<?php
  1423. $s = $a{$d}(1) + 1;
  1424. $t = $a{1}(2);
  1425. ',
  1426. '<?php
  1427. $s = ($a{$d}(1)) + 1;
  1428. $t = ($a{1}(2));
  1429. ',
  1430. ];
  1431. }
  1432. /**
  1433. * @dataProvider provideFixPhp80Cases
  1434. *
  1435. * @requires PHP 8.0
  1436. */
  1437. public function testFixPhp80(string $expected, ?string $input = null): void
  1438. {
  1439. $this->fixer->configure(
  1440. [
  1441. 'statements' => [
  1442. 'break',
  1443. 'clone',
  1444. 'continue',
  1445. 'echo_print',
  1446. 'return',
  1447. 'switch_case',
  1448. 'yield',
  1449. 'yield_from',
  1450. 'others',
  1451. ],
  1452. ],
  1453. );
  1454. $this->doTest($expected, $input);
  1455. }
  1456. public static function provideFixPhp80Cases(): iterable
  1457. {
  1458. yield 'fn throw' => [
  1459. '<?php $triggerError = fn () => throw new MyError();',
  1460. '<?php $triggerError = fn () => (throw new MyError());',
  1461. ];
  1462. yield 'match' => [
  1463. "<?php
  1464. \$r = match (\$food) {
  1465. 'apple' => 'An apple',
  1466. 'cake' => 'Some cake',
  1467. };
  1468. ",
  1469. "<?php
  1470. \$r = match ((\$food)) {
  1471. 'apple' => 'An apple',
  1472. 'cake' => 'Some cake',
  1473. };
  1474. ",
  1475. ];
  1476. yield 'wrapped FN with return types' => [
  1477. '<?php
  1478. $fn8 = fn(): int|bool => 123456;
  1479. ',
  1480. '<?php
  1481. $fn8 = fn(): int|bool => (123456);
  1482. ',
  1483. ];
  1484. yield [
  1485. '<?php echo 1 + $obj?->value + 3;',
  1486. '<?php echo 1 + ($obj?->value) + 3;',
  1487. ];
  1488. }
  1489. /**
  1490. * @dataProvider provideFixPhp81Cases
  1491. *
  1492. * @requires PHP 8.1
  1493. */
  1494. public function testFixPhp81(string $expected, ?string $input = null): void
  1495. {
  1496. $this->fixer->configure(
  1497. [
  1498. 'statements' => [
  1499. 'break',
  1500. 'clone',
  1501. 'continue',
  1502. 'echo_print',
  1503. 'return',
  1504. 'switch_case',
  1505. 'yield',
  1506. 'yield_from',
  1507. 'others',
  1508. ],
  1509. ],
  1510. );
  1511. $this->doTest($expected, $input);
  1512. }
  1513. public static function provideFixPhp81Cases(): iterable
  1514. {
  1515. yield [
  1516. '<?php
  1517. enum Foo: string
  1518. {
  1519. case Bar = "do fix";
  1520. }
  1521. ',
  1522. '<?php
  1523. enum Foo: string
  1524. {
  1525. case Bar = ("do fix");
  1526. }
  1527. ',
  1528. ];
  1529. yield [
  1530. '<?php echo Number::Two->value;',
  1531. '<?php echo (Number::Two)->value;',
  1532. ];
  1533. yield 'wrapped FN with return types' => [
  1534. '<?php
  1535. $fn8 = fn(): A&B => new C();
  1536. ',
  1537. '<?php
  1538. $fn8 = fn(): A&B => (new C());
  1539. ',
  1540. ];
  1541. yield 'wrapped FN with return types and ref' => [
  1542. '<?php
  1543. $fn9 = fn & (): D & E => new F();
  1544. ',
  1545. '<?php
  1546. $fn9 = fn & (): D & E => (new F());
  1547. ',
  1548. ];
  1549. yield [
  1550. '<?php
  1551. enum Suit
  1552. {
  1553. case Hearts;
  1554. }$i++;
  1555. ',
  1556. '<?php
  1557. enum Suit
  1558. {
  1559. case Hearts;
  1560. }($i++);
  1561. ',
  1562. ];
  1563. }
  1564. }