NoUnneededFinalMethodFixerTest.php 11 KB

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