HeaderCommentFixerTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  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\Comment;
  13. use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException;
  14. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  15. use PhpCsFixer\WhitespacesFixerConfig;
  16. /**
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\Comment\HeaderCommentFixer
  20. */
  21. final class HeaderCommentFixerTest extends AbstractFixerTestCase
  22. {
  23. /**
  24. * @dataProvider provideFixCases
  25. */
  26. public function testFix(array $configuration, string $expected, string $input): void
  27. {
  28. $this->fixer->configure($configuration);
  29. $this->doTest($expected, $input);
  30. }
  31. public function provideFixCases()
  32. {
  33. return [
  34. [
  35. ['header' => ''],
  36. '<?php
  37. $a;',
  38. '<?php
  39. /**
  40. * new
  41. */
  42. $a;',
  43. ],
  44. [
  45. [
  46. 'header' => 'tmp',
  47. 'location' => 'after_declare_strict',
  48. ],
  49. '<?php
  50. declare(strict_types=1);
  51. /*
  52. * tmp
  53. */
  54. namespace A\B;
  55. echo 1;',
  56. '<?php
  57. declare(strict_types=1);namespace A\B;
  58. echo 1;',
  59. ],
  60. [
  61. [
  62. 'header' => 'tmp',
  63. 'location' => 'after_declare_strict',
  64. 'separate' => 'bottom',
  65. 'comment_type' => 'PHPDoc',
  66. ],
  67. '<?php
  68. declare(strict_types=1);
  69. /**
  70. * tmp
  71. */
  72. namespace A\B;
  73. echo 1;',
  74. '<?php
  75. declare(strict_types=1);
  76. namespace A\B;
  77. echo 1;',
  78. ],
  79. [
  80. [
  81. 'header' => 'tmp',
  82. 'location' => 'after_open',
  83. ],
  84. '<?php
  85. /*
  86. * tmp
  87. */
  88. declare(strict_types=1);
  89. namespace A\B;
  90. echo 1;',
  91. '<?php
  92. declare(strict_types=1);
  93. namespace A\B;
  94. echo 1;',
  95. ],
  96. [
  97. [
  98. 'header' => 'new',
  99. 'comment_type' => 'comment',
  100. ],
  101. '<?php
  102. /*
  103. * new
  104. */
  105. ',
  106. '<?php
  107. /** test */
  108. ',
  109. ],
  110. [
  111. [
  112. 'header' => 'new',
  113. 'comment_type' => 'PHPDoc',
  114. ],
  115. '<?php
  116. /**
  117. * new
  118. */
  119. ',
  120. '<?php
  121. /* test */
  122. ',
  123. ],
  124. [
  125. [
  126. 'header' => 'def',
  127. 'comment_type' => 'PHPDoc',
  128. ],
  129. '<?php
  130. /**
  131. * def
  132. */
  133. ',
  134. '<?php
  135. ',
  136. ],
  137. [
  138. ['header' => 'xyz'],
  139. '<?php
  140. /*
  141. * xyz
  142. */
  143. $b;',
  144. '<?php
  145. $b;',
  146. ],
  147. [
  148. [
  149. 'header' => 'xyz123',
  150. 'separate' => 'none',
  151. ],
  152. '<?php
  153. /*
  154. * xyz123
  155. */
  156. $a;',
  157. '<?php
  158. $a;',
  159. ],
  160. [
  161. [
  162. 'header' => 'abc',
  163. 'comment_type' => 'PHPDoc',
  164. ],
  165. '<?php
  166. /**
  167. * abc
  168. */
  169. $c;',
  170. '<?php
  171. $c;',
  172. ],
  173. [
  174. [
  175. 'header' => 'ghi',
  176. 'separate' => 'both',
  177. ],
  178. '<?php
  179. /*
  180. * ghi
  181. */
  182. $d;',
  183. '<?php
  184. $d;',
  185. ],
  186. [
  187. [
  188. 'header' => 'ghi',
  189. 'separate' => 'top',
  190. ],
  191. '<?php
  192. /*
  193. * ghi
  194. */
  195. $d;',
  196. '<?php
  197. $d;',
  198. ],
  199. [
  200. [
  201. 'header' => 'tmp',
  202. 'location' => 'after_declare_strict',
  203. ],
  204. '<?php
  205. /*
  206. * tmp
  207. */
  208. declare(ticks=1);
  209. echo 1;',
  210. '<?php
  211. declare(ticks=1);
  212. echo 1;',
  213. ],
  214. [
  215. ['header' => 'Foo'],
  216. '<?php
  217. /*
  218. * Foo
  219. */
  220. echo \'bar\';',
  221. '<?php echo \'bar\';',
  222. ],
  223. [
  224. ['header' => 'x'],
  225. '<?php
  226. /*
  227. * x
  228. */
  229. echo \'a\';',
  230. '<?php
  231. /*
  232. * y
  233. * z
  234. */
  235. echo \'a\';',
  236. ],
  237. [
  238. ['header' => "a\na"],
  239. '<?php
  240. /*
  241. * a
  242. * a
  243. */
  244. echo \'x\';',
  245. '<?php
  246. /*
  247. * b
  248. * c
  249. */
  250. echo \'x\';',
  251. ],
  252. [
  253. [
  254. 'header' => 'foo',
  255. 'location' => 'after_open',
  256. 'separate' => 'bottom',
  257. 'comment_type' => 'PHPDoc',
  258. ],
  259. '<?php
  260. /**
  261. * foo
  262. */
  263. declare(strict_types=1);
  264. namespace A;
  265. echo 1;',
  266. '<?php
  267. declare(strict_types=1);
  268. /**
  269. * foo
  270. */
  271. namespace A;
  272. echo 1;',
  273. ],
  274. [
  275. [
  276. 'header' => 'foo',
  277. 'location' => 'after_open',
  278. 'separate' => 'bottom',
  279. 'comment_type' => 'PHPDoc',
  280. ],
  281. '<?php
  282. /**
  283. * foo
  284. */
  285. declare(strict_types=1);
  286. /**
  287. * bar
  288. */
  289. namespace A;
  290. echo 1;',
  291. '<?php
  292. declare(strict_types=1);
  293. /**
  294. * bar
  295. */
  296. namespace A;
  297. echo 1;',
  298. ],
  299. [
  300. [
  301. 'header' => 'Foo',
  302. 'separate' => 'none',
  303. ],
  304. '<?php
  305. declare(strict_types=1);
  306. /*
  307. * Foo
  308. */
  309. namespace SebastianBergmann\Foo;
  310. class Bar
  311. {
  312. }',
  313. '<?php
  314. /*
  315. * Foo
  316. */
  317. declare(strict_types=1);
  318. namespace SebastianBergmann\Foo;
  319. class Bar
  320. {
  321. }',
  322. ],
  323. [
  324. ['header' => 'tmp'],
  325. '<?php
  326. /*
  327. * tmp
  328. */
  329. /**
  330. * Foo class doc.
  331. */
  332. class Foo {}',
  333. '<?php
  334. /**
  335. * Foo class doc.
  336. */
  337. class Foo {}',
  338. ],
  339. [
  340. ['header' => 'tmp'],
  341. '<?php
  342. /*
  343. * tmp
  344. */
  345. class Foo {}',
  346. '<?php
  347. /*
  348. * Foo class doc.
  349. */
  350. class Foo {}',
  351. ],
  352. [
  353. [
  354. 'header' => 'tmp',
  355. 'comment_type' => 'PHPDoc',
  356. ],
  357. '<?php
  358. /**
  359. * tmp
  360. */
  361. /**
  362. * Foo class doc.
  363. */
  364. class Foo {}',
  365. '<?php
  366. /**
  367. * Foo class doc.
  368. */
  369. class Foo {}',
  370. ],
  371. [
  372. [
  373. 'header' => 'tmp',
  374. 'comment_type' => 'PHPDoc',
  375. ],
  376. '<?php
  377. /**
  378. * tmp
  379. */
  380. class Foo {}',
  381. '<?php
  382. /**
  383. * tmp
  384. */
  385. class Foo {}',
  386. ],
  387. [
  388. [
  389. 'header' => 'tmp',
  390. 'separate' => 'top',
  391. ],
  392. '<?php
  393. /*
  394. * tmp
  395. */
  396. class Foo {}',
  397. '<?php
  398. /**
  399. * Foo class doc.
  400. */
  401. class Foo {}',
  402. ],
  403. [
  404. [
  405. 'header' => 'bar',
  406. 'location' => 'after_open',
  407. ],
  408. '<?php
  409. /*
  410. * bar
  411. */
  412. declare(strict_types=1);
  413. // foo
  414. foo();',
  415. '<?php
  416. /*
  417. * foo
  418. */
  419. declare(strict_types=1);
  420. // foo
  421. foo();',
  422. ],
  423. [
  424. [
  425. 'header' => 'bar',
  426. 'location' => 'after_open',
  427. ],
  428. '<?php
  429. /*
  430. * bar
  431. */
  432. declare(strict_types=1);
  433. /* foo */
  434. foo();',
  435. '<?php
  436. /*
  437. * foo
  438. */
  439. declare(strict_types=1);
  440. /* foo */
  441. foo();',
  442. ],
  443. [
  444. [
  445. 'header' => 'tmp',
  446. 'location' => 'after_declare_strict',
  447. ],
  448. '<?php
  449. /*
  450. * tmp
  451. */
  452. declare(strict_types=1) ?>',
  453. '<?php
  454. declare(strict_types=1) ?>',
  455. ],
  456. ];
  457. }
  458. public function testDefaultConfiguration(): void
  459. {
  460. $this->fixer->configure(['header' => 'a']);
  461. $this->doTest(
  462. '<?php
  463. /*
  464. * a
  465. */
  466. echo 1;',
  467. '<?php
  468. echo 1;'
  469. );
  470. }
  471. /**
  472. * @dataProvider provideMisconfigurationCases
  473. */
  474. public function testMisconfiguration(?array $configuration, string $exceptionMessage): void
  475. {
  476. $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class);
  477. $this->expectExceptionMessageMatches("#^\\[header_comment\\] {$exceptionMessage}$#");
  478. $this->fixer->configure($configuration);
  479. }
  480. public function provideMisconfigurationCases()
  481. {
  482. return [
  483. [[], 'Missing required configuration: The required option "header" is missing.'],
  484. [
  485. ['header' => 1],
  486. 'Invalid configuration: The option "header" with value 1 is expected to be of type "string", but is of type "(int|integer)"\.',
  487. ],
  488. [
  489. [
  490. 'header' => '',
  491. 'comment_type' => 'foo',
  492. ],
  493. 'Invalid configuration: The option "comment_type" with value "foo" is invalid\. Accepted values are: "PHPDoc", "comment"\.',
  494. ],
  495. [
  496. [
  497. 'header' => '',
  498. 'comment_type' => new \stdClass(),
  499. ],
  500. 'Invalid configuration: The option "comment_type" with value stdClass is invalid\. Accepted values are: "PHPDoc", "comment"\.',
  501. ],
  502. [
  503. [
  504. 'header' => '',
  505. 'location' => new \stdClass(),
  506. ],
  507. 'Invalid configuration: The option "location" with value stdClass is invalid\. Accepted values are: "after_open", "after_declare_strict"\.',
  508. ],
  509. [
  510. [
  511. 'header' => '',
  512. 'separate' => new \stdClass(),
  513. ],
  514. 'Invalid configuration: The option "separate" with value stdClass is invalid\. Accepted values are: "both", "top", "bottom", "none"\.',
  515. ],
  516. ];
  517. }
  518. /**
  519. * @dataProvider provideHeaderGenerationCases
  520. */
  521. public function testHeaderGeneration(string $expected, string $header, string $type): void
  522. {
  523. $this->fixer->configure([
  524. 'header' => $header,
  525. 'comment_type' => $type,
  526. ]);
  527. $this->doTest(
  528. '<?php
  529. '.$expected.'
  530. echo 1;',
  531. '<?php
  532. echo 1;'
  533. );
  534. }
  535. public function provideHeaderGenerationCases()
  536. {
  537. return [
  538. [
  539. '/*
  540. * a
  541. */',
  542. 'a',
  543. 'comment',
  544. ],
  545. [
  546. '/**
  547. * a
  548. */',
  549. 'a',
  550. 'PHPDoc',
  551. ],
  552. ];
  553. }
  554. /**
  555. * @dataProvider provideDoNotTouchCases
  556. */
  557. public function testDoNotTouch(string $expected): void
  558. {
  559. $this->fixer->configure([
  560. 'header' => '',
  561. ]);
  562. $this->doTest($expected);
  563. }
  564. public function provideDoNotTouchCases()
  565. {
  566. return [
  567. ["<?php\nphpinfo();\n?>\n<?"],
  568. [" <?php\nphpinfo();\n"],
  569. ["<?php\nphpinfo();\n?><hr/>"],
  570. [" <?php\n"],
  571. ['<?= 1?>'],
  572. ["<?= 1?><?php\n"],
  573. ["<?= 1?>\n<?php\n"],
  574. ];
  575. }
  576. public function testWithoutConfiguration(): void
  577. {
  578. $this->expectException(\PhpCsFixer\ConfigurationException\RequiredFixerConfigurationException::class);
  579. $this->doTest('<?php echo 1;');
  580. }
  581. /**
  582. * @dataProvider provideMessyWhitespacesCases
  583. */
  584. public function testMessyWhitespaces(array $configuration, string $expected, ?string $input = null): void
  585. {
  586. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t", "\r\n"));
  587. $this->fixer->configure($configuration);
  588. $this->doTest($expected, $input);
  589. }
  590. public function provideMessyWhitespacesCases()
  591. {
  592. return [
  593. [
  594. [
  595. 'header' => 'whitemess',
  596. 'location' => 'after_declare_strict',
  597. 'separate' => 'bottom',
  598. 'comment_type' => 'PHPDoc',
  599. ],
  600. "<?php\r\ndeclare(strict_types=1);\r\n/**\r\n * whitemess\r\n */\r\n\r\nnamespace A\\B;\r\n\r\necho 1;",
  601. "<?php\r\ndeclare(strict_types=1);\r\n\r\nnamespace A\\B;\r\n\r\necho 1;",
  602. ],
  603. ];
  604. }
  605. public function testConfigurationUpdatedWithWhitespsacesConfig(): void
  606. {
  607. $this->fixer->configure(['header' => 'Foo']);
  608. $this->doTest(
  609. "<?php\n\n/*\n * Foo\n */\n\necho 1;",
  610. "<?php\necho 1;"
  611. );
  612. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig(' ', "\r\n"));
  613. $this->doTest(
  614. "<?php\r\n\r\n/*\r\n * Foo\r\n */\r\n\r\necho 1;",
  615. "<?php\r\necho 1;"
  616. );
  617. $this->fixer->configure(['header' => 'Bar']);
  618. $this->doTest(
  619. "<?php\r\n\r\n/*\r\n * Bar\r\n */\r\n\r\necho 1;",
  620. "<?php\r\necho 1;"
  621. );
  622. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig(' ', "\n"));
  623. $this->doTest(
  624. "<?php\n\n/*\n * Bar\n */\n\necho 1;",
  625. "<?php\necho 1;"
  626. );
  627. }
  628. public function testInvalidHeaderConfiguration(): void
  629. {
  630. $this->expectException(InvalidFixerConfigurationException::class);
  631. $this->expectExceptionMessageMatches('#^\[header_comment\] Cannot use \'\*/\' in header\.$#');
  632. $this->fixer->configure([
  633. 'header' => '/** test */',
  634. 'comment_type' => 'PHPDoc',
  635. ]);
  636. }
  637. }