NoUnneededFinalMethodFixerTest.php 12 KB

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