PhpdocTypesOrderFixerTest.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  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\Phpdoc;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @internal
  16. *
  17. * @covers \PhpCsFixer\Fixer\Phpdoc\PhpdocTypesOrderFixer
  18. *
  19. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Phpdoc\PhpdocTypesOrderFixer>
  20. *
  21. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\Phpdoc\PhpdocTypesOrderFixer
  22. */
  23. final class PhpdocTypesOrderFixerTest extends AbstractFixerTestCase
  24. {
  25. /**
  26. * @dataProvider provideFixWithAlphaAlgorithmAndNullAlwaysFirstCases
  27. */
  28. public function testFix(string $expected, ?string $input = null): void
  29. {
  30. $this->doTest($expected, $input);
  31. }
  32. /**
  33. * @dataProvider provideFixWithNullFirstCases
  34. */
  35. public function testFixWithNullFirst(string $expected, ?string $input = null): void
  36. {
  37. $this->fixer->configure([
  38. 'sort_algorithm' => 'none',
  39. 'null_adjustment' => 'always_first',
  40. ]);
  41. $this->doTest($expected, $input);
  42. }
  43. /**
  44. * @return iterable<int|string, array{0: string, 1?: string}>
  45. */
  46. public static function provideFixWithNullFirstCases(): iterable
  47. {
  48. yield [
  49. '<?php /** @var null|string */',
  50. '<?php /** @var string|null */',
  51. ];
  52. yield [
  53. '<?php /** @param null|string $foo */',
  54. '<?php /** @param string|null $foo */',
  55. ];
  56. yield [
  57. '<?php /** @property null|string $foo */',
  58. '<?php /** @property string|null $foo */',
  59. ];
  60. yield [
  61. '<?php /** @property-read null|string $foo */',
  62. '<?php /** @property-read string|null $foo */',
  63. ];
  64. yield [
  65. '<?php /** @property-write null|string $foo */',
  66. '<?php /** @property-write string|null $foo */',
  67. ];
  68. yield [
  69. '<?php /** @method null|string foo(null|int $foo, null|string $bar) */',
  70. '<?php /** @method string|null foo(int|null $foo, string|null $bar) */',
  71. ];
  72. yield [
  73. '<?php /** @return null|string */',
  74. '<?php /** @return string|null */',
  75. ];
  76. yield [
  77. '<?php /** @var null|string[]|resource|false|object|Foo|Bar\Baz|bool[]|string|array|int */',
  78. '<?php /** @var string[]|resource|false|object|null|Foo|Bar\Baz|bool[]|string|array|int */',
  79. ];
  80. yield [
  81. '<?php /** @var null|array<int, string> Foo */',
  82. '<?php /** @var array<int, string>|null Foo */',
  83. ];
  84. yield [
  85. '<?php /** @var null|array<int, array<string>> Foo */',
  86. '<?php /** @var array<int, array<string>>|null Foo */',
  87. ];
  88. yield [
  89. '<?php /** @var NULL|string */',
  90. '<?php /** @var string|NULL */',
  91. ];
  92. yield [
  93. '<?php /** @var Foo|?Bar */',
  94. ];
  95. yield [
  96. '<?php /** @var ?Foo|Bar */',
  97. ];
  98. yield [
  99. '<?php /** @var array<null|string> */',
  100. '<?php /** @var array<string|null> */',
  101. ];
  102. yield [
  103. '<?php /** @var array<int, null|string> */',
  104. '<?php /** @var array<int, string|null> */',
  105. ];
  106. yield [
  107. '<?php /** @var array<int, array<null|int|string>> */',
  108. '<?php /** @var array<int, array<int|string|null>> */',
  109. ];
  110. yield [
  111. '<?php /** @var null|null */',
  112. ];
  113. yield [
  114. '<?php /** @var null|\null */',
  115. ];
  116. yield [
  117. '<?php /** @var \null|null */',
  118. ];
  119. yield [
  120. '<?php /** @var \null|\null */',
  121. ];
  122. yield [
  123. '<?php /** @var \null|int */',
  124. '<?php /** @var int|\null */',
  125. ];
  126. yield [
  127. '<?php /** @var array<\null|int> */',
  128. '<?php /** @var array<int|\null> */',
  129. ];
  130. yield [
  131. '<?php /** @var array<int, array<int, array<int, array<int, array<null|OutputInterface>>>>> */',
  132. '<?php /** @var array<int, array<int, array<int, array<int, array<OutputInterface|null>>>>> */',
  133. ];
  134. yield [
  135. '<?php /** @var null|Foo[]|Foo|Foo\Bar|Foo_Bar */',
  136. '<?php /** @var Foo[]|null|Foo|Foo\Bar|Foo_Bar */',
  137. ];
  138. yield [
  139. '<?php /** @method null|Y|X setOrder(array<string, null|array{Y,X,null|Z}> $by) */',
  140. '<?php /** @method Y|null|X setOrder(array<string, array{Y,X,Z|null}|null> $by) */',
  141. ];
  142. yield '@method with invalid 2nd phpdoc' => [
  143. '<?php /** @method null|X setOrder($$by) */',
  144. '<?php /** @method X|null setOrder($$by) */',
  145. ];
  146. yield [
  147. '<?php /** @var array<array<int, int>, OutputInterface> */',
  148. ];
  149. yield [
  150. '<?php /** @var iterable<array{names:array<string>, surname:string}> */',
  151. ];
  152. yield [
  153. '<?php /** @var iterable<array{surname:string, names:array<string>}> */',
  154. ];
  155. yield [
  156. '<?php /** @return array<array{level:string, message:string, context:array<mixed>}> */',
  157. ];
  158. yield [
  159. '<?php /** @return Data<array{enabled: string[], all: array<string, string>}> */',
  160. ];
  161. yield [
  162. '<?php /** @return array<int, callable(array<string, null|string> , DateTime): bool> */',
  163. ];
  164. yield [
  165. '<?php /** @param null|callable(array<string>): array<string, T> $callback */',
  166. ];
  167. yield [
  168. '<?php /** @return Closure(Iterator<TKey, T>): Generator<int, array<TKey, T>> */',
  169. ];
  170. yield [
  171. '<?php /** @var Closure(Iterator<TKey, T>): Generator<int, array<TKey, T>> $pipe */',
  172. ];
  173. yield [
  174. '<?php /** @return Generator<int, Promise<mixed>, mixed, Identity> */',
  175. ];
  176. yield [
  177. '<?php /** @param null|callable(null|foo, null|bar): array<string, T> $callback */',
  178. '<?php /** @param null|callable(foo|null, bar|null): array<string, T> $callback */',
  179. ];
  180. yield [
  181. '<?php /** @param null|string$foo */',
  182. '<?php /** @param string|null$foo */',
  183. ];
  184. }
  185. /**
  186. * @dataProvider provideFixWithNullLastCases
  187. */
  188. public function testFixWithNullLast(string $expected, ?string $input = null): void
  189. {
  190. $this->fixer->configure([
  191. 'sort_algorithm' => 'none',
  192. 'null_adjustment' => 'always_last',
  193. ]);
  194. $this->doTest($expected, $input);
  195. }
  196. /**
  197. * @return iterable<array{0: string, 1?: string}>
  198. */
  199. public static function provideFixWithNullLastCases(): iterable
  200. {
  201. yield [
  202. '<?php /** @var string|null */',
  203. '<?php /** @var null|string */',
  204. ];
  205. yield [
  206. '<?php /** @param string|null $foo */',
  207. '<?php /** @param null|string $foo */',
  208. ];
  209. yield [
  210. '<?php /** @property string|null $foo */',
  211. '<?php /** @property null|string $foo */',
  212. ];
  213. yield [
  214. '<?php /** @property-read string|null $foo */',
  215. '<?php /** @property-read null|string $foo */',
  216. ];
  217. yield [
  218. '<?php /** @property-write string|null $foo */',
  219. '<?php /** @property-write null|string $foo */',
  220. ];
  221. yield [
  222. '<?php /** @method string|null foo(int|null $foo, string|null $bar) */',
  223. '<?php /** @method null|string foo(null|int $foo, null|string $bar) */',
  224. ];
  225. yield [
  226. '<?php /** @return string|null */',
  227. '<?php /** @return null|string */',
  228. ];
  229. yield [
  230. '<?php /** @var string[]|resource|false|object|Foo|Bar\Baz|bool[]|string|array|int|null */',
  231. '<?php /** @var string[]|resource|false|object|null|Foo|Bar\Baz|bool[]|string|array|int */',
  232. ];
  233. yield [
  234. '<?php /** @var array<int, string>|null Foo */',
  235. '<?php /** @var null|array<int, string> Foo */',
  236. ];
  237. yield [
  238. '<?php /** @var array<int, array<string>>|null Foo */',
  239. '<?php /** @var null|array<int, array<string>> Foo */',
  240. ];
  241. yield [
  242. '<?php /** @var string|NULL */',
  243. '<?php /** @var NULL|string */',
  244. ];
  245. yield [
  246. '<?php /** @var Foo|?Bar */',
  247. ];
  248. yield [
  249. '<?php /** @var ?Foo|Bar */',
  250. ];
  251. yield [
  252. '<?php /** @var Foo|?\Bar */',
  253. ];
  254. yield [
  255. '<?php /** @var ?\Foo|Bar */',
  256. ];
  257. yield [
  258. '<?php /** @var array<string|null> */',
  259. '<?php /** @var array<null|string> */',
  260. ];
  261. yield [
  262. '<?php /** @var array<int, string|null> */',
  263. '<?php /** @var array<int, null|string> */',
  264. ];
  265. yield [
  266. '<?php /** @var array<int, array<int|string|null>> */',
  267. '<?php /** @var array<int, array<null|int|string>> */',
  268. ];
  269. yield [
  270. '<?php /** @var null|null */',
  271. ];
  272. yield [
  273. '<?php /** @var null|\null */',
  274. ];
  275. yield [
  276. '<?php /** @var \null|null */',
  277. ];
  278. yield [
  279. '<?php /** @var \null|\null */',
  280. ];
  281. yield [
  282. '<?php /** @var int|\null */',
  283. '<?php /** @var \null|int */',
  284. ];
  285. yield [
  286. '<?php /** @var array<int|\null> */',
  287. '<?php /** @var array<\null|int> */',
  288. ];
  289. yield [
  290. '<?php /** @var array<int, array<int, array<int, array<int, array<OutputInterface|null>>>>> */',
  291. '<?php /** @var array<int, array<int, array<int, array<int, array<null|OutputInterface>>>>> */',
  292. ];
  293. yield [
  294. '<?php /** @var Foo[]|Foo|Foo\Bar|Foo_Bar|null */',
  295. '<?php /** @var Foo[]|null|Foo|Foo\Bar|Foo_Bar */',
  296. ];
  297. yield [
  298. '<?php /** @return array<int, callable(array<string, string|null> , DateTime): bool> */',
  299. '<?php /** @return array<int, callable(array<string, null|string> , DateTime): bool> */',
  300. ];
  301. }
  302. /**
  303. * @dataProvider provideFixWithAlphaAlgorithmCases
  304. */
  305. public function testFixWithAlphaAlgorithm(string $expected, ?string $input = null): void
  306. {
  307. $this->fixer->configure([
  308. 'sort_algorithm' => 'alpha',
  309. 'null_adjustment' => 'none',
  310. ]);
  311. $this->doTest($expected, $input);
  312. }
  313. /**
  314. * @return iterable<array{0: string, 1?: string}>
  315. */
  316. public static function provideFixWithAlphaAlgorithmCases(): iterable
  317. {
  318. yield [
  319. '<?php /** @var int|null|string */',
  320. '<?php /** @var string|int|null */',
  321. ];
  322. yield [
  323. '<?php /** @param Bar|\Foo */',
  324. '<?php /** @param \Foo|Bar */',
  325. ];
  326. yield [
  327. '<?php /** @property-read \Bar|Foo */',
  328. '<?php /** @property-read Foo|\Bar */',
  329. ];
  330. yield [
  331. '<?php /** @property-write bar|Foo */',
  332. '<?php /** @property-write Foo|bar */',
  333. ];
  334. yield [
  335. '<?php /** @return Bar|foo */',
  336. '<?php /** @return foo|Bar */',
  337. ];
  338. yield [
  339. '<?php /** @method \Bar|Foo foo(\Bar|Foo $foo, \Bar|Foo $bar) */',
  340. '<?php /** @method Foo|\Bar foo(Foo|\Bar $foo, Foo|\Bar $bar) */',
  341. ];
  342. yield [
  343. '<?php /** @var array|Bar\Baz|bool[]|false|Foo|int|null|object|resource|string|string[] */',
  344. '<?php /** @var string[]|resource|false|object|null|Foo|Bar\Baz|bool[]|string|array|int */',
  345. ];
  346. yield [
  347. '<?php /** @var array<int, string>|null Foo */',
  348. '<?php /** @var null|array<int, string> Foo */',
  349. ];
  350. yield [
  351. '<?php /** @var array<int, array<string>>|null Foo */',
  352. '<?php /** @var null|array<int, array<string>> Foo */',
  353. ];
  354. yield [
  355. '<?php /** @var ?Bar|Foo */',
  356. '<?php /** @var Foo|?Bar */',
  357. ];
  358. yield [
  359. '<?php /** @var Bar|?Foo */',
  360. '<?php /** @var ?Foo|Bar */',
  361. ];
  362. yield [
  363. '<?php /** @var ?\Bar|Foo */',
  364. '<?php /** @var Foo|?\Bar */',
  365. ];
  366. yield [
  367. '<?php /** @var Bar|?\Foo */',
  368. '<?php /** @var ?\Foo|Bar */',
  369. ];
  370. yield [
  371. '<?php /** @var array<null|string> */',
  372. '<?php /** @var array<string|null> */',
  373. ];
  374. yield [
  375. '<?php /** @var array<int|string, null|string> */',
  376. '<?php /** @var array<string|int, string|null> */',
  377. ];
  378. yield [
  379. '<?php /** @var array<int|string, array<int|string, null|string>> */',
  380. '<?php /** @var array<string|int, array<string|int, string|null>> */',
  381. ];
  382. yield [
  383. '<?php /** @var null|null */',
  384. ];
  385. yield [
  386. '<?php /** @var null|\null */',
  387. ];
  388. yield [
  389. '<?php /** @var \null|null */',
  390. ];
  391. yield [
  392. '<?php /** @var \null|\null */',
  393. ];
  394. yield [
  395. '<?php /** @var int|\null|string */',
  396. '<?php /** @var string|\null|int */',
  397. ];
  398. yield [
  399. '<?php /** @var array<int|\null|string> */',
  400. '<?php /** @var array<string|\null|int> */',
  401. ];
  402. yield [
  403. '<?php /** @var array<int, array<int, array<int, array<int, array<null|OutputInterface>>>>> */',
  404. '<?php /** @var array<int, array<int, array<int, array<int, array<OutputInterface|null>>>>> */',
  405. ];
  406. yield [
  407. '<?php /** @var Foo|Foo[]|Foo\Bar|Foo_Bar|null */',
  408. '<?php /** @var Foo[]|null|Foo|Foo\Bar|Foo_Bar */',
  409. ];
  410. yield [
  411. '<?php /** @return array<int, callable(array<string, null|string> , DateTime): bool> */',
  412. ];
  413. yield [
  414. '<?php /** @return A&B&C */',
  415. '<?php /** @return A&C&B */',
  416. ];
  417. yield [
  418. '<?php /** @return array<A&B&C> */',
  419. '<?php /** @return array<A&C&B> */',
  420. ];
  421. yield [
  422. '<?php /** @return array<A&B&C>|bool|string */',
  423. '<?php /** @return bool|array<A&B&C>|string */',
  424. ];
  425. yield [
  426. '<?php /** @return A&B<X|Y|Z>&C&D */',
  427. '<?php /** @return A&D&B<X|Y|Z>&C */',
  428. ];
  429. yield [
  430. '<?php /** @param A|(B&C) */',
  431. '<?php /** @param (C&B)|A */',
  432. ];
  433. yield [
  434. '<?php /** @param A|((A&B)|(B&C)) */',
  435. '<?php /** @param ((B&C)|(B&A))|A */',
  436. ];
  437. yield [
  438. '<?php /** @param A&(B&C) */',
  439. '<?php /** @param (C&B)&A */',
  440. ];
  441. yield [
  442. '<?php /** @param (A&C)|(B&C)|(C&D) */',
  443. '<?php /** @param (C&A)|(C&B)|(C&D) */',
  444. ];
  445. yield [
  446. '<?php /** @param \A|(\B&\C)|D */',
  447. '<?php /** @param D|\A|(\C&\B) */',
  448. ];
  449. yield [
  450. '<?php /** @param A|((B&C)|D) */',
  451. '<?php /** @param (D|(C&B))|A */',
  452. ];
  453. yield [
  454. '<?php /** @var Closure<T>(T): T|null|string */',
  455. '<?php /** @var string|Closure<T>(T): T|null */',
  456. ];
  457. yield [
  458. '<?php /** @var \Closure<T of Model, T2, T3>(A|T, T3, T2): (T|T2)|null|string */',
  459. '<?php /** @var string|\Closure<T of Model, T2, T3>(T|A, T3, T2): (T2|T)|null */',
  460. ];
  461. yield [
  462. '<?php /** @var Closure<Closure_can_be_regular_class>|null|string */',
  463. '<?php /** @var string|Closure<Closure_can_be_regular_class>|null */',
  464. ];
  465. }
  466. /**
  467. * @dataProvider provideFixWithAlphaAlgorithmAndNullAlwaysFirstCases
  468. */
  469. public function testFixWithAlphaAlgorithmAndNullAlwaysFirst(string $expected, ?string $input = null): void
  470. {
  471. $this->fixer->configure([
  472. 'sort_algorithm' => 'alpha',
  473. 'null_adjustment' => 'always_first',
  474. ]);
  475. $this->doTest($expected, $input);
  476. }
  477. /**
  478. * @return iterable<array{0: string, 1?: string}>
  479. */
  480. public static function provideFixWithAlphaAlgorithmAndNullAlwaysFirstCases(): iterable
  481. {
  482. yield [
  483. '<?php /** @var null|int|string */',
  484. '<?php /** @var string|int|null */',
  485. ];
  486. yield [
  487. '<?php /** @param Bar|\Foo */',
  488. '<?php /** @param \Foo|Bar */',
  489. ];
  490. yield [
  491. '<?php /** @property-read \Bar|Foo */',
  492. '<?php /** @property-read Foo|\Bar */',
  493. ];
  494. yield [
  495. '<?php /** @property-write bar|Foo */',
  496. '<?php /** @property-write Foo|bar */',
  497. ];
  498. yield [
  499. '<?php /** @return Bar|foo */',
  500. '<?php /** @return foo|Bar */',
  501. ];
  502. yield [
  503. '<?php /** @method \Bar|Foo foo(\Bar|Foo $foo, \Bar|Foo $bar) */',
  504. '<?php /** @method Foo|\Bar foo(Foo|\Bar $foo, Foo|\Bar $bar) */',
  505. ];
  506. yield [
  507. '<?php /** @var null|array|Bar\Baz|bool[]|false|Foo|int|object|resource|string|string[] */',
  508. '<?php /** @var string[]|resource|false|object|null|Foo|Bar\Baz|bool[]|string|array|int */',
  509. ];
  510. yield [
  511. '<?php /** @var null|array<int, string> Foo */',
  512. ];
  513. yield [
  514. '<?php /** @var null|array<int, array<string>> Foo */',
  515. ];
  516. yield [
  517. '<?php /** @var NULL|int|string */',
  518. '<?php /** @var string|int|NULL */',
  519. ];
  520. yield [
  521. '<?php /** @var ?Bar|Foo */',
  522. '<?php /** @var Foo|?Bar */',
  523. ];
  524. yield [
  525. '<?php /** @var Bar|?Foo */',
  526. '<?php /** @var ?Foo|Bar */',
  527. ];
  528. yield [
  529. '<?php /** @var ?\Bar|Foo */',
  530. '<?php /** @var Foo|?\Bar */',
  531. ];
  532. yield [
  533. '<?php /** @var Bar|?\Foo */',
  534. '<?php /** @var ?\Foo|Bar */',
  535. ];
  536. yield [
  537. '<?php /** @var array<null|int|string> */',
  538. '<?php /** @var array<string|int|null> */',
  539. ];
  540. yield [
  541. '<?php /** @var array<int|string, null|int|string> */',
  542. '<?php /** @var array<string|int, string|int|null> */',
  543. ];
  544. yield [
  545. '<?php /** @var array<int|string, array<int|string, null|int|string>> */',
  546. '<?php /** @var array<string|int, array<string|int, string|int|null>> */',
  547. ];
  548. yield [
  549. '<?php /** @var null|null */',
  550. ];
  551. yield [
  552. '<?php /** @var null|\null */',
  553. ];
  554. yield [
  555. '<?php /** @var \null|null */',
  556. ];
  557. yield [
  558. '<?php /** @var \null|\null */',
  559. ];
  560. yield [
  561. '<?php /** @var array<\null|int|string> */',
  562. '<?php /** @var array<string|\null|int> */',
  563. ];
  564. yield [
  565. '<?php /** @var array<int, array<int, array<int, array<int, array<null|OutputInterface>>>>> */',
  566. '<?php /** @var array<int, array<int, array<int, array<int, array<OutputInterface|null>>>>> */',
  567. ];
  568. yield [
  569. '<?php /** @var null|Foo|Foo[]|Foo\Bar|Foo_Bar */',
  570. '<?php /** @var Foo[]|null|Foo|Foo\Bar|Foo_Bar */',
  571. ];
  572. yield [
  573. '<?php /** @return array<array<string, int>> */',
  574. ];
  575. yield [
  576. '<?php /** @return array<int, callable(array<string, null|string> , DateTime): bool> */',
  577. ];
  578. }
  579. /**
  580. * @dataProvider provideFixWithAlphaAlgorithmAndNullAlwaysLastCases
  581. */
  582. public function testFixWithAlphaAlgorithmAndNullAlwaysLast(string $expected, ?string $input = null): void
  583. {
  584. $this->fixer->configure([
  585. 'sort_algorithm' => 'alpha',
  586. 'null_adjustment' => 'always_last',
  587. ]);
  588. $this->doTest($expected, $input);
  589. }
  590. /**
  591. * @return iterable<array{0: string, 1?: string}>
  592. */
  593. public static function provideFixWithAlphaAlgorithmAndNullAlwaysLastCases(): iterable
  594. {
  595. yield [
  596. '<?php /** @var int|string|null */',
  597. '<?php /** @var string|int|null */',
  598. ];
  599. yield [
  600. '<?php /** @param Bar|\Foo */',
  601. '<?php /** @param \Foo|Bar */',
  602. ];
  603. yield [
  604. '<?php /** @property-read \Bar|Foo */',
  605. '<?php /** @property-read Foo|\Bar */',
  606. ];
  607. yield [
  608. '<?php /** @property-write bar|Foo */',
  609. '<?php /** @property-write Foo|bar */',
  610. ];
  611. yield [
  612. '<?php /** @return Bar|foo */',
  613. '<?php /** @return foo|Bar */',
  614. ];
  615. yield [
  616. '<?php /** @method \Bar|Foo foo(\Bar|Foo $foo, \Bar|Foo $bar) */',
  617. '<?php /** @method Foo|\Bar foo(Foo|\Bar $foo, Foo|\Bar $bar) */',
  618. ];
  619. yield [
  620. '<?php /** @var array|Bar\Baz|bool[]|false|Foo|int|object|resource|string|string[]|null */',
  621. '<?php /** @var string[]|resource|false|object|null|Foo|Bar\Baz|bool[]|string|array|int */',
  622. ];
  623. yield [
  624. '<?php /** @var array<int, string>|null Foo */',
  625. '<?php /** @var null|array<int, string> Foo */',
  626. ];
  627. yield [
  628. '<?php /** @var array<int, array<string>>|null Foo */',
  629. '<?php /** @var null|array<int, array<string>> Foo */',
  630. ];
  631. yield [
  632. '<?php /** @var int|string|NULL */',
  633. '<?php /** @var string|int|NULL */',
  634. ];
  635. yield [
  636. '<?php /** @var ?Bar|Foo */',
  637. '<?php /** @var Foo|?Bar */',
  638. ];
  639. yield [
  640. '<?php /** @var Bar|?Foo */',
  641. '<?php /** @var ?Foo|Bar */',
  642. ];
  643. yield [
  644. '<?php /** @var ?\Bar|Foo */',
  645. '<?php /** @var Foo|?\Bar */',
  646. ];
  647. yield [
  648. '<?php /** @var Bar|?\Foo */',
  649. '<?php /** @var ?\Foo|Bar */',
  650. ];
  651. yield [
  652. '<?php /** @var array<int|string|null> */',
  653. '<?php /** @var array<string|int|null> */',
  654. ];
  655. yield [
  656. '<?php /** @var array<int|string, int|string|null> */',
  657. '<?php /** @var array<string|int, string|int|null> */',
  658. ];
  659. yield [
  660. '<?php /** @var array<int|string, array<int|string, int|string|null>> */',
  661. '<?php /** @var array<string|int, array<string|int, string|int|null>> */',
  662. ];
  663. yield [
  664. '<?php /** @var null|null */',
  665. ];
  666. yield [
  667. '<?php /** @var null|\null */',
  668. ];
  669. yield [
  670. '<?php /** @var \null|null */',
  671. ];
  672. yield [
  673. '<?php /** @var \null|\null */',
  674. ];
  675. yield [
  676. '<?php /** @var array<int|string|\null> */',
  677. '<?php /** @var array<string|\null|int> */',
  678. ];
  679. yield [
  680. '<?php /** @var array<int, array<int, array<int, array<int, array<OutputInterface|null>>>>> */',
  681. '<?php /** @var array<int, array<int, array<int, array<int, array<null|OutputInterface>>>>> */',
  682. ];
  683. yield [
  684. '<?php /** @var Foo|Foo[]|Foo\Bar|Foo_Bar|null */',
  685. '<?php /** @var Foo[]|null|Foo|Foo\Bar|Foo_Bar */',
  686. ];
  687. yield [
  688. '<?php /** @return array<int, callable(array<string, string|null> , DateTime): bool> */',
  689. '<?php /** @return array<int, callable(array<string, null|string> , DateTime): bool> */',
  690. ];
  691. yield [
  692. '<?php /** @var ?Deferred<TestLocations> */',
  693. ];
  694. }
  695. /**
  696. * @dataProvider provideFixWithCaseSensitiveCases
  697. */
  698. public function testFixWithCaseSensitive(string $expected, ?string $input = null): void
  699. {
  700. $this->fixer->configure([
  701. 'case_sensitive' => true,
  702. ]);
  703. $this->doTest($expected, $input);
  704. }
  705. /**
  706. * @return iterable<array{string, string}>
  707. */
  708. public static function provideFixWithCaseSensitiveCases(): iterable
  709. {
  710. return [
  711. [
  712. '<?php /** @var AA|Aaa */',
  713. '<?php /** @var Aaa|AA */',
  714. ],
  715. ];
  716. }
  717. }