NoEmptyStatementFixerTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  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\Semicolon;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  16. *
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\Semicolon\NoEmptyStatementFixer
  20. *
  21. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Semicolon\NoEmptyStatementFixer>
  22. */
  23. final class NoEmptyStatementFixerTest extends AbstractFixerTestCase
  24. {
  25. /**
  26. * @dataProvider provideNoEmptyStatementsCases
  27. */
  28. public function testNoEmptyStatements(string $expected, ?string $input = null): void
  29. {
  30. $this->doTest($expected, $input);
  31. }
  32. /**
  33. * @return iterable<array{0: string, 1?: string}>
  34. */
  35. public static function provideNoEmptyStatementsCases(): iterable
  36. {
  37. yield [
  38. '<?php
  39. abstract class TestClass0 extends Test IMPLEMENTS TestInterface, TestInterface2
  40. {
  41. }
  42. ',
  43. '<?php
  44. abstract class TestClass0 extends Test IMPLEMENTS TestInterface, TestInterface2
  45. {
  46. };
  47. ',
  48. ];
  49. yield [
  50. '<?php
  51. abstract class TestClass1 EXTENDS Test implements TestInterface
  52. {
  53. }
  54. ',
  55. '<?php
  56. abstract class TestClass1 EXTENDS Test implements TestInterface
  57. {
  58. };
  59. ',
  60. ];
  61. yield [
  62. '<?php
  63. CLASS TestClass2 extends Test
  64. {
  65. }
  66. ',
  67. '<?php
  68. CLASS TestClass2 extends Test
  69. {
  70. };
  71. ',
  72. ];
  73. yield [
  74. '<?php
  75. class TestClass3 implements TestInterface1
  76. {
  77. }
  78. ',
  79. '<?php
  80. class TestClass3 implements TestInterface1
  81. {
  82. };
  83. ',
  84. ];
  85. yield [
  86. '<?php
  87. class TestClass4
  88. {
  89. }
  90. ',
  91. '<?php
  92. class TestClass4
  93. {
  94. };
  95. ',
  96. ];
  97. yield [
  98. '<?php
  99. interface TestInterface1
  100. {
  101. }
  102. ',
  103. '<?php
  104. interface TestInterface1
  105. {
  106. };
  107. ',
  108. ];
  109. yield [
  110. '<?php
  111. interface TestExtendingInterface extends TestInterface2, TestInterface3 {
  112. }
  113. ',
  114. '<?php
  115. interface TestExtendingInterface extends TestInterface2, TestInterface3 {
  116. };
  117. ',
  118. ];
  119. yield [
  120. '<?php
  121. namespace Two {
  122. $a = 1; {
  123. }
  124. }
  125. ',
  126. '<?php
  127. namespace Two {;;
  128. $a = 1; {
  129. };
  130. }
  131. ',
  132. ];
  133. yield [
  134. '<?php
  135. {
  136. '.'
  137. }
  138. echo 1;
  139. ',
  140. '<?php
  141. {
  142. ;
  143. };
  144. echo 1;
  145. ',
  146. ];
  147. yield [
  148. '<?php
  149. while($time < $a)
  150. ;
  151. echo "done waiting.";
  152. $b = \Test;
  153. ',
  154. ];
  155. yield [
  156. '<?php
  157. if($a>1){
  158. }
  159. ',
  160. '<?php
  161. if($a>1){
  162. };
  163. ',
  164. ];
  165. yield [
  166. '<?php
  167. if($a>1) {
  168. } else {
  169. }
  170. ',
  171. '<?php
  172. if($a>1) {
  173. } else {
  174. };
  175. ',
  176. ];
  177. yield [
  178. '<?php
  179. try{
  180. }catch (\Exception $e) {
  181. }
  182. ',
  183. '<?php
  184. try{
  185. }catch (\Exception $e) {
  186. };
  187. ',
  188. ];
  189. yield [
  190. '<?php ',
  191. '<?php ;',
  192. ];
  193. yield [
  194. '<?php
  195. function foo()
  196. {
  197. // a
  198. }
  199. ',
  200. '<?php
  201. function foo()
  202. {
  203. ; // a
  204. }
  205. ',
  206. ];
  207. yield [
  208. '<?php function foo(){}',
  209. '<?php function foo(){;;}',
  210. ];
  211. yield [
  212. '<?php class Test{}',
  213. '<?php class Test{};',
  214. ];
  215. yield [
  216. '<?php
  217. for(;;) {
  218. }
  219. ',
  220. '<?php
  221. for(;;) {
  222. };
  223. ',
  224. ];
  225. yield [
  226. '<?php
  227. foreach($a as $b) {
  228. }
  229. foreach($a as $b => $c) {
  230. }
  231. ',
  232. '<?php
  233. foreach($a as $b) {
  234. };
  235. foreach($a as $b => $c) {
  236. };
  237. ',
  238. ];
  239. yield [
  240. '<?php
  241. while($a > 1){
  242. }
  243. do {
  244. } while($a>1); // 1
  245. ',
  246. '<?php
  247. while($a > 1){
  248. };
  249. do {
  250. } while($a>1); 1; // 1
  251. ',
  252. ];
  253. yield [
  254. '<?php
  255. switch($a) {
  256. default : {echo 1;}
  257. }
  258. ',
  259. '<?php
  260. switch($a) {
  261. default : {echo 1;}
  262. };
  263. ',
  264. ];
  265. yield [
  266. '<?php
  267. function test($a, $b) {
  268. }
  269. ',
  270. '<?php
  271. function test($a, $b) {
  272. };
  273. ',
  274. ];
  275. yield [
  276. '<?php
  277. function foo($n)
  278. {
  279. '.'
  280. $a = function(){};
  281. $b = function() use ($a) {};
  282. ++${"a"};
  283. switch(fooBar()) {
  284. case 5;{
  285. }
  286. }
  287. return $n->{$o};
  288. }
  289. ',
  290. '<?php
  291. function foo($n)
  292. {
  293. ;
  294. $a = function(){};
  295. $b = function() use ($a) {};
  296. ++${"a"};
  297. switch(fooBar()) {
  298. case 5;{
  299. }
  300. };
  301. return $n->{$o};
  302. };
  303. ',
  304. ];
  305. yield [
  306. '<?php
  307. declare(ticks=1) {
  308. // entire script here
  309. }
  310. declare(ticks=1);
  311. ',
  312. '<?php
  313. declare(ticks=1) {
  314. // entire script here
  315. };
  316. declare(ticks=1);
  317. ',
  318. ];
  319. yield [
  320. '<?php
  321. namespace A\B\C;
  322. use D;
  323. ',
  324. '<?php
  325. namespace A\B\C;;;;
  326. use D;;;;
  327. ',
  328. ];
  329. yield [
  330. '<?php
  331. namespace A\B\C;
  332. use D;
  333. ',
  334. '<?php
  335. namespace A\B\C;
  336. use D;;;;
  337. ',
  338. ];
  339. yield [
  340. '<?php
  341. namespace A\B\C;use D;
  342. ',
  343. '<?php
  344. namespace A\B\C;;use D;
  345. ',
  346. ];
  347. yield [
  348. '<?php
  349. trait TestTrait
  350. {
  351. }
  352. ',
  353. '<?php
  354. trait TestTrait
  355. {
  356. };
  357. ',
  358. ];
  359. yield [
  360. '<?php
  361. try {
  362. throw new \Exception("Foo.");
  363. } catch (\Exception $e){
  364. //
  365. } finally {
  366. } '.'
  367. ',
  368. '<?php
  369. try {
  370. throw new \Exception("Foo.");
  371. } catch (\Exception $e){
  372. //
  373. } finally {
  374. } ;
  375. ',
  376. ];
  377. foreach (['break', 'continue'] as $ops) {
  378. yield [
  379. \sprintf('<?php while(true) {%s ;}', $ops),
  380. \sprintf('<?php while(true) {%s 1;}', $ops),
  381. ];
  382. }
  383. foreach (['1', '1.0', '"foo"', '$foo'] as $noop) {
  384. yield [
  385. '<?php echo "foo"; ',
  386. \sprintf('<?php echo "foo"; %s ;', $noop),
  387. ];
  388. }
  389. yield [
  390. '<?php /* 1 */ /* 2 */ /* 3 */ ',
  391. '<?php /* 1 */ ; /* 2 */ 1 /* 3 */ ;',
  392. ];
  393. yield [
  394. '<?php
  395. while(true) {while(true) {break 2;}}
  396. while(true) {continue;}
  397. ',
  398. ];
  399. yield [
  400. '<?php if ($foo1) {} ',
  401. '<?php if ($foo1) {} 1;',
  402. ];
  403. yield [
  404. '<?php if ($foo2) {}',
  405. '<?php if ($foo2) {1;}',
  406. ];
  407. }
  408. /**
  409. * @dataProvider provideFixCases
  410. */
  411. public function testFix(string $expected, ?string $input = null): void
  412. {
  413. $this->doTest($expected, $input);
  414. }
  415. /**
  416. * @return iterable<array{0: string, 1?: string}>
  417. */
  418. public static function provideFixCases(): iterable
  419. {
  420. yield [
  421. '<?php
  422. use function Functional\map;
  423. $a = new class {
  424. public function log($msg)
  425. {
  426. }
  427. };
  428. ',
  429. ];
  430. yield [
  431. '<?php
  432. use function Functional\map;
  433. $a = new class extends A {
  434. };
  435. ',
  436. ];
  437. yield [
  438. '<?php
  439. use function Functional\map;
  440. $a = new class implements B {
  441. };
  442. ',
  443. ];
  444. yield [
  445. '<?php
  446. use function Functional\map;
  447. $a = new class extends A implements B {
  448. };
  449. ',
  450. ];
  451. yield [
  452. '<?php
  453. $a = new class extends \A implements B\C {
  454. };
  455. ',
  456. ];
  457. yield [
  458. '<?php {{}}',
  459. '<?php {{}};',
  460. ];
  461. yield [
  462. '<?php
  463. namespace A\B\C {
  464. }
  465. ',
  466. '<?php
  467. namespace A\B\C {
  468. };
  469. ',
  470. ];
  471. yield [
  472. '<?php
  473. namespace A{
  474. }
  475. ',
  476. '<?php
  477. namespace A{
  478. };
  479. ',
  480. ];
  481. yield [
  482. '<?php
  483. namespace{
  484. }
  485. ',
  486. '<?php
  487. namespace{
  488. };
  489. ',
  490. ];
  491. }
  492. /**
  493. * @dataProvider provideCasesWithShortOpenTagCases
  494. */
  495. public function testCasesWithShortOpenTag(string $expected, ?string $input = null): void
  496. {
  497. if (!\ini_get('short_open_tag')) {
  498. self::markTestSkipped('No short tag tests possible.');
  499. }
  500. $this->doTest($expected, $input);
  501. }
  502. /**
  503. * @return iterable<array{string, string}>
  504. */
  505. public static function provideCasesWithShortOpenTagCases(): iterable
  506. {
  507. yield [
  508. '<? ',
  509. '<? ;',
  510. ];
  511. }
  512. /**
  513. * @dataProvider provideFixMultipleSemicolonsCases
  514. */
  515. public function testFixMultipleSemicolons(string $expected, ?string $input = null): void
  516. {
  517. $this->doTest($expected, $input);
  518. }
  519. /**
  520. * @return iterable<array{0: string, 1?: string}>
  521. */
  522. public static function provideFixMultipleSemicolonsCases(): iterable
  523. {
  524. yield [
  525. '<?php $foo = 2 ; //
  526. '.'
  527. ',
  528. '<?php $foo = 2 ; //
  529. ;
  530. ',
  531. ];
  532. yield [
  533. '<?php $foo = 3; /**/ ',
  534. '<?php $foo = 3; /**/; ;',
  535. ];
  536. yield [
  537. '<?php $foo = 1;',
  538. '<?php $foo = 1;;;',
  539. ];
  540. yield [
  541. '<?php $foo = 4; ',
  542. '<?php $foo = 4;; ;;',
  543. ];
  544. yield [
  545. '<?php $foo = 5;
  546. ',
  547. '<?php $foo = 5;;
  548. ;
  549. ;',
  550. ];
  551. yield [
  552. '<?php $foo = 6; ',
  553. '<?php $foo = 6;; ',
  554. ];
  555. yield [
  556. '<?php for ($i = 7; ; ++$i) {}',
  557. ];
  558. yield [
  559. '<?php
  560. switch($a){
  561. case 8;
  562. echo 9;
  563. }
  564. ',
  565. '<?php
  566. switch($a){
  567. case 8;;
  568. echo 9;
  569. }
  570. ',
  571. ];
  572. }
  573. /**
  574. * @dataProvider provideFix81Cases
  575. *
  576. * @requires PHP 8.1
  577. */
  578. public function testFix81(string $expected, string $input): void
  579. {
  580. $this->doTest($expected, $input);
  581. }
  582. /**
  583. * @return iterable<array{string, string}>
  584. */
  585. public static function provideFix81Cases(): iterable
  586. {
  587. yield [
  588. '<?php enum Foo{}',
  589. '<?php enum Foo{};',
  590. ];
  591. }
  592. }