NoUnusedImportsFixerTest.php 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655
  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. * @internal
  16. *
  17. * @covers \PhpCsFixer\Fixer\Import\NoUnusedImportsFixer
  18. */
  19. final class NoUnusedImportsFixerTest extends AbstractFixerTestCase
  20. {
  21. /**
  22. * @dataProvider provideFixCases
  23. */
  24. public function testFix(string $expected, ?string $input = null): void
  25. {
  26. $this->doTest($expected, $input);
  27. }
  28. public static function provideFixCases(): iterable
  29. {
  30. yield 'simple' => [
  31. <<<'EOF'
  32. <?php
  33. use Foo\Bar;
  34. use Foo\Bar\FooBar as FooBaz;
  35. use SomeClass;
  36. $a = new Bar();
  37. $a = new FooBaz();
  38. $a = new SomeClass();
  39. use Symfony\Annotation\Template;
  40. use Symfony\Doctrine\Entities\Entity;
  41. use Symfony\Array123\ArrayInterface;
  42. class AnnotatedClass
  43. {
  44. /**
  45. * @Template(foobar=21)
  46. * @param Entity $foo
  47. */
  48. public function doSomething($foo)
  49. {
  50. $bar = $foo->toArray();
  51. /** @var ArrayInterface $bar */
  52. }
  53. }
  54. EOF
  55. ,
  56. <<<'EOF'
  57. <?php
  58. use Foo\Bar;
  59. use Foo\Bar\Baz;
  60. use Foo\Bar\FooBar as FooBaz;
  61. use Foo\Bar\Foo as Fooo;
  62. use Foo\Bar\Baar\Baar;
  63. use SomeClass;
  64. $a = new Bar();
  65. $a = new FooBaz();
  66. $a = new SomeClass();
  67. use Symfony\Annotation\Template;
  68. use Symfony\Doctrine\Entities\Entity;
  69. use Symfony\Array123\ArrayInterface;
  70. class AnnotatedClass
  71. {
  72. /**
  73. * @Template(foobar=21)
  74. * @param Entity $foo
  75. */
  76. public function doSomething($foo)
  77. {
  78. $bar = $foo->toArray();
  79. /** @var ArrayInterface $bar */
  80. }
  81. }
  82. EOF
  83. ,
  84. ];
  85. yield 'with_indents' => [
  86. <<<'EOF'
  87. <?php
  88. use Foo\Bar;
  89. $foo = 1;
  90. use Foo\Bar\FooBar as FooBaz;
  91. use SomeClassIndented;
  92. $a = new Bar();
  93. $a = new FooBaz();
  94. $a = new SomeClassIndented();
  95. EOF
  96. ,
  97. <<<'EOF'
  98. <?php
  99. use Foo\Bar;
  100. use Foo\Bar\Baz;
  101. $foo = 1;
  102. use Foo\Bar\FooBar as FooBaz;
  103. use Foo\Bar\Foo as Fooo;
  104. use Foo\Bar\Baar\Baar;
  105. use SomeClassIndented;
  106. $a = new Bar();
  107. $a = new FooBaz();
  108. $a = new SomeClassIndented();
  109. EOF
  110. ,
  111. ];
  112. yield 'in_same_namespace_1' => [
  113. <<<'EOF'
  114. <?php
  115. namespace Foo\Bar\FooBar;
  116. use Foo\Bar\FooBar\Foo as Fooz;
  117. use Foo\Bar\FooBar\Aaa\Bbb;
  118. use XYZ\FQCN_XYZ;
  119. $a = new Baz();
  120. $b = new Fooz();
  121. $c = new Bar\Fooz();
  122. $d = new Bbb();
  123. $e = new FQCN_Babo();
  124. $f = new FQCN_XYZ();
  125. EOF
  126. ,
  127. <<<'EOF'
  128. <?php
  129. namespace Foo\Bar\FooBar;
  130. use Foo\Bar\FooBar\Baz;
  131. use Foo\Bar\FooBar\Foo as Fooz;
  132. use Foo\Bar\FooBar\Bar;
  133. use Foo\Bar\FooBar\Aaa\Bbb;
  134. use \Foo\Bar\FooBar\FQCN_Babo;
  135. use XYZ\FQCN_XYZ;
  136. $a = new Baz();
  137. $b = new Fooz();
  138. $c = new Bar\Fooz();
  139. $d = new Bbb();
  140. $e = new FQCN_Babo();
  141. $f = new FQCN_XYZ();
  142. EOF
  143. ,
  144. ];
  145. yield 'in_same_namespace_2' => [
  146. <<<'EOF'
  147. <?php namespace App\Http\Controllers;
  148. EOF
  149. ,
  150. <<<'EOF'
  151. <?php namespace App\Http\Controllers;
  152. use Illuminate\Http\Request;
  153. use App\Http\Controllers\Controller;
  154. EOF
  155. ,
  156. ];
  157. yield 'in_same_namespace_multiple_1' => [
  158. <<<'EOF'
  159. <?php
  160. namespace Foooooooo;
  161. namespace Foo;
  162. use Foooooooo\Baaaaz;
  163. $a = new Bar();
  164. $b = new Baz();
  165. $c = new Baaaaz();
  166. EOF
  167. ,
  168. <<<'EOF'
  169. <?php
  170. namespace Foooooooo;
  171. namespace Foo;
  172. use Foo\Bar;
  173. use Foo\Baz;
  174. use Foooooooo\Baaaar;
  175. use Foooooooo\Baaaaz;
  176. $a = new Bar();
  177. $b = new Baz();
  178. $c = new Baaaaz();
  179. EOF
  180. ,
  181. ];
  182. yield 'in_same_namespace_multiple_2' => [
  183. <<<'EOF'
  184. <?php
  185. namespace Foooooooo;
  186. use Foo\Bar;
  187. $a = new Baaaar();
  188. $b = new Baaaaz();
  189. $c = new Bar();
  190. namespace Foo;
  191. use Foooooooo\Baaaaz;
  192. $a = new Bar();
  193. $b = new Baz();
  194. $c = new Baaaaz();
  195. EOF
  196. ,
  197. <<<'EOF'
  198. <?php
  199. namespace Foooooooo;
  200. use Foo\Bar;
  201. use Foo\Baz;
  202. use Foooooooo\Baaaar;
  203. use Foooooooo\Baaaaz;
  204. $a = new Baaaar();
  205. $b = new Baaaaz();
  206. $c = new Bar();
  207. namespace Foo;
  208. use Foo\Bar;
  209. use Foo\Baz;
  210. use Foooooooo\Baaaar;
  211. use Foooooooo\Baaaaz;
  212. $a = new Bar();
  213. $b = new Baz();
  214. $c = new Baaaaz();
  215. EOF
  216. ,
  217. ];
  218. yield 'in_same_namespace_multiple_braces' => [
  219. <<<'EOF'
  220. <?php
  221. namespace Foooooooo
  222. {
  223. use Foo\Bar;
  224. $a = new Baaaar();
  225. $b = new Baaaaz();
  226. $c = new Bar();
  227. }
  228. namespace Foo
  229. {
  230. use Foooooooo\Baaaaz;
  231. $a = new Bar();
  232. $b = new Baz();
  233. $c = new Baaaaz();
  234. }
  235. EOF
  236. ,
  237. <<<'EOF'
  238. <?php
  239. namespace Foooooooo
  240. {
  241. use Foo\Bar;
  242. use Foo\Baz;
  243. use Foooooooo\Baaaar;
  244. use Foooooooo\Baaaaz;
  245. $a = new Baaaar();
  246. $b = new Baaaaz();
  247. $c = new Bar();
  248. }
  249. namespace Foo
  250. {
  251. use Foo\Bar;
  252. use Foo\Baz;
  253. use Foooooooo\Baaaar;
  254. use Foooooooo\Baaaaz;
  255. $a = new Bar();
  256. $b = new Baz();
  257. $c = new Baaaaz();
  258. }
  259. EOF
  260. ,
  261. ];
  262. yield 'multiple_use' => [
  263. <<<'EOF'
  264. <?php
  265. namespace Foo;
  266. use BarB, BarC as C, BarD;
  267. use BarE;
  268. $c = new D();
  269. $e = new BarE();
  270. EOF
  271. ,
  272. <<<'EOF'
  273. <?php
  274. namespace Foo;
  275. use Bar;
  276. use BarA;
  277. use BarB, BarC as C, BarD;
  278. use BarB2;
  279. use BarB\B2;
  280. use BarE;
  281. $c = new D();
  282. $e = new BarE();
  283. EOF
  284. ,
  285. ];
  286. yield 'with_braces' => [
  287. <<<'EOF'
  288. <?php
  289. namespace Foo\Bar\FooBar {
  290. use Foo\Bar\FooBar\Foo as Fooz;
  291. use Foo\Bar\FooBar\Aaa\Bbb;
  292. $a = new Baz();
  293. $b = new Fooz();
  294. $c = new Bar\Fooz();
  295. $d = new Bbb();
  296. }
  297. EOF
  298. ,
  299. <<<'EOF'
  300. <?php
  301. namespace Foo\Bar\FooBar {
  302. use Foo\Bar\FooBar\Baz;
  303. use Foo\Bar\FooBar\Foo as Fooz;
  304. use Foo\Bar\FooBar\Bar;
  305. use Foo\Bar\FooBar\Aaa\Bbb;
  306. $a = new Baz();
  307. $b = new Fooz();
  308. $c = new Bar\Fooz();
  309. $d = new Bbb();
  310. }
  311. EOF
  312. ,
  313. ];
  314. yield 'trailing_spaces' => [
  315. <<<'EOF'
  316. <?php
  317. use Foo\Bar ;
  318. use Foo\Bar\FooBar as FooBaz ;
  319. $a = new Bar();
  320. $a = new FooBaz();
  321. EOF
  322. ,
  323. <<<'EOF'
  324. <?php
  325. use Foo\Bar ;
  326. use Foo\Bar\FooBar as FooBaz ;
  327. use Foo\Bar\Foo as Fooo ;
  328. use SomeClass ;
  329. $a = new Bar();
  330. $a = new FooBaz();
  331. EOF
  332. ,
  333. ];
  334. yield 'traits' => [
  335. <<<'EOF'
  336. <?php
  337. use Foo as Bar;
  338. use A\MyTrait1;
  339. class MyParent
  340. {
  341. use MyTrait1;
  342. use MyTrait2;
  343. use Bar;
  344. }
  345. EOF
  346. ,
  347. <<<'EOF'
  348. <?php
  349. use Foo;
  350. use Foo as Bar;
  351. use A\MyTrait1;
  352. class MyParent
  353. {
  354. use MyTrait1;
  355. use MyTrait2;
  356. use Bar;
  357. }
  358. EOF
  359. ,
  360. ];
  361. yield 'function_use' => [
  362. <<<'EOF'
  363. <?php
  364. use Foo;
  365. $f = new Foo();
  366. $a = function ($item) use ($f) {
  367. return !in_array($item, $f);
  368. };
  369. EOF
  370. ,
  371. <<<'EOF'
  372. <?php
  373. use Foo;
  374. use Bar;
  375. $f = new Foo();
  376. $a = function ($item) use ($f) {
  377. return !in_array($item, $f);
  378. };
  379. EOF
  380. ,
  381. ];
  382. yield 'similar_names' => [
  383. <<<'EOF'
  384. <?php
  385. use SomeEntityRepository;
  386. class SomeService
  387. {
  388. public function __construct(SomeEntityRepository $repo)
  389. {
  390. $this->repo = $repo;
  391. }
  392. }
  393. EOF
  394. ,
  395. <<<'EOF'
  396. <?php
  397. use SomeEntityRepository;
  398. use SomeEntity;
  399. class SomeService
  400. {
  401. public function __construct(SomeEntityRepository $repo)
  402. {
  403. $this->repo = $repo;
  404. }
  405. }
  406. EOF
  407. ,
  408. ];
  409. yield 'variable_name' => [
  410. <<<'EOF'
  411. <?php
  412. $bar = null;
  413. EOF
  414. ,
  415. <<<'EOF'
  416. <?php
  417. use Foo\Bar;
  418. $bar = null;
  419. EOF
  420. ,
  421. ];
  422. yield 'property name, method name, static method call, static property' => [
  423. <<<'EOF'
  424. <?php
  425. $foo->bar = null;
  426. $foo->bar();
  427. $foo::bar();
  428. $foo::bar;
  429. EOF
  430. ,
  431. <<<'EOF'
  432. <?php
  433. use Foo\Bar;
  434. $foo->bar = null;
  435. $foo->bar();
  436. $foo::bar();
  437. $foo::bar;
  438. EOF
  439. ,
  440. ];
  441. yield 'constant_name' => [
  442. <<<'EOF'
  443. <?php
  444. class Baz
  445. {
  446. const BAR = 0;
  447. }
  448. EOF
  449. ,
  450. <<<'EOF'
  451. <?php
  452. use Foo\Bar;
  453. class Baz
  454. {
  455. const BAR = 0;
  456. }
  457. EOF
  458. ,
  459. ];
  460. yield 'namespace_part' => [
  461. <<<'EOF'
  462. <?php
  463. new \Baz\Bar();
  464. EOF
  465. ,
  466. <<<'EOF'
  467. <?php
  468. use Foo\Bar;
  469. new \Baz\Bar();
  470. EOF
  471. ,
  472. ];
  473. yield 'use_in_string_1' => [
  474. <<<'EOF'
  475. <?php
  476. $x=<<<'EOA'
  477. use a;
  478. use b;
  479. EOA;
  480. EOF
  481. ,
  482. ];
  483. yield 'use_in_string_2' => [
  484. <<<'EOF'
  485. <?php
  486. $x='
  487. use a;
  488. use b;
  489. ';
  490. EOF
  491. ,
  492. ];
  493. yield 'use_in_string_3' => [
  494. <<<'EOF'
  495. <?php
  496. $x="
  497. use a;
  498. use b;
  499. ";
  500. EOF
  501. ,
  502. ];
  503. yield 'import_in_global_namespace' => [
  504. <<<'EOF'
  505. <?php
  506. namespace A;
  507. use \SplFileInfo;
  508. new SplFileInfo(__FILE__);
  509. EOF
  510. ,
  511. ];
  512. yield 'no_import_in_global_namespace' => [
  513. <<<'EOF'
  514. <?php
  515. namespace A;
  516. new \SplFileInfo(__FILE__);
  517. EOF
  518. ,
  519. <<<'EOF'
  520. <?php
  521. namespace A;
  522. use SplFileInfo;
  523. new \SplFileInfo(__FILE__);
  524. EOF
  525. ,
  526. ];
  527. yield 'no_import_attribute_in_global_namespace' => [
  528. <<<'EOF'
  529. <?php
  530. namespace A;
  531. #[\Attribute(\Attribute::TARGET_PROPERTY)]
  532. final class B {}
  533. EOF
  534. ,
  535. <<<'EOF'
  536. <?php
  537. namespace A;
  538. use Attribute;
  539. #[\Attribute(\Attribute::TARGET_PROPERTY)]
  540. final class B {}
  541. EOF
  542. ,
  543. ];
  544. yield 'use_as_last_statement' => [
  545. <<<'EOF'
  546. <?php
  547. EOF
  548. ,
  549. <<<'EOF'
  550. <?php
  551. use Bar\Finder;
  552. EOF
  553. ,
  554. ];
  555. yield 'use_with_same_last_part_that_is_in_namespace' => [
  556. <<<'EOF'
  557. <?php
  558. namespace Foo\Finder;
  559. EOF
  560. ,
  561. <<<'EOF'
  562. <?php
  563. namespace Foo\Finder;
  564. use Bar\Finder;
  565. EOF
  566. ,
  567. ];
  568. yield 'used_use_with_same_last_part_that_is_in_namespace' => [
  569. <<<'EOF'
  570. <?php
  571. namespace Foo\Finder;
  572. use Bar\Finder;
  573. class Baz extends Finder
  574. {
  575. }
  576. EOF
  577. ,
  578. ];
  579. yield 'foo' => [
  580. <<<'EOF'
  581. <?php
  582. namespace Aaa;
  583. class Ddd
  584. {
  585. }
  586. EOF
  587. ,
  588. <<<'EOF'
  589. <?php
  590. namespace Aaa;
  591. use Aaa\Bbb;
  592. use Ccc;
  593. class Ddd
  594. {
  595. }
  596. EOF
  597. ,
  598. ];
  599. yield 'close_tag_1' => [
  600. '<?php
  601. ?>inline content<?php ?>',
  602. '<?php
  603. use A\AA;
  604. use B\C?>inline content<?php use A\D; use E\F ?>',
  605. ];
  606. yield 'close_tag_2' => [
  607. '<?php ?>',
  608. '<?php use A\B;?>',
  609. ];
  610. yield 'close_tag_3' => [
  611. '<?php ?>',
  612. '<?php use A\B?>',
  613. ];
  614. yield 'case_mismatch_typo' => [
  615. '<?php
  616. use Foo\exception; // must be kept by non-risky fixer
  617. try {
  618. x();
  619. } catch (Exception $e) {
  620. echo \'Foo\Exception caught\';
  621. } catch (\Exception $e) {
  622. echo \'Exception caught\';
  623. }
  624. ',
  625. ];
  626. yield 'with_matches_in_comments' => [
  627. '<?php
  628. use Foo;
  629. use Bar;
  630. use Baz;
  631. //Foo
  632. #Bar
  633. /*Baz*/',
  634. ];
  635. yield 'with_case_insensitive_matches_in_comments' => [
  636. '<?php
  637. use Foo;
  638. use Bar;
  639. use Baz;
  640. //foo
  641. #bar
  642. /*baz*/',
  643. ];
  644. yield 'with_same_namespace_import_and_unused_import' => [
  645. <<<'EOF'
  646. <?php
  647. namespace Foo;
  648. use Bar\C;
  649. /* test */
  650. abstract class D extends A implements C
  651. {
  652. }
  653. EOF
  654. ,
  655. <<<'EOF'
  656. <?php
  657. namespace Foo;
  658. use Bar\C;
  659. use Foo\A;
  660. use Foo\Bar\B /* test */ ;
  661. abstract class D extends A implements C
  662. {
  663. }
  664. EOF
  665. ,
  666. ];
  667. yield 'with_same_namespace_import_and_unused_import_after_namespace_statement' => [
  668. <<<'EOF'
  669. <?php
  670. namespace Foo;
  671. use Foo\Bar\C;
  672. abstract class D extends A implements C
  673. {
  674. }
  675. EOF
  676. ,
  677. <<<'EOF'
  678. <?php
  679. namespace Foo;
  680. use Foo\A;
  681. use Foo\Bar\B;
  682. use Foo\Bar\C;
  683. abstract class D extends A implements C
  684. {
  685. }
  686. EOF
  687. ,
  688. ];
  689. yield 'wrong_casing' => [
  690. <<<'EOF'
  691. <?php
  692. use Foo\Foo;
  693. use Bar\Bar;
  694. $a = new FOO();
  695. $b = new bar();
  696. EOF
  697. ,
  698. ];
  699. yield 'phpdoc_unused' => [
  700. <<<'EOF'
  701. <?php
  702. class Foo extends \PHPUnit_Framework_TestCase
  703. {
  704. /**
  705. * @expectedException \Exception
  706. */
  707. public function testBar()
  708. { }
  709. }
  710. EOF
  711. ,
  712. <<<'EOF'
  713. <?php
  714. use Some\Exception;
  715. class Foo extends \PHPUnit_Framework_TestCase
  716. {
  717. /**
  718. * @expectedException \Exception
  719. */
  720. public function testBar()
  721. { }
  722. }
  723. EOF
  724. ,
  725. ];
  726. yield 'imported_class_is_used_for_constants_1' => [
  727. '<?php
  728. use A\ABC;
  729. $a = 5-ABC::Test;
  730. $a = 5-ABC::Test-5;
  731. $a = ABC::Test-5;
  732. ',
  733. ];
  734. yield 'imported_class_is_used_for_constants_2' => [
  735. '<?php
  736. use A\ABC;
  737. $a = 5-ABC::Test;
  738. $a = 5-ABC::Test-5;
  739. ',
  740. ];
  741. yield 'imported_class_is_used_for_constants_3' => [
  742. '<?php
  743. use A\ABC;
  744. $a = 5-ABC::Test;
  745. ',
  746. ];
  747. yield 'imported_class_is_used_for_constants_4' => ['<?php
  748. use A\ABC;
  749. $a = ABC::Test-5;
  750. ',
  751. ];
  752. yield 'imported_class_is_used_for_constants_5' => ['<?php
  753. use A\ABC;
  754. $a = 5-ABC::Test-5;
  755. ',
  756. ];
  757. yield 'imported_class_is_used_for_constants_6' => ['<?php
  758. use A\ABC;
  759. $b = $a-->ABC::Test;
  760. ',
  761. ];
  762. yield 'imported_class_name_is_prefix_with_dash_of_constant' => [
  763. <<<'EOF'
  764. <?php
  765. class Dummy
  766. {
  767. const C = 'bar-bados';
  768. }
  769. EOF
  770. ,
  771. <<<'EOF'
  772. <?php
  773. use Foo\Bar;
  774. class Dummy
  775. {
  776. const C = 'bar-bados';
  777. }
  778. EOF
  779. ,
  780. ];
  781. yield 'imported_class_name_is_suffix_with_dash_of_constant' => [
  782. <<<'EOF'
  783. <?php
  784. class Dummy
  785. {
  786. const C = 'tool-bar';
  787. }
  788. EOF
  789. ,
  790. <<<'EOF'
  791. <?php
  792. use Foo\Bar;
  793. class Dummy
  794. {
  795. const C = 'tool-bar';
  796. }
  797. EOF
  798. ,
  799. ];
  800. yield 'imported_class_name_is_inside_with_dash_of_constant' => [
  801. <<<'EOF'
  802. <?php
  803. class Dummy
  804. {
  805. const C = 'tool-bar-bados';
  806. }
  807. EOF
  808. ,
  809. <<<'EOF'
  810. <?php
  811. use Foo\Bar;
  812. class Dummy
  813. {
  814. const C = 'tool-bar-bados';
  815. }
  816. EOF
  817. ,
  818. ];
  819. yield 'functions_in_the_global_namespace_should_not_be_removed_even_when_declaration_has_new_lines_and_is_uppercase' => [
  820. <<<'EOF'
  821. <?php
  822. namespace Foo;
  823. use function is_int;
  824. is_int(1);
  825. EOF
  826. ,
  827. <<<'EOF'
  828. <?php
  829. namespace Foo;
  830. use function is_int;
  831. use function is_float;
  832. is_int(1);
  833. EOF
  834. ,
  835. ];
  836. yield 'constants_in_the_global_namespace_should_not_be_removed' => [
  837. $expected = <<<'EOF'
  838. <?php
  839. namespace Foo;
  840. use const PHP_INT_MAX;
  841. echo PHP_INT_MAX;
  842. EOF
  843. ,
  844. <<<'EOF'
  845. <?php
  846. namespace Foo;
  847. use const PHP_INT_MAX;
  848. use const PHP_INT_MIN;
  849. echo PHP_INT_MAX;
  850. EOF
  851. ,
  852. ];
  853. yield 'functions_in_the_global_namespace_should_not_be_removed_even_when_declaration_has_ne_lines_and_is_uppercase' => [
  854. <<<'EOF'
  855. <?php
  856. namespace Foo;use/**/FUNCTION#1
  857. is_int;#2
  858. is_int(1);
  859. EOF
  860. ,
  861. <<<'EOF'
  862. <?php
  863. namespace Foo;use/**/FUNCTION#1
  864. is_int;#2
  865. use function
  866. is_float;
  867. use
  868. const
  869. PHP_INT_MIN;
  870. is_int(1);
  871. EOF
  872. ,
  873. ];
  874. yield 'use_trait should never be removed' => [
  875. <<<'EOF'
  876. <?php
  877. class UsesTraits
  878. {
  879. /**
  880. * @see #4086
  881. */
  882. private function withComplexStringVariable()
  883. {
  884. $name = 'World';
  885. return "Hello, {$name}!";
  886. }
  887. use MyTrait;
  888. }
  889. EOF
  890. ];
  891. yield 'imported_name_is_part_of_namespace' => [
  892. <<<'EOF'
  893. <?php
  894. namespace App\Foo;
  895. class Baz
  896. {
  897. }
  898. EOF
  899. ,
  900. <<<'EOF'
  901. <?php
  902. namespace App\Foo;
  903. use Foo\Bar\App;
  904. class Baz
  905. {
  906. }
  907. EOF
  908. ];
  909. yield 'imported_name_is_part_of_namespace with closing tag' => [
  910. <<<'EOF'
  911. <?php
  912. namespace A\B {?>
  913. <?php
  914. require_once __DIR__.'/test2.php' ?>
  915. <?php
  916. use X\Z\Y
  917. ?>
  918. <?php
  919. $y = new Y() ?>
  920. <?php
  921. var_dump($y);}
  922. EOF
  923. ];
  924. yield [
  925. '<?php
  926. use App\Http\Requests\StoreRequest;
  927. class StoreController
  928. {
  929. /**
  930. * @param \App\Http\Requests\StoreRequest $request
  931. */
  932. public function __invoke(StoreRequest $request)
  933. {}
  934. }',
  935. '<?php
  936. use App\Http\Requests\StoreRequest;
  937. use Illuminate\Http\Request;
  938. class StoreController
  939. {
  940. /**
  941. * @param \App\Http\Requests\StoreRequest $request
  942. */
  943. public function __invoke(StoreRequest $request)
  944. {}
  945. }',
  946. ];
  947. yield 'unused import matching function call' => [
  948. '<?php
  949. namespace Foo;
  950. bar();',
  951. '<?php
  952. namespace Foo;
  953. use Bar;
  954. bar();',
  955. ];
  956. yield 'unused import matching function declaration' => [
  957. '<?php
  958. namespace Foo;
  959. function bar () {}',
  960. '<?php
  961. namespace Foo;
  962. use Bar;
  963. function bar () {}',
  964. ];
  965. yield 'unused import matching method declaration' => [
  966. '<?php
  967. namespace Foo;
  968. class Foo {
  969. public function bar () {}
  970. }',
  971. '<?php
  972. namespace Foo;
  973. use Bar;
  974. class Foo {
  975. public function bar () {}
  976. }',
  977. ];
  978. yield 'unused import matching constant usage' => [
  979. '<?php
  980. namespace Foo;
  981. echo BAR;',
  982. '<?php
  983. namespace Foo;
  984. use Bar;
  985. echo BAR;',
  986. ];
  987. yield 'unused import matching class constant' => [
  988. '<?php
  989. namespace Foo;
  990. class Foo {
  991. const BAR = 1;
  992. }',
  993. '<?php
  994. namespace Foo;
  995. use Bar;
  996. class Foo {
  997. const BAR = 1;
  998. }',
  999. ];
  1000. yield 'unused function import matching class usage' => [
  1001. '<?php
  1002. namespace Foo;
  1003. new Bar();
  1004. Baz::method();',
  1005. '<?php
  1006. namespace Foo;
  1007. use function bar;
  1008. use function baz;
  1009. new Bar();
  1010. Baz::method();',
  1011. ];
  1012. yield 'unused function import matching method call' => [
  1013. '<?php
  1014. namespace Foo;
  1015. Foo::bar();',
  1016. '<?php
  1017. namespace Foo;
  1018. use function bar;
  1019. Foo::bar();',
  1020. ];
  1021. yield 'unused function import matching method declaration' => [
  1022. '<?php
  1023. namespace Foo;
  1024. class Foo {
  1025. public function bar () {}
  1026. }',
  1027. '<?php
  1028. namespace Foo;
  1029. use function bar;
  1030. class Foo {
  1031. public function bar () {}
  1032. }',
  1033. ];
  1034. yield 'unused function import matching constant usage' => [
  1035. '<?php
  1036. namespace Foo;
  1037. echo BAR;',
  1038. '<?php
  1039. namespace Foo;
  1040. use function bar;
  1041. echo BAR;',
  1042. ];
  1043. yield 'unused function import matching class constant' => [
  1044. '<?php
  1045. namespace Foo;
  1046. class Foo {
  1047. const BAR = 1;
  1048. }',
  1049. '<?php
  1050. namespace Foo;
  1051. use function bar;
  1052. class Foo {
  1053. const BAR = 1;
  1054. }',
  1055. ];
  1056. yield 'unused constant import matching function call' => [
  1057. '<?php
  1058. namespace Foo;
  1059. bar();',
  1060. '<?php
  1061. namespace Foo;
  1062. use const BAR;
  1063. bar();',
  1064. ];
  1065. yield 'unused constant import matching function declaration' => [
  1066. '<?php
  1067. namespace Foo;
  1068. function bar () {}',
  1069. '<?php
  1070. namespace Foo;
  1071. use const BAR;
  1072. function bar () {}',
  1073. ];
  1074. yield 'unused constant import matching method declaration' => [
  1075. '<?php
  1076. namespace Foo;
  1077. class Foo {
  1078. public function bar () {}
  1079. }',
  1080. '<?php
  1081. namespace Foo;
  1082. use const BAR;
  1083. class Foo {
  1084. public function bar () {}
  1085. }',
  1086. ];
  1087. yield 'unused constant import matching class constant' => [
  1088. '<?php
  1089. namespace Foo;
  1090. class Foo {
  1091. const BAR = 1;
  1092. }',
  1093. '<?php
  1094. namespace Foo;
  1095. use const BAR;
  1096. class Foo {
  1097. const BAR = 1;
  1098. }',
  1099. ];
  1100. yield 'attribute without braces' => [
  1101. '<?php
  1102. use Foo;
  1103. class Controller
  1104. {
  1105. #[Foo]
  1106. public function foo() {}
  1107. }',
  1108. ];
  1109. yield 'attribute with braces' => [
  1110. '<?php
  1111. use Foo;
  1112. class Controller
  1113. {
  1114. #[Foo()]
  1115. public function foo() {}
  1116. }',
  1117. ];
  1118. yield 'go to' => [
  1119. '<?php
  1120. Bar1:
  1121. Bar2:
  1122. Bar3:
  1123. ',
  1124. '<?php
  1125. use Bar1;
  1126. use const Bar2;
  1127. use function Bar3;
  1128. Bar1:
  1129. Bar2:
  1130. Bar3:
  1131. ',
  1132. ];
  1133. yield [
  1134. $expected = <<<'EOF'
  1135. <?php
  1136. use some\a\{ClassD};
  1137. use some\b\{ClassA, ClassB, ClassC as C};
  1138. use function some\c\{fn_a, fn_b, fn_c};
  1139. use const some\d\{ConstA, ConstB, ConstC};
  1140. new CLassD();
  1141. echo fn_a();
  1142. EOF
  1143. ];
  1144. yield [ // TODO test shows lot of cases where imports are not removed while could be
  1145. '<?php use A\{B,};
  1146. use some\y\{ClassA, ClassB, ClassC as C,};
  1147. use function some\a\{fn_a, fn_b, fn_c,};
  1148. use const some\Z\{ConstAA,ConstBB,ConstCC,};
  1149. use const some\X\{ConstA,ConstB,ConstC,ConstF};
  1150. use C\{D,E,};
  1151. echo ConstA.ConstB.ConstC,ConstF;
  1152. echo ConstBB.ConstCC;
  1153. fn_a(ClassA::test, new C());
  1154. ',
  1155. '<?php use A\{B,};
  1156. use some\y\{ClassA, ClassB, ClassC as C,};
  1157. use function some\a\{fn_a, fn_b, fn_c,};
  1158. use const some\Z\{ConstAA,ConstBB,ConstCC,};
  1159. use const some\X\{ConstA,ConstB,ConstC,ConstF};
  1160. use C\{D,E,};
  1161. use Z;
  1162. echo ConstA.ConstB.ConstC,ConstF;
  1163. echo ConstBB.ConstCC;
  1164. fn_a(ClassA::test, new C());
  1165. ',
  1166. ];
  1167. }
  1168. /**
  1169. * @requires PHP <8.0
  1170. */
  1171. public function testFixPrePHP80(): void
  1172. {
  1173. $this->doTest(
  1174. '<?php
  1175. # 1
  1176. # 2
  1177. # 3
  1178. # 4
  1179. use /**/A\B/**/;
  1180. echo 1;
  1181. new B();
  1182. ',
  1183. '<?php
  1184. use# 1
  1185. \# 2
  1186. Exception# 3
  1187. # 4
  1188. ;
  1189. use /**/A\B/**/;
  1190. echo 1;
  1191. new B();
  1192. '
  1193. );
  1194. }
  1195. /**
  1196. * @requires PHP 8.0
  1197. *
  1198. * @dataProvider provideFix80Cases
  1199. */
  1200. public function testFix80(string $expected, ?string $input = null): void
  1201. {
  1202. $this->doTest($expected, $input);
  1203. }
  1204. public static function provideFix80Cases(): iterable
  1205. {
  1206. yield [
  1207. '<?php
  1208. $x = $foo?->bar;
  1209. $y = foo?->bar();
  1210. ',
  1211. '<?php
  1212. use Foo\Bar;
  1213. $x = $foo?->bar;
  1214. $y = foo?->bar();
  1215. ',
  1216. ];
  1217. yield 'with union type in non-capturing catch' => [
  1218. '<?php
  1219. use Foo;
  1220. use Bar;
  1221. try {} catch (Foo | Bar) {}',
  1222. ];
  1223. yield 'union return' => [
  1224. '<?php
  1225. use Foo;
  1226. use Bar;
  1227. abstract class Baz
  1228. {
  1229. abstract public function test(): Foo|Bar;
  1230. }
  1231. ',
  1232. ];
  1233. yield 'attribute' => [
  1234. "<?php
  1235. use Acme\\JsonSchemaValidationBundle\\Annotation\\JsonSchema;
  1236. use Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\IsGranted;
  1237. use Symfony\\Component\\Routing\\Annotation\\Route;
  1238. #[
  1239. Route('/basket/{uuid}/item', name: 'addBasketItem', requirements: ['uuid' => '%regex.uuid%'], methods: ['POST']),
  1240. IsGranted('ROLE_USER'),
  1241. JsonSchema('Public/Basket/addItem.json'),
  1242. ]
  1243. class Foo {}
  1244. ",
  1245. ];
  1246. yield 'attribute 2' => [
  1247. '<?php
  1248. use Psr\Log\LoggerInterface;
  1249. function f( #[Target(\'xxx\')] LoggerInterface|null $logger) {}
  1250. ',
  1251. ];
  1252. }
  1253. /**
  1254. * @requires PHP 8.1
  1255. *
  1256. * @dataProvider provideFix81Cases
  1257. */
  1258. public function testFix81(string $expected, ?string $input = null): void
  1259. {
  1260. $this->doTest($expected, $input);
  1261. }
  1262. public static function provideFix81Cases(): iterable
  1263. {
  1264. yield 'final const' => [
  1265. '<?php
  1266. class Foo
  1267. {
  1268. final public const B1 = "2";
  1269. }
  1270. ',
  1271. '<?php
  1272. use A\B1;
  1273. class Foo
  1274. {
  1275. final public const B1 = "2";
  1276. }
  1277. ',
  1278. ];
  1279. yield 'first callable class' => [
  1280. '<?php
  1281. use Foo;
  1282. Foo::method(...);',
  1283. '<?php
  1284. use Foo;
  1285. use Bar;
  1286. Foo::method(...);',
  1287. ];
  1288. yield 'New in initializers' => [
  1289. '<?php
  1290. namespace A\B\C;
  1291. use Foo1;
  1292. use Foo2;
  1293. use Foo3;
  1294. use Foo4;
  1295. use Foo5;
  1296. use Foo6;
  1297. use Foo7;
  1298. class Test {
  1299. public function __construct(
  1300. public $prop = (new Foo1),
  1301. ) {}
  1302. }
  1303. function test(
  1304. $foo = (new Foo2),
  1305. $baz = (new Foo3(x: 2)),
  1306. ) {
  1307. }
  1308. static $x = new Foo4();
  1309. const C = (new Foo5);
  1310. function test2($param = (new Foo6)) {}
  1311. const D = new Foo7(1,2);
  1312. ',
  1313. ];
  1314. }
  1315. /**
  1316. * @requires PHP 8.1
  1317. *
  1318. * @dataProvider provideFixPhp81Cases
  1319. */
  1320. public function testFixPhp81(string $expected): void
  1321. {
  1322. $this->doTest($expected);
  1323. }
  1324. public static function provideFixPhp81Cases(): iterable
  1325. {
  1326. yield [
  1327. '<?php
  1328. enum Foo: string
  1329. {
  1330. use Bar;
  1331. case Test1 = "a";
  1332. }
  1333. ',
  1334. ];
  1335. yield [
  1336. '<?php
  1337. use Foo\Class1;
  1338. use Foo\Class2;
  1339. class C
  1340. {
  1341. public function t(Class1 | Class2 $fields) {}
  1342. }
  1343. ',
  1344. ];
  1345. yield [
  1346. '<?php
  1347. use Foo\Class1;
  1348. use Foo\Class2;
  1349. class C
  1350. {
  1351. public function t(Class1 | Class2 ...$fields) {}
  1352. }
  1353. ',
  1354. ];
  1355. }
  1356. }