GlobalNamespaceImportFixerTest.php 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349
  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. yield 'key in PHPDoc\'s array shape matching class name' => [
  1002. '<?php
  1003. namespace Foo;
  1004. use Exception;
  1005. class Bar {
  1006. /**
  1007. * @return array{code: int, exception: \Exception}
  1008. */
  1009. public function f1(): array {}
  1010. /**
  1011. * @return array{exception: \Exception}
  1012. */
  1013. public function f2(): array {}
  1014. /**
  1015. * @return array{exceptions: array<\Exception>}
  1016. */
  1017. public function f3(): array {}
  1018. }',
  1019. '<?php
  1020. namespace Foo;
  1021. use Exception;
  1022. class Bar {
  1023. /**
  1024. * @return array{code: int, exception: Exception}
  1025. */
  1026. public function f1(): array {}
  1027. /**
  1028. * @return array{exception: Exception}
  1029. */
  1030. public function f2(): array {}
  1031. /**
  1032. * @return array{exceptions: array<Exception>}
  1033. */
  1034. public function f3(): array {}
  1035. }',
  1036. ];
  1037. }
  1038. /**
  1039. * @dataProvider provideFixFullyQualifyClasses80Cases
  1040. *
  1041. * @requires PHP 8.0
  1042. */
  1043. public function testFixFullyQualifyClasses80(string $expected, string $input): void
  1044. {
  1045. $this->fixer->configure(['import_classes' => false]);
  1046. $this->doTest($expected, $input);
  1047. }
  1048. public static function provideFixFullyQualifyClasses80Cases(): iterable
  1049. {
  1050. yield 'try catch without variable' => [
  1051. <<<'EXPECTED'
  1052. <?php
  1053. namespace Test;
  1054. use Exception;
  1055. try {
  1056. } catch (\Exception) {
  1057. }
  1058. EXPECTED
  1059. ,
  1060. <<<'INPUT'
  1061. <?php
  1062. namespace Test;
  1063. use Exception;
  1064. try {
  1065. } catch (Exception) {
  1066. }
  1067. INPUT
  1068. ];
  1069. yield 'try catch without variable and comments' => [
  1070. <<<'EXPECTED'
  1071. <?php
  1072. namespace Test;
  1073. use Exception;
  1074. try {
  1075. } catch (/* non-capturing catch */ \Exception /* just because! */) {
  1076. }
  1077. EXPECTED
  1078. ,
  1079. <<<'INPUT'
  1080. <?php
  1081. namespace Test;
  1082. use Exception;
  1083. try {
  1084. } catch (/* non-capturing catch */ Exception /* just because! */) {
  1085. }
  1086. INPUT
  1087. ];
  1088. }
  1089. /**
  1090. * @dataProvider provideMultipleNamespacesCases
  1091. */
  1092. public function testMultipleNamespaces(string $expected): void
  1093. {
  1094. $this->fixer->configure(['import_constants' => true]);
  1095. $this->doTest($expected);
  1096. }
  1097. public static function provideMultipleNamespacesCases(): iterable
  1098. {
  1099. yield [
  1100. <<<'INPUT'
  1101. <?php
  1102. namespace Test;
  1103. echo \FOO, \BAR;
  1104. namespace OtherTest;
  1105. echo \FOO, \BAR;
  1106. INPUT
  1107. ];
  1108. yield [
  1109. <<<'INPUT'
  1110. <?php
  1111. namespace Test {
  1112. echo \FOO, \BAR;
  1113. }
  1114. namespace OtherTest {
  1115. echo \FOO, \BAR;
  1116. }
  1117. INPUT
  1118. ];
  1119. yield [
  1120. <<<'INPUT'
  1121. <?php
  1122. namespace {
  1123. echo \FOO, \BAR;
  1124. }
  1125. namespace OtherTest {
  1126. echo \FOO, \BAR;
  1127. }
  1128. INPUT
  1129. ];
  1130. yield [
  1131. <<<'INPUT'
  1132. <?php
  1133. namespace Test {
  1134. echo \FOO, \BAR;
  1135. }
  1136. namespace {
  1137. echo \FOO, \BAR;
  1138. }
  1139. INPUT
  1140. ];
  1141. }
  1142. /**
  1143. * @requires PHP 8.0
  1144. */
  1145. public function testAttributes(): void
  1146. {
  1147. $this->fixer->configure([
  1148. 'import_classes' => true,
  1149. 'import_constants' => true,
  1150. 'import_functions' => true,
  1151. ]);
  1152. $this->doTest(
  1153. '<?php
  1154. namespace Foo;
  1155. use AnAttribute1;
  1156. use AnAttribute2;
  1157. use AnAttribute3;
  1158. class Bar
  1159. {
  1160. #[AnAttribute1]
  1161. public function f1() {}
  1162. #[AnAttribute2, AnAttribute3]
  1163. public function f2() {}
  1164. }',
  1165. '<?php
  1166. namespace Foo;
  1167. class Bar
  1168. {
  1169. #[\AnAttribute1]
  1170. public function f1() {}
  1171. #[\AnAttribute2, \AnAttribute3]
  1172. public function f2() {}
  1173. }'
  1174. );
  1175. }
  1176. /**
  1177. * @dataProvider provideFix81Cases
  1178. *
  1179. * @requires PHP 8.1
  1180. */
  1181. public function testFix81(string $expected, ?string $input = null): void
  1182. {
  1183. $this->fixer->configure([
  1184. 'import_constants' => true,
  1185. 'import_functions' => true,
  1186. ]);
  1187. $this->doTest($expected, $input);
  1188. }
  1189. public static function provideFix81Cases(): iterable
  1190. {
  1191. yield 'ignore enum methods' => [
  1192. <<<'EXPECTED'
  1193. <?php
  1194. namespace Test;
  1195. use function foo;
  1196. enum Bar {
  1197. function foo() {}
  1198. }
  1199. foo();
  1200. EXPECTED
  1201. ,
  1202. <<<'INPUT'
  1203. <?php
  1204. namespace Test;
  1205. enum Bar {
  1206. function foo() {}
  1207. }
  1208. \foo();
  1209. INPUT
  1210. ];
  1211. yield 'ignore enum constants' => [
  1212. <<<'EXPECTED'
  1213. <?php
  1214. namespace Test;
  1215. use const FOO;
  1216. enum Bar {
  1217. const FOO = 1;
  1218. }
  1219. echo FOO;
  1220. EXPECTED
  1221. ,
  1222. <<<'INPUT'
  1223. <?php
  1224. namespace Test;
  1225. enum Bar {
  1226. const FOO = 1;
  1227. }
  1228. echo \FOO;
  1229. INPUT
  1230. ];
  1231. }
  1232. }