NoBlankLinesAfterPhpdocFixerTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  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. * @author Graham Campbell <hello@gjcampbell.co.uk>
  16. *
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\Phpdoc\NoBlankLinesAfterPhpdocFixer
  20. *
  21. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Phpdoc\NoBlankLinesAfterPhpdocFixer>
  22. */
  23. final class NoBlankLinesAfterPhpdocFixerTest extends AbstractFixerTestCase
  24. {
  25. public function testSimpleExampleIsNotChanged(): void
  26. {
  27. $input = <<<'EOF'
  28. <?php
  29. /**
  30. * This is the bar class.
  31. */
  32. class Bar
  33. {
  34. /**
  35. * @return void
  36. */
  37. public function foo()
  38. {
  39. //
  40. }
  41. }
  42. EOF;
  43. $this->doTest($input);
  44. }
  45. public function testComplexExampleIsNotChanged(): void
  46. {
  47. $input = <<<'EOF'
  48. <?php
  49. /**
  50. * This is the hello function.
  51. * Yeh, this layout should be allowed.
  52. * We're fixing lines following a docblock.
  53. */
  54. function hello($foo) {}
  55. /**
  56. * This is the bar class.
  57. */
  58. final class Bar
  59. {
  60. /**
  61. * @return void
  62. */
  63. public static function foo()
  64. {
  65. //
  66. }
  67. /**
  68. * @return void
  69. */
  70. static private function bar123() {}
  71. /*
  72. * This T_COMMENT should not be moved
  73. *
  74. * Only T_DOC_COMMENT should be moved
  75. */
  76. final protected
  77. // mixin' it up a bit
  78. function baz() {
  79. }
  80. /*
  81. * This T_COMMENT should not be moved
  82. *
  83. * Only T_DOC_COMMENT should be moved
  84. */
  85. public function cool() {}
  86. /**
  87. * This is the first docblock
  88. *
  89. * Not removing blank line here.
  90. * No element is being documented
  91. */
  92. /**
  93. * Another docblock
  94. */
  95. public function silly() {}
  96. }
  97. EOF;
  98. $this->doTest($input);
  99. }
  100. public function testCommentsAreNotChanged(): void
  101. {
  102. $input = <<<'EOF'
  103. <?php
  104. /*
  105. * This file is part of xyz.
  106. *
  107. * License etc...
  108. */
  109. namespace Foo\Bar;
  110. EOF;
  111. $this->doTest($input);
  112. }
  113. public function testLineBeforeDeclareIsNotRemoved(): void
  114. {
  115. $expected = <<<'EOF'
  116. <?php
  117. /**
  118. * This is some license header.
  119. */
  120. declare(strict_types=1);
  121. EOF;
  122. $this->doTest($expected);
  123. }
  124. public function testLineBeforeUseStatementIsNotRemoved(): void
  125. {
  126. $expected = <<<'EOF'
  127. <?php
  128. /**
  129. * This is some license header.
  130. */
  131. use Foo\Bar;
  132. EOF;
  133. $this->doTest($expected);
  134. }
  135. /**
  136. * @dataProvider provideLineBeforeIncludeOrRequireIsNotRemovedCases
  137. */
  138. public function testLineBeforeIncludeOrRequireIsNotRemoved(string $expected, ?string $input = null): void
  139. {
  140. $this->doTest($expected, $input);
  141. }
  142. /**
  143. * @return iterable<array{string}>
  144. */
  145. public static function provideLineBeforeIncludeOrRequireIsNotRemovedCases(): iterable
  146. {
  147. yield [
  148. <<<'EOF'
  149. <?php
  150. /**
  151. * This describes what my script does.
  152. */
  153. include 'vendor/autoload.php';
  154. EOF,
  155. ];
  156. yield [
  157. <<<'EOF'
  158. <?php
  159. /**
  160. * This describes what my script does.
  161. */
  162. include_once 'vendor/autoload.php';
  163. EOF,
  164. ];
  165. yield [
  166. <<<'EOF'
  167. <?php
  168. /**
  169. * This describes what my script does.
  170. */
  171. require 'vendor/autoload.php';
  172. EOF,
  173. ];
  174. yield [
  175. <<<'EOF'
  176. <?php
  177. /**
  178. * This describes what my script does.
  179. */
  180. require_once 'vendor/autoload.php';
  181. EOF,
  182. ];
  183. }
  184. public function testLineWithSpacesIsRemovedWhenNextTokenIsIndented(): void
  185. {
  186. $this->doTest(
  187. '<?php
  188. /**
  189. * PHPDoc with a line with space
  190. */
  191. class Foo {}',
  192. '<?php
  193. /**
  194. * PHPDoc with a line with space
  195. */
  196. '.'
  197. class Foo {}'
  198. );
  199. }
  200. public function testLineWithSpacesIsRemovedWhenNextTokenIsNotIndented(): void
  201. {
  202. $this->doTest(
  203. '<?php
  204. /**
  205. * PHPDoc with a line with space
  206. */
  207. class Foo {}',
  208. '<?php
  209. /**
  210. * PHPDoc with a line with space
  211. */
  212. '.'
  213. class Foo {}'
  214. );
  215. }
  216. public function testFixesSimpleClass(): void
  217. {
  218. $expected = <<<'EOF'
  219. <?php
  220. /**
  221. * This is the bar class.
  222. */
  223. class Bar {}
  224. EOF;
  225. $input = <<<'EOF'
  226. <?php
  227. /**
  228. * This is the bar class.
  229. */
  230. class Bar {}
  231. EOF;
  232. $this->doTest($expected, $input);
  233. }
  234. public function testFixesIndentedClass(): void
  235. {
  236. $expected = <<<'EOF'
  237. <?php
  238. /**
  239. *
  240. */
  241. class Foo {
  242. private $a;
  243. }
  244. EOF;
  245. $input = <<<'EOF'
  246. <?php
  247. /**
  248. *
  249. */
  250. class Foo {
  251. private $a;
  252. }
  253. EOF;
  254. $this->doTest($expected, $input);
  255. }
  256. public function testFixesOthers(): void
  257. {
  258. $expected = <<<'EOF'
  259. <?php
  260. /**
  261. * Constant!
  262. */
  263. const test = 'constant';
  264. /**
  265. * Foo!
  266. */
  267. $foo = 123;
  268. EOF;
  269. $input = <<<'EOF'
  270. <?php
  271. /**
  272. * Constant!
  273. */
  274. const test = 'constant';
  275. /**
  276. * Foo!
  277. */
  278. $foo = 123;
  279. EOF;
  280. $this->doTest($expected, $input);
  281. }
  282. public function testWhitespaceInDocBlockAboveNamespaceIsNotTouched(): void
  283. {
  284. $expected = <<<'EOF'
  285. <?php
  286. /**
  287. * This is a file-level docblock.
  288. */
  289. namespace Foo\Bar\Baz;
  290. EOF;
  291. $this->doTest($expected);
  292. }
  293. public function testFixesWindowsStyle(): void
  294. {
  295. $expected = "<?php\r\n /** * Constant! */\n \$foo = 123;";
  296. $input = "<?php\r\n /** * Constant! */\r\n\r\n\r\n \$foo = 123;";
  297. $this->doTest($expected, $input);
  298. }
  299. /**
  300. * Empty line between typehinting docs and return statement should be preserved.
  301. *
  302. * @dataProvider provideInlineTypehintingDocsBeforeFlowBreakCases
  303. */
  304. public function testInlineTypehintingDocsBeforeFlowBreak(string $expected, ?string $input = null): void
  305. {
  306. $this->doTest($expected, $input);
  307. }
  308. /**
  309. * @return iterable<array{string}>
  310. */
  311. public static function provideInlineTypehintingDocsBeforeFlowBreakCases(): iterable
  312. {
  313. yield [
  314. <<<'EOF'
  315. <?php
  316. function parseTag($tag)
  317. {
  318. $tagClass = get_class($tag);
  319. if ('phpDocumentor\Reflection\DocBlock\Tag\VarTag' === $tagClass) {
  320. /** @var DocBlock\Tag\VarTag $tag */
  321. return $tag->getDescription();
  322. }
  323. }
  324. EOF,
  325. ];
  326. yield [
  327. <<<'EOF'
  328. <?php
  329. function parseTag($tag)
  330. {
  331. $tagClass = get_class($tag);
  332. if ('phpDocumentor\Reflection\DocBlock\Tag\VarTag' === $tagClass) {
  333. /** @var DocBlock\Tag\VarTag $tag */
  334. throw new Exception($tag->getDescription());
  335. }
  336. }
  337. EOF,
  338. ];
  339. yield [
  340. <<<'EOF'
  341. <?php
  342. function parseTag($tag)
  343. {
  344. $tagClass = get_class($tag);
  345. if ('phpDocumentor\Reflection\DocBlock\Tag\VarTag' === $tagClass) {
  346. /** @var DocBlock\Tag\VarTag $tag */
  347. goto FOO;
  348. }
  349. FOO:
  350. }
  351. EOF,
  352. ];
  353. yield [
  354. <<<'EOF'
  355. <?php
  356. function parseTag($tag)
  357. {
  358. while (true) {
  359. $tagClass = get_class($tag);
  360. if ('phpDocumentor\Reflection\DocBlock\Tag\VarTag' === $tagClass) {
  361. /** @var DocBlock\Tag\VarTag $tag */
  362. continue;
  363. }
  364. }
  365. }
  366. EOF,
  367. ];
  368. yield [
  369. <<<'EOF'
  370. <?php
  371. function parseTag($tag)
  372. {
  373. while (true) {
  374. $tagClass = get_class($tag);
  375. if ('phpDocumentor\Reflection\DocBlock\Tag\VarTag' === $tagClass) {
  376. /** @var DocBlock\Tag\VarTag $tag */
  377. break;
  378. }
  379. }
  380. }
  381. EOF,
  382. ];
  383. }
  384. }