GlobalNamespaceImportFixerTest.php 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312
  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\Import;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @author Gregor Harlan <gharlan@web.de>
  16. *
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\Import\GlobalNamespaceImportFixer
  20. */
  21. final class GlobalNamespaceImportFixerTest extends AbstractFixerTestCase
  22. {
  23. /**
  24. * @dataProvider provideFixImportConstantsCases
  25. */
  26. public function testFixImportConstants(string $expected, ?string $input = null): void
  27. {
  28. $this->fixer->configure(['import_constants' => true]);
  29. $this->doTest($expected, $input);
  30. }
  31. public static function provideFixImportConstantsCases(): iterable
  32. {
  33. yield 'non-global names' => [
  34. <<<'EXPECTED'
  35. <?php
  36. namespace Test;
  37. echo FOO, \Bar\BAZ, namespace\FOO2;
  38. EXPECTED
  39. ];
  40. yield 'name already used [1]' => [
  41. <<<'EXPECTED'
  42. <?php
  43. namespace Test;
  44. echo \FOO, FOO, \FOO;
  45. EXPECTED
  46. ];
  47. yield 'name already used [2]' => [
  48. <<<'EXPECTED'
  49. <?php
  50. namespace Test;
  51. use const Bar\FOO;
  52. echo \FOO;
  53. EXPECTED
  54. ];
  55. yield 'name already used [3]' => [
  56. <<<'EXPECTED'
  57. <?php
  58. namespace Test;
  59. const FOO = 1;
  60. echo \FOO;
  61. EXPECTED
  62. ];
  63. yield 'without namespace / do not import' => [
  64. <<<'INPUT'
  65. <?php
  66. echo \FOO, \BAR, \FOO;
  67. INPUT
  68. ];
  69. yield 'with namespace' => [
  70. <<<'EXPECTED'
  71. <?php
  72. namespace Test;
  73. use const FOO;
  74. use const BAR;
  75. echo FOO, BAR;
  76. EXPECTED
  77. ,
  78. <<<'INPUT'
  79. <?php
  80. namespace Test;
  81. echo \FOO, \BAR;
  82. INPUT
  83. ];
  84. yield 'with namespace with {} syntax' => [
  85. <<<'EXPECTED'
  86. <?php
  87. namespace Test {
  88. use const FOO;
  89. use const BAR;
  90. echo FOO, BAR;
  91. }
  92. EXPECTED
  93. ,
  94. <<<'INPUT'
  95. <?php
  96. namespace Test {
  97. echo \FOO, \BAR;
  98. }
  99. INPUT
  100. ];
  101. yield 'ignore other imported types' => [
  102. <<<'EXPECTED'
  103. <?php
  104. namespace Test;
  105. use BAR;
  106. use const FOO;
  107. use const BAR;
  108. echo FOO, BAR;
  109. EXPECTED
  110. ,
  111. <<<'INPUT'
  112. <?php
  113. namespace Test;
  114. use BAR;
  115. echo \FOO, \BAR;
  116. INPUT
  117. ];
  118. yield 'respect already imported names [1]' => [
  119. <<<'EXPECTED'
  120. <?php
  121. namespace Test;
  122. use const BAR;
  123. use const FOO;
  124. echo FOO, BAR;
  125. EXPECTED
  126. ,
  127. <<<'INPUT'
  128. <?php
  129. namespace Test;
  130. use const BAR;
  131. echo \FOO, \BAR;
  132. INPUT
  133. ];
  134. yield 'respect already imported names [2]' => [
  135. <<<'EXPECTED'
  136. <?php
  137. namespace Test;
  138. use const \BAR;
  139. use const FOO;
  140. echo FOO, BAR, BAR;
  141. EXPECTED
  142. ,
  143. <<<'INPUT'
  144. <?php
  145. namespace Test;
  146. use const \BAR;
  147. echo \FOO, \BAR, BAR;
  148. INPUT
  149. ];
  150. yield 'handle case sensitivity' => [
  151. <<<'EXPECTED'
  152. <?php
  153. namespace Test;
  154. use const fOO;
  155. use const FOO;
  156. use const Foo;
  157. const foO = 1;
  158. echo FOO, Foo;
  159. EXPECTED
  160. ,
  161. <<<'INPUT'
  162. <?php
  163. namespace Test;
  164. use const fOO;
  165. const foO = 1;
  166. echo \FOO, \Foo;
  167. INPUT
  168. ];
  169. yield 'handle aliased imports' => [
  170. <<<'EXPECTED'
  171. <?php
  172. namespace Test;
  173. use const BAR as BAZ;
  174. use const FOO;
  175. echo FOO, BAZ;
  176. EXPECTED
  177. ,
  178. <<<'INPUT'
  179. <?php
  180. namespace Test;
  181. use const BAR as BAZ;
  182. echo \FOO, \BAR;
  183. INPUT
  184. ];
  185. yield 'ignore class constants' => [
  186. <<<'EXPECTED'
  187. <?php
  188. namespace Test;
  189. use const FOO;
  190. class Bar {
  191. const FOO = 1;
  192. }
  193. echo FOO;
  194. EXPECTED
  195. ,
  196. <<<'INPUT'
  197. <?php
  198. namespace Test;
  199. class Bar {
  200. const FOO = 1;
  201. }
  202. echo \FOO;
  203. INPUT
  204. ];
  205. yield 'global namespace' => [
  206. <<<'INPUT'
  207. <?php
  208. echo \FOO, \BAR;
  209. INPUT
  210. ];
  211. yield [
  212. <<<'INPUT'
  213. <?php
  214. namespace {
  215. echo \FOO, \BAR;
  216. }
  217. INPUT
  218. ];
  219. }
  220. /**
  221. * @dataProvider provideFixImportFunctionsCases
  222. */
  223. public function testFixImportFunctions(string $expected, ?string $input = null): void
  224. {
  225. $this->fixer->configure(['import_functions' => true]);
  226. $this->doTest($expected, $input);
  227. }
  228. public static function provideFixImportFunctionsCases(): iterable
  229. {
  230. yield 'non-global names' => [
  231. <<<'EXPECTED'
  232. <?php
  233. namespace Test;
  234. foo();
  235. Bar\baz();
  236. namespace\foo2();
  237. EXPECTED
  238. ];
  239. yield 'name already used [1]' => [
  240. <<<'EXPECTED'
  241. <?php
  242. namespace Test;
  243. \foo();
  244. Foo();
  245. \foo();
  246. EXPECTED
  247. ];
  248. yield 'name already used [2]' => [
  249. <<<'EXPECTED'
  250. <?php
  251. namespace Test;
  252. use function Bar\foo;
  253. \Foo();
  254. EXPECTED
  255. ];
  256. yield 'name already used [3]' => [
  257. <<<'EXPECTED'
  258. <?php
  259. namespace Test;
  260. function foo() {}
  261. \Foo();
  262. EXPECTED
  263. ];
  264. yield 'without namespace / do not import' => [
  265. <<<'INPUT'
  266. <?php
  267. \foo();
  268. \bar();
  269. \Foo();
  270. INPUT
  271. ];
  272. yield 'with namespace' => [
  273. <<<'EXPECTED'
  274. <?php
  275. namespace Test;
  276. use function foo;
  277. use function bar;
  278. foo();
  279. bar();
  280. EXPECTED
  281. ,
  282. <<<'INPUT'
  283. <?php
  284. namespace Test;
  285. \foo();
  286. \bar();
  287. INPUT
  288. ];
  289. yield 'with namespace with {} syntax' => [
  290. <<<'EXPECTED'
  291. <?php
  292. namespace Test {
  293. use function foo;
  294. use function bar;
  295. foo();
  296. bar();
  297. }
  298. EXPECTED
  299. ,
  300. <<<'INPUT'
  301. <?php
  302. namespace Test {
  303. \foo();
  304. \bar();
  305. }
  306. INPUT
  307. ];
  308. yield 'ignore other imported types' => [
  309. <<<'EXPECTED'
  310. <?php
  311. namespace Test;
  312. use bar;
  313. use function foo;
  314. use function bar;
  315. foo();
  316. bar();
  317. EXPECTED
  318. ,
  319. <<<'INPUT'
  320. <?php
  321. namespace Test;
  322. use bar;
  323. \foo();
  324. \bar();
  325. INPUT
  326. ];
  327. yield 'respect already imported names [1]' => [
  328. <<<'EXPECTED'
  329. <?php
  330. namespace Test;
  331. use function bar;
  332. use function foo;
  333. foo();
  334. Bar();
  335. EXPECTED
  336. ,
  337. <<<'INPUT'
  338. <?php
  339. namespace Test;
  340. use function bar;
  341. \foo();
  342. \Bar();
  343. INPUT
  344. ];
  345. yield 'respect already imported names [2]' => [
  346. <<<'EXPECTED'
  347. <?php
  348. namespace Test;
  349. use function \bar;
  350. use function foo;
  351. foo();
  352. Bar();
  353. bar();
  354. EXPECTED
  355. ,
  356. <<<'INPUT'
  357. <?php
  358. namespace Test;
  359. use function \bar;
  360. \foo();
  361. \Bar();
  362. bar();
  363. INPUT
  364. ];
  365. yield 'handle aliased imports' => [
  366. <<<'EXPECTED'
  367. <?php
  368. namespace Test;
  369. use function bar as baz;
  370. use function foo;
  371. foo();
  372. baz();
  373. EXPECTED
  374. ,
  375. <<<'INPUT'
  376. <?php
  377. namespace Test;
  378. use function bar as baz;
  379. \foo();
  380. \Bar();
  381. INPUT
  382. ];
  383. yield 'ignore class methods' => [
  384. <<<'EXPECTED'
  385. <?php
  386. namespace Test;
  387. use function foo;
  388. class Bar {
  389. function foo() {}
  390. }
  391. foo();
  392. EXPECTED
  393. ,
  394. <<<'INPUT'
  395. <?php
  396. namespace Test;
  397. class Bar {
  398. function foo() {}
  399. }
  400. \foo();
  401. INPUT
  402. ];
  403. yield 'name already used' => [
  404. <<<'EXPECTED'
  405. <?php
  406. namespace Test;
  407. class Bar {
  408. function baz() {
  409. new class() {
  410. function baz() {
  411. function foo() {}
  412. }
  413. };
  414. }
  415. }
  416. \foo();
  417. EXPECTED
  418. ];
  419. }
  420. /**
  421. * @dataProvider provideFixImportClassesCases
  422. */
  423. public function testFixImportClasses(string $expected, ?string $input = null): void
  424. {
  425. $this->fixer->configure(['import_classes' => true]);
  426. $this->doTest($expected, $input);
  427. }
  428. public static function provideFixImportClassesCases(): iterable
  429. {
  430. yield 'non-global names' => [
  431. <<<'EXPECTED'
  432. <?php
  433. namespace Test;
  434. new Foo();
  435. new Bar\Baz();
  436. new namespace\Foo2();
  437. /** @var Foo|Bar\Baz $x */
  438. $x = x();
  439. EXPECTED
  440. ];
  441. yield 'name already used [1]' => [
  442. <<<'EXPECTED'
  443. <?php
  444. namespace Test;
  445. new \Foo();
  446. new foo();
  447. /** @var \Foo $foo */
  448. $foo = new \Foo();
  449. EXPECTED
  450. ];
  451. yield 'name already used [2]' => [
  452. <<<'EXPECTED'
  453. <?php
  454. namespace Test;
  455. use Bar\foo;
  456. /** @var \Foo $foo */
  457. $foo = new \Foo();
  458. EXPECTED
  459. ];
  460. yield 'name already used [3]' => [
  461. <<<'EXPECTED'
  462. <?php
  463. namespace Test;
  464. class foo {}
  465. /** @var \Foo $foo */
  466. $foo = new \Foo();
  467. EXPECTED
  468. ];
  469. yield 'name already used [4]' => [
  470. <<<'EXPECTED'
  471. <?php
  472. namespace Test;
  473. /** @return array<string, foo> */
  474. function x() {}
  475. /** @var \Foo $foo */
  476. $foo = new \Foo();
  477. EXPECTED
  478. ];
  479. yield 'without namespace / do not import' => [
  480. <<<'INPUT'
  481. <?php
  482. /** @var \Foo $foo */
  483. $foo = new \foo();
  484. new \Bar();
  485. \FOO::baz();
  486. INPUT
  487. ];
  488. yield 'with namespace' => [
  489. <<<'EXPECTED'
  490. <?php
  491. namespace Test;
  492. use Bar;
  493. use Baz;
  494. use foo;
  495. new Foo();
  496. Bar::baz();
  497. /** @return Baz<string, foo> */
  498. function x() {}
  499. EXPECTED
  500. ,
  501. <<<'INPUT'
  502. <?php
  503. namespace Test;
  504. new \Foo();
  505. \Bar::baz();
  506. /** @return \Baz<string, \foo> */
  507. function x() {}
  508. INPUT
  509. ];
  510. yield 'with namespace with {} syntax' => [
  511. <<<'EXPECTED'
  512. <?php
  513. namespace Test {
  514. use Foo;
  515. use Bar;
  516. new Foo();
  517. Bar::baz();
  518. }
  519. EXPECTED
  520. ,
  521. <<<'INPUT'
  522. <?php
  523. namespace Test {
  524. new \Foo();
  525. \Bar::baz();
  526. }
  527. INPUT
  528. ];
  529. yield 'phpdoc only' => [
  530. <<<'EXPECTED'
  531. <?php
  532. namespace Test;
  533. use Throwable;
  534. /** @throws Throwable */
  535. function x() {}
  536. EXPECTED
  537. ,
  538. <<<'INPUT'
  539. <?php
  540. namespace Test;
  541. /** @throws \Throwable */
  542. function x() {}
  543. INPUT
  544. ];
  545. yield 'ignore other imported types' => [
  546. <<<'EXPECTED'
  547. <?php
  548. namespace Test;
  549. use function Bar;
  550. use Foo;
  551. use Bar;
  552. new Foo();
  553. Bar::baz();
  554. EXPECTED
  555. ,
  556. <<<'INPUT'
  557. <?php
  558. namespace Test;
  559. use function Bar;
  560. new \Foo();
  561. \Bar::baz();
  562. INPUT
  563. ];
  564. yield 'respect already imported names [1]' => [
  565. <<<'EXPECTED'
  566. <?php
  567. namespace Test;
  568. use Bar;
  569. use Foo;
  570. new Foo();
  571. bar::baz();
  572. EXPECTED
  573. ,
  574. <<<'INPUT'
  575. <?php
  576. namespace Test;
  577. use Bar;
  578. new \Foo();
  579. \bar::baz();
  580. INPUT
  581. ];
  582. yield 'respect already imported names [2]' => [
  583. <<<'EXPECTED'
  584. <?php
  585. namespace Test;
  586. use \Bar;
  587. use Foo;
  588. new Foo();
  589. new bar();
  590. new Bar();
  591. EXPECTED
  592. ,
  593. <<<'INPUT'
  594. <?php
  595. namespace Test;
  596. use \Bar;
  597. new \Foo();
  598. new \bar();
  599. new Bar();
  600. INPUT
  601. ];
  602. yield 'respect already imported names [3]' => [
  603. <<<'EXPECTED'
  604. <?php
  605. namespace Test;
  606. use Throwable;
  607. /** @throws Throwable */
  608. function x() {}
  609. /** @throws Throwable */
  610. function y() {}
  611. EXPECTED
  612. ,
  613. <<<'INPUT'
  614. <?php
  615. namespace Test;
  616. use Throwable;
  617. /** @throws Throwable */
  618. function x() {}
  619. /** @throws \Throwable */
  620. function y() {}
  621. INPUT
  622. ];
  623. yield 'handle aliased imports' => [
  624. <<<'EXPECTED'
  625. <?php
  626. namespace Test;
  627. use Bar as Baz;
  628. use Foo;
  629. new Foo();
  630. /** @var Baz $bar */
  631. $bar = new Baz();
  632. EXPECTED
  633. ,
  634. <<<'INPUT'
  635. <?php
  636. namespace Test;
  637. use Bar as Baz;
  638. new \Foo();
  639. /** @var \bar $bar */
  640. $bar = new \bar();
  641. INPUT
  642. ];
  643. yield 'handle typehints' => [
  644. <<<'EXPECTED'
  645. <?php
  646. namespace Test;
  647. use Bar;
  648. use Foo;
  649. use Baz;
  650. class Abc {
  651. function bar(Foo $a, Bar $b, foo &$c, Baz ...$d) {}
  652. }
  653. EXPECTED
  654. ,
  655. <<<'INPUT'
  656. <?php
  657. namespace Test;
  658. class Abc {
  659. function bar(\Foo $a, \Bar $b, \foo &$c, \Baz ...$d) {}
  660. }
  661. INPUT
  662. ];
  663. yield 'handle typehints 2' => [
  664. <<<'EXPECTED'
  665. <?php
  666. namespace Test;
  667. use Foo;
  668. use Bar;
  669. class Abc {
  670. function bar(?Foo $a): ?Bar {}
  671. }
  672. EXPECTED
  673. ,
  674. <<<'INPUT'
  675. <?php
  676. namespace Test;
  677. class Abc {
  678. function bar(?\Foo $a): ?\Bar {}
  679. }
  680. INPUT
  681. ];
  682. yield 'try catch' => [
  683. <<<'EXPECTED'
  684. <?php
  685. namespace Test;
  686. use Exception;
  687. try {
  688. } catch (Exception $e) {
  689. }
  690. EXPECTED
  691. ,
  692. <<<'INPUT'
  693. <?php
  694. namespace Test;
  695. try {
  696. } catch (\Exception $e) {
  697. }
  698. INPUT
  699. ];
  700. yield 'try catch with comments' => [
  701. <<<'EXPECTED'
  702. <?php
  703. namespace Test;
  704. use Exception;
  705. try {
  706. } catch (/* ... */ Exception $e /* ... */) {
  707. }
  708. EXPECTED
  709. ,
  710. <<<'INPUT'
  711. <?php
  712. namespace Test;
  713. try {
  714. } catch (/* ... */ \Exception $e /* ... */) {
  715. }
  716. INPUT
  717. ];
  718. }
  719. /**
  720. * @dataProvider provideFixImportClasses80Cases
  721. *
  722. * @requires PHP 8.0
  723. */
  724. public function testFixImportClasses80(string $expected, string $input): void
  725. {
  726. $this->fixer->configure(['import_classes' => true]);
  727. $this->doTest($expected, $input);
  728. }
  729. public static function provideFixImportClasses80Cases(): iterable
  730. {
  731. yield 'try catch without variable' => [
  732. <<<'EXPECTED'
  733. <?php
  734. namespace Test;
  735. use Exception;
  736. try {
  737. } catch (Exception) {
  738. }
  739. EXPECTED
  740. ,
  741. <<<'INPUT'
  742. <?php
  743. namespace Test;
  744. try {
  745. } catch (\Exception) {
  746. }
  747. INPUT
  748. ];
  749. yield 'try catch without variable and comments' => [
  750. <<<'EXPECTED'
  751. <?php
  752. namespace Test;
  753. use Exception;
  754. try {
  755. } catch (/* non-capturing catch */ Exception /* just because! */) {
  756. }
  757. EXPECTED
  758. ,
  759. <<<'INPUT'
  760. <?php
  761. namespace Test;
  762. try {
  763. } catch (/* non-capturing catch */ \Exception /* just because! */) {
  764. }
  765. INPUT
  766. ];
  767. }
  768. /**
  769. * @dataProvider provideFixFullyQualifyConstantsCases
  770. */
  771. public function testFixFullyQualifyConstants(string $expected, ?string $input = null): void
  772. {
  773. $this->fixer->configure(['import_constants' => false]);
  774. $this->doTest($expected, $input);
  775. }
  776. public static function provideFixFullyQualifyConstantsCases(): iterable
  777. {
  778. yield 'already fqn or sub namespace' => [
  779. <<<'EXPECTED'
  780. <?php
  781. use const FOO;
  782. use const BAR;
  783. echo \FOO, Baz\BAR;
  784. EXPECTED
  785. ];
  786. yield 'handle all occurrences' => [
  787. <<<'EXPECTED'
  788. <?php
  789. namespace X;
  790. use const FOO;
  791. use const BAR;
  792. echo \FOO, \BAR, \FOO;
  793. EXPECTED
  794. ,
  795. <<<'INPUT'
  796. <?php
  797. namespace X;
  798. use const FOO;
  799. use const BAR;
  800. echo FOO, BAR, FOO;
  801. INPUT
  802. ];
  803. yield 'ignore other imports and non-imported names' => [
  804. <<<'EXPECTED'
  805. <?php
  806. namespace Test;
  807. use FOO;
  808. use const BAR;
  809. use const Baz;
  810. echo FOO, \BAR, BAZ, QUX;
  811. EXPECTED
  812. ,
  813. <<<'INPUT'
  814. <?php
  815. namespace Test;
  816. use FOO;
  817. use const BAR;
  818. use const Baz;
  819. echo FOO, BAR, BAZ, QUX;
  820. INPUT
  821. ];
  822. }
  823. /**
  824. * @dataProvider provideFixFullyQualifyFunctionsCases
  825. */
  826. public function testFixFullyQualifyFunctions(string $expected, ?string $input = null): void
  827. {
  828. $this->fixer->configure(['import_functions' => false]);
  829. $this->doTest($expected, $input);
  830. }
  831. public static function provideFixFullyQualifyFunctionsCases(): iterable
  832. {
  833. yield 'already fqn or sub namespace' => [
  834. <<<'EXPECTED'
  835. <?php
  836. use function foo;
  837. use function bar;
  838. \foo();
  839. Baz\bar();
  840. EXPECTED
  841. ];
  842. yield 'handle all occurrences' => [
  843. <<<'EXPECTED'
  844. <?php
  845. namespace X;
  846. use function foo;
  847. use function bar;
  848. \foo();
  849. \bar();
  850. \Foo();
  851. EXPECTED
  852. ,
  853. <<<'INPUT'
  854. <?php
  855. namespace X;
  856. use function foo;
  857. use function bar;
  858. foo();
  859. bar();
  860. Foo();
  861. INPUT
  862. ];
  863. yield 'ignore other imports and non-imported names' => [
  864. <<<'EXPECTED'
  865. <?php
  866. namespace Test;
  867. use foo;
  868. use function bar;
  869. foo();
  870. \bar();
  871. baz();
  872. EXPECTED
  873. ,
  874. <<<'INPUT'
  875. <?php
  876. namespace Test;
  877. use foo;
  878. use function bar;
  879. foo();
  880. bar();
  881. baz();
  882. INPUT
  883. ];
  884. }
  885. /**
  886. * @dataProvider provideFixFullyQualifyClassesCases
  887. */
  888. public function testFixFullyQualifyClasses(string $expected, ?string $input = null): void
  889. {
  890. $this->fixer->configure(['import_classes' => false]);
  891. $this->doTest($expected, $input);
  892. }
  893. public static function provideFixFullyQualifyClassesCases(): iterable
  894. {
  895. yield 'already fqn or sub namespace' => [
  896. <<<'EXPECTED'
  897. <?php
  898. use Foo;
  899. use Bar;
  900. new \Foo();
  901. Baz\Bar::baz();
  902. /**
  903. * @param \Foo $foo
  904. * @param Baz\Bar $bar
  905. */
  906. function abc(\Foo $foo, Baz\Bar $bar = null) {}
  907. EXPECTED
  908. ];
  909. yield 'handle all occurrences' => [
  910. <<<'EXPECTED'
  911. <?php
  912. namespace X;
  913. use Foo;
  914. use Bar;
  915. new \Foo();
  916. new \Bar();
  917. \foo::baz();
  918. /**
  919. * @param \Foo|string $foo
  920. * @param null|\Bar[] $bar
  921. * @return array<string, ?\Bar<int, \foo>>|null
  922. */
  923. function abc($foo, \Bar $bar = null) {}
  924. EXPECTED
  925. ,
  926. <<<'INPUT'
  927. <?php
  928. namespace X;
  929. use Foo;
  930. use Bar;
  931. new Foo();
  932. new Bar();
  933. foo::baz();
  934. /**
  935. * @param Foo|string $foo
  936. * @param null|Bar[] $bar
  937. * @return array<string, ?Bar<int, foo>>|null
  938. */
  939. function abc($foo, Bar $bar = null) {}
  940. INPUT
  941. ];
  942. yield 'ignore other imports and non-imported names' => [
  943. <<<'EXPECTED'
  944. <?php
  945. namespace Test;
  946. use function Foo;
  947. use Bar;
  948. new Foo();
  949. new \Bar();
  950. new Baz();
  951. EXPECTED
  952. ,
  953. <<<'INPUT'
  954. <?php
  955. namespace Test;
  956. use function Foo;
  957. use Bar;
  958. new Foo();
  959. new Bar();
  960. new Baz();
  961. INPUT
  962. ];
  963. yield 'try catch' => [
  964. <<<'EXPECTED'
  965. <?php
  966. namespace Test;
  967. use Exception;
  968. try {
  969. } catch (\Exception $e) {
  970. }
  971. EXPECTED
  972. ,
  973. <<<'INPUT'
  974. <?php
  975. namespace Test;
  976. use Exception;
  977. try {
  978. } catch (Exception $e) {
  979. }
  980. INPUT
  981. ];
  982. yield 'try catch with comments' => [
  983. <<<'EXPECTED'
  984. <?php
  985. namespace Test;
  986. use Exception;
  987. try {
  988. } catch (/* ... */ \Exception $e /* ... */) {
  989. }
  990. EXPECTED
  991. ,
  992. <<<'INPUT'
  993. <?php
  994. namespace Test;
  995. use Exception;
  996. try {
  997. } catch (/* ... */ Exception $e /* ... */) {
  998. }
  999. INPUT
  1000. ];
  1001. }
  1002. /**
  1003. * @dataProvider provideFixFullyQualifyClasses80Cases
  1004. *
  1005. * @requires PHP 8.0
  1006. */
  1007. public function testFixFullyQualifyClasses80(string $expected, string $input): void
  1008. {
  1009. $this->fixer->configure(['import_classes' => false]);
  1010. $this->doTest($expected, $input);
  1011. }
  1012. public static function provideFixFullyQualifyClasses80Cases(): iterable
  1013. {
  1014. yield 'try catch without variable' => [
  1015. <<<'EXPECTED'
  1016. <?php
  1017. namespace Test;
  1018. use Exception;
  1019. try {
  1020. } catch (\Exception) {
  1021. }
  1022. EXPECTED
  1023. ,
  1024. <<<'INPUT'
  1025. <?php
  1026. namespace Test;
  1027. use Exception;
  1028. try {
  1029. } catch (Exception) {
  1030. }
  1031. INPUT
  1032. ];
  1033. yield 'try catch without variable and comments' => [
  1034. <<<'EXPECTED'
  1035. <?php
  1036. namespace Test;
  1037. use Exception;
  1038. try {
  1039. } catch (/* non-capturing catch */ \Exception /* just because! */) {
  1040. }
  1041. EXPECTED
  1042. ,
  1043. <<<'INPUT'
  1044. <?php
  1045. namespace Test;
  1046. use Exception;
  1047. try {
  1048. } catch (/* non-capturing catch */ Exception /* just because! */) {
  1049. }
  1050. INPUT
  1051. ];
  1052. }
  1053. /**
  1054. * @dataProvider provideMultipleNamespacesCases
  1055. */
  1056. public function testMultipleNamespaces(string $expected): void
  1057. {
  1058. $this->fixer->configure(['import_constants' => true]);
  1059. $this->doTest($expected);
  1060. }
  1061. public static function provideMultipleNamespacesCases(): iterable
  1062. {
  1063. yield [
  1064. <<<'INPUT'
  1065. <?php
  1066. namespace Test;
  1067. echo \FOO, \BAR;
  1068. namespace OtherTest;
  1069. echo \FOO, \BAR;
  1070. INPUT
  1071. ];
  1072. yield [
  1073. <<<'INPUT'
  1074. <?php
  1075. namespace Test {
  1076. echo \FOO, \BAR;
  1077. }
  1078. namespace OtherTest {
  1079. echo \FOO, \BAR;
  1080. }
  1081. INPUT
  1082. ];
  1083. yield [
  1084. <<<'INPUT'
  1085. <?php
  1086. namespace {
  1087. echo \FOO, \BAR;
  1088. }
  1089. namespace OtherTest {
  1090. echo \FOO, \BAR;
  1091. }
  1092. INPUT
  1093. ];
  1094. yield [
  1095. <<<'INPUT'
  1096. <?php
  1097. namespace Test {
  1098. echo \FOO, \BAR;
  1099. }
  1100. namespace {
  1101. echo \FOO, \BAR;
  1102. }
  1103. INPUT
  1104. ];
  1105. }
  1106. /**
  1107. * @requires PHP 8.0
  1108. */
  1109. public function testAttributes(): void
  1110. {
  1111. $this->fixer->configure([
  1112. 'import_classes' => true,
  1113. 'import_constants' => true,
  1114. 'import_functions' => true,
  1115. ]);
  1116. $this->doTest(
  1117. '<?php
  1118. namespace Foo;
  1119. use AnAttribute1;
  1120. use AnAttribute2;
  1121. use AnAttribute3;
  1122. class Bar
  1123. {
  1124. #[AnAttribute1]
  1125. public function f1() {}
  1126. #[AnAttribute2, AnAttribute3]
  1127. public function f2() {}
  1128. }',
  1129. '<?php
  1130. namespace Foo;
  1131. class Bar
  1132. {
  1133. #[\AnAttribute1]
  1134. public function f1() {}
  1135. #[\AnAttribute2, \AnAttribute3]
  1136. public function f2() {}
  1137. }'
  1138. );
  1139. }
  1140. /**
  1141. * @dataProvider provideFix81Cases
  1142. *
  1143. * @requires PHP 8.1
  1144. */
  1145. public function testFix81(string $expected, ?string $input = null): void
  1146. {
  1147. $this->fixer->configure([
  1148. 'import_constants' => true,
  1149. 'import_functions' => true,
  1150. ]);
  1151. $this->doTest($expected, $input);
  1152. }
  1153. public static function provideFix81Cases(): iterable
  1154. {
  1155. yield 'ignore enum methods' => [
  1156. <<<'EXPECTED'
  1157. <?php
  1158. namespace Test;
  1159. use function foo;
  1160. enum Bar {
  1161. function foo() {}
  1162. }
  1163. foo();
  1164. EXPECTED
  1165. ,
  1166. <<<'INPUT'
  1167. <?php
  1168. namespace Test;
  1169. enum Bar {
  1170. function foo() {}
  1171. }
  1172. \foo();
  1173. INPUT
  1174. ];
  1175. yield 'ignore enum constants' => [
  1176. <<<'EXPECTED'
  1177. <?php
  1178. namespace Test;
  1179. use const FOO;
  1180. enum Bar {
  1181. const FOO = 1;
  1182. }
  1183. echo FOO;
  1184. EXPECTED
  1185. ,
  1186. <<<'INPUT'
  1187. <?php
  1188. namespace Test;
  1189. enum Bar {
  1190. const FOO = 1;
  1191. }
  1192. echo \FOO;
  1193. INPUT
  1194. ];
  1195. }
  1196. }