HeaderCommentFixerTest.php 15 KB

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