NoUnneededControlParenthesesFixerTest.php 50 KB

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