OrderedImportsFixerTest.php 55 KB

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