NoEmptyStatementFixerTest.php 14 KB

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