OrderedImportsFixerTest.php 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248
  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\ConfigurationException\InvalidFixerConfigurationException;
  14. use PhpCsFixer\Fixer\Import\OrderedImportsFixer;
  15. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  16. /**
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\Import\OrderedImportsFixer
  20. *
  21. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Import\OrderedImportsFixer>
  22. *
  23. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\Import\OrderedImportsFixer
  24. */
  25. final class OrderedImportsFixerTest extends AbstractFixerTestCase
  26. {
  27. /**
  28. * @dataProvider provideFixWithMultipleNamespaceCases
  29. */
  30. public function testFixWithMultipleNamespace(string $expected, string $input): void
  31. {
  32. $this->doTest($expected, $input);
  33. }
  34. /**
  35. * @return iterable<int|string, array{string, string}>
  36. */
  37. public static function provideFixWithMultipleNamespaceCases(): iterable
  38. {
  39. $expected = <<<'EOF'
  40. <?php
  41. namespace FooRoo {
  42. use Foo\Bar;
  43. use Foo\Bar\Foo as Fooo, Foo\Bar\FooBar as FooBaz;
  44. use Foo\Bir as FBB;
  45. use Foo\Zar\Baz;
  46. use SomeClass;
  47. use Symfony\Annotation\Template, Zoo\Bar as ZooBar;
  48. use Zoo\Tar1;
  49. $a = new Bar();
  50. $a = new FooBaz();
  51. $a = new someclass();
  52. use Zoo\Tar2;
  53. class AnnotatedClass
  54. {
  55. /**
  56. * @Template(foobar=21)
  57. * @param Entity $foo
  58. */
  59. public function doSomething($foo)
  60. {
  61. $bar = $foo->toArray();
  62. /** @var ArrayInterface $bar */
  63. return function () use ($bar, $foo) {};
  64. }
  65. }
  66. }
  67. namespace BlaRoo {
  68. use Foo\Zar\Baz;
  69. use SomeClass;
  70. use Symfony\Annotation\Template;
  71. use Symfony\Doctrine\Entities\Entity, Zoo\Bar;
  72. class AnnotatedClass
  73. {
  74. /**
  75. * @Template(foobar=21)
  76. * @param Entity $foo
  77. */
  78. public function doSomething($foo)
  79. {
  80. $bar = $foo->toArray();
  81. /** @var ArrayInterface $bar */
  82. return function () use ($bar, $foo) {};
  83. }
  84. }
  85. }
  86. EOF;
  87. $input = <<<'EOF'
  88. <?php
  89. namespace FooRoo {
  90. use Foo\Bar\FooBar as FooBaz;
  91. use Zoo\Bar as ZooBar, Zoo\Tar1;
  92. use Foo\Bar;
  93. use Foo\Zar\Baz;
  94. use Symfony\Annotation\Template;
  95. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  96. use SomeClass;
  97. $a = new Bar();
  98. $a = new FooBaz();
  99. $a = new someclass();
  100. use Zoo\Tar2;
  101. class AnnotatedClass
  102. {
  103. /**
  104. * @Template(foobar=21)
  105. * @param Entity $foo
  106. */
  107. public function doSomething($foo)
  108. {
  109. $bar = $foo->toArray();
  110. /** @var ArrayInterface $bar */
  111. return function () use ($bar, $foo) {};
  112. }
  113. }
  114. }
  115. namespace BlaRoo {
  116. use Foo\Zar\Baz;
  117. use Zoo\Bar;
  118. use SomeClass;
  119. use Symfony\Annotation\Template, Symfony\Doctrine\Entities\Entity;
  120. class AnnotatedClass
  121. {
  122. /**
  123. * @Template(foobar=21)
  124. * @param Entity $foo
  125. */
  126. public function doSomething($foo)
  127. {
  128. $bar = $foo->toArray();
  129. /** @var ArrayInterface $bar */
  130. return function () use ($bar, $foo) {};
  131. }
  132. }
  133. }
  134. EOF;
  135. yield [$expected, $input];
  136. $expected = <<<'EOF'
  137. <?php namespace Space1 {
  138. use Foo\Bar\Foo;
  139. use Symfony\Annotation\Template;
  140. }
  141. namespace Space2 { use A,B; }
  142. namespace Space3 {
  143. use Symfony\Annotation\Template;
  144. use Symfony\Doctrine\Entities\Entity0, Zoo\Bar;
  145. echo Bar::C;
  146. use A\B;
  147. }
  148. namespace Space4{}
  149. EOF;
  150. $input = <<<'EOF'
  151. <?php namespace Space1 {
  152. use Symfony\Annotation\Template;
  153. use Foo\Bar\Foo;
  154. }
  155. namespace Space2 { use B,A; }
  156. namespace Space3 {
  157. use Zoo\Bar;
  158. use Symfony\Annotation\Template, Symfony\Doctrine\Entities\Entity0;
  159. echo Bar::C;
  160. use A\B;
  161. }
  162. namespace Space4{}
  163. EOF;
  164. yield [$expected, $input];
  165. $expected =
  166. '<?php
  167. use B;
  168. use C;
  169. $foo = new C();
  170. use A;
  171. ';
  172. $input =
  173. '<?php
  174. use C;
  175. use B;
  176. $foo = new C();
  177. use A;
  178. ';
  179. yield [$expected, $input];
  180. yield 'open-close groups' => [
  181. '
  182. <?php use X ?>
  183. <?php use Z ?>
  184. <?php echo X::class ?>
  185. <?php use E ?> output
  186. <?php use F ?><?php echo E::class; use A; ?>
  187. ',
  188. '
  189. <?php use Z ?>
  190. <?php use X ?>
  191. <?php echo X::class ?>
  192. <?php use F ?> output
  193. <?php use E ?><?php echo E::class; use A; ?>
  194. ',
  195. ];
  196. }
  197. public function testFixWithComment(): void
  198. {
  199. $expected = <<<'EOF'
  200. The normal
  201. use of this fixer
  202. should not change this sentence nor those statements below
  203. use Zoo\Bar;
  204. use Foo\Bar;
  205. use Foo\Zar\Baz;
  206. <?php
  207. use Foo\Bar;
  208. use Foo\Bar\Foo as Fooo, Foo\Bar\FooBar /* He there */ as FooBaz;
  209. use Foo\Bir as FBB;
  210. use Foo\Zar\Baz;
  211. use SomeClass;
  212. use /* check */Symfony\Annotation\Template, Zoo\Bar as ZooBar;
  213. use Zoo\Tar;
  214. $a = new Bar();
  215. $a = new FooBaz();
  216. $a = new someclass();
  217. class AnnotatedClass
  218. {
  219. /**
  220. * @Template(foobar=21)
  221. * @param Entity $foo
  222. */
  223. public function doSomething($foo)
  224. {
  225. $bar = $foo->toArray();
  226. /** @var ArrayInterface $bar */
  227. return function () use ($bar, $foo) {};
  228. }
  229. }
  230. EOF;
  231. $input = <<<'EOF'
  232. The normal
  233. use of this fixer
  234. should not change this sentence nor those statements below
  235. use Zoo\Bar;
  236. use Foo\Bar;
  237. use Foo\Zar\Baz;
  238. <?php
  239. use Foo\Bar\FooBar /* He there */ as FooBaz;
  240. use Zoo\Bar as ZooBar, Zoo\Tar;
  241. use Foo\Bar;
  242. use Foo\Zar\Baz;
  243. use /* check */Symfony\Annotation\Template;
  244. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  245. use SomeClass;
  246. $a = new Bar();
  247. $a = new FooBaz();
  248. $a = new someclass();
  249. class AnnotatedClass
  250. {
  251. /**
  252. * @Template(foobar=21)
  253. * @param Entity $foo
  254. */
  255. public function doSomething($foo)
  256. {
  257. $bar = $foo->toArray();
  258. /** @var ArrayInterface $bar */
  259. return function () use ($bar, $foo) {};
  260. }
  261. }
  262. EOF;
  263. $this->doTest($expected, $input);
  264. }
  265. public function testWithTraits(): void
  266. {
  267. $expected = <<<'EOF'
  268. <?php
  269. use Foo\Bar;
  270. use Foo\Bar\Foo as Fooo, Foo\Bar\FooBar as FooBaz;
  271. use Foo\Bir as FBB;
  272. use Foo\Zar\Baz;
  273. use SomeClass;
  274. use Symfony\Annotation\Template, Zoo\Bar as ZooBar;
  275. use Zoo\Tar;
  276. trait Foo {}
  277. trait Zoo {}
  278. class AnnotatedClass
  279. {
  280. use Foo, Bar;
  281. /**
  282. * @Template(foobar=21)
  283. * @param Entity $foo
  284. */
  285. public function doSomething($foo)
  286. {
  287. $bar = $foo->toArray();
  288. /** @var ArrayInterface $bar */
  289. return function () use ($bar, $foo) {};
  290. }
  291. }
  292. EOF;
  293. $input = <<<'EOF'
  294. <?php
  295. use Foo\Bar\FooBar as FooBaz;
  296. use Zoo\Bar as ZooBar, Zoo\Tar;
  297. use Foo\Bar;
  298. use Foo\Zar\Baz;
  299. use Symfony\Annotation\Template;
  300. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  301. use SomeClass;
  302. trait Foo {}
  303. trait Zoo {}
  304. class AnnotatedClass
  305. {
  306. use Foo, Bar;
  307. /**
  308. * @Template(foobar=21)
  309. * @param Entity $foo
  310. */
  311. public function doSomething($foo)
  312. {
  313. $bar = $foo->toArray();
  314. /** @var ArrayInterface $bar */
  315. return function () use ($bar, $foo) {};
  316. }
  317. }
  318. EOF;
  319. $this->doTest($expected, $input);
  320. }
  321. public function testFixWithTraitImports(): void
  322. {
  323. $expected = <<<'EOF'
  324. The normal
  325. use of this fixer
  326. should not change this sentence nor those statements below
  327. use Zoo\Bar;
  328. use Foo\Bar;
  329. use Foo\Zar\Baz;
  330. <?php
  331. use Acme\MyReusableTrait;
  332. use Foo\Bar, Foo\Bar\Foo as Fooo;
  333. use Foo\Bar\FooBar as FooBaz;
  334. use Foo\Bir as FBB;
  335. use Foo\Zar\Baz;
  336. use SomeClass;
  337. use Symfony\Annotation\Template, Zoo\Bar as ZooBar;
  338. use Zoo\Tar;
  339. $a = new Bar();
  340. $a = new FooBaz();
  341. $a = new someclass();
  342. class AnnotatedClass
  343. {
  344. use MyReusableTrait;
  345. /**
  346. * @Template(foobar=21)
  347. * @param Entity $foo
  348. */
  349. public function doSomething($foo)
  350. {
  351. $bar = $foo->toArray();
  352. /** @var ArrayInterface $bar */
  353. return function () use ($bar, $baz) {};
  354. }
  355. }
  356. EOF;
  357. $input = <<<'EOF'
  358. The normal
  359. use of this fixer
  360. should not change this sentence nor those statements below
  361. use Zoo\Bar;
  362. use Foo\Bar;
  363. use Foo\Zar\Baz;
  364. <?php
  365. use Foo\Bar\FooBar as FooBaz;
  366. use Zoo\Bar as ZooBar, Zoo\Tar;
  367. use Foo\Bar;
  368. use Foo\Zar\Baz;
  369. use Acme\MyReusableTrait;
  370. use Symfony\Annotation\Template;
  371. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  372. use SomeClass;
  373. $a = new Bar();
  374. $a = new FooBaz();
  375. $a = new someclass();
  376. class AnnotatedClass
  377. {
  378. use MyReusableTrait;
  379. /**
  380. * @Template(foobar=21)
  381. * @param Entity $foo
  382. */
  383. public function doSomething($foo)
  384. {
  385. $bar = $foo->toArray();
  386. /** @var ArrayInterface $bar */
  387. return function () use ($bar, $baz) {};
  388. }
  389. }
  390. EOF;
  391. $this->doTest($expected, $input);
  392. }
  393. public function testFixWithDifferentCases(): void
  394. {
  395. $expected = <<<'EOF'
  396. The normal
  397. use of this fixer
  398. should not change this sentence nor those statements below
  399. use Zoo\Baz;
  400. use abc\Bar;
  401. <?php
  402. use abc\Bar;
  403. use Zoo\Baz;
  404. class Test
  405. {
  406. }
  407. EOF;
  408. $input = <<<'EOF'
  409. The normal
  410. use of this fixer
  411. should not change this sentence nor those statements below
  412. use Zoo\Baz;
  413. use abc\Bar;
  414. <?php
  415. use Zoo\Baz;
  416. use abc\Bar;
  417. class Test
  418. {
  419. }
  420. EOF;
  421. $this->doTest($expected, $input);
  422. }
  423. public function testWithoutUses(): void
  424. {
  425. $expected = <<<'EOF'
  426. <?php
  427. $c = 1;
  428. EOF;
  429. $this->doTest($expected);
  430. }
  431. public function testOrderWithTrailingDigit(): void
  432. {
  433. $expected = <<<'EOF'
  434. <?php
  435. use abc\Bar;
  436. use abc2\Bar2;
  437. use xyz\abc\Bar6;
  438. use xyz\abc2\Bar7;
  439. use xyz\xyz\Bar4;
  440. use xyz\xyz\Bar5;
  441. class Test
  442. {
  443. }
  444. EOF;
  445. $input = <<<'EOF'
  446. <?php
  447. use abc2\Bar2;
  448. use abc\Bar;
  449. use xyz\abc2\Bar7;
  450. use xyz\abc\Bar6;
  451. use xyz\xyz\Bar4;
  452. use xyz\xyz\Bar5;
  453. class Test
  454. {
  455. }
  456. EOF;
  457. $this->doTest($expected, $input);
  458. }
  459. public function testCodeWithImportsOnly(): void
  460. {
  461. $expected = <<<'EOF'
  462. <?php
  463. use Aaa;
  464. use Bbb;
  465. EOF;
  466. $input = <<<'EOF'
  467. <?php
  468. use Bbb;
  469. use Aaa;
  470. EOF;
  471. $this->doTest($expected, $input);
  472. }
  473. public function testCodeWithCloseTag(): void
  474. {
  475. $this->doTest(
  476. '<?php
  477. use A\C1;
  478. use A\D?><?php use B\C2; use E\F ?>',
  479. '<?php
  480. use A\C1;
  481. use B\C2?><?php use A\D; use E\F ?>'
  482. );
  483. }
  484. public function testCodeWithComments(): void
  485. {
  486. $this->doTest(
  487. '<?php
  488. use A\C1 /* A */;
  489. use /* B */ B\C2;',
  490. '<?php
  491. use /* B */ B\C2;
  492. use A\C1 /* A */;'
  493. );
  494. }
  495. /**
  496. * @requires PHP <8.0
  497. */
  498. public function testCodeWithCommentsAndMultiLine(): void
  499. {
  500. $this->doTest(
  501. '<?php
  502. use#
  503. A\C1;
  504. use B#
  505. \C2#
  506. #
  507. ;',
  508. '<?php
  509. use#
  510. B#
  511. \C2#
  512. #
  513. ;
  514. use A\C1;'
  515. );
  516. }
  517. /**
  518. * @param _AutogeneratedInputConfiguration $config
  519. *
  520. * @dataProvider provideFixCases
  521. */
  522. public function testFix(string $expected, ?string $input = null, array $config = []): void
  523. {
  524. $this->fixer->configure($config);
  525. $this->doTest($expected, $input);
  526. }
  527. public static function provideFixCases(): iterable
  528. {
  529. yield [
  530. <<<'EOF'
  531. The normal
  532. use of this fixer
  533. should not change this sentence nor those statements below
  534. use Zoo\Bar as ZooBar;
  535. use Foo\Bar;
  536. use Foo\Zar\Baz;
  537. <?php
  538. use Foo\Bar;
  539. use Foo\Bar\Foo as Fooo, Foo\Bar\FooBar as FooBaz;
  540. use Foo\Bir as FBB;
  541. use Foo\Zar\Baz;
  542. use SomeClass;
  543. use Symfony\Annotation\Template, Zoo\Bar as ZooBar;
  544. use Zoo\Tar;
  545. $a = new Bar();
  546. $a = new FooBaz();
  547. $a = new someclass();
  548. class AnnotatedClass
  549. {
  550. /**
  551. * @Template(foobar=21)
  552. * @param Entity $foo
  553. */
  554. public function doSomething($foo)
  555. {
  556. $bar = $foo->toArray();
  557. /** @var ArrayInterface $bar */
  558. return function () use ($bar, $foo) {};
  559. }
  560. }
  561. EOF,
  562. <<<'EOF'
  563. The normal
  564. use of this fixer
  565. should not change this sentence nor those statements below
  566. use Zoo\Bar as ZooBar;
  567. use Foo\Bar;
  568. use Foo\Zar\Baz;
  569. <?php
  570. use Foo\Bar\FooBar as FooBaz;
  571. use Zoo\Bar as ZooBar, Zoo\Tar;
  572. use Foo\Bar;
  573. use Foo\Zar\Baz;
  574. use Symfony\Annotation\Template;
  575. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  576. use SomeClass;
  577. $a = new Bar();
  578. $a = new FooBaz();
  579. $a = new someclass();
  580. class AnnotatedClass
  581. {
  582. /**
  583. * @Template(foobar=21)
  584. * @param Entity $foo
  585. */
  586. public function doSomething($foo)
  587. {
  588. $bar = $foo->toArray();
  589. /** @var ArrayInterface $bar */
  590. return function () use ($bar, $foo) {};
  591. }
  592. }
  593. EOF,
  594. ];
  595. yield [
  596. '<?php
  597. use A\B;
  598. use some\a\{ClassA, ClassB, ClassC as C};
  599. use some\b\{
  600. ClassF,
  601. ClassG
  602. };
  603. use const some\a\{ConstA, ConstB, ConstC};
  604. use const some\b\{
  605. ConstX,
  606. ConstY,
  607. ConstZ
  608. };
  609. use function some\a\{fn_a, fn_b, fn_c};
  610. use function some\b\{
  611. fn_x,
  612. fn_y,
  613. fn_z
  614. };
  615. ',
  616. '<?php
  617. use some\a\{ClassA, ClassB, ClassC as C};
  618. use function some\b\{
  619. fn_y,
  620. fn_z,
  621. fn_x
  622. };
  623. use function some\a\{fn_a, fn_b, fn_c};
  624. use A\B;
  625. use const some\b\{
  626. ConstZ,
  627. ConstX,
  628. ConstY
  629. };
  630. use const some\a\{ConstA, ConstB, ConstC};
  631. use some\b\{
  632. ClassG,
  633. ClassF
  634. };
  635. ',
  636. [
  637. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  638. 'imports_order' => ['class', 'const', 'function'],
  639. ],
  640. ];
  641. yield [
  642. '<?php
  643. use A\B;
  644. use some\a\{ClassA as A /*z*/, ClassB, ClassC};
  645. use const some\a\{
  646. ConstA,
  647. ConstB,
  648. ConstC
  649. };
  650. use function some\a\{fn_a, fn_b, fn_c};
  651. ',
  652. '<?php
  653. use some\a\{ ClassB,ClassC, /*z*/ ClassA as A};
  654. use function some\a\{fn_c, fn_a,fn_b };
  655. use A\B;
  656. use const some\a\{
  657. ConstA,
  658. ConstB,
  659. ConstC
  660. };
  661. ',
  662. [
  663. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  664. 'imports_order' => ['class', 'const', 'function'],
  665. ],
  666. ];
  667. yield [
  668. '<?php
  669. use A\B;
  670. use some\a\{ClassA, ClassB, ClassC as C};
  671. use const some\a\{ConstA, ConstB, ConstC};
  672. use function some\a\{fn_a, fn_b, fn_c};
  673. use some\b\{
  674. ClassF,
  675. ClassG
  676. };
  677. use const some\b\{
  678. ConstX,
  679. ConstY,
  680. ConstZ
  681. };
  682. use function some\b\{
  683. fn_x,
  684. fn_y,
  685. fn_z
  686. };
  687. ',
  688. '<?php
  689. use some\a\{ClassA, ClassB, ClassC as C};
  690. use function some\b\{
  691. fn_y,
  692. fn_z,
  693. fn_x
  694. };
  695. use function some\a\{fn_a, fn_b, fn_c};
  696. use A\B;
  697. use const some\b\{
  698. ConstZ,
  699. ConstX,
  700. ConstY
  701. };
  702. use const some\a\{ConstA, ConstB, ConstC};
  703. use some\b\{
  704. ClassG,
  705. ClassF
  706. };
  707. ',
  708. ];
  709. yield [
  710. '<?php
  711. use A\B;
  712. use const some\a\{
  713. ConstA,
  714. ConstB,
  715. ConstC
  716. };
  717. use some\a\{ClassA as A /*z2*/, ClassB, ClassC};
  718. use function some\a\{fn_a, fn_b, fn_c};
  719. ',
  720. '<?php
  721. use some\a\{ ClassB,ClassC, /*z2*/ ClassA as A};
  722. use function some\a\{fn_c, fn_a,fn_b };
  723. use A\B;
  724. use const some\a\{
  725. ConstA,
  726. ConstB,
  727. ConstC
  728. };
  729. ',
  730. ];
  731. yield [
  732. '<?php
  733. use C\B;
  734. use function B\fn_a;
  735. use const A\ConstA;
  736. ',
  737. '<?php
  738. use const A\ConstA;
  739. use function B\fn_a;
  740. use C\B;
  741. ',
  742. [
  743. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  744. 'imports_order' => ['class', 'function', 'const'],
  745. ],
  746. ];
  747. yield [
  748. '<?php
  749. use Foo\Bar\Baz;use Foo\Bar\{ClassA, ClassB, ClassC};
  750. use Foo\Bir;
  751. ',
  752. '<?php
  753. use Foo\Bar\Baz, Foo\Bir;
  754. use Foo\Bar\{ClassC, ClassB, ClassA};
  755. ',
  756. ];
  757. yield [
  758. '<?php
  759. use A\A;use Foo3\Bar\{ClassA};use G\G;use H\H;use Ioo2\Bar\{ClassB};use J\J;use K\K;use Loo1\Bar\{ClassC};use M\M;
  760. ',
  761. '<?php
  762. use A\A,G\G;use Foo3\Bar\{ClassA};use H\H,J\J;use Ioo2\Bar\{ClassB};use K\K,M\M;use Loo1\Bar\{ClassC};
  763. ',
  764. ];
  765. yield [
  766. '<?php
  767. use Foo\Bar\{ClassA, ClassB, ClassC};
  768. use Foo\Bir\{
  769. ClassD,
  770. ClassE,
  771. ClassF
  772. };
  773. use Foo\Bor\{
  774. ClassG,
  775. ClassH,
  776. ClassI,
  777. ClassJ
  778. };
  779. ',
  780. '<?php
  781. use Foo\Bar\{ClassC, ClassB, ClassA};
  782. use Foo\Bir\{ClassE, ClassF,
  783. ClassD};
  784. use Foo\Bor\{
  785. ClassJ,
  786. ClassI,
  787. ClassH,
  788. ClassG
  789. };
  790. ',
  791. ];
  792. yield 'alpha - [\'class\', \'function\', \'const\']' => [
  793. '<?php
  794. use Z\Z;
  795. use function X\X;
  796. use const Y\Y;
  797. ',
  798. '<?php
  799. use const Y\Y;
  800. use function X\X;
  801. use Z\Z;
  802. ',
  803. [
  804. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  805. 'imports_order' => ['class', 'function', 'const'],
  806. ],
  807. ];
  808. yield 'alpha - [\'class\', \'const\', \'function\']' => [
  809. '<?php
  810. use Z\Z;
  811. use const Y\Y;
  812. use function X\X;
  813. ',
  814. '<?php
  815. use function X\X;
  816. use const Y\Y;
  817. use Z\Z;
  818. ',
  819. [
  820. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  821. 'imports_order' => ['class', 'const', 'function'],
  822. ],
  823. ];
  824. yield 'alpha - [\'function\', \'class\', \'const\']' => [
  825. '<?php
  826. use function Z\Z;
  827. use Y\Y;
  828. use const X\X;
  829. ',
  830. '<?php
  831. use const X\X;
  832. use Y\Y;
  833. use function Z\Z;
  834. ',
  835. [
  836. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  837. 'imports_order' => ['function', 'class', 'const'],
  838. ],
  839. ];
  840. yield 'alpha - [\'function\', \'const\', \'class\']' => [
  841. '<?php
  842. use function Z\Z;
  843. use const Y\Y;
  844. use X\X;
  845. ',
  846. '<?php
  847. use X\X;
  848. use const Y\Y;
  849. use function Z\Z;
  850. ',
  851. [
  852. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  853. 'imports_order' => ['function', 'const', 'class'],
  854. ],
  855. ];
  856. yield 'alpha - [\'const\', \'function\', \'class\']' => [
  857. '<?php
  858. use const Z\Z;
  859. use function Y\Y;
  860. use X\X;
  861. ',
  862. '<?php
  863. use X\X;
  864. use function Y\Y;
  865. use const Z\Z;
  866. ',
  867. [
  868. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  869. 'imports_order' => ['const', 'function', 'class'],
  870. ],
  871. ];
  872. yield 'alpha - [\'const\', \'class\', \'function\']' => [
  873. '<?php
  874. use const Z\Z;
  875. use Y\Y;
  876. use function X\X;
  877. ',
  878. '<?php
  879. use function X\X;
  880. use Y\Y;
  881. use const Z\Z;
  882. ',
  883. [
  884. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  885. 'imports_order' => ['const', 'class', 'function'],
  886. ],
  887. ];
  888. yield '"strcasecmp" vs. "strnatcasecmp"' => [
  889. '<?php
  890. use A\A1;
  891. use A\A10;
  892. use A\A2;
  893. use A\A20;
  894. ',
  895. '<?php
  896. use A\A20;
  897. use A\A2;
  898. use A\A10;
  899. use A\A1;
  900. ',
  901. [
  902. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  903. ],
  904. ];
  905. yield [
  906. '<?php
  907. use A\{B,};
  908. use C\{D,E,};
  909. ',
  910. '<?php
  911. use C\{D,E,};
  912. use A\{B,};
  913. ',
  914. ];
  915. yield [
  916. '<?php
  917. use Foo\{
  918. Aaa,
  919. Bbb,
  920. };',
  921. '<?php
  922. use Foo\{
  923. Bbb,
  924. Aaa,
  925. };',
  926. ];
  927. yield [
  928. '<?php
  929. use Foo\{
  930. Aaa /* 3 *//* 4 *//* 5 */,
  931. Bbb /* 1 *//* 2 */,
  932. };',
  933. '<?php
  934. use Foo\{
  935. /* 1 */Bbb/* 2 */,/* 3 */
  936. /* 4 */Aaa/* 5 */,/* 6 */
  937. };',
  938. ];
  939. $input =
  940. '<?php use A\{B,};
  941. use some\y\{ClassA, ClassB, ClassC as C,};
  942. use function some\a\{fn_a, fn_b, fn_c,};
  943. use const some\Z\{ConstAA,ConstBB,ConstCC,};
  944. use const some\X\{ConstA,ConstB,ConstC,ConstF};
  945. use C\{D,E,};
  946. ';
  947. yield [
  948. '<?php use A\{B,};
  949. use C\{D,E,};
  950. use some\y\{ClassA, ClassB, ClassC as C,};
  951. use const some\X\{ConstA,ConstB,ConstC,ConstF};
  952. use const some\Z\{ConstAA,ConstBB,ConstCC,};
  953. use function some\a\{fn_a, fn_b, fn_c,};
  954. ',
  955. $input,
  956. [
  957. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  958. 'imports_order' => [OrderedImportsFixer::IMPORT_TYPE_CLASS, OrderedImportsFixer::IMPORT_TYPE_CONST, OrderedImportsFixer::IMPORT_TYPE_FUNCTION],
  959. ],
  960. ];
  961. yield [
  962. '<?php use A\{B,};
  963. use C\{D,E,};
  964. use some\y\{ClassA, ClassB, ClassC as C,};
  965. use const some\Z\{ConstAA,ConstBB,ConstCC,};
  966. use const some\X\{ConstA,ConstB,ConstC,ConstF};
  967. use function some\a\{fn_a, fn_b, fn_c,};
  968. ',
  969. $input,
  970. [
  971. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  972. 'imports_order' => [OrderedImportsFixer::IMPORT_TYPE_CLASS, OrderedImportsFixer::IMPORT_TYPE_CONST, OrderedImportsFixer::IMPORT_TYPE_FUNCTION],
  973. ],
  974. ];
  975. yield [
  976. '<?php use A\{B,};
  977. use some\y\{ClassA, ClassB, ClassC as C,};
  978. use C\{D,E,};
  979. use const some\Z\{ConstAA,ConstBB,ConstCC,};
  980. use const some\X\{ConstA,ConstB,ConstC,ConstF};
  981. use function some\a\{fn_a, fn_b, fn_c,};
  982. ',
  983. $input,
  984. [
  985. 'sort_algorithm' => OrderedImportsFixer::SORT_NONE,
  986. 'imports_order' => [OrderedImportsFixer::IMPORT_TYPE_CLASS, OrderedImportsFixer::IMPORT_TYPE_CONST, OrderedImportsFixer::IMPORT_TYPE_FUNCTION],
  987. ],
  988. ];
  989. yield [
  990. '<?php use const CONST_A, CONST_B, CONST_C;',
  991. '<?php use const CONST_C, CONST_B, CONST_A;',
  992. ];
  993. yield [
  994. '<?php use function Foo\A, Foo\B, Foo\C;',
  995. '<?php use function Foo\B, Foo\C, Foo\A;',
  996. ];
  997. }
  998. public function testUnknownOrderTypes(): void
  999. {
  1000. $this->expectException(InvalidFixerConfigurationException::class);
  1001. $this->expectExceptionMessage('[ordered_imports] Invalid configuration: Unknown sort types "foo" and "bar".');
  1002. $this->fixer->configure([
  1003. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  1004. 'imports_order' => ['class', 'const', 'function', 'foo', 'bar'],
  1005. ]);
  1006. }
  1007. /*
  1008. |--------------------------------------------------------------------------
  1009. | Test sorting by length
  1010. |--------------------------------------------------------------------------
  1011. */
  1012. public function testInvalidOrderTypesSize(): void
  1013. {
  1014. $this->expectException(InvalidFixerConfigurationException::class);
  1015. $this->expectExceptionMessage('[ordered_imports] Invalid configuration: Missing sort type "function".');
  1016. $this->fixer->configure([
  1017. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  1018. 'imports_order' => ['class', 'const'],
  1019. ]);
  1020. }
  1021. public function testInvalidOrderType(): void
  1022. {
  1023. $this->expectException(InvalidFixerConfigurationException::class);
  1024. $this->expectExceptionMessage('[ordered_imports] Invalid configuration: Missing sort type "class".');
  1025. $this->fixer->configure([
  1026. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  1027. 'imports_order' => ['const', 'function', 'bar'],
  1028. ]);
  1029. }
  1030. /**
  1031. * @param _AutogeneratedInputConfiguration $configuration
  1032. *
  1033. * @dataProvider provideInvalidSortAlgorithmCases
  1034. */
  1035. public function testInvalidSortAlgorithm(array $configuration, string $expectedValue): void
  1036. {
  1037. $this->expectException(InvalidFixerConfigurationException::class);
  1038. $this->expectExceptionMessage(\sprintf(
  1039. '[ordered_imports] Invalid configuration: The option "sort_algorithm" with value %s is invalid. Accepted values are: "alpha", "length", "none".',
  1040. $expectedValue
  1041. ));
  1042. $this->fixer->configure($configuration);
  1043. }
  1044. public static function provideInvalidSortAlgorithmCases(): iterable
  1045. {
  1046. yield [
  1047. [
  1048. 'sort_algorithm' => 'dope',
  1049. 'imports_order' => null,
  1050. ],
  1051. '"dope"',
  1052. ];
  1053. yield [
  1054. [
  1055. 'sort_algorithm' => [OrderedImportsFixer::SORT_ALPHA, OrderedImportsFixer::SORT_LENGTH],
  1056. 'imports_order' => null,
  1057. ],
  1058. 'array',
  1059. ];
  1060. yield [
  1061. [
  1062. 'sort_algorithm' => new \stdClass(),
  1063. 'imports_order' => null,
  1064. ],
  1065. \stdClass::class,
  1066. ];
  1067. }
  1068. public function testByLengthFixWithSameLength(): void
  1069. {
  1070. $this->fixer->configure([
  1071. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1072. 'imports_order' => null,
  1073. ]);
  1074. $expected = <<<'EOF'
  1075. <?php
  1076. use Acme;
  1077. use Bar1;
  1078. use Barr;
  1079. use Fooo;
  1080. class AnnotatedClass
  1081. {
  1082. /**
  1083. * @Template(foobar=21)
  1084. * @param Entity $foo
  1085. */
  1086. public function doSomething($foo)
  1087. {
  1088. $bar = $foo->toArray();
  1089. /** @var ArrayInterface $bar */
  1090. return function () use ($bar, $foo) {};
  1091. }
  1092. }
  1093. EOF;
  1094. $input = <<<'EOF'
  1095. <?php
  1096. use Acme;
  1097. use Fooo;
  1098. use Barr;
  1099. use Bar1;
  1100. class AnnotatedClass
  1101. {
  1102. /**
  1103. * @Template(foobar=21)
  1104. * @param Entity $foo
  1105. */
  1106. public function doSomething($foo)
  1107. {
  1108. $bar = $foo->toArray();
  1109. /** @var ArrayInterface $bar */
  1110. return function () use ($bar, $foo) {};
  1111. }
  1112. }
  1113. EOF;
  1114. $this->doTest($expected, $input);
  1115. }
  1116. public function testByLengthFixWithSameLengthAndCaseSensitive(): void
  1117. {
  1118. $this->fixer->configure([
  1119. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1120. 'imports_order' => null,
  1121. 'case_sensitive' => true,
  1122. ]);
  1123. $expected = <<<'EOF'
  1124. <?php
  1125. use Acme;
  1126. use BaRr;
  1127. use Bar1;
  1128. use Fooo;
  1129. class AnnotatedClass { }
  1130. EOF;
  1131. $input = <<<'EOF'
  1132. <?php
  1133. use Acme;
  1134. use Fooo;
  1135. use Bar1;
  1136. use BaRr;
  1137. class AnnotatedClass { }
  1138. EOF;
  1139. $this->doTest($expected, $input);
  1140. }
  1141. public function testByLengthFixWithMultipleNamespace(): void
  1142. {
  1143. $this->fixer->configure([
  1144. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1145. 'imports_order' => null,
  1146. ]);
  1147. $expected = <<<'EOF'
  1148. <?php
  1149. namespace FooRoo {
  1150. use Foo\Bar;
  1151. use Zoo\Tar1, Zoo\Tar2;
  1152. use SomeClass;
  1153. use Foo\Zar\Baz;
  1154. use Foo\Bir as FBB;
  1155. use Zoo\Bar as ZooBar, Foo\Bar\Foo as Fooo;
  1156. use Foo\Bar\FooBar as FooBaz;
  1157. use Symfony\Annotation\Template;
  1158. $a = new Bar();
  1159. $a = new FooBaz();
  1160. $a = new someclass();
  1161. class AnnotatedClass
  1162. {
  1163. /**
  1164. * @Template(foobar=21)
  1165. * @param Entity $foo
  1166. */
  1167. public function doSomething($foo)
  1168. {
  1169. $bar = $foo->toArray();
  1170. /** @var ArrayInterface $bar */
  1171. return function () use ($bar, $foo) {};
  1172. }
  1173. }
  1174. }
  1175. namespace BlaRoo {
  1176. use Zoo\Bar;
  1177. use SomeClass;
  1178. use Foo\Zar\Baz;
  1179. use Symfony\Annotation\Template, Symfony\Doctrine\Entities\Entity;
  1180. class AnnotatedClass
  1181. {
  1182. /**
  1183. * @Template(foobar=21)
  1184. * @param Entity $foo
  1185. */
  1186. public function doSomething($foo)
  1187. {
  1188. $bar = $foo->toArray();
  1189. /** @var ArrayInterface $bar */
  1190. return function () use ($bar, $foo) {};
  1191. }
  1192. }
  1193. }
  1194. EOF;
  1195. $input = <<<'EOF'
  1196. <?php
  1197. namespace FooRoo {
  1198. use Foo\Bar\FooBar as FooBaz;
  1199. use Zoo\Bar as ZooBar, Zoo\Tar1;
  1200. use Foo\Bar;
  1201. use Foo\Zar\Baz;
  1202. use Symfony\Annotation\Template;
  1203. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  1204. use SomeClass;
  1205. use Zoo\Tar2;
  1206. $a = new Bar();
  1207. $a = new FooBaz();
  1208. $a = new someclass();
  1209. class AnnotatedClass
  1210. {
  1211. /**
  1212. * @Template(foobar=21)
  1213. * @param Entity $foo
  1214. */
  1215. public function doSomething($foo)
  1216. {
  1217. $bar = $foo->toArray();
  1218. /** @var ArrayInterface $bar */
  1219. return function () use ($bar, $foo) {};
  1220. }
  1221. }
  1222. }
  1223. namespace BlaRoo {
  1224. use Foo\Zar\Baz;
  1225. use Zoo\Bar;
  1226. use SomeClass;
  1227. use Symfony\Annotation\Template, Symfony\Doctrine\Entities\Entity;
  1228. class AnnotatedClass
  1229. {
  1230. /**
  1231. * @Template(foobar=21)
  1232. * @param Entity $foo
  1233. */
  1234. public function doSomething($foo)
  1235. {
  1236. $bar = $foo->toArray();
  1237. /** @var ArrayInterface $bar */
  1238. return function () use ($bar, $foo) {};
  1239. }
  1240. }
  1241. }
  1242. EOF;
  1243. $this->doTest($expected, $input);
  1244. }
  1245. public function testByLengthFixWithComment(): void
  1246. {
  1247. $this->fixer->configure([
  1248. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1249. 'imports_order' => null,
  1250. ]);
  1251. $expected = <<<'EOF'
  1252. The normal
  1253. use of this fixer
  1254. should not change this sentence nor those statements below
  1255. use Zoo\Bar;
  1256. use Foo\Bar;
  1257. use Foo\Zar\Baz;
  1258. <?php
  1259. use Foo\Bar;
  1260. use Zoo\Tar, SomeClass;
  1261. use Foo\Zar\Baz;
  1262. use Foo\Bir as FBB;
  1263. use Zoo\Bar as ZooBar;
  1264. use Foo\Bar\Foo as Fooo, Foo\Bar\FooBar /* He there */ as FooBaz;
  1265. use /* FIXME */Symfony\Annotation\Template;
  1266. $a = new Bar();
  1267. $a = new FooBaz();
  1268. $a = new someclass();
  1269. use Symfony\Doctrine\Entities\Entity;
  1270. class AnnotatedClass
  1271. {
  1272. /**
  1273. * @Template(foobar=21)
  1274. * @param Entity $foo
  1275. */
  1276. public function doSomething($foo)
  1277. {
  1278. $bar = $foo->toArray();
  1279. /** @var ArrayInterface $bar */
  1280. return function () use ($bar, $foo) {};
  1281. }
  1282. }
  1283. EOF;
  1284. $input = <<<'EOF'
  1285. The normal
  1286. use of this fixer
  1287. should not change this sentence nor those statements below
  1288. use Zoo\Bar;
  1289. use Foo\Bar;
  1290. use Foo\Zar\Baz;
  1291. <?php
  1292. use Foo\Bar\FooBar /* He there */ as FooBaz;
  1293. use Zoo\Bar as ZooBar, Zoo\Tar;
  1294. use Foo\Bar;
  1295. use Foo\Zar\Baz;
  1296. use /* FIXME */Symfony\Annotation\Template;
  1297. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  1298. use SomeClass;
  1299. $a = new Bar();
  1300. $a = new FooBaz();
  1301. $a = new someclass();
  1302. use Symfony\Doctrine\Entities\Entity;
  1303. class AnnotatedClass
  1304. {
  1305. /**
  1306. * @Template(foobar=21)
  1307. * @param Entity $foo
  1308. */
  1309. public function doSomething($foo)
  1310. {
  1311. $bar = $foo->toArray();
  1312. /** @var ArrayInterface $bar */
  1313. return function () use ($bar, $foo) {};
  1314. }
  1315. }
  1316. EOF;
  1317. $this->doTest($expected, $input);
  1318. }
  1319. public function testByLength(): void
  1320. {
  1321. $this->fixer->configure([
  1322. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1323. 'imports_order' => null,
  1324. ]);
  1325. $expected = <<<'EOF'
  1326. <?php
  1327. use Foo\Bar;
  1328. use Zoo\Tar, SomeClass;
  1329. use Foo\Zar\Baz;
  1330. use Foo\Bir as FBB;
  1331. use Zoo\Bar as ZooBar;
  1332. use Foo\Bar\Foo as Fooo, Foo\Bar\FooBar as FooBaz;
  1333. use Symfony\Annotation\Template;
  1334. use Symfony\Doctrine\Entities\Entity;
  1335. trait Foo {}
  1336. trait Zoo {}
  1337. class AnnotatedClass
  1338. {
  1339. use Foo, Bar;
  1340. /**
  1341. * @Template(foobar=21)
  1342. * @param Entity $foo
  1343. */
  1344. public function doSomething($foo)
  1345. {
  1346. $bar = $foo->toArray();
  1347. /** @var ArrayInterface $bar */
  1348. return function () use ($bar, $foo) {};
  1349. }
  1350. }
  1351. EOF;
  1352. $input = <<<'EOF'
  1353. <?php
  1354. use Foo\Bar\FooBar as FooBaz;
  1355. use Zoo\Bar as ZooBar, Zoo\Tar;
  1356. use Foo\Bar;
  1357. use Foo\Zar\Baz;
  1358. use Symfony\Annotation\Template;
  1359. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  1360. use SomeClass;
  1361. use Symfony\Doctrine\Entities\Entity;
  1362. trait Foo {}
  1363. trait Zoo {}
  1364. class AnnotatedClass
  1365. {
  1366. use Foo, Bar;
  1367. /**
  1368. * @Template(foobar=21)
  1369. * @param Entity $foo
  1370. */
  1371. public function doSomething($foo)
  1372. {
  1373. $bar = $foo->toArray();
  1374. /** @var ArrayInterface $bar */
  1375. return function () use ($bar, $foo) {};
  1376. }
  1377. }
  1378. EOF;
  1379. $this->doTest($expected, $input);
  1380. }
  1381. public function testByLengthFixWithTraitImports(): void
  1382. {
  1383. $this->fixer->configure([
  1384. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1385. 'imports_order' => null,
  1386. ]);
  1387. $expected = <<<'EOF'
  1388. The normal
  1389. use of this fixer
  1390. should not change this sentence nor those statements below
  1391. use Zoo\Bar;
  1392. use Foo\Bar;
  1393. use Foo\Zar\Baz;
  1394. <?php
  1395. use Foo\Bar;
  1396. use Zoo\Tar, SomeClass;
  1397. use Foo\Zar\Baz;
  1398. use Foo\Bir as FBB;
  1399. use Zoo\Bar as ZooBar;
  1400. use Foo\Bar\Foo as Fooo;
  1401. use Acme\MyReusableTrait, Foo\Bar\FooBar as FooBaz;
  1402. use Symfony\Annotation\Template;
  1403. $a = new Bar();
  1404. $a = new FooBaz();
  1405. $a = new someclass();
  1406. use Symfony\Doctrine\Entities\Entity;
  1407. class AnnotatedClass
  1408. {
  1409. use MyReusableTrait;
  1410. /**
  1411. * @Template(foobar=21)
  1412. * @param Entity $foo
  1413. */
  1414. public function doSomething($foo)
  1415. {
  1416. $bar = $foo->toArray();
  1417. /** @var ArrayInterface $bar */
  1418. return function () use ($bar, $baz) {};
  1419. }
  1420. }
  1421. EOF;
  1422. $input = <<<'EOF'
  1423. The normal
  1424. use of this fixer
  1425. should not change this sentence nor those statements below
  1426. use Zoo\Bar;
  1427. use Foo\Bar;
  1428. use Foo\Zar\Baz;
  1429. <?php
  1430. use Foo\Bar\FooBar as FooBaz;
  1431. use Zoo\Bar as ZooBar, Zoo\Tar;
  1432. use Foo\Bar;
  1433. use Foo\Zar\Baz;
  1434. use Acme\MyReusableTrait;
  1435. use Symfony\Annotation\Template;
  1436. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  1437. use SomeClass;
  1438. $a = new Bar();
  1439. $a = new FooBaz();
  1440. $a = new someclass();
  1441. use Symfony\Doctrine\Entities\Entity;
  1442. class AnnotatedClass
  1443. {
  1444. use MyReusableTrait;
  1445. /**
  1446. * @Template(foobar=21)
  1447. * @param Entity $foo
  1448. */
  1449. public function doSomething($foo)
  1450. {
  1451. $bar = $foo->toArray();
  1452. /** @var ArrayInterface $bar */
  1453. return function () use ($bar, $baz) {};
  1454. }
  1455. }
  1456. EOF;
  1457. $this->doTest($expected, $input);
  1458. }
  1459. public function testByLengthFixWithDifferentCases(): void
  1460. {
  1461. $this->fixer->configure([
  1462. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1463. 'imports_order' => null,
  1464. ]);
  1465. $expected = <<<'EOF'
  1466. The normal
  1467. use of this fixer
  1468. should not change this sentence nor those statements below
  1469. use Zoo\Baz;
  1470. use abc\Bar;
  1471. <?php
  1472. use abc\Bar;
  1473. use Zoo\Baz;
  1474. class Test
  1475. {
  1476. }
  1477. EOF;
  1478. $input = <<<'EOF'
  1479. The normal
  1480. use of this fixer
  1481. should not change this sentence nor those statements below
  1482. use Zoo\Baz;
  1483. use abc\Bar;
  1484. <?php
  1485. use Zoo\Baz;
  1486. use abc\Bar;
  1487. class Test
  1488. {
  1489. }
  1490. EOF;
  1491. $this->doTest($expected, $input);
  1492. }
  1493. public function testByLengthOrderWithTrailingDigit(): void
  1494. {
  1495. $this->fixer->configure([
  1496. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1497. 'imports_order' => null,
  1498. ]);
  1499. $expected = <<<'EOF'
  1500. <?php
  1501. use abc\Bar;
  1502. use abc2\Bar2;
  1503. use xyz\abc\Bar6;
  1504. use xyz\xyz\Bar4;
  1505. use xyz\xyz\Bar5;
  1506. use xyz\abc2\Bar7;
  1507. class Test
  1508. {
  1509. }
  1510. EOF;
  1511. $input = <<<'EOF'
  1512. <?php
  1513. use abc2\Bar2;
  1514. use abc\Bar;
  1515. use xyz\abc2\Bar7;
  1516. use xyz\abc\Bar6;
  1517. use xyz\xyz\Bar4;
  1518. use xyz\xyz\Bar5;
  1519. class Test
  1520. {
  1521. }
  1522. EOF;
  1523. $this->doTest($expected, $input);
  1524. }
  1525. public function testByLengthCodeWithImportsOnly(): void
  1526. {
  1527. $this->fixer->configure([
  1528. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1529. 'imports_order' => null,
  1530. ]);
  1531. $expected = <<<'EOF'
  1532. <?php
  1533. use Aaa;
  1534. use Bbb;
  1535. EOF;
  1536. $input = <<<'EOF'
  1537. <?php
  1538. use Bbb;
  1539. use Aaa;
  1540. EOF;
  1541. $this->doTest($expected, $input);
  1542. }
  1543. public function testByLengthWithoutUses(): void
  1544. {
  1545. $this->fixer->configure([
  1546. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1547. 'imports_order' => null,
  1548. ]);
  1549. $expected = <<<'EOF'
  1550. <?php
  1551. $c = 1;
  1552. EOF;
  1553. $this->doTest($expected);
  1554. }
  1555. /**
  1556. * @dataProvider provideFixByLengthCases
  1557. */
  1558. public function testFixByLength(string $expected, ?string $input = null): void
  1559. {
  1560. $this->fixer->configure([
  1561. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1562. 'imports_order' => null,
  1563. ]);
  1564. $this->doTest($expected, $input);
  1565. }
  1566. /**
  1567. * @return iterable<array{string, string}>
  1568. */
  1569. public static function provideFixByLengthCases(): iterable
  1570. {
  1571. yield [
  1572. <<<'EOF'
  1573. The normal
  1574. use of this fixer
  1575. should not change this sentence nor those statements below
  1576. use Zoo\Bar as ZooBar;
  1577. use Foo\Bar;
  1578. use Foo\Zar\Baz;
  1579. <?php
  1580. use Foo\Bar;
  1581. use Zoo\Tar, SomeClass;
  1582. use Foo\Zar\Baz;
  1583. use Foo\Bir as FBB;
  1584. use Zoo\Bar as ZooBar;
  1585. use Foo\Bar\Foo as Fooo, Foo\Bar\FooBar as FooBaz;
  1586. use Symfony\Annotation\Template;
  1587. $a = new Bar();
  1588. $a = new FooBaz();
  1589. $a = new someclass();
  1590. use Symfony\Doctrine\Entities\Entity;
  1591. class AnnotatedClass
  1592. {
  1593. /**
  1594. * @Template(foobar=21)
  1595. * @param Entity $foo
  1596. */
  1597. public function doSomething($foo)
  1598. {
  1599. $bar = $foo->toArray();
  1600. /** @var ArrayInterface $bar */
  1601. return function () use ($bar, $foo) {};
  1602. }
  1603. }
  1604. EOF,
  1605. <<<'EOF'
  1606. The normal
  1607. use of this fixer
  1608. should not change this sentence nor those statements below
  1609. use Zoo\Bar as ZooBar;
  1610. use Foo\Bar;
  1611. use Foo\Zar\Baz;
  1612. <?php
  1613. use Foo\Bar\FooBar as FooBaz;
  1614. use Zoo\Bar as ZooBar, Zoo\Tar;
  1615. use Foo\Bar;
  1616. use Foo\Zar\Baz;
  1617. use Symfony\Annotation\Template;
  1618. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  1619. use SomeClass;
  1620. $a = new Bar();
  1621. $a = new FooBaz();
  1622. $a = new someclass();
  1623. use Symfony\Doctrine\Entities\Entity;
  1624. class AnnotatedClass
  1625. {
  1626. /**
  1627. * @Template(foobar=21)
  1628. * @param Entity $foo
  1629. */
  1630. public function doSomething($foo)
  1631. {
  1632. $bar = $foo->toArray();
  1633. /** @var ArrayInterface $bar */
  1634. return function () use ($bar, $foo) {};
  1635. }
  1636. }
  1637. EOF,
  1638. ];
  1639. yield [
  1640. '<?php
  1641. use A\B;
  1642. use Foo\Bar\Biz;
  1643. use some\b\{
  1644. ClassF,
  1645. ClassG
  1646. };
  1647. use function some\a\{fn_a, fn_b, fn_c};
  1648. use some\b\{ClassA, ClassB, ClassC as C};
  1649. use const some\a\{ConstA, ConstB, ConstC};
  1650. use some\a\{ClassX as X /*z*/, ClassY, ClassZ};
  1651. use Some\Biz\Barz\Boozz\Foz\Which\Is\Really\Long;
  1652. use const some\b\{ConstG, ConstX, ConstY, ConstZ};
  1653. use some\c\{ClassR, ClassT, ClassV as V, NiceClassName};
  1654. ',
  1655. '<?php
  1656. use function some\a\{fn_a, fn_b, fn_c};
  1657. use Foo\Bar\Biz;
  1658. use some\c\{ClassR, ClassT, ClassV as V, NiceClassName};
  1659. use A\B;
  1660. use Some\Biz\Barz\Boozz\Foz\Which\Is\Really\Long;
  1661. use some\b\{
  1662. ClassF,
  1663. ClassG
  1664. };
  1665. use const some\a\{ConstB, ConstA, ConstC};
  1666. use const some\b\{ConstX, ConstY, ConstZ, ConstG};
  1667. use some\b\{ClassA, ClassB, ClassC as C};
  1668. use some\a\{ ClassY,ClassZ, /*z*/ ClassX as X};
  1669. ',
  1670. ];
  1671. yield [
  1672. '<?php
  1673. use const ZZZ;
  1674. use function B;
  1675. use function A123;
  1676. ',
  1677. '<?php
  1678. use function B;
  1679. use function A123;
  1680. use const ZZZ;
  1681. ',
  1682. ];
  1683. }
  1684. /**
  1685. * @dataProvider provideFixTypesOrderAndLengthCases
  1686. */
  1687. public function testFixTypesOrderAndLength(string $expected, ?string $input = null): void
  1688. {
  1689. $this->fixer->configure([
  1690. 'sort_algorithm' => OrderedImportsFixer::SORT_LENGTH,
  1691. 'imports_order' => [OrderedImportsFixer::IMPORT_TYPE_CLASS, OrderedImportsFixer::IMPORT_TYPE_CONST, OrderedImportsFixer::IMPORT_TYPE_FUNCTION],
  1692. ]);
  1693. $this->doTest($expected, $input);
  1694. }
  1695. /**
  1696. * @return iterable<array{string, string}>
  1697. */
  1698. public static function provideFixTypesOrderAndLengthCases(): iterable
  1699. {
  1700. yield [
  1701. '<?php
  1702. use A\B;
  1703. use Some\Bar;
  1704. use Foo\Zar\Baz;
  1705. use some\b\{
  1706. ClassF,
  1707. ClassG
  1708. };
  1709. use some\a\{ClassA, ClassB, ClassC as C};
  1710. use some\b\{ClassK, ClassL, ClassM as M};
  1711. use some\a\{ClassX as X /*z*/, ClassY, ClassZ};
  1712. use const some\a\{ConstA, ConstB, ConstC};
  1713. use const some\b\{ConstD, ConstE, ConstF};
  1714. use function some\a\{fn_a, fn_b};
  1715. use function some\f\{fn_c, fn_d, fn_e};
  1716. use function some\b\{fn_k, fn_l, func_m};
  1717. ',
  1718. '<?php
  1719. use const some\a\{ConstA, ConstB, ConstC};
  1720. use some\a\{ClassA, ClassB, ClassC as C};
  1721. use Foo\Zar\Baz;
  1722. use some\b\{ClassK, ClassL, ClassM as M};
  1723. use some\a\{ClassX as X /*z*/, ClassY, ClassZ};
  1724. use A\B;
  1725. use some\b\{
  1726. ClassF,
  1727. ClassG
  1728. };
  1729. use function some\b\{fn_k, fn_l, func_m};
  1730. use Some\Bar;
  1731. use function some\a\{fn_a, fn_b};
  1732. use const some\b\{ConstD, ConstE, ConstF};
  1733. use function some\f\{fn_c, fn_d, fn_e};
  1734. ',
  1735. ];
  1736. }
  1737. /**
  1738. * @dataProvider provideFixTypesOrderAndAlphabetCases
  1739. *
  1740. * @param list<string> $importOrder
  1741. */
  1742. public function testFixTypesOrderAndAlphabet(string $expected, ?string $input = null, ?array $importOrder = null): void
  1743. {
  1744. $this->fixer->configure([
  1745. 'sort_algorithm' => OrderedImportsFixer::SORT_ALPHA,
  1746. 'imports_order' => $importOrder,
  1747. ]);
  1748. $this->doTest($expected, $input);
  1749. }
  1750. public static function provideFixTypesOrderAndAlphabetCases(): iterable
  1751. {
  1752. yield [
  1753. '<?php
  1754. use Aaa\Bbb;
  1755. use Aaa\Ccc;
  1756. use Bar\Biz\Boooz\Bum;
  1757. use Foo\Zar\Baz;
  1758. use some\a\{ClassA};
  1759. use some\b\{
  1760. ClassF,
  1761. ClassG
  1762. };
  1763. use some\b\{ClassB, ClassC as C, ClassD};
  1764. use Some\Cloz;
  1765. use const some\a\{ConstA};
  1766. use const some\a\{ConstB, ConstC as CC};
  1767. use const some\a\{ConstD};
  1768. use const some\b\{ConstE};
  1769. use function some\a\{fn_a, fn_b};
  1770. use function some\a\{fn_bc};
  1771. use function some\b\{fn_c, fn_d, fn_e};
  1772. use function some\c\{fn_f};
  1773. use function some\f\{fn_g, fn_h, fn_i};
  1774. ',
  1775. '<?php
  1776. use Aaa\Ccc;
  1777. use Foo\Zar\Baz;
  1778. use function some\f\{fn_g, fn_h, fn_i};
  1779. use some\a\{ClassA};
  1780. use some\b\{ClassD, ClassB, ClassC as C};
  1781. use Bar\Biz\Boooz\Bum;
  1782. use function some\c\{fn_f};
  1783. use some\b\{
  1784. ClassF,
  1785. ClassG
  1786. };
  1787. use const some\a\{ConstD};
  1788. use Some\Cloz;
  1789. use function some\a\{fn_bc};
  1790. use const some\a\{ConstA};
  1791. use function some\b\{fn_c, fn_d, fn_e};
  1792. use const some\a\{ConstB, ConstC as CC};
  1793. use Aaa\Bbb;
  1794. use const some\b\{ConstE};
  1795. use function some\a\{fn_a, fn_b};
  1796. ',
  1797. [OrderedImportsFixer::IMPORT_TYPE_CLASS, OrderedImportsFixer::IMPORT_TYPE_CONST, OrderedImportsFixer::IMPORT_TYPE_FUNCTION],
  1798. ];
  1799. }
  1800. /**
  1801. * @dataProvider provideFixTypesOrderAndNoneCases
  1802. *
  1803. * @param null|list<string> $importOrder
  1804. */
  1805. public function testFixTypesOrderAndNone(string $expected, ?string $input = null, ?array $importOrder = null): void
  1806. {
  1807. $this->fixer->configure([
  1808. 'sort_algorithm' => OrderedImportsFixer::SORT_NONE,
  1809. 'imports_order' => $importOrder,
  1810. ]);
  1811. $this->doTest($expected, $input);
  1812. }
  1813. public static function provideFixTypesOrderAndNoneCases(): iterable
  1814. {
  1815. yield [
  1816. '<?php
  1817. use Aaa\Ccc;
  1818. use Foo\Zar\Baz;
  1819. use some\a\{ClassA};
  1820. use some\b\{ClassD, ClassB, ClassC as C};
  1821. use Bar\Biz\Boooz\Bum;
  1822. use some\b\{
  1823. ClassF,
  1824. ClassG
  1825. };
  1826. use Some\Cloz;
  1827. use Aaa\Bbb;
  1828. use const some\a\{ConstD};
  1829. use const some\a\{ConstA};
  1830. use const some\a\{ConstB, ConstC as CC};
  1831. use const some\b\{ConstE};
  1832. use function some\f\{fn_g, fn_h, fn_i};
  1833. use function some\c\{fn_f};
  1834. use function some\a\{fn_x};
  1835. use function some\b\{fn_c, fn_d, fn_e};
  1836. use function some\a\{fn_a, fn_b};
  1837. ',
  1838. '<?php
  1839. use Aaa\Ccc;
  1840. use Foo\Zar\Baz;
  1841. use function some\f\{fn_g, fn_h, fn_i};
  1842. use some\a\{ClassA};
  1843. use some\b\{ClassD, ClassB, ClassC as C};
  1844. use Bar\Biz\Boooz\Bum;
  1845. use function some\c\{fn_f};
  1846. use some\b\{
  1847. ClassF,
  1848. ClassG
  1849. };
  1850. use const some\a\{ConstD};
  1851. use Some\Cloz;
  1852. use function some\a\{fn_x};
  1853. use const some\a\{ConstA};
  1854. use function some\b\{fn_c, fn_d, fn_e};
  1855. use const some\a\{ConstB, ConstC as CC};
  1856. use Aaa\Bbb;
  1857. use const some\b\{ConstE};
  1858. use function some\a\{fn_a, fn_b};
  1859. ',
  1860. [OrderedImportsFixer::IMPORT_TYPE_CLASS, OrderedImportsFixer::IMPORT_TYPE_CONST, OrderedImportsFixer::IMPORT_TYPE_FUNCTION],
  1861. ];
  1862. }
  1863. public function testFixByNone(): void
  1864. {
  1865. $this->fixer->configure([
  1866. 'sort_algorithm' => OrderedImportsFixer::SORT_NONE,
  1867. 'imports_order' => null,
  1868. ]);
  1869. $expected = <<<'EOF'
  1870. The normal
  1871. use of this fixer
  1872. should not change this sentence nor those statements below
  1873. use Zoo\Bar as ZooBar;
  1874. use Foo\Bar;
  1875. use Foo\Zar\Baz;
  1876. <?php
  1877. use Foo\Bar\FooBar as FooBaz;
  1878. use Zoo\Bar as ZooBar, Zoo\Tar;
  1879. use Foo\Bar;
  1880. use Foo\Zar\Baz;
  1881. use Symfony\Annotation\Template;
  1882. use Foo\Bar\Foo as Fooo, Foo\Bir as FBB;
  1883. use SomeClass;
  1884. $a = new Bar();
  1885. $a = new FooBaz();
  1886. $a = new someclass();
  1887. use Symfony\Doctrine\Entities\Entity;
  1888. class AnnotatedClass
  1889. {
  1890. /**
  1891. * @Template(foobar=21)
  1892. * @param Entity $foo
  1893. */
  1894. public function doSomething($foo)
  1895. {
  1896. $bar = $foo->toArray();
  1897. /** @var ArrayInterface $bar */
  1898. return function () use ($bar, $foo) {};
  1899. }
  1900. }
  1901. EOF;
  1902. $this->doTest($expected);
  1903. }
  1904. public function testFixWithCaseSensitive(): void
  1905. {
  1906. $this->fixer->configure([
  1907. 'case_sensitive' => true,
  1908. ]);
  1909. $expected = <<<'EOF'
  1910. <?php
  1911. use AA;
  1912. use Aaa;
  1913. class Foo { }
  1914. EOF;
  1915. $input = <<<'EOF'
  1916. <?php
  1917. use Aaa;
  1918. use AA;
  1919. class Foo { }
  1920. EOF;
  1921. $this->doTest($expected, $input);
  1922. }
  1923. }