SelfStaticAccessorFixerTest.php 11 KB

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