PhpdocAlignFixerTest.php 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566
  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\ConfigurationException\InvalidFixerConfigurationException;
  14. use PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer;
  15. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  16. use PhpCsFixer\WhitespacesFixerConfig;
  17. /**
  18. * @internal
  19. *
  20. * @covers \PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer
  21. *
  22. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer>
  23. *
  24. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer
  25. */
  26. final class PhpdocAlignFixerTest extends AbstractFixerTestCase
  27. {
  28. /**
  29. * @dataProvider provideFixCases
  30. *
  31. * @param _AutogeneratedInputConfiguration $configuration
  32. */
  33. public function testFix(
  34. array $configuration,
  35. string $expected,
  36. ?string $input = null,
  37. ?WhitespacesFixerConfig $whitespacesFixerConfig = null
  38. ): void {
  39. $this->fixer->configure($configuration);
  40. if (null !== $whitespacesFixerConfig) {
  41. $this->fixer->setWhitespacesConfig($whitespacesFixerConfig);
  42. }
  43. $this->doTest($expected, $input);
  44. }
  45. public static function provideFixCases(): iterable
  46. {
  47. yield 'none, one and four spaces between type and variable' => [
  48. ['tags' => ['param']],
  49. '<?php
  50. /**
  51. * @param int $a
  52. * @param int $b
  53. * @param int $c
  54. */',
  55. '<?php
  56. /**
  57. * @param int $a
  58. * @param int $b
  59. * @param int$c
  60. */',
  61. ];
  62. yield 'aligning params' => [
  63. ['tags' => ['param']],
  64. '<?php
  65. /**
  66. * @param EngineInterface $templating
  67. * @param string $format
  68. * @param int $code An HTTP response status code
  69. * @param bool $debug
  70. * @param mixed &$reference A parameter passed by reference
  71. */
  72. ',
  73. '<?php
  74. /**
  75. * @param EngineInterface $templating
  76. * @param string $format
  77. * @param int $code An HTTP response status code
  78. * @param bool $debug
  79. * @param mixed &$reference A parameter passed by reference
  80. */
  81. ',
  82. ];
  83. yield 'left align' => [
  84. ['tags' => ['param'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  85. '<?php
  86. /**
  87. * @param EngineInterface $templating
  88. * @param string $format
  89. * @param int $code An HTTP response status code
  90. * @param bool $debug
  91. * @param mixed &$reference A parameter passed by reference
  92. */
  93. ',
  94. '<?php
  95. /**
  96. * @param EngineInterface $templating
  97. * @param string $format
  98. * @param int $code An HTTP response status code
  99. * @param bool $debug
  100. * @param mixed &$reference A parameter passed by reference
  101. */
  102. ',
  103. ];
  104. yield 'partially untyped' => [
  105. ['tags' => ['param']],
  106. '<?php
  107. /**
  108. * @param $id
  109. * @param $parentId
  110. * @param int $websiteId
  111. * @param $position
  112. * @param int[][] $siblings
  113. */
  114. ',
  115. '<?php
  116. /**
  117. * @param $id
  118. * @param $parentId
  119. * @param int $websiteId
  120. * @param $position
  121. * @param int[][] $siblings
  122. */
  123. ',
  124. ];
  125. yield 'partially untyped left align' => [
  126. ['tags' => ['param'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  127. '<?php
  128. /**
  129. * @param $id
  130. * @param $parentId
  131. * @param int $websiteId
  132. * @param $position
  133. * @param int[][] $siblings
  134. */
  135. ',
  136. '<?php
  137. /**
  138. * @param $id
  139. * @param $parentId
  140. * @param int $websiteId
  141. * @param $position
  142. * @param int[][] $siblings
  143. */
  144. ',
  145. ];
  146. yield 'multiline description' => [
  147. ['tags' => ['param', 'property', 'method']],
  148. '<?php
  149. /**
  150. * @param EngineInterface $templating
  151. * @param string $format
  152. * @param int $code An HTTP response status code
  153. * See constants
  154. * @param bool $debug
  155. * @param bool $debug See constants
  156. * See constants
  157. * @param mixed &$reference A parameter passed by reference
  158. * @property mixed $foo A foo
  159. * See constants
  160. * @method static baz($bop) A method that does a thing
  161. * It does it well
  162. */
  163. ',
  164. '<?php
  165. /**
  166. * @param EngineInterface $templating
  167. * @param string $format
  168. * @param int $code An HTTP response status code
  169. * See constants
  170. * @param bool $debug
  171. * @param bool $debug See constants
  172. * See constants
  173. * @param mixed &$reference A parameter passed by reference
  174. * @property mixed $foo A foo
  175. * See constants
  176. * @method static baz($bop) A method that does a thing
  177. * It does it well
  178. */
  179. ',
  180. ];
  181. yield 'multiline description left align' => [
  182. ['tags' => ['param', 'property', 'method'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  183. '<?php
  184. /**
  185. * @param EngineInterface $templating
  186. * @param string $format
  187. * @param int $code An HTTP response status code
  188. * See constants
  189. * @param bool $debug
  190. * @param bool $debug See constants
  191. * See constants
  192. * @param mixed &$reference A parameter passed by reference
  193. * @property mixed $foo A foo
  194. * See constants
  195. * @method static baz($bop) A method that does a thing
  196. * It does it well
  197. */
  198. ',
  199. '<?php
  200. /**
  201. * @param EngineInterface $templating
  202. * @param string $format
  203. * @param int $code An HTTP response status code
  204. * See constants
  205. * @param bool $debug
  206. * @param bool $debug See constants
  207. * See constants
  208. * @param mixed &$reference A parameter passed by reference
  209. * @property mixed $foo A foo
  210. * See constants
  211. * @method static baz($bop) A method that does a thing
  212. * It does it well
  213. */
  214. ',
  215. ];
  216. yield 'multiline description with throws' => [
  217. ['tags' => ['param', 'return', 'throws']],
  218. '<?php
  219. /**
  220. * @param EngineInterface $templating
  221. * @param string $format
  222. * @param int $code An HTTP response status code
  223. * See constants
  224. * @param bool $debug
  225. * @param bool $debug See constants
  226. * See constants
  227. * @param mixed &$reference A parameter passed by reference
  228. *
  229. * @return Foo description foo
  230. *
  231. * @throws Foo description foo
  232. * description foo
  233. */
  234. ',
  235. '<?php
  236. /**
  237. * @param EngineInterface $templating
  238. * @param string $format
  239. * @param int $code An HTTP response status code
  240. * See constants
  241. * @param bool $debug
  242. * @param bool $debug See constants
  243. * See constants
  244. * @param mixed &$reference A parameter passed by reference
  245. *
  246. * @return Foo description foo
  247. *
  248. * @throws Foo description foo
  249. * description foo
  250. */
  251. ',
  252. ];
  253. yield 'multiline description with throws left align' => [
  254. ['tags' => ['param', 'return', 'throws'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  255. '<?php
  256. /**
  257. * @param EngineInterface $templating
  258. * @param string $format
  259. * @param int $code An HTTP response status code
  260. * See constants
  261. * @param bool $debug
  262. * @param bool $debug See constants
  263. * See constants
  264. * @param mixed &$reference A parameter passed by reference
  265. *
  266. * @return Foo description foo
  267. *
  268. * @throws Foo description foo
  269. * description foo
  270. */
  271. ',
  272. '<?php
  273. /**
  274. * @param EngineInterface $templating
  275. * @param string $format
  276. * @param int $code An HTTP response status code
  277. * See constants
  278. * @param bool $debug
  279. * @param bool $debug See constants
  280. * See constants
  281. * @param mixed &$reference A parameter passed by reference
  282. *
  283. * @return Foo description foo
  284. *
  285. * @throws Foo description foo
  286. * description foo
  287. */
  288. ',
  289. ];
  290. yield 'return and throws' => [
  291. ['tags' => ['param', 'throws', 'return']],
  292. '<?php
  293. /**
  294. * @param EngineInterface $templating
  295. * @param mixed &$reference A parameter passed by reference
  296. * Multiline description
  297. * @throws Bar description bar
  298. * @return Foo description foo
  299. * multiline description
  300. */
  301. ',
  302. '<?php
  303. /**
  304. * @param EngineInterface $templating
  305. * @param mixed &$reference A parameter passed by reference
  306. * Multiline description
  307. * @throws Bar description bar
  308. * @return Foo description foo
  309. * multiline description
  310. */
  311. ',
  312. ];
  313. // https://github.com/FriendsOfPhp/PHP-CS-Fixer/issues/55
  314. yield 'three params with return' => [
  315. ['tags' => ['param', 'return']],
  316. '<?php
  317. /**
  318. * @param string $param1
  319. * @param bool $param2 lorem ipsum
  320. * @param string $param3 lorem ipsum
  321. * @return int lorem ipsum
  322. */
  323. ',
  324. '<?php
  325. /**
  326. * @param string $param1
  327. * @param bool $param2 lorem ipsum
  328. * @param string $param3 lorem ipsum
  329. * @return int lorem ipsum
  330. */
  331. ',
  332. ];
  333. yield 'only return' => [
  334. ['tags' => ['return']],
  335. '<?php
  336. /**
  337. * @return Foo description foo
  338. */
  339. ',
  340. '<?php
  341. /**
  342. * @return Foo description foo
  343. */
  344. ',
  345. ];
  346. yield 'return with $this' => [
  347. ['tags' => ['param', 'return']],
  348. '<?php
  349. /**
  350. * @param Foo $foo
  351. * @return $this
  352. */
  353. ',
  354. '<?php
  355. /**
  356. * @param Foo $foo
  357. * @return $this
  358. */
  359. ',
  360. ];
  361. yield 'custom annotations stay untouched' => [
  362. ['tags' => ['return']],
  363. '<?php
  364. /**
  365. * @return string
  366. * @SuppressWarnings(PHPMD.UnusedLocalVariable)
  367. */
  368. ',
  369. '<?php
  370. /**
  371. * @return string
  372. * @SuppressWarnings(PHPMD.UnusedLocalVariable)
  373. */
  374. ',
  375. ];
  376. yield 'custom annotations stay untouched 2' => [
  377. ['tags' => ['var']],
  378. '<?php
  379. class X
  380. {
  381. /**
  382. * @var Collection<Value>|Value[]
  383. * @ORM\ManyToMany(
  384. * targetEntity="\Dl\Component\DomainModel\Product\Value\AbstractValue",
  385. * inversedBy="externalAliases"
  386. * )
  387. */
  388. private $values;
  389. }
  390. ',
  391. ];
  392. yield 'left align 2' => [
  393. ['tags' => ['param'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  394. '<?php
  395. /**
  396. * @param int $a
  397. * @param string $b
  398. *
  399. * @dataProvider dataJobCreation
  400. */
  401. ',
  402. '<?php
  403. /**
  404. * @param int $a
  405. * @param string $b
  406. *
  407. * @dataProvider dataJobCreation
  408. */
  409. ',
  410. ];
  411. yield 'params and data provider' => [
  412. ['tags' => ['param']],
  413. '<?php
  414. /**
  415. * @param int $a
  416. * @param string|null $b
  417. *
  418. * @dataProvider dataJobCreation
  419. */
  420. ',
  421. '<?php
  422. /**
  423. * @param int $a
  424. * @param string|null $b
  425. *
  426. * @dataProvider dataJobCreation
  427. */
  428. ',
  429. ];
  430. yield 'var' => [
  431. ['tags' => ['var']],
  432. '<?php
  433. /**
  434. * @var Type
  435. */
  436. ',
  437. '<?php
  438. /**
  439. * @var Type
  440. */
  441. ',
  442. ];
  443. yield 'type' => [
  444. ['tags' => ['type']],
  445. '<?php
  446. /**
  447. * @type Type
  448. */
  449. ',
  450. '<?php
  451. /**
  452. * @type Type
  453. */
  454. ',
  455. ];
  456. yield 'var and description' => [
  457. ['tags' => ['var']],
  458. '<?php
  459. /**
  460. * This is a variable.
  461. *
  462. * @var Type
  463. */
  464. ',
  465. '<?php
  466. /**
  467. * This is a variable.
  468. *
  469. * @var Type
  470. */
  471. ',
  472. ];
  473. yield 'var and inline description' => [
  474. ['tags' => ['var']],
  475. '<?php
  476. /**
  477. * @var Type This is a variable.
  478. */
  479. ',
  480. '<?php
  481. /**
  482. * @var Type This is a variable.
  483. */
  484. ',
  485. ];
  486. yield 'type and inline description' => [
  487. ['tags' => ['type']],
  488. '<?php
  489. /**
  490. * @type Type This is a variable.
  491. */
  492. ',
  493. '<?php
  494. /**
  495. * @type Type This is a variable.
  496. */
  497. ',
  498. ];
  499. yield 'when we are not modifying a docblock, then line endings should not change' => [
  500. ['tags' => ['param']],
  501. "<?php\r /**\r * @param Example Hello there!\r */\r",
  502. ];
  503. yield 'malformed doc block' => [
  504. ['tags' => ['return']],
  505. '<?php
  506. /**
  507. * @return string
  508. * */
  509. ',
  510. ];
  511. yield 'different indentation' => [
  512. ['tags' => ['param', 'return']],
  513. '<?php
  514. /**
  515. * @param int $limit
  516. * @param string $more
  517. *
  518. * @return array
  519. */
  520. /**
  521. * @param int $limit
  522. * @param string $more
  523. *
  524. * @return array
  525. */
  526. ',
  527. '<?php
  528. /**
  529. * @param int $limit
  530. * @param string $more
  531. *
  532. * @return array
  533. */
  534. /**
  535. * @param int $limit
  536. * @param string $more
  537. *
  538. * @return array
  539. */
  540. ',
  541. ];
  542. yield 'different indentation left align' => [
  543. ['tags' => ['param', 'return'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  544. '<?php
  545. /**
  546. * @param int $limit
  547. * @param string $more
  548. *
  549. * @return array
  550. */
  551. /**
  552. * @param int $limit
  553. * @param string $more
  554. *
  555. * @return array
  556. */
  557. ',
  558. '<?php
  559. /**
  560. * @param int $limit
  561. * @param string $more
  562. *
  563. * @return array
  564. */
  565. /**
  566. * @param int $limit
  567. * @param string $more
  568. *
  569. * @return array
  570. */
  571. ',
  572. ];
  573. yield 'messy whitespaces 1' => [
  574. ['tags' => ['type']],
  575. "<?php\r\n\t/**\r\n\t * @type Type This is a variable.\r\n\t */",
  576. "<?php\r\n\t/**\r\n\t * @type Type This is a variable.\r\n\t */",
  577. new WhitespacesFixerConfig("\t", "\r\n"),
  578. ];
  579. yield 'messy whitespaces 2' => [
  580. ['tags' => ['param', 'return']],
  581. "<?php\r\n/**\r\n * @param int \$limit\r\n * @param string \$more\r\n *\r\n * @return array\r\n */",
  582. "<?php\r\n/**\r\n * @param int \$limit\r\n * @param string \$more\r\n *\r\n * @return array\r\n */",
  583. new WhitespacesFixerConfig("\t", "\r\n"),
  584. ];
  585. yield 'messy whitespaces 3' => [
  586. [],
  587. "<?php\r\n/**\r\n * @param int \$limit\r\n * @param string \$more\r\n *\r\n * @return array\r\n */",
  588. "<?php\r\n/**\r\n * @param int \$limit\r\n * @param string \$more\r\n *\r\n * @return array\r\n */",
  589. new WhitespacesFixerConfig("\t", "\r\n"),
  590. ];
  591. yield 'messy whitespaces 4' => [
  592. [],
  593. "<?php\n/**\n * @param int \$a\n * @param int \$b\n * ABC\n */",
  594. "<?php\n/**\n * @param int \$a\n * @param int \$b\n * ABC\n */",
  595. new WhitespacesFixerConfig(' ', "\n"),
  596. ];
  597. yield 'messy whitespaces 5' => [
  598. [],
  599. "<?php\r\n/**\r\n * @param int \$z\r\n * @param int \$b\r\n * XYZ\r\n */",
  600. "<?php\r\n/**\r\n * @param int \$z\r\n * @param int \$b\r\n * XYZ\r\n */",
  601. new WhitespacesFixerConfig(' ', "\r\n"),
  602. ];
  603. yield 'badly formatted' => [
  604. ['tags' => ['var']],
  605. "<?php\n /**\n * @var Foo */\n",
  606. ];
  607. yield 'unicode' => [
  608. ['tags' => ['param', 'return']],
  609. '<?php
  610. /**
  611. * Method test.
  612. *
  613. * @param int $foobar Description
  614. * @param string $foo Description
  615. * @param mixed $bar Description word_with_ą
  616. * @param int|null $test Description
  617. */
  618. $a = 1;
  619. /**
  620. * @return string
  621. * @SuppressWarnings(PHPMD.UnusedLocalVariable) word_with_ą
  622. */
  623. $b = 1;
  624. ',
  625. '<?php
  626. /**
  627. * Method test.
  628. *
  629. * @param int $foobar Description
  630. * @param string $foo Description
  631. * @param mixed $bar Description word_with_ą
  632. * @param int|null $test Description
  633. */
  634. $a = 1;
  635. /**
  636. * @return string
  637. * @SuppressWarnings(PHPMD.UnusedLocalVariable) word_with_ą
  638. */
  639. $b = 1;
  640. ',
  641. ];
  642. yield 'does align property by default' => [
  643. [],
  644. '<?php
  645. /**
  646. * @param int $foobar Description
  647. * @return int
  648. * @throws Exception
  649. * @var FooBar
  650. * @type BarFoo
  651. * @property string $foo Hello World
  652. */
  653. ',
  654. '<?php
  655. /**
  656. * @param int $foobar Description
  657. * @return int
  658. * @throws Exception
  659. * @var FooBar
  660. * @type BarFoo
  661. * @property string $foo Hello World
  662. */
  663. ',
  664. ];
  665. yield 'aligns property' => [
  666. ['tags' => ['param', 'property', 'return', 'throws', 'type', 'var']],
  667. '<?php
  668. /**
  669. * @param int $foobar Description
  670. * @return int
  671. * @throws Exception
  672. * @var FooBar
  673. * @type BarFoo
  674. * @property string $foo Hello World
  675. */
  676. ',
  677. '<?php
  678. /**
  679. * @param int $foobar Description
  680. * @return int
  681. * @throws Exception
  682. * @var FooBar
  683. * @type BarFoo
  684. * @property string $foo Hello World
  685. */
  686. ',
  687. ];
  688. yield 'does align method by default' => [
  689. [],
  690. '<?php
  691. /**
  692. * @param int $foobar Description
  693. * @return int
  694. * @throws Exception
  695. * @var FooBar
  696. * @type BarFoo
  697. * @method string foo(string $bar) Hello World
  698. */
  699. ',
  700. '<?php
  701. /**
  702. * @param int $foobar Description
  703. * @return int
  704. * @throws Exception
  705. * @var FooBar
  706. * @type BarFoo
  707. * @method string foo(string $bar) Hello World
  708. */
  709. ',
  710. ];
  711. yield 'aligns method' => [
  712. ['tags' => ['param', 'method', 'return', 'throws', 'type', 'var']],
  713. '<?php
  714. /**
  715. * @param int $foobar Description
  716. * @return int
  717. * @throws Exception
  718. * @var FooBar
  719. * @type BarFoo
  720. * @method int foo(string $bar, string ...$things, int &$baz) Description
  721. */
  722. ',
  723. '<?php
  724. /**
  725. * @param int $foobar Description
  726. * @return int
  727. * @throws Exception
  728. * @var FooBar
  729. * @type BarFoo
  730. * @method int foo(string $bar, string ...$things, int &$baz) Description
  731. */
  732. ',
  733. ];
  734. yield 'aligns method without parameters' => [
  735. ['tags' => ['method', 'property']],
  736. '<?php
  737. /**
  738. * @property string $foo Desc
  739. * @method int foo() Description
  740. */
  741. ',
  742. '<?php
  743. /**
  744. * @property string $foo Desc
  745. * @method int foo() Description
  746. */
  747. ',
  748. ];
  749. yield 'aligns method without parameters left align' => [
  750. ['tags' => ['method', 'property'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  751. '<?php
  752. /**
  753. * @property string $foo Desc
  754. * @method int foo() Description
  755. */
  756. ',
  757. '<?php
  758. /**
  759. * @property string $foo Desc
  760. * @method int foo() Description
  761. */
  762. ',
  763. ];
  764. yield 'does not format method' => [
  765. ['tags' => ['method']],
  766. '<?php
  767. /**
  768. * @method int foo( string $bar ) Description
  769. */
  770. ',
  771. ];
  772. yield 'aligns method without return type' => [
  773. ['tags' => ['method', 'property']],
  774. '<?php
  775. /**
  776. * @property string $foo Desc
  777. * @method int foo() Description
  778. * @method bar() Descrip
  779. */
  780. ',
  781. '<?php
  782. /**
  783. * @property string $foo Desc
  784. * @method int foo() Description
  785. * @method bar() Descrip
  786. */
  787. ',
  788. ];
  789. yield 'aligns methods without return type' => [
  790. ['tags' => ['method']],
  791. '<?php
  792. /**
  793. * @method fooBaz() Description
  794. * @method bar(string $foo) Descrip
  795. */
  796. ',
  797. '<?php
  798. /**
  799. * @method fooBaz() Description
  800. * @method bar(string $foo) Descrip
  801. */
  802. ',
  803. ];
  804. yield 'aligns static and non-static methods' => [
  805. ['tags' => ['method', 'property']],
  806. '<?php
  807. /**
  808. * @property string $foo Desc1
  809. * @property int $bar Desc2
  810. * @method foo(string $foo) DescriptionFoo
  811. * @method static bar(string $foo) DescriptionBar
  812. * @method string|null baz(bool $baz) DescriptionBaz
  813. * @method static int|false qux(float $qux) DescriptionQux
  814. * @method static static quux(int $quux) DescriptionQuux
  815. * @method static $this quuz(bool $quuz) DescriptionQuuz
  816. */
  817. ',
  818. '<?php
  819. /**
  820. * @property string $foo Desc1
  821. * @property int $bar Desc2
  822. * @method foo(string $foo) DescriptionFoo
  823. * @method static bar(string $foo) DescriptionBar
  824. * @method string|null baz(bool $baz) DescriptionBaz
  825. * @method static int|false qux(float $qux) DescriptionQux
  826. * @method static static quux(int $quux) DescriptionQuux
  827. * @method static $this quuz(bool $quuz) DescriptionQuuz
  828. */
  829. ',
  830. ];
  831. yield 'aligns static and non-static methods left align' => [
  832. ['tags' => ['method', 'property'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  833. '<?php
  834. /**
  835. * @property string $foo Desc1
  836. * @property int $bar Desc2
  837. * @method foo(string $foo) DescriptionFoo
  838. * @method static bar(string $foo) DescriptionBar
  839. * @method string|null baz(bool $baz) DescriptionBaz
  840. * @method static int|false qux(float $qux) DescriptionQux
  841. * @method static static quux(int $quux) DescriptionQuux
  842. * @method static $this quuz(bool $quuz) DescriptionQuuz
  843. */
  844. ',
  845. '<?php
  846. /**
  847. * @property string $foo Desc1
  848. * @property int $bar Desc2
  849. * @method foo(string $foo) DescriptionFoo
  850. * @method static bar(string $foo) DescriptionBar
  851. * @method string|null baz(bool $baz) DescriptionBaz
  852. * @method static int|false qux(float $qux) DescriptionQux
  853. * @method static static quux(int $quux) DescriptionQuux
  854. * @method static $this quuz(bool $quuz) DescriptionQuuz
  855. */
  856. ',
  857. ];
  858. yield 'aligns return static' => [
  859. ['tags' => ['param', 'return', 'throws']],
  860. '<?php
  861. /**
  862. * @param string $foobar Desc1
  863. * @param int &$baz Desc2
  864. * @param ?Qux $qux Desc3
  865. * @param int|float $quux Desc4
  866. * @return static DescriptionReturn
  867. * @throws Exception DescriptionException
  868. */
  869. ',
  870. '<?php
  871. /**
  872. * @param string $foobar Desc1
  873. * @param int &$baz Desc2
  874. * @param ?Qux $qux Desc3
  875. * @param int|float $quux Desc4
  876. * @return static DescriptionReturn
  877. * @throws Exception DescriptionException
  878. */
  879. ',
  880. ];
  881. yield 'aligns return static left align' => [
  882. ['tags' => ['param', 'return', 'throws'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  883. '<?php
  884. /**
  885. * @param string $foobar Desc1
  886. * @param int &$baz Desc2
  887. * @param ?Qux $qux Desc3
  888. * @param int|float $quux Desc4
  889. * @return static DescriptionReturn
  890. * @throws Exception DescriptionException
  891. */
  892. ',
  893. '<?php
  894. /**
  895. * @param string $foobar Desc1
  896. * @param int &$baz Desc2
  897. * @param ?Qux $qux Desc3
  898. * @param int|float $quux Desc4
  899. * @return static DescriptionReturn
  900. * @throws Exception DescriptionException
  901. */
  902. ',
  903. ];
  904. yield 'does not align with empty config' => [
  905. ['tags' => []],
  906. '<?php
  907. /**
  908. * @param int $foobar Description
  909. * @return int
  910. * @throws Exception
  911. * @var FooBar
  912. * @type BarFoo
  913. * @property string $foo Hello World
  914. * @method int bar() Description
  915. */
  916. ',
  917. ];
  918. yield 'variadic params 1' => [
  919. ['tags' => ['param']],
  920. '<?php
  921. final class Sample
  922. {
  923. /**
  924. * @param int[] $a A
  925. * @param int &$b B
  926. * @param array ...$c C
  927. */
  928. public function sample2($a, &$b, ...$c)
  929. {
  930. }
  931. }
  932. ',
  933. '<?php
  934. final class Sample
  935. {
  936. /**
  937. * @param int[] $a A
  938. * @param int &$b B
  939. * @param array ...$c C
  940. */
  941. public function sample2($a, &$b, ...$c)
  942. {
  943. }
  944. }
  945. ',
  946. ];
  947. yield 'variadic params 2' => [
  948. ['tags' => ['param']],
  949. '<?php
  950. final class Sample
  951. {
  952. /**
  953. * @param int $a
  954. * @param int $b
  955. * @param array[] ...$c
  956. */
  957. public function sample2($a, $b, ...$c)
  958. {
  959. }
  960. }
  961. ',
  962. '<?php
  963. final class Sample
  964. {
  965. /**
  966. * @param int $a
  967. * @param int $b
  968. * @param array[] ...$c
  969. */
  970. public function sample2($a, $b, ...$c)
  971. {
  972. }
  973. }
  974. ',
  975. ];
  976. yield 'variadic params 3' => [
  977. ['tags' => ['param'], 'align' => PhpdocAlignFixer::ALIGN_LEFT],
  978. '<?php
  979. final class Sample
  980. {
  981. /**
  982. * @param int $a
  983. * @param int $b
  984. * @param array[] ...$c
  985. */
  986. public function sample2($a, $b, ...$c)
  987. {
  988. }
  989. }
  990. ',
  991. '<?php
  992. final class Sample
  993. {
  994. /**
  995. * @param int $a
  996. * @param int $b
  997. * @param array[] ...$c
  998. */
  999. public function sample2($a, $b, ...$c)
  1000. {
  1001. }
  1002. }
  1003. ',
  1004. ];
  1005. yield 'variadic params 4' => [
  1006. ['tags' => ['property', 'property-read', 'property-write']],
  1007. '<?php
  1008. /**
  1009. * @property string $myMagicProperty magic property
  1010. * @property-read string $myMagicReadProperty magic read-only property
  1011. * @property-write string $myMagicWriteProperty magic write-only property
  1012. */
  1013. class Foo {}
  1014. ',
  1015. '<?php
  1016. /**
  1017. * @property string $myMagicProperty magic property
  1018. * @property-read string $myMagicReadProperty magic read-only property
  1019. * @property-write string $myMagicWriteProperty magic write-only property
  1020. */
  1021. class Foo {}
  1022. ',
  1023. ];
  1024. yield 'invalid PHPDoc 1' => [
  1025. ['tags' => ['param', 'return', 'throws', 'type', 'var']],
  1026. '<?php
  1027. /**
  1028. * @ Security("is_granted(\'CANCEL\', giftCard)")
  1029. */
  1030. ',
  1031. ];
  1032. yield 'invalid PHPDoc 2' => [
  1033. ['tags' => ['param', 'return', 'throws', 'type', 'var', 'method']],
  1034. '<?php
  1035. /**
  1036. * @ Security("is_granted(\'CANCEL\', giftCard)")
  1037. */
  1038. ',
  1039. ];
  1040. yield 'invalid PHPDoc 3' => [
  1041. ['tags' => ['param', 'return', 'throws', 'type', 'var']],
  1042. '<?php
  1043. /**
  1044. * @ Security("is_granted(\'CANCEL\', giftCard)")
  1045. * @ foo bar
  1046. * @ foo
  1047. */
  1048. ',
  1049. ];
  1050. yield 'types containing callables' => [
  1051. [],
  1052. '<?php
  1053. /**
  1054. * @param callable(Foo): Bar $x Description
  1055. * @param callable(FooFoo): BarBar $yy Description
  1056. */
  1057. ',
  1058. '<?php
  1059. /**
  1060. * @param callable(Foo): Bar $x Description
  1061. * @param callable(FooFoo): BarBar $yy Description
  1062. */
  1063. ',
  1064. ];
  1065. yield 'types containing whitespace' => [
  1066. [],
  1067. '<?php
  1068. /**
  1069. * @var int $key
  1070. * @var iterable<int, string> $value
  1071. */
  1072. /**
  1073. * @param array<int, $this> $arrayOfIntegers
  1074. * @param array<string, $this> $arrayOfStrings
  1075. */
  1076. ', ];
  1077. yield 'closure types containing backslash' => [
  1078. [],
  1079. '<?php
  1080. /**
  1081. * @var string $input
  1082. * @var \Closure $fn
  1083. * @var \Closure(bool):int $fn2
  1084. * @var Closure $fn3
  1085. * @var Closure(string):string $fn4
  1086. * @var array<string, array<string, mixed>> $data
  1087. */
  1088. /**
  1089. * @param string $input
  1090. * @param \Closure $fn
  1091. * @param \Closure(bool):int $fn2
  1092. * @param Closure $fn3
  1093. * @param Closure(string):string $fn4
  1094. * @param array<string, array<string, mixed>> $data
  1095. */
  1096. /**
  1097. * @var string $value
  1098. * @var \Closure(string): string $callback
  1099. * @var Closure(int): bool $callback2
  1100. */
  1101. /**
  1102. * @param string $value
  1103. * @param \Closure(string): string $callback
  1104. * @param Closure(int): bool $callback2
  1105. */
  1106. /**
  1107. * @var Closure(array<int, bool>): bool $callback1
  1108. * @var \Closure(string): string $callback2
  1109. */
  1110. /**
  1111. * @param Closure(array<int, bool>): bool $callback1
  1112. * @param \Closure(string): string $callback2
  1113. */
  1114. ', ];
  1115. yield 'types parenthesized' => [
  1116. [],
  1117. '<?php
  1118. /**
  1119. * @param list<string> $allowedTypes
  1120. * @param null|list<\Closure(mixed): (bool|null|scalar)> $allowedValues
  1121. */
  1122. ',
  1123. '<?php
  1124. /**
  1125. * @param list<string> $allowedTypes
  1126. * @param null|list<\Closure(mixed): (bool|null|scalar)> $allowedValues
  1127. */
  1128. ',
  1129. ];
  1130. yield 'callable types with ugly code 1' => [
  1131. [],
  1132. '<?php
  1133. /**
  1134. * @var callable $fn
  1135. * @var callable(bool): int $fn2
  1136. * @var Closure $fn3
  1137. * @var Closure(string|object):string $fn4
  1138. * @var \Closure $fn5
  1139. * @var \Closure(int, bool): bool $fn6
  1140. */
  1141. ',
  1142. '<?php
  1143. /**
  1144. * @var callable $fn
  1145. * @var callable(bool): int $fn2
  1146. * @var Closure $fn3
  1147. * @var Closure(string|object):string $fn4
  1148. * @var \Closure $fn5
  1149. * @var \Closure(int, bool): bool $fn6
  1150. */
  1151. ',
  1152. ];
  1153. yield 'callable types with ugly code 2' => [
  1154. [],
  1155. '<?php
  1156. /**
  1157. * @var callable $fn
  1158. * @var callable(bool): int $fn2
  1159. * @var Closure $fn3
  1160. * @var Closure(string|object):string $fn4
  1161. * @var \Closure $fn5
  1162. * @var \Closure(int, bool): bool $fn6
  1163. */
  1164. ',
  1165. '<?php
  1166. /**
  1167. * @var callable $fn
  1168. * @var callable(bool): int $fn2
  1169. * @var Closure $fn3
  1170. * @var Closure(string|object):string $fn4
  1171. * @var \Closure $fn5
  1172. * @var \Closure(int, bool): bool $fn6
  1173. */
  1174. ',
  1175. ];
  1176. yield 'CUSTOM tags' => [
  1177. ['tags' => ['param', 'xxx-xxxxxxxxx']],
  1178. '<?php
  1179. /**
  1180. * @param EngineInterface $templating
  1181. * @param string $format
  1182. * @xxx-xxxxxxxxx int $code An HTTP response status code
  1183. * @param bool $debug
  1184. * @param mixed &$reference A parameter passed by reference
  1185. */
  1186. ',
  1187. '<?php
  1188. /**
  1189. * @param EngineInterface $templating
  1190. * @param string $format
  1191. * @xxx-xxxxxxxxx int $code An HTTP response status code
  1192. * @param bool $debug
  1193. * @param mixed &$reference A parameter passed by reference
  1194. */
  1195. ',
  1196. ];
  1197. yield 'no/2+ spaces after comment star' => [
  1198. [],
  1199. '<?php
  1200. /**
  1201. * @property string $age @Atk4\Field()
  1202. * @property string $city @Atk4\Field()
  1203. */
  1204. ',
  1205. '<?php
  1206. /**
  1207. * @property string $age @Atk4\Field()
  1208. *@property string $city @Atk4\Field()
  1209. */
  1210. ',
  1211. ];
  1212. yield 'untyped param with multiline desc' => [
  1213. [],
  1214. '<?php
  1215. /**
  1216. * @param $typeless Foo.
  1217. * Bar.
  1218. */
  1219. function foo($typeless): void {}',
  1220. '<?php
  1221. /**
  1222. * @param $typeless Foo.
  1223. * Bar.
  1224. */
  1225. function foo($typeless): void {}',
  1226. ];
  1227. yield 'left align and @param with 2 spaces' => [
  1228. [
  1229. 'align' => PhpdocAlignFixer::ALIGN_LEFT,
  1230. 'spacing' => ['param' => 2],
  1231. ],
  1232. '<?php
  1233. /**
  1234. * @param EngineInterface $templating
  1235. * @param string $format
  1236. * @param int $code An HTTP response status code
  1237. * See constants
  1238. * @param bool $debug
  1239. * @param bool $debug See constants
  1240. * See constants
  1241. * @param mixed &$reference A parameter passed by reference
  1242. *
  1243. * @return Foo description foo
  1244. *
  1245. * @throws Foo description foo
  1246. * description foo
  1247. *
  1248. */
  1249. ',
  1250. '<?php
  1251. /**
  1252. * @param EngineInterface $templating
  1253. * @param string $format
  1254. * @param int $code An HTTP response status code
  1255. * See constants
  1256. * @param bool $debug
  1257. * @param bool $debug See constants
  1258. * See constants
  1259. * @param mixed &$reference A parameter passed by reference
  1260. *
  1261. * @return Foo description foo
  1262. *
  1263. * @throws Foo description foo
  1264. * description foo
  1265. *
  1266. */
  1267. ',
  1268. ];
  1269. yield 'vertical align with various spacing' => [
  1270. [
  1271. 'align' => PhpdocAlignFixer::ALIGN_VERTICAL,
  1272. 'spacing' => ['param' => 2, 'return' => 4],
  1273. ],
  1274. '<?php
  1275. /**
  1276. * @param EngineInterface $templating
  1277. * @param string $format
  1278. * @param int $code An HTTP response status code
  1279. * See constants
  1280. * @param bool $debug
  1281. * @param bool $debug See constants
  1282. * See constants
  1283. * @param mixed &$reference A parameter passed by reference
  1284. *
  1285. * @return Foo description foo bar hello world!
  1286. * return description continuation
  1287. *
  1288. * @throws Foo description foo
  1289. * description foo
  1290. *
  1291. */
  1292. ',
  1293. '<?php
  1294. /**
  1295. * @param EngineInterface $templating
  1296. * @param string $format
  1297. * @param int $code An HTTP response status code
  1298. * See constants
  1299. * @param bool $debug
  1300. * @param bool $debug See constants
  1301. * See constants
  1302. * @param mixed &$reference A parameter passed by reference
  1303. *
  1304. * @return Foo description foo bar hello world!
  1305. * return description continuation
  1306. *
  1307. * @throws Foo description foo
  1308. * description foo
  1309. *
  1310. */
  1311. ',
  1312. ];
  1313. yield 'left align with various spacing' => [
  1314. [
  1315. 'align' => PhpdocAlignFixer::ALIGN_LEFT,
  1316. 'spacing' => ['param' => 2, 'return' => 4],
  1317. ],
  1318. '<?php
  1319. /**
  1320. * @param EngineInterface $templating
  1321. * @param string $format
  1322. * @param int $code An HTTP response status code
  1323. * See constants
  1324. * @param bool $debug
  1325. * @param bool $debug See constants
  1326. * See constants
  1327. * @param mixed &$reference A parameter passed by reference
  1328. *
  1329. * @return Foo description foo
  1330. *
  1331. * @throws Foo description foo
  1332. * description foo
  1333. *
  1334. */
  1335. ',
  1336. '<?php
  1337. /**
  1338. * @param EngineInterface $templating
  1339. * @param string $format
  1340. * @param int $code An HTTP response status code
  1341. * See constants
  1342. * @param bool $debug
  1343. * @param bool $debug See constants
  1344. * See constants
  1345. * @param mixed &$reference A parameter passed by reference
  1346. *
  1347. * @return Foo description foo
  1348. *
  1349. * @throws Foo description foo
  1350. * description foo
  1351. *
  1352. */
  1353. ',
  1354. ];
  1355. yield 'left align with changed default spacing' => [
  1356. [
  1357. 'align' => PhpdocAlignFixer::ALIGN_LEFT,
  1358. 'spacing' => ['_default' => 2, 'return' => 4],
  1359. ],
  1360. '<?php
  1361. /**
  1362. * @property string $bar Foo-Bar lorem ipsum
  1363. * @param EngineInterface $templating
  1364. * @param string $format
  1365. * @param int $code An HTTP response status code
  1366. * See constants
  1367. * @param bool $debug
  1368. * @param bool $debug See constants
  1369. * See constants
  1370. * @param mixed &$reference A parameter passed by reference
  1371. *
  1372. * @return Foo description foo
  1373. *
  1374. * @throws Foo description foo
  1375. * description foo
  1376. *
  1377. */
  1378. ',
  1379. '<?php
  1380. /**
  1381. * @property string $bar Foo-Bar lorem ipsum
  1382. * @param EngineInterface $templating
  1383. * @param string $format
  1384. * @param int $code An HTTP response status code
  1385. * See constants
  1386. * @param bool $debug
  1387. * @param bool $debug See constants
  1388. * See constants
  1389. * @param mixed &$reference A parameter passed by reference
  1390. *
  1391. * @return Foo description foo
  1392. *
  1393. * @throws Foo description foo
  1394. * description foo
  1395. *
  1396. */
  1397. ',
  1398. ];
  1399. }
  1400. /**
  1401. * @dataProvider provideInvalidConfigurationCases
  1402. *
  1403. * @param _AutogeneratedInputConfiguration $config
  1404. */
  1405. public function testInvalidConfiguration(array $config, string $expectedMessage): void
  1406. {
  1407. $this->expectException(InvalidFixerConfigurationException::class);
  1408. $this->expectExceptionMessage($expectedMessage);
  1409. $this->fixer->configure($config);
  1410. }
  1411. /**
  1412. * @return iterable<array{array<string,mixed>, string}>
  1413. */
  1414. public static function provideInvalidConfigurationCases(): iterable
  1415. {
  1416. yield 'zero' => [
  1417. ['spacing' => 0],
  1418. 'The option "spacing" is invalid. All spacings must be greater than zero.',
  1419. ];
  1420. yield 'negative' => [
  1421. ['spacing' => -2],
  1422. 'The option "spacing" is invalid. All spacings must be greater than zero.',
  1423. ];
  1424. yield 'zeroInArray' => [
  1425. ['spacing' => ['param' => 1, 'return' => 0]],
  1426. 'The option "spacing" is invalid. All spacings must be greater than zero.',
  1427. ];
  1428. yield 'negativeInArray' => [
  1429. [
  1430. 'align' => PhpdocAlignFixer::ALIGN_LEFT,
  1431. 'spacing' => ['return' => 2, 'param' => -1],
  1432. ],
  1433. 'The option "spacing" is invalid. All spacings must be greater than zero.',
  1434. ];
  1435. }
  1436. }