NoUnneededFinalMethodFixerTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  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\ClassNotation;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @author Filippo Tessarotto <zoeslam@gmail.com>
  16. *
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\ClassNotation\NoUnneededFinalMethodFixer
  20. *
  21. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\ClassNotation\NoUnneededFinalMethodFixer>
  22. *
  23. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\ClassNotation\NoUnneededFinalMethodFixer
  24. */
  25. final class NoUnneededFinalMethodFixerTest extends AbstractFixerTestCase
  26. {
  27. /**
  28. * @dataProvider provideFixCases
  29. *
  30. * @param _AutogeneratedInputConfiguration $configuration
  31. */
  32. public function testFix(string $expected, ?string $input = null, array $configuration = []): void
  33. {
  34. $this->fixer->configure($configuration);
  35. $this->doTest($expected, $input);
  36. }
  37. public static function provideFixCases(): iterable
  38. {
  39. yield 'default' => [
  40. '<?php
  41. final class Foo {
  42. public function foo() {}
  43. protected function bar() {}
  44. private function baz() {}
  45. }',
  46. '<?php
  47. final class Foo {
  48. final public function foo() {}
  49. final protected function bar() {}
  50. final private function baz() {}
  51. }',
  52. ];
  53. yield 'final-after-visibility' => [
  54. '<?php
  55. final class Foo {
  56. public function foo() {}
  57. protected function bar() {}
  58. private function baz() {}
  59. }',
  60. '<?php
  61. final class Foo {
  62. public final function foo() {}
  63. protected final function bar() {}
  64. private final function baz() {}
  65. }',
  66. ];
  67. yield 'default-static' => [
  68. '<?php
  69. final class SomeClass {
  70. public static function foo() {}
  71. protected static function bar() {}
  72. private static function baz() {}
  73. }',
  74. '<?php
  75. final class SomeClass {
  76. final public static function foo() {}
  77. final protected static function bar() {}
  78. final private static function baz() {}
  79. }',
  80. ];
  81. yield 'visibility-then-final-then-static' => [
  82. '<?php
  83. final class SomeClass {
  84. public static function foo() {}
  85. protected static function bar() {}
  86. private static function baz() {}
  87. }',
  88. '<?php
  89. final class SomeClass {
  90. public final static function foo() {}
  91. protected final static function bar() {}
  92. private final static function baz() {}
  93. }',
  94. ];
  95. yield 'visibility-then-static-then-final' => [
  96. '<?php
  97. final class SomeClass {
  98. public static function foo() {}
  99. protected static function bar() {}
  100. private static function baz() {}
  101. }',
  102. '<?php
  103. final class SomeClass {
  104. public static final function foo() {}
  105. protected static final function bar() {}
  106. private static final function baz() {}
  107. }',
  108. ];
  109. yield 'static-then-visibility-then-final' => [
  110. '<?php
  111. final class SomeClass {
  112. static public function foo() {}
  113. static protected function bar() {}
  114. static private function baz() {}
  115. }',
  116. '<?php
  117. final class SomeClass {
  118. static public final function foo() {}
  119. static protected final function bar() {}
  120. static private final function baz() {}
  121. }',
  122. ];
  123. yield 'static-then-final-then-visibility' => [
  124. '<?php
  125. final class SomeClass {
  126. static public function foo() {}
  127. static protected function bar() {}
  128. static private function baz() {}
  129. }',
  130. '<?php
  131. final class SomeClass {
  132. static final public function foo() {}
  133. static final protected function bar() {}
  134. static final private function baz() {}
  135. }',
  136. ];
  137. yield 'no-visibility' => [
  138. '<?php
  139. final class Foo {
  140. function foo() {}
  141. function bar() {}
  142. function baz() {}
  143. }',
  144. '<?php
  145. final class Foo {
  146. final function foo() {}
  147. final function bar() {}
  148. final function baz() {}
  149. }',
  150. ];
  151. yield 'no-visibility-final-then-static' => [
  152. '<?php
  153. final class SomeClass {
  154. static function foo() {}
  155. static function bar() {}
  156. static function baz() {}
  157. }',
  158. '<?php
  159. final class SomeClass {
  160. final static function foo() {}
  161. final static function bar() {}
  162. final static function baz() {}
  163. }',
  164. ];
  165. yield 'no-visibility-static-then-final' => [
  166. '<?php
  167. final class SomeClass {
  168. static function foo() {}
  169. static function bar() {}
  170. static function baz() {}
  171. }',
  172. '<?php
  173. final class SomeClass {
  174. static final function foo() {}
  175. static final function bar() {}
  176. static final function baz() {}
  177. }',
  178. ];
  179. yield 'private-method' => [
  180. '<?php
  181. class Foo {
  182. final function bar0() {}
  183. final public function bar1() {}
  184. final protected function bar2() {}
  185. final static public function bar4() {}
  186. final public static function bar5() {}
  187. private function bar31() {}
  188. private function bar32() {}
  189. }',
  190. '<?php
  191. class Foo {
  192. final function bar0() {}
  193. final public function bar1() {}
  194. final protected function bar2() {}
  195. final static public function bar4() {}
  196. final public static function bar5() {}
  197. final private function bar31() {}
  198. private final function bar32() {}
  199. }',
  200. ];
  201. yield 'private-method-with-visibility-before-final' => [
  202. '<?php
  203. class Foo {
  204. private function bar() {}
  205. }',
  206. '<?php
  207. class Foo {
  208. private final function bar() {}
  209. }',
  210. ];
  211. yield 'preserve-comment' => [
  212. '<?php final class Foo { /* comment */public function foo() {} }',
  213. '<?php final class Foo { final/* comment */public function foo() {} }',
  214. ];
  215. yield 'multiple-classes-per-file' => [
  216. '<?php final class Foo { public function foo() {} } abstract class Bar { final public function bar() {} }',
  217. '<?php final class Foo { final public function foo() {} } abstract class Bar { final public function bar() {} }',
  218. ];
  219. yield 'non-final' => [
  220. '<php class Foo { final public function foo() {} }',
  221. ];
  222. yield 'abstract-class' => [
  223. '<php abstract class Foo { final public function foo() {} }',
  224. ];
  225. yield 'final-method-with-private-attribute' => [
  226. '<?php abstract class Foo { private static $var; final public function foo() {} }',
  227. ];
  228. yield 'trait' => [
  229. '<php trait Foo { final public function foo() {} }',
  230. ];
  231. yield 'do not fix constructors' => [
  232. '<?php
  233. class Bar
  234. {
  235. final private function __construct()
  236. {
  237. }
  238. }',
  239. ];
  240. yield 'anonymous-class-inside' => [
  241. '<?php
  242. final class Foo
  243. {
  244. public function foo()
  245. {
  246. }
  247. private function bar()
  248. {
  249. new class {
  250. final public function baz()
  251. {
  252. }
  253. };
  254. }
  255. }
  256. ',
  257. '<?php
  258. final class Foo
  259. {
  260. final public function foo()
  261. {
  262. }
  263. private function bar()
  264. {
  265. new class {
  266. final public function baz()
  267. {
  268. }
  269. };
  270. }
  271. }
  272. ',
  273. ];
  274. yield 'anonymous-class-inside-with-final-private-method' => [
  275. '<?php
  276. class Foo
  277. {
  278. private function bar()
  279. {
  280. new class {
  281. private function qux()
  282. {
  283. }
  284. };
  285. }
  286. }
  287. ',
  288. '<?php
  289. class Foo
  290. {
  291. private function bar()
  292. {
  293. new class {
  294. final private function qux()
  295. {
  296. }
  297. };
  298. }
  299. }
  300. ',
  301. ];
  302. yield 'final private static' => [
  303. '<?php
  304. class Foo {
  305. public function bar(){}
  306. private static function bar1() {echo 1;}
  307. private static function bar2() {echo 2;}
  308. static private function bar3() {echo 3;}
  309. private static function bar4() {echo 4;}
  310. static private function bar5() {echo 5;}
  311. static private function bar6() {echo 6;}
  312. }
  313. ',
  314. '<?php
  315. class Foo {
  316. public function bar(){}
  317. private static final function bar1() {echo 1;}
  318. private final static function bar2() {echo 2;}
  319. final static private function bar3() {echo 3;}
  320. final private static function bar4() {echo 4;}
  321. static final private function bar5() {echo 5;}
  322. static private final function bar6() {echo 6;}
  323. }
  324. ',
  325. ];
  326. yield [
  327. '<?php
  328. abstract class Foo {
  329. public final function bar1(){ $this->bar3(); }
  330. private function bar2(){ echo 1; }
  331. private function bar3(){ echo 2; }
  332. }',
  333. '<?php
  334. abstract class Foo {
  335. public final function bar1(){ $this->bar3(); }
  336. private function bar2(){ echo 1; }
  337. private final function bar3(){ echo 2; }
  338. }',
  339. ];
  340. yield [
  341. '<?php
  342. final class Foo
  343. {
  344. private function baz() {}
  345. }
  346. class Bar
  347. {
  348. final private function bar1() {}
  349. }
  350. ',
  351. '<?php
  352. final class Foo
  353. {
  354. final private function baz() {}
  355. }
  356. class Bar
  357. {
  358. final private function bar1() {}
  359. }
  360. ',
  361. ['private_methods' => false],
  362. ];
  363. }
  364. /**
  365. * @dataProvider provideFix81Cases
  366. *
  367. * @requires PHP 8.1
  368. */
  369. public function testFix81(string $expected, ?string $input = null): void
  370. {
  371. $this->doTest($expected, $input);
  372. }
  373. /**
  374. * @return iterable<int|string, array{0: string, 1?: string}>
  375. */
  376. public static function provideFix81Cases(): iterable
  377. {
  378. yield [
  379. '<?php
  380. final class Foo81 {
  381. public readonly string $prop1;
  382. readonly public string $prop2;
  383. readonly string $prop3;
  384. }
  385. ',
  386. ];
  387. yield [
  388. '<?php
  389. class Foo81 {
  390. public readonly string $prop1;
  391. readonly public string $prop2;
  392. readonly string $prop3;
  393. }
  394. ',
  395. ];
  396. yield [
  397. '<?php
  398. final class Foo81 {
  399. public function foo81() {}
  400. protected function bar81() {}
  401. private function baz81() {}
  402. public readonly string $prop81;
  403. final public const Y = "i81";
  404. final const XY = "i81";
  405. }
  406. ',
  407. '<?php
  408. final class Foo81 {
  409. final public function foo81() {}
  410. final protected function bar81() {}
  411. final private function baz81() {}
  412. public readonly string $prop81;
  413. final public const Y = "i81";
  414. final const XY = "i81";
  415. }
  416. ',
  417. ];
  418. yield 'enum' => [
  419. '<?php
  420. enum Foo: string
  421. {
  422. case Hearts = "H";
  423. public function test() {
  424. echo 123;
  425. }
  426. }
  427. var_dump(Foo::Spades);',
  428. '<?php
  429. enum Foo: string
  430. {
  431. case Hearts = "H";
  432. final public function test() {
  433. echo 123;
  434. }
  435. }
  436. var_dump(Foo::Spades);',
  437. ];
  438. }
  439. /**
  440. * @dataProvider provideFix82Cases
  441. *
  442. * @requires PHP 8.2
  443. */
  444. public function testFix82(string $expected, string $input): void
  445. {
  446. $this->doTest($expected, $input);
  447. }
  448. /**
  449. * @return iterable<string, array{string, string}>
  450. */
  451. public static function provideFix82Cases(): iterable
  452. {
  453. yield 'final readonly class - final after visibility method' => [
  454. '<?php
  455. final readonly class Foo {
  456. public function foo() {}
  457. protected function bar() {}
  458. private function baz() {}
  459. }',
  460. '<?php
  461. final readonly class Foo {
  462. public final function foo() {}
  463. protected final function bar() {}
  464. private final function baz() {}
  465. }',
  466. ];
  467. yield 'readonly comment final class - final before visibility method' => [
  468. '<?php
  469. readonly /* X */ final class Foo {
  470. public function foo() {}
  471. protected function bar() {}
  472. private function baz() {}
  473. }',
  474. '<?php
  475. readonly /* X */ final class Foo {
  476. final public function foo() {}
  477. final protected function bar() {}
  478. final private function baz() {}
  479. }',
  480. ];
  481. }
  482. }