GeneralPhpdocTagRenameFixerTest.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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\Tests\Test\AbstractFixerTestCase;
  15. /**
  16. * @internal
  17. *
  18. * @covers \PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocTagRenameFixer
  19. *
  20. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocTagRenameFixer>
  21. *
  22. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocTagRenameFixer
  23. */
  24. final class GeneralPhpdocTagRenameFixerTest extends AbstractFixerTestCase
  25. {
  26. /**
  27. * @param _AutogeneratedInputConfiguration $configuration
  28. *
  29. * @dataProvider provideFixCases
  30. */
  31. public function testFix(string $expected, ?string $input = null, array $configuration = []): void
  32. {
  33. $this->fixer->configure($configuration);
  34. $this->doTest($expected, $input);
  35. }
  36. public static function provideFixCases(): iterable
  37. {
  38. yield [
  39. '<?php
  40. /**
  41. * @inheritdocs
  42. * @inheritDocs
  43. * {@inheritdocs}
  44. * {@inheritDocs}
  45. * @see Foo::bar()
  46. * {@see Foo::bar()}
  47. */',
  48. ];
  49. yield [
  50. '<?php
  51. /**
  52. * @inheritDoc
  53. * @inheritDoc
  54. * {@inheritDoc}
  55. * {@inheritDoc}
  56. * @see Foo::bar()
  57. * {@see Foo::bar()}
  58. */',
  59. '<?php
  60. /**
  61. * @inheritdocs
  62. * @inheritDocs
  63. * {@inheritdocs}
  64. * {@inheritDocs}
  65. * @see Foo::bar()
  66. * {@see Foo::bar()}
  67. */',
  68. [
  69. 'replacements' => ['inheritDocs' => 'inheritDoc'],
  70. ],
  71. ];
  72. yield [
  73. '<?php
  74. /**
  75. * @inheritdoc
  76. * @inheritdoc
  77. * {@inheritdoc}
  78. * {@inheritdoc}
  79. * @see Foo::bar()
  80. * {@see Foo::bar()}
  81. */',
  82. '<?php
  83. /**
  84. * @inheritdocs
  85. * @inheritDocs
  86. * {@inheritdocs}
  87. * {@inheritDocs}
  88. * @see Foo::bar()
  89. * {@see Foo::bar()}
  90. */',
  91. [
  92. 'fix_annotation' => true,
  93. 'fix_inline' => true,
  94. 'replacements' => ['inheritdocs' => 'inheritdoc'],
  95. 'case_sensitive' => false,
  96. ],
  97. ];
  98. yield [
  99. '<?php
  100. /**
  101. * @inheritDoc
  102. * @inheritDoc
  103. * {@inheritdocs}
  104. * {@inheritDocs}
  105. * @see Foo::bar()
  106. * {@see Foo::bar()}
  107. */',
  108. '<?php
  109. /**
  110. * @inheritdocs
  111. * @inheritDocs
  112. * {@inheritdocs}
  113. * {@inheritDocs}
  114. * @see Foo::bar()
  115. * {@see Foo::bar()}
  116. */',
  117. [
  118. 'fix_inline' => false,
  119. 'replacements' => ['inheritDocs' => 'inheritDoc'],
  120. ],
  121. ];
  122. yield [
  123. '<?php
  124. /**
  125. * @inheritdocs
  126. * @inheritDocs
  127. * {@inheritDoc}
  128. * {@inheritDoc}
  129. * @see Foo::bar()
  130. * {@see Foo::bar()}
  131. */',
  132. '<?php
  133. /**
  134. * @inheritdocs
  135. * @inheritDocs
  136. * {@inheritdocs}
  137. * {@inheritDocs}
  138. * @see Foo::bar()
  139. * {@see Foo::bar()}
  140. */',
  141. [
  142. 'fix_annotation' => false,
  143. 'replacements' => ['inheritDocs' => 'inheritDoc'],
  144. ],
  145. ];
  146. yield [
  147. '<?php
  148. /**
  149. * @inheritdocs
  150. * @inheritDoc
  151. * {@inheritdocs}
  152. * {@inheritDoc}
  153. * @see Foo::bar()
  154. * {@see Foo::bar()}
  155. */',
  156. '<?php
  157. /**
  158. * @inheritdocs
  159. * @inheritDocs
  160. * {@inheritdocs}
  161. * {@inheritDocs}
  162. * @see Foo::bar()
  163. * {@see Foo::bar()}
  164. */',
  165. [
  166. 'case_sensitive' => true,
  167. 'replacements' => ['inheritDocs' => 'inheritDoc'],
  168. ],
  169. ];
  170. yield [
  171. '<?php
  172. /**
  173. * @inheritdoc
  174. * @inheritdoc
  175. * {@inheritdoc}
  176. * {@inheritdoc}
  177. * @see Foo::bar()
  178. * {@see Foo::bar()}
  179. */',
  180. '<?php
  181. /**
  182. * @inheritdocs
  183. * @inheritDocs
  184. * {@inheritdocs}
  185. * {@inheritDocs}
  186. * @link Foo::bar()
  187. * {@link Foo::bar()}
  188. */',
  189. [
  190. 'replacements' => [
  191. 'inheritdocs' => 'inheritdoc',
  192. 'link' => 'see',
  193. ],
  194. ],
  195. ];
  196. yield [
  197. '<?php
  198. /**
  199. * @var int $foo
  200. * @Annotation("@type")
  201. */',
  202. '<?php
  203. /**
  204. * @type int $foo
  205. * @Annotation("@type")
  206. */',
  207. [
  208. 'fix_annotation' => true,
  209. 'fix_inline' => true,
  210. 'replacements' => [
  211. 'type' => 'var',
  212. ],
  213. ],
  214. ];
  215. yield [
  216. '<?php
  217. /**
  218. * @var int $foo
  219. * @Annotation("@type")
  220. */',
  221. '<?php
  222. /**
  223. * @type int $foo
  224. * @Annotation("@type")
  225. */',
  226. [
  227. 'fix_annotation' => true,
  228. 'fix_inline' => false,
  229. 'replacements' => [
  230. 'type' => 'var',
  231. ],
  232. ],
  233. ];
  234. }
  235. public function testConfigureWithInvalidOption(): void
  236. {
  237. $this->expectException(InvalidFixerConfigurationException::class);
  238. $this->expectExceptionMessageMatches('/^\[general_phpdoc_tag_rename\] Invalid configuration: The option "replacements" with value true is expected to be of type "string\[\]", but is of type "bool"\.$/');
  239. $this->fixer->configure([ // @phpstan-ignore-line
  240. 'replacements' => true,
  241. ]);
  242. }
  243. public function testConfigureWithUnknownOption(): void
  244. {
  245. $this->expectException(InvalidFixerConfigurationException::class);
  246. $this->expectExceptionMessageMatches('/^\[general_phpdoc_tag_rename\] Invalid configuration: The option "foo" does not exist\. (Known|Defined) options are: "case_sensitive", "fix_annotation", "fix_inline", "replacements"\.$/');
  247. $this->fixer->configure([
  248. 'foo' => true,
  249. ]);
  250. }
  251. /**
  252. * @param array<array-key, mixed> $replacements
  253. *
  254. * @dataProvider provideConfigureWithInvalidReplacementsCases
  255. */
  256. public function testConfigureWithInvalidReplacements(array $replacements, bool $caseSensitive, string $expectedMessage): void
  257. {
  258. $this->expectException(InvalidFixerConfigurationException::class);
  259. $this->expectExceptionMessageMatches(\sprintf(
  260. '/^\[general_phpdoc_tag_rename\] Invalid configuration: %s$/',
  261. preg_quote($expectedMessage, '/')
  262. ));
  263. $this->fixer->configure([
  264. 'replacements' => $replacements,
  265. 'case_sensitive' => $caseSensitive,
  266. ]);
  267. }
  268. public static function provideConfigureWithInvalidReplacementsCases(): iterable
  269. {
  270. yield [
  271. [1 => 'abc'],
  272. true,
  273. 'Tag to replace must be a string.',
  274. ];
  275. yield [
  276. ['a' => null],
  277. true,
  278. 'The option "replacements" with value array is expected to be of type "string[]", but one of the elements is of type "null".',
  279. ];
  280. yield [
  281. ['see' => 'link*/'],
  282. true,
  283. 'Tag "see" cannot be replaced by invalid tag "link*/".',
  284. ];
  285. yield [
  286. [
  287. 'link' => 'see',
  288. 'a' => 'b',
  289. 'see' => 'link',
  290. ],
  291. true,
  292. 'Cannot change tag "link" to tag "see", as the tag "see" is configured to be replaced to "link".',
  293. ];
  294. yield [
  295. [
  296. 'b' => 'see',
  297. 'see' => 'link',
  298. 'link' => 'b',
  299. ],
  300. true,
  301. 'Cannot change tag "b" to tag "see", as the tag "see" is configured to be replaced to "link".',
  302. ];
  303. yield [
  304. [
  305. 'see' => 'link',
  306. 'link' => 'b',
  307. ],
  308. true,
  309. 'Cannot change tag "see" to tag "link", as the tag "link" is configured to be replaced to "b".',
  310. ];
  311. yield [
  312. [
  313. 'Foo' => 'bar',
  314. 'foo' => 'baz',
  315. ],
  316. false,
  317. 'Tag "foo" cannot be configured to be replaced with several different tags when case sensitivity is off.',
  318. ];
  319. }
  320. }