ReturnAssignmentFixerTest.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431
  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\ReturnNotation;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @internal
  16. *
  17. * @covers \PhpCsFixer\Fixer\ReturnNotation\ReturnAssignmentFixer
  18. */
  19. final class ReturnAssignmentFixerTest extends AbstractFixerTestCase
  20. {
  21. /**
  22. * @dataProvider provideFixNestedFunctionsCases
  23. */
  24. public function testFixNestedFunctions(string $expected, string $input): void
  25. {
  26. $this->doTest($expected, $input);
  27. }
  28. public static function provideFixNestedFunctionsCases(): iterable
  29. {
  30. yield [
  31. '<?php
  32. function A($a0,$a1,$a2,$d)
  33. {
  34. if ($a0) {
  35. return 1;
  36. // fix me
  37. }
  38. if ($a1) {
  39. return 2;
  40. // fix me
  41. }
  42. $nested0 = function() {
  43. global $a;
  44. ++$a;
  45. $d = 2;
  46. $nested1 = function () use ($d) {
  47. if ($d) {
  48. return 3;
  49. // fix me
  50. }
  51. $nested2 = function (&$d) {
  52. if ($d) {
  53. $f = 1;
  54. return $f; // fix me not
  55. }
  56. $d = function () {
  57. return 4;
  58. // fix me
  59. };
  60. if ($d+1) {
  61. $f = 1;
  62. return $f; // fix me not
  63. }
  64. };
  65. return $nested2();
  66. };
  67. return $a; // fix me not
  68. };
  69. if ($a2) {
  70. return 5;
  71. // fix me
  72. }
  73. }
  74. function B($b0, $b1, $b2)
  75. {
  76. if ($b0) {
  77. return 10;
  78. // fix me
  79. }
  80. if ($b1) {
  81. return 20;
  82. // fix me
  83. }
  84. if ($b2) {
  85. return 30;
  86. // fix me
  87. }
  88. }
  89. ',
  90. '<?php
  91. function A($a0,$a1,$a2,$d)
  92. {
  93. if ($a0) {
  94. $b = 1;
  95. return $b; // fix me
  96. }
  97. if ($a1) {
  98. $c = 2;
  99. return $c; // fix me
  100. }
  101. $nested0 = function() {
  102. global $a;
  103. ++$a;
  104. $d = 2;
  105. $nested1 = function () use ($d) {
  106. if ($d) {
  107. $f = 3;
  108. return $f; // fix me
  109. }
  110. $nested2 = function (&$d) {
  111. if ($d) {
  112. $f = 1;
  113. return $f; // fix me not
  114. }
  115. $d = function () {
  116. $a = 4;
  117. return $a; // fix me
  118. };
  119. if ($d+1) {
  120. $f = 1;
  121. return $f; // fix me not
  122. }
  123. };
  124. return $nested2();
  125. };
  126. return $a; // fix me not
  127. };
  128. if ($a2) {
  129. $d = 5;
  130. return $d; // fix me
  131. }
  132. }
  133. function B($b0, $b1, $b2)
  134. {
  135. if ($b0) {
  136. $b = 10;
  137. return $b; // fix me
  138. }
  139. if ($b1) {
  140. $c = 20;
  141. return $c; // fix me
  142. }
  143. if ($b2) {
  144. $d = 30;
  145. return $d; // fix me
  146. }
  147. }
  148. ',
  149. ];
  150. }
  151. /**
  152. * @dataProvider provideFixCases
  153. */
  154. public function testFix(string $expected, string $input): void
  155. {
  156. $this->doTest($expected, $input);
  157. }
  158. public static function provideFixCases(): iterable
  159. {
  160. yield [
  161. '<?php
  162. function A()
  163. {
  164. return 15;
  165. }
  166. ',
  167. '<?php
  168. function A()
  169. {
  170. $a = 15;
  171. return $a;
  172. }
  173. ',
  174. ];
  175. yield [
  176. '<?php
  177. function A()
  178. {
  179. /*0*/return /*1*//*2*/15;/*3*//*4*/ /*5*/ /*6*//*7*//*8*/
  180. }
  181. ',
  182. '<?php
  183. function A()
  184. {
  185. /*0*/$a/*1*/=/*2*/15;/*3*//*4*/ /*5*/ return/*6*/$a/*7*/;/*8*/
  186. }
  187. ',
  188. ];
  189. yield 'comments with leading space' => [
  190. '<?php
  191. function A()
  192. { #1
  193. #2
  194. return #3
  195. #4
  196. #5
  197. #6
  198. 15 #7
  199. ; #8
  200. #9
  201. #10
  202. #11
  203. #12
  204. #13
  205. #14
  206. #15
  207. }
  208. ',
  209. '<?php
  210. function A()
  211. { #1
  212. #2
  213. $a #3
  214. #4
  215. = #5
  216. #6
  217. 15 #7
  218. ; #8
  219. #9
  220. return #10
  221. #11
  222. $a #12
  223. #13
  224. ; #14
  225. #15
  226. }
  227. ',
  228. ];
  229. yield [
  230. '<?php
  231. abstract class B
  232. {
  233. abstract protected function Z();public function A()
  234. {
  235. return 16;
  236. }
  237. }
  238. ',
  239. '<?php
  240. abstract class B
  241. {
  242. abstract protected function Z();public function A()
  243. {
  244. $a = 16; return $a;
  245. }
  246. }
  247. ',
  248. ];
  249. yield [
  250. '<?php
  251. function b() {
  252. if ($c) {
  253. return 0;
  254. }
  255. return testFunction(654+1);
  256. }
  257. ',
  258. '<?php
  259. function b() {
  260. if ($c) {
  261. $b = 0;
  262. return $b;
  263. }
  264. $a = testFunction(654+1);
  265. return $a;
  266. }
  267. ',
  268. ];
  269. yield 'minimal notation' => [
  270. '<?php $e=function(){return 1;};$f=function(){return 1;};$g=function(){return 1;};',
  271. '<?php $e=function(){$a=1;return$a;};$f=function(){$a=1;return$a;};$g=function(){$a=1;return$a;};',
  272. ];
  273. yield [
  274. '<?php
  275. function A()
  276. {#1
  277. #2 '.'
  278. return #3
  279. #4
  280. #5
  281. #6
  282. 15#7
  283. ;#8
  284. #9
  285. #10
  286. #11
  287. #12
  288. #13
  289. #14
  290. #15
  291. }
  292. ',
  293. '<?php
  294. function A()
  295. {#1
  296. #2 '.'
  297. $a#3
  298. #4
  299. =#5
  300. #6
  301. 15#7
  302. ;#8
  303. #9
  304. return#10
  305. #11
  306. $a#12
  307. #13
  308. ;#14
  309. #15
  310. }
  311. ',
  312. ];
  313. yield [
  314. '<?php
  315. function A($b)
  316. {
  317. // Comment
  318. return a("2", 4, $b);
  319. }
  320. ',
  321. '<?php
  322. function A($b)
  323. {
  324. // Comment
  325. $value = a("2", 4, $b);
  326. return $value;
  327. }
  328. ',
  329. ];
  330. yield [
  331. '<?php function a($b,$c) {if($c>1){echo 1;} return (1 + 2 + $b); }',
  332. '<?php function a($b,$c) {if($c>1){echo 1;} $a= (1 + 2 + $b);return $a; }',
  333. ];
  334. yield [
  335. '<?php function a($b,$c) {return (3 * 4 + $b); }',
  336. '<?php function a($b,$c) {$zz= (3 * 4 + $b);return $zz; }',
  337. ];
  338. yield [
  339. '<?php
  340. function a() {
  341. return 4563;
  342. ?> <?php
  343. }
  344. ',
  345. '<?php
  346. function a() {
  347. $a = 4563;
  348. return $a ?> <?php
  349. }
  350. ',
  351. ];
  352. yield [
  353. '<?php
  354. function a()
  355. {
  356. return $c + 1; /*
  357. var names are case-insensitive */ }
  358. ',
  359. '<?php
  360. function a()
  361. {
  362. $A = $c + 1; /*
  363. var names are case-insensitive */ return $a ;}
  364. ',
  365. ];
  366. yield [
  367. '<?php
  368. function A()
  369. {
  370. return $f[1]->a();
  371. }
  372. ',
  373. '<?php
  374. function A()
  375. {
  376. $a = $f[1]->a();
  377. return $a;
  378. }
  379. ',
  380. [
  381. '<?php
  382. function a($foos) {
  383. return array_map(function ($foo) {
  384. return (string) $foo;
  385. }, $foos);
  386. }',
  387. '<?php
  388. function a($foos) {
  389. $bars = array_map(function ($foo) {
  390. return (string) $foo;
  391. }, $foos);
  392. return $bars;
  393. }',
  394. ],
  395. [
  396. '<?php
  397. function a($foos) {
  398. return ($foos = [\'bar\']);
  399. }',
  400. '<?php
  401. function a($foos) {
  402. $bars = ($foos = [\'bar\']);
  403. return $bars;
  404. }',
  405. ],
  406. ];
  407. yield [
  408. '<?php
  409. function a($foos) {
  410. return (function ($foos) {
  411. return $foos;
  412. })($foos);
  413. }',
  414. '<?php
  415. function a($foos) {
  416. $bars = (function ($foos) {
  417. return $foos;
  418. })($foos);
  419. return $bars;
  420. }',
  421. ];
  422. yield 'anonymous classes' => [
  423. '<?php
  424. function A()
  425. {
  426. return new class {};
  427. }
  428. function B()
  429. {
  430. return new class() {};
  431. }
  432. function C()
  433. {
  434. return new class(1,2) { public function Z(Foo $d){} };
  435. }
  436. function D()
  437. {
  438. return new class extends Y {};
  439. }
  440. function E()
  441. {
  442. return new class extends Y implements A\O,P {};
  443. }
  444. ',
  445. '<?php
  446. function A()
  447. {
  448. $a = new class {};
  449. return $a;
  450. }
  451. function B()
  452. {
  453. $b = new class() {};
  454. return $b;
  455. }
  456. function C()
  457. {
  458. $c = new class(1,2) { public function Z(Foo $d){} };
  459. return $c;
  460. }
  461. function D()
  462. {
  463. $c = new class extends Y {};
  464. return $c;
  465. }
  466. function E()
  467. {
  468. $c = new class extends Y implements A\O,P {};
  469. return $c;
  470. }
  471. ',
  472. ];
  473. yield 'lambda' => [
  474. '<?php
  475. function A()
  476. {
  477. return function () {};
  478. }
  479. function B()
  480. {
  481. return function ($a, $b) use ($z) {};
  482. }
  483. function C()
  484. {
  485. return static function ($a, $b) use ($z) {};
  486. }
  487. function D()
  488. {
  489. return function &() use(&$b) {
  490. return $b; // do not fix
  491. };
  492. // fix
  493. }
  494. function E()
  495. {
  496. return function &() {
  497. $z = new A(); return $z; // do not fix
  498. };
  499. // fix
  500. }
  501. function A99()
  502. {
  503. $v = static function ($a, $b) use ($z) {};
  504. return 15;
  505. }
  506. ',
  507. '<?php
  508. function A()
  509. {
  510. $a = function () {};
  511. return $a;
  512. }
  513. function B()
  514. {
  515. $b = function ($a, $b) use ($z) {};
  516. return $b;
  517. }
  518. function C()
  519. {
  520. $c = static function ($a, $b) use ($z) {};
  521. return $c;
  522. }
  523. function D()
  524. {
  525. $a = function &() use(&$b) {
  526. return $b; // do not fix
  527. };
  528. return $a; // fix
  529. }
  530. function E()
  531. {
  532. $a = function &() {
  533. $z = new A(); return $z; // do not fix
  534. };
  535. return $a; // fix
  536. }
  537. function A99()
  538. {
  539. $v = static function ($a, $b) use ($z) {};
  540. $a = 15;
  541. return $a;
  542. }
  543. ',
  544. ];
  545. yield 'arrow functions' => [
  546. '<?php
  547. function Foo() {
  548. return fn($x) => $x + $y;
  549. }
  550. ',
  551. '<?php
  552. function Foo() {
  553. $fn1 = fn($x) => $x + $y;
  554. return $fn1;
  555. }
  556. ',
  557. ];
  558. yield 'try catch' => [
  559. '<?php
  560. function foo()
  561. {
  562. if (isSomeCondition()) {
  563. return getSomeResult();
  564. }
  565. try {
  566. $result = getResult();
  567. return $result;
  568. } catch (\Throwable $exception) {
  569. baz($result ?? null);
  570. }
  571. }
  572. ',
  573. '<?php
  574. function foo()
  575. {
  576. if (isSomeCondition()) {
  577. $result = getSomeResult();
  578. return $result;
  579. }
  580. try {
  581. $result = getResult();
  582. return $result;
  583. } catch (\Throwable $exception) {
  584. baz($result ?? null);
  585. }
  586. }
  587. ',
  588. ];
  589. yield 'multiple try/catch blocks separated with conditional return' => [
  590. '<?php
  591. function foo()
  592. {
  593. try {
  594. return getResult();
  595. } catch (\Throwable $exception) {
  596. error_log($exception->getMessage());
  597. }
  598. if (isSomeCondition()) {
  599. return getSomeResult();
  600. }
  601. try {
  602. $result = $a + $b;
  603. return $result;
  604. } catch (\Throwable $th) {
  605. var_dump($result ?? null);
  606. }
  607. }
  608. ',
  609. '<?php
  610. function foo()
  611. {
  612. try {
  613. $result = getResult();
  614. return $result;
  615. } catch (\Throwable $exception) {
  616. error_log($exception->getMessage());
  617. }
  618. if (isSomeCondition()) {
  619. $result = getSomeResult();
  620. return $result;
  621. }
  622. try {
  623. $result = $a + $b;
  624. return $result;
  625. } catch (\Throwable $th) {
  626. var_dump($result ?? null);
  627. }
  628. }
  629. ',
  630. ];
  631. yield 'try/catch/finally' => [
  632. '<?php
  633. function foo()
  634. {
  635. if (isSomeCondition()) {
  636. return getSomeResult();
  637. }
  638. try {
  639. $result = getResult();
  640. return $result;
  641. } catch (\Throwable $exception) {
  642. error_log($exception->getMessage());
  643. } finally {
  644. baz($result);
  645. }
  646. }
  647. ',
  648. '<?php
  649. function foo()
  650. {
  651. if (isSomeCondition()) {
  652. $result = getSomeResult();
  653. return $result;
  654. }
  655. try {
  656. $result = getResult();
  657. return $result;
  658. } catch (\Throwable $exception) {
  659. error_log($exception->getMessage());
  660. } finally {
  661. baz($result);
  662. }
  663. }
  664. ',
  665. ];
  666. yield 'multiple try/catch separated with conditional return, with finally block' => [
  667. '<?php
  668. function foo()
  669. {
  670. try {
  671. return getResult();
  672. } catch (\Throwable $exception) {
  673. error_log($exception->getMessage());
  674. }
  675. if (isSomeCondition()) {
  676. return getSomeResult();
  677. }
  678. try {
  679. $result = $a + $b;
  680. return $result;
  681. } catch (\Throwable $th) {
  682. throw $th;
  683. } finally {
  684. echo "result:", $result, \PHP_EOL;
  685. }
  686. }
  687. ',
  688. '<?php
  689. function foo()
  690. {
  691. try {
  692. $result = getResult();
  693. return $result;
  694. } catch (\Throwable $exception) {
  695. error_log($exception->getMessage());
  696. }
  697. if (isSomeCondition()) {
  698. $result = getSomeResult();
  699. return $result;
  700. }
  701. try {
  702. $result = $a + $b;
  703. return $result;
  704. } catch (\Throwable $th) {
  705. throw $th;
  706. } finally {
  707. echo "result:", $result, \PHP_EOL;
  708. }
  709. }
  710. ',
  711. ];
  712. }
  713. /**
  714. * @dataProvider provideDoNotFixCases
  715. */
  716. public function testDoNotFix(string $expected): void
  717. {
  718. $this->doTest($expected);
  719. }
  720. public static function provideDoNotFixCases(): iterable
  721. {
  722. yield 'invalid reference stays invalid' => [
  723. '<?php
  724. function bar() {
  725. $foo = &foo();
  726. return $foo;
  727. }',
  728. ];
  729. yield 'static' => [
  730. '<?php
  731. function a() {
  732. static $a;
  733. $a = time();
  734. return $a;
  735. }
  736. ',
  737. ];
  738. yield 'global' => [
  739. '<?php
  740. function a() {
  741. global $a;
  742. $a = time();
  743. return $a;
  744. }
  745. ',
  746. ];
  747. yield 'passed by reference' => [
  748. '<?php
  749. function foo(&$var)
  750. {
  751. $var = 1;
  752. return $var;
  753. }
  754. ',
  755. ];
  756. yield 'not in function scope' => [
  757. '<?php
  758. $a = 1; // var might be global here
  759. return $a;
  760. ',
  761. ];
  762. yield 'open-close with ;' => [
  763. '<?php
  764. function a()
  765. {
  766. $a = 1;
  767. ?>
  768. <?php
  769. ;
  770. return $a;
  771. }
  772. ',
  773. ];
  774. yield 'open-close single line' => [
  775. '<?php
  776. function a()
  777. {
  778. $a = 1 ?><?php return $a;
  779. }',
  780. ];
  781. yield 'open-close' => [
  782. '<?php
  783. function a()
  784. {
  785. $a = 1
  786. ?>
  787. <?php
  788. return $a;
  789. }
  790. ',
  791. ];
  792. yield 'open-close before function' => [
  793. '<?php
  794. $zz = 1 ?><?php
  795. function a($zz)
  796. {
  797. ;
  798. return $zz;
  799. }
  800. ',
  801. ];
  802. yield 'return complex statement' => [
  803. '<?php
  804. function a($c)
  805. {
  806. $a = 1;
  807. return $a + $c;
  808. }
  809. ',
  810. ];
  811. yield 'array assign' => [
  812. '<?php
  813. function a($c)
  814. {
  815. $_SERVER["abc"] = 3;
  816. return $_SERVER;
  817. }
  818. ',
  819. ];
  820. yield 'if assign' => [
  821. '<?php
  822. function foo ($bar)
  823. {
  824. $a = 123;
  825. if ($bar)
  826. $a = 12345;
  827. return $a;
  828. }
  829. ',
  830. ];
  831. yield 'else assign' => [
  832. '<?php
  833. function foo ($bar)
  834. {
  835. $a = 123;
  836. if ($bar)
  837. ;
  838. else
  839. $a = 12345;
  840. return $a;
  841. }
  842. ',
  843. ];
  844. yield 'elseif assign' => [
  845. '<?php
  846. function foo ($bar)
  847. {
  848. $a = 123;
  849. if ($bar)
  850. ;
  851. elseif($b)
  852. $a = 12345;
  853. return $a;
  854. }
  855. ',
  856. ];
  857. yield 'echo $a = N / comment $a = N;' => [
  858. '<?php
  859. function a($c)
  860. {
  861. $a = 1;
  862. echo $a."=1";
  863. return $a;
  864. }
  865. function b($c)
  866. {
  867. $a = 1;
  868. echo $a."=1;";
  869. return $a;
  870. }
  871. function c($c)
  872. {
  873. $a = 1;
  874. echo $a;
  875. // $a =1;
  876. return $a;
  877. }
  878. ',
  879. ];
  880. yield 'if ($a = N)' => [
  881. '<?php
  882. function a($c)
  883. {
  884. if ($a = 1)
  885. return $a;
  886. }
  887. ',
  888. ];
  889. yield 'changed after declaration' => [
  890. '<?php
  891. function a($c)
  892. {
  893. $a = 1;
  894. $a += 1;
  895. return $a;
  896. }
  897. function b($c)
  898. {
  899. $a = 1;
  900. $a -= 1;
  901. return $a;
  902. }
  903. ',
  904. ];
  905. yield 'complex statement' => [
  906. '<?php
  907. function a($c)
  908. {
  909. $d = $c && $a = 1;
  910. return $a;
  911. }
  912. ',
  913. ];
  914. yield 'PHP close tag within function' => [
  915. '<?php
  916. function a($zz)
  917. {
  918. $zz = 1 ?><?php
  919. ;
  920. return $zz;
  921. }
  922. ',
  923. ];
  924. yield 'import global using "require"' => [
  925. '<?php
  926. function a()
  927. {
  928. require __DIR__."/test3.php";
  929. $b = 1;
  930. return $b;
  931. }
  932. ',
  933. ];
  934. yield 'import global using "require_once"' => [
  935. '<?php
  936. function a()
  937. {
  938. require_once __DIR__."/test3.php";
  939. $b = 1;
  940. return $b;
  941. }
  942. ',
  943. ];
  944. yield 'import global using "include"' => [
  945. '<?php
  946. function a()
  947. {
  948. include __DIR__."/test3.php";
  949. $b = 1;
  950. return $b;
  951. }
  952. ',
  953. ];
  954. yield 'import global using "include_once"' => [
  955. '<?php
  956. function a()
  957. {
  958. include_once __DIR__."/test3.php";
  959. $b = 1;
  960. return $b;
  961. }
  962. ',
  963. ];
  964. yield 'eval' => [
  965. '<?php
  966. $b = function ($z) {
  967. $c = eval($z);
  968. return $c;
  969. };
  970. $c = function ($x) {
  971. $x = eval($x);
  972. $x = 1;
  973. return $x;
  974. };
  975. ',
  976. ];
  977. yield '${X}' => [
  978. '<?php
  979. function A($g)
  980. {
  981. $h = ${$g};
  982. return $h;
  983. }
  984. ',
  985. ];
  986. yield '$$' => [
  987. '<?php
  988. function B($c)
  989. {
  990. $b = $$c;
  991. return $b;
  992. }
  993. ',
  994. ];
  995. yield [
  996. '<?php
  997. class XYZ
  998. {
  999. public function test1()
  1000. {
  1001. $GLOBALS[\'a\'] = 2;
  1002. return $GLOBALS;
  1003. }
  1004. public function test2()
  1005. {
  1006. $_server = 2;
  1007. return $_server;
  1008. }
  1009. public function __destruct()
  1010. {
  1011. $GLOBALS[\'a\'] = 2;
  1012. return $GLOBALS[\'a\']; // destruct cannot return but still lints
  1013. }
  1014. };
  1015. $a = new XYZ();
  1016. $a = 1;
  1017. var_dump($a); // $a = 2 here _╯°□°╯︵┻━┻
  1018. ',
  1019. ];
  1020. yield 'variable returned by reference in function' => [
  1021. '<?php
  1022. function &foo() {
  1023. $var = 1;
  1024. return $var;
  1025. }',
  1026. ];
  1027. yield 'variable returned by reference in method' => [
  1028. '<?php
  1029. class Foo {
  1030. public function &bar() {
  1031. $var = 1;
  1032. return $var;
  1033. }
  1034. }',
  1035. ];
  1036. yield 'variable returned by reference in lambda' => [
  1037. '<?php $a = function &() {$z = new A(); return $z;};',
  1038. ];
  1039. yield [
  1040. '<?php
  1041. function F() {
  1042. $a = 1;
  1043. while(bar()) {
  1044. ++$a;
  1045. }; // keep this
  1046. return $a;
  1047. }
  1048. ',
  1049. ];
  1050. yield 'try/catch/finally' => [
  1051. '<?php
  1052. function add($a, $b): mixed
  1053. {
  1054. try {
  1055. $result = $a + $b;
  1056. return $result;
  1057. } catch (\Throwable $th) {
  1058. throw $th;
  1059. } finally {
  1060. echo \'result:\', $result, \PHP_EOL;
  1061. }
  1062. }
  1063. ',
  1064. ];
  1065. yield 'try with multiple catch blocks' => [
  1066. '<?php
  1067. function foo() {
  1068. try {
  1069. $bar = bar();
  1070. return $bar;
  1071. } catch (\LogicException $e) {
  1072. echo "catch ... ";
  1073. } catch (\RuntimeException $e) {
  1074. echo $bar;
  1075. }
  1076. }',
  1077. ];
  1078. yield 'try/catch/finally with some comments' => [
  1079. '<?php
  1080. function add($a, $b): mixed
  1081. {
  1082. try {
  1083. $result = $a + $b;
  1084. return $result;
  1085. } /* foo */ catch /** bar */ (\LogicException $th) {
  1086. throw $th;
  1087. }
  1088. // Or maybe this....
  1089. catch (\RuntimeException $th) {
  1090. throw $th;
  1091. }
  1092. # Print the result anyway
  1093. finally {
  1094. echo \'result:\', $result, \PHP_EOL;
  1095. }
  1096. }
  1097. ',
  1098. ];
  1099. }
  1100. /**
  1101. * @dataProvider provideDoNotFix80Cases
  1102. *
  1103. * @requires PHP 8.0
  1104. */
  1105. public function testDoNotFix80(string $expected): void
  1106. {
  1107. $this->doTest($expected);
  1108. }
  1109. public static function provideDoNotFix80Cases(): iterable
  1110. {
  1111. yield 'try with non-capturing catch block' => [
  1112. '<?php
  1113. function add($a, $b): mixed
  1114. {
  1115. try {
  1116. $result = $a + $b;
  1117. return $result;
  1118. }
  1119. catch (\Throwable) {
  1120. noop();
  1121. }
  1122. finally {
  1123. echo \'result:\', $result, \PHP_EOL;
  1124. }
  1125. }
  1126. ',
  1127. ];
  1128. }
  1129. /**
  1130. * @dataProvider provideRepetitiveFixCases
  1131. */
  1132. public function testRepetitiveFix(string $expected, ?string $input = null): void
  1133. {
  1134. $this->doTest($expected, $input);
  1135. }
  1136. public static function provideRepetitiveFixCases(): iterable
  1137. {
  1138. yield [
  1139. '<?php
  1140. function foo() {
  1141. return bar();
  1142. }
  1143. ',
  1144. '<?php
  1145. function foo() {
  1146. $a = bar();
  1147. $b = $a;
  1148. return $b;
  1149. }
  1150. ',
  1151. ];
  1152. yield [
  1153. '<?php
  1154. function foo(&$c) {
  1155. $a = $c;
  1156. $b = $a;
  1157. return $b;
  1158. }
  1159. ',
  1160. ];
  1161. $expected = "<?php\n";
  1162. $input = "<?php\n";
  1163. for ($i = 0; $i < 10; ++$i) {
  1164. $expected .= sprintf("\nfunction foo%d() {\n\treturn bar();\n}", $i);
  1165. $input .= sprintf("\nfunction foo%d() {\n\t\$a = bar();\n\t\$b = \$a;\n\nreturn \$b;\n}", $i);
  1166. }
  1167. yield [$expected, $input];
  1168. }
  1169. /**
  1170. * @requires PHP 8.0
  1171. *
  1172. * @dataProvider provideFix80Cases
  1173. */
  1174. public function testFix80(string $expected, ?string $input = null): void
  1175. {
  1176. $this->doTest($expected, $input);
  1177. }
  1178. public static function provideFix80Cases(): iterable
  1179. {
  1180. yield 'match' => [
  1181. '<?php
  1182. function Foo($food) {
  1183. return match ($food) {
  1184. "apple" => "This food is an apple",
  1185. "cake" => "This food is a cake",
  1186. };
  1187. }
  1188. ',
  1189. '<?php
  1190. function Foo($food) {
  1191. $return_value = match ($food) {
  1192. "apple" => "This food is an apple",
  1193. "cake" => "This food is a cake",
  1194. };
  1195. return $return_value;
  1196. }
  1197. ',
  1198. ];
  1199. yield 'attribute before anonymous `class`' => [
  1200. '<?php
  1201. function A()
  1202. {
  1203. return new #[Foo] class {};
  1204. }
  1205. ',
  1206. '<?php
  1207. function A()
  1208. {
  1209. $a = new #[Foo] class {};
  1210. return $a;
  1211. }
  1212. ',
  1213. ];
  1214. }
  1215. /**
  1216. * @requires PHP 8.3
  1217. *
  1218. * @dataProvider provideFixPhp83Cases
  1219. */
  1220. public function testFixPhp83(string $expected, ?string $input = null): void
  1221. {
  1222. $this->doTest($expected, $input);
  1223. }
  1224. public static function provideFixPhp83Cases(): iterable
  1225. {
  1226. yield 'anonymous readonly class' => [
  1227. '<?php
  1228. function A()
  1229. {
  1230. return new readonly class {};
  1231. }
  1232. ',
  1233. '<?php
  1234. function A()
  1235. {
  1236. $a = new readonly class {};
  1237. return $a;
  1238. }
  1239. ',
  1240. ];
  1241. yield 'attribute before anonymous `readonly class`' => [
  1242. '<?php
  1243. function A()
  1244. {
  1245. return new #[Foo] readonly class {};
  1246. }
  1247. ',
  1248. '<?php
  1249. function A()
  1250. {
  1251. $a = new #[Foo] readonly class {};
  1252. return $a;
  1253. }
  1254. ',
  1255. ];
  1256. }
  1257. }