NoUnneededControlParenthesesFixerTest.php 50 KB

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