HeaderCommentFixerTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  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\Tests\Test\AbstractFixerTestCase;
  13. use PhpCsFixer\Tokenizer\Tokens;
  14. use PhpCsFixer\WhitespacesFixerConfig;
  15. /**
  16. * @internal
  17. *
  18. * @covers \PhpCsFixer\Fixer\Comment\HeaderCommentFixer
  19. */
  20. final class HeaderCommentFixerTest extends AbstractFixerTestCase
  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->fixer->configure($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. 'commentType' => '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. 'commentType' => 'comment',
  102. ],
  103. '<?php
  104. /*
  105. * new
  106. */
  107. '.'
  108. ',
  109. '<?php
  110. /** test */
  111. ',
  112. ],
  113. [
  114. [
  115. 'header' => 'new',
  116. 'commentType' => 'PHPDoc',
  117. ],
  118. '<?php
  119. /**
  120. * new
  121. */
  122. '.'
  123. ',
  124. '<?php
  125. /* test */
  126. ',
  127. ],
  128. [
  129. [
  130. 'header' => 'def',
  131. 'commentType' => 'PHPDoc',
  132. ],
  133. '<?php
  134. /**
  135. * def
  136. */
  137. ',
  138. '<?php
  139. ',
  140. ],
  141. [
  142. ['header' => 'xyz'],
  143. '<?php
  144. /*
  145. * xyz
  146. */
  147. $b;',
  148. '<?php
  149. $b;',
  150. ],
  151. [
  152. [
  153. 'header' => 'xyz123',
  154. 'separate' => 'none',
  155. ],
  156. '<?php
  157. /*
  158. * xyz123
  159. */
  160. $a;',
  161. '<?php
  162. $a;',
  163. ],
  164. [
  165. [
  166. 'header' => 'abc',
  167. 'commentType' => 'PHPDoc',
  168. ],
  169. '<?php
  170. /**
  171. * abc
  172. */
  173. $c;',
  174. '<?php
  175. $c;',
  176. ],
  177. [
  178. [
  179. 'header' => 'ghi',
  180. 'separate' => 'both',
  181. ],
  182. '<?php
  183. /*
  184. * ghi
  185. */
  186. $d;',
  187. '<?php
  188. $d;',
  189. ],
  190. [
  191. [
  192. 'header' => 'ghi',
  193. 'separate' => 'top',
  194. ],
  195. '<?php
  196. /*
  197. * ghi
  198. */
  199. $d;',
  200. '<?php
  201. $d;',
  202. ],
  203. [
  204. [
  205. 'header' => 'tmp',
  206. 'location' => 'after_declare_strict',
  207. ],
  208. '<?php
  209. /*
  210. * tmp
  211. */
  212. declare(ticks=1);
  213. echo 1;',
  214. '<?php
  215. declare(ticks=1);
  216. echo 1;',
  217. ],
  218. [
  219. ['header' => 'Foo'],
  220. '<?php
  221. /*
  222. * Foo
  223. */
  224. echo \'bar\';',
  225. '<?php echo \'bar\';',
  226. ],
  227. [
  228. ['header' => 'x'],
  229. '<?php
  230. /*
  231. * x
  232. */
  233. echo \'a\';',
  234. '<?php
  235. /*
  236. * y
  237. * z
  238. */
  239. echo \'a\';',
  240. ],
  241. [
  242. ['header' => "a\na"],
  243. '<?php
  244. /*
  245. * a
  246. * a
  247. */
  248. echo \'x\';',
  249. '<?php
  250. /*
  251. * b
  252. * c
  253. */
  254. echo \'x\';',
  255. ],
  256. ];
  257. }
  258. public function testDefaultConfiguration()
  259. {
  260. $this->fixer->configure(['header' => 'a']);
  261. $this->doTest(
  262. '<?php
  263. /*
  264. * a
  265. */
  266. echo 1;',
  267. '<?php
  268. echo 1;'
  269. );
  270. }
  271. /**
  272. * @param null|array $configuration
  273. * @param string $exceptionMessage
  274. *
  275. * @dataProvider provideMisconfigurationCases
  276. */
  277. public function testMisconfiguration($configuration, $exceptionMessage)
  278. {
  279. $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class);
  280. $this->expectExceptionMessage('[header_comment] '.$exceptionMessage);
  281. $this->fixer->configure($configuration);
  282. }
  283. public function provideMisconfigurationCases()
  284. {
  285. return [
  286. [[], 'Missing required configuration: The required option "header" is missing.'],
  287. [
  288. ['header' => 1],
  289. 'Invalid configuration: The option "header" with value 1 is expected to be of type "string", but is of type "integer".',
  290. ],
  291. [
  292. [
  293. 'header' => '',
  294. 'commentType' => 'foo',
  295. ],
  296. 'Invalid configuration: The option "commentType" with value "foo" is invalid. Accepted values are: "PHPDoc", "comment".',
  297. ],
  298. [
  299. [
  300. 'header' => '',
  301. 'commentType' => new \stdClass(),
  302. ],
  303. 'Invalid configuration: The option "commentType" with value stdClass is invalid. Accepted values are: "PHPDoc", "comment".',
  304. ],
  305. [
  306. [
  307. 'header' => '',
  308. 'location' => new \stdClass(),
  309. ],
  310. 'Invalid configuration: The option "location" with value stdClass is invalid. Accepted values are: "after_open", "after_declare_strict".',
  311. ],
  312. [
  313. [
  314. 'header' => '',
  315. 'separate' => new \stdClass(),
  316. ],
  317. 'Invalid configuration: The option "separate" with value stdClass is invalid. Accepted values are: "both", "top", "bottom", "none".',
  318. ],
  319. ];
  320. }
  321. /**
  322. * @param string $expected
  323. * @param string $header
  324. * @param string $type
  325. *
  326. * @dataProvider provideHeaderGenerationCases
  327. */
  328. public function testHeaderGeneration($expected, $header, $type)
  329. {
  330. $this->fixer->configure([
  331. 'header' => $header,
  332. 'commentType' => $type,
  333. ]);
  334. $this->doTest(
  335. '<?php
  336. '.$expected.'
  337. echo 1;',
  338. '<?php
  339. echo 1;'
  340. );
  341. }
  342. public function provideHeaderGenerationCases()
  343. {
  344. return [
  345. [
  346. '/*
  347. * a
  348. */',
  349. 'a',
  350. 'comment',
  351. ],
  352. [
  353. '/**
  354. * a
  355. */',
  356. 'a',
  357. 'PHPDoc',
  358. ],
  359. ];
  360. }
  361. /**
  362. * @param int $expected
  363. * @param string $code
  364. *
  365. * @dataProvider provideFindHeaderCommentInsertionIndexCases
  366. */
  367. public function testFindHeaderCommentInsertionIndex($expected, $code, array $config)
  368. {
  369. Tokens::clearCache();
  370. $tokens = Tokens::fromCode($code);
  371. $this->fixer->configure($config);
  372. $method = new \ReflectionMethod($this->fixer, 'findHeaderCommentInsertionIndex');
  373. $method->setAccessible(true);
  374. $this->assertSame($expected, $method->invoke($this->fixer, $tokens));
  375. }
  376. public function provideFindHeaderCommentInsertionIndexCases()
  377. {
  378. $config = ['header' => ''];
  379. $cases = [
  380. [1, '<?php #', $config],
  381. [1, '<?php /**/ $bc;', $config],
  382. [1, '<?php $bc;', $config],
  383. [1, "<?php\n\n", $config],
  384. [1, '<?php ', $config],
  385. ];
  386. $config['location'] = 'after_declare_strict';
  387. $cases[] = [
  388. 8,
  389. '<?php
  390. declare(strict_types=1);
  391. namespace A\B;
  392. echo 1;',
  393. $config,
  394. ];
  395. $cases[] = [
  396. 8,
  397. '<?php
  398. declare(strict_types=0);
  399. echo 1;',
  400. $config,
  401. ];
  402. $cases[] = [
  403. 1,
  404. '<?php
  405. declare(strict_types=1)?>',
  406. $config,
  407. ];
  408. return $cases;
  409. }
  410. /**
  411. * @param string $expected
  412. *
  413. * @dataProvider provideDoNotTouchCases
  414. */
  415. public function testDoNotTouch($expected)
  416. {
  417. $this->fixer->configure([
  418. 'header' => '',
  419. ]);
  420. $this->doTest($expected);
  421. }
  422. public function provideDoNotTouchCases()
  423. {
  424. return [
  425. ["<?php\nphpinfo();\n?>\n<?"],
  426. [" <?php\nphpinfo();\n"],
  427. ["<?php\nphpinfo();\n?><hr/>"],
  428. [" <?php\n"],
  429. ['<?= 1?>'],
  430. ['<?= 1?><?php'],
  431. ["<?= 1?>\n<?php"],
  432. ];
  433. }
  434. public function testWithoutConfiguration()
  435. {
  436. $this->expectException(\PhpCsFixer\ConfigurationException\RequiredFixerConfigurationException::class);
  437. $this->doTest('<?php echo 1;');
  438. }
  439. /**
  440. * @param string $expected
  441. * @param null|string $input
  442. *
  443. * @dataProvider provideMessyWhitespacesCases
  444. */
  445. public function testMessyWhitespaces(array $configuration, $expected, $input = null)
  446. {
  447. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t", "\r\n"));
  448. $this->fixer->configure($configuration);
  449. $this->doTest($expected, $input);
  450. }
  451. public function provideMessyWhitespacesCases()
  452. {
  453. return [
  454. [
  455. [
  456. 'header' => 'whitemess',
  457. 'location' => 'after_declare_strict',
  458. 'separate' => 'bottom',
  459. 'commentType' => 'PHPDoc',
  460. ],
  461. "<?php\r\ndeclare(strict_types=1);\r\n/**\r\n * whitemess\r\n */\r\n\r\nnamespace A\\B;\r\n\r\necho 1;",
  462. "<?php\r\ndeclare(strict_types=1);\r\n\r\nnamespace A\\B;\r\n\r\necho 1;",
  463. ],
  464. ];
  465. }
  466. public function testConfigurationUpdatedWithWhitespsacesConfig()
  467. {
  468. $this->fixer->configure(['header' => 'Foo']);
  469. $this->doTest(
  470. "<?php\n\n/*\n * Foo\n */\n\necho 1;",
  471. "<?php\necho 1;"
  472. );
  473. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig(' ', "\r\n"));
  474. $this->doTest(
  475. "<?php\r\n\r\n/*\r\n * Foo\r\n */\r\n\r\necho 1;",
  476. "<?php\r\necho 1;"
  477. );
  478. $this->fixer->configure(['header' => 'Bar']);
  479. $this->doTest(
  480. "<?php\r\n\r\n/*\r\n * Bar\r\n */\r\n\r\necho 1;",
  481. "<?php\r\necho 1;"
  482. );
  483. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig(' ', "\n"));
  484. $this->doTest(
  485. "<?php\n\n/*\n * Bar\n */\n\necho 1;",
  486. "<?php\necho 1;"
  487. );
  488. }
  489. }