StatementIndentationFixerTest.php 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677
  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\Whitespace;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. use PhpCsFixer\WhitespacesFixerConfig;
  15. /**
  16. * @internal
  17. *
  18. * @covers \PhpCsFixer\Fixer\Whitespace\StatementIndentationFixer
  19. *
  20. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Whitespace\StatementIndentationFixer>
  21. *
  22. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\Whitespace\StatementIndentationFixer
  23. */
  24. final class StatementIndentationFixerTest extends AbstractFixerTestCase
  25. {
  26. /**
  27. * @param _AutogeneratedInputConfiguration $configuration
  28. *
  29. * @dataProvider provideFixCases
  30. */
  31. public function testFix(string $expected, ?string $input = null, array $configuration = []): void
  32. {
  33. $this->fixer->configure($configuration);
  34. $this->doTest($expected, $input);
  35. }
  36. /**
  37. * @return iterable<array{0: string, 1?: ?string, 2?: array<string, mixed>}>
  38. */
  39. public static function provideFixCases(): iterable
  40. {
  41. yield 'no brace block' => [
  42. '<?php
  43. foo();
  44. bar();',
  45. '<?php
  46. foo();
  47. bar();',
  48. ];
  49. yield 'simple' => [
  50. '<?php
  51. if ($foo) {
  52. foo();
  53. bar();
  54. }',
  55. '<?php
  56. if ($foo) {
  57. foo();
  58. bar();
  59. }',
  60. ];
  61. yield 'braces on same line as code' => [
  62. '<?php
  63. if ($foo) {
  64. foo();
  65. if ($bar) { bar(); }
  66. }',
  67. '<?php
  68. if ($foo) {
  69. foo();
  70. if ($bar) { bar(); }
  71. }',
  72. ];
  73. yield 'with several closing braces on same line' => [
  74. '<?php
  75. if ($foo) { foo();
  76. if ($bar) { bar();
  77. if ($baz) { baz(); }}
  78. foo();
  79. }
  80. foo();',
  81. '<?php
  82. if ($foo) { foo();
  83. if ($bar) { bar();
  84. if ($baz) { baz(); }}
  85. foo();
  86. }
  87. foo();',
  88. ];
  89. yield 'with meaningful content on closing line' => [
  90. '<?php
  91. if ($foo) {
  92. foo(); }
  93. foo();',
  94. '<?php
  95. if ($foo) {
  96. foo(); }
  97. foo();',
  98. ];
  99. // @TODO brace at line 6 should have one level of indentation
  100. yield 'with several opening braces on same line' => [
  101. '<?php
  102. if ($foo) { if ($foo) { foo();
  103. if ($bar) { if ($bar) { bar(); }
  104. baz();
  105. }
  106. }
  107. baz();
  108. }
  109. baz();',
  110. '<?php
  111. if ($foo) { if ($foo) { foo();
  112. if ($bar) { if ($bar) { bar(); }
  113. baz();
  114. }
  115. }
  116. baz();
  117. }
  118. baz();',
  119. ];
  120. yield 'function definition arguments' => [
  121. '<?php
  122. function foo(
  123. $bar,
  124. $baz
  125. ) {
  126. }',
  127. '<?php
  128. function foo(
  129. $bar,
  130. $baz
  131. ) {
  132. }',
  133. ];
  134. yield 'anonymous function definition arguments' => [
  135. '<?php
  136. $foo = function(
  137. $bar,
  138. $baz
  139. ) {
  140. };',
  141. '<?php
  142. $foo = function(
  143. $bar,
  144. $baz
  145. ) {
  146. };',
  147. ];
  148. yield 'interface method definition arguments' => [
  149. '<?php
  150. interface Foo {
  151. public function foo(
  152. $bar,
  153. $baz
  154. );
  155. }',
  156. '<?php
  157. interface Foo {
  158. public function foo(
  159. $bar,
  160. $baz
  161. );
  162. }',
  163. ];
  164. yield 'class method definition arguments' => [
  165. '<?php
  166. class Foo {
  167. public function foo(
  168. $bar,
  169. $baz
  170. ) {
  171. }
  172. }',
  173. '<?php
  174. class Foo {
  175. public function foo(
  176. $bar,
  177. $baz
  178. ) {
  179. }
  180. }',
  181. ];
  182. yield 'multiple class methods with many permutations of visibility modifiers' => [
  183. '<?php
  184. abstract class Test {
  185. final protected function test_final_protected() {}
  186. static private function test_static_private() {}
  187. private function test_private() {}
  188. private static function test_private_static() {}
  189. abstract public static function test_abstract_public_static();
  190. abstract static public function test_abstract_static_public();
  191. abstract public function test_abstract_public();
  192. protected abstract function test_protected_abstract();
  193. public abstract function test_public_abstract();
  194. final static protected function test_final_static_protected() {}
  195. final private static function test_final_private_static() {}
  196. public final function test_public_final() {}
  197. final private function test_final_private() {}
  198. static final public function test_static_final_public() {}
  199. protected abstract static function test_protected_abstract_static();
  200. public static abstract function test_public_static_abstract();
  201. protected static abstract function test_protected_static_abstract();
  202. static final function test_static_final() {}
  203. final static private function test_final_static_private() {}
  204. static protected abstract function test_static_protected_abstract();
  205. public abstract static function test_public_abstract_static();
  206. static final protected function test_static_final_protected() {}
  207. final public static function test_final_public_static() {}
  208. static final private function test_static_final_private() {}
  209. abstract protected function test_abstract_protected();
  210. abstract static protected function test_abstract_static_protected();
  211. private static final function test_private_static_final() {}
  212. final static function test_final_static() {}
  213. protected static function test_protected_static() {}
  214. protected function test_protected() {}
  215. public static function test_public_static() {}
  216. final function test_final() {}
  217. abstract protected static function test_abstract_protected_static();
  218. static protected function test_static_protected() {}
  219. static abstract function test_static_abstract();
  220. static abstract protected function test_static_abstract_protected();
  221. protected final static function test_protected_final_static() {}
  222. static public final function test_static_public_final() {}
  223. public final static function test_public_final_static() {}
  224. abstract static function test_abstract_static();
  225. public static final function test_public_static_final() {}
  226. static function test_static() {}
  227. abstract function test_abstract();
  228. static protected final function test_static_protected_final() {}
  229. static private final function test_static_private_final() {}
  230. private final function test_private_final() {}
  231. static public abstract function test_static_public_abstract();
  232. protected static final function test_protected_static_final() {}
  233. final protected static function test_final_protected_static() {}
  234. final static public function test_final_static_public() {}
  235. static public function test_static_public() {}
  236. function test_() {}
  237. static abstract public function test_static_abstract_public();
  238. final public function test_final_public() {}
  239. private final static function test_private_final_static() {}
  240. protected final function test_protected_final() {}
  241. public function test_public() {}
  242. }',
  243. '<?php
  244. abstract class Test {
  245. final protected function test_final_protected() {}
  246. static private function test_static_private() {}
  247. private function test_private() {}
  248. private static function test_private_static() {}
  249. abstract public static function test_abstract_public_static();
  250. abstract static public function test_abstract_static_public();
  251. abstract public function test_abstract_public();
  252. protected abstract function test_protected_abstract();
  253. public abstract function test_public_abstract();
  254. final static protected function test_final_static_protected() {}
  255. final private static function test_final_private_static() {}
  256. public final function test_public_final() {}
  257. final private function test_final_private() {}
  258. static final public function test_static_final_public() {}
  259. protected abstract static function test_protected_abstract_static();
  260. public static abstract function test_public_static_abstract();
  261. protected static abstract function test_protected_static_abstract();
  262. static final function test_static_final() {}
  263. final static private function test_final_static_private() {}
  264. static protected abstract function test_static_protected_abstract();
  265. public abstract static function test_public_abstract_static();
  266. static final protected function test_static_final_protected() {}
  267. final public static function test_final_public_static() {}
  268. static final private function test_static_final_private() {}
  269. abstract protected function test_abstract_protected();
  270. abstract static protected function test_abstract_static_protected();
  271. private static final function test_private_static_final() {}
  272. final static function test_final_static() {}
  273. protected static function test_protected_static() {}
  274. protected function test_protected() {}
  275. public static function test_public_static() {}
  276. final function test_final() {}
  277. abstract protected static function test_abstract_protected_static();
  278. static protected function test_static_protected() {}
  279. static abstract function test_static_abstract();
  280. static abstract protected function test_static_abstract_protected();
  281. protected final static function test_protected_final_static() {}
  282. static public final function test_static_public_final() {}
  283. public final static function test_public_final_static() {}
  284. abstract static function test_abstract_static();
  285. public static final function test_public_static_final() {}
  286. static function test_static() {}
  287. abstract function test_abstract();
  288. static protected final function test_static_protected_final() {}
  289. static private final function test_static_private_final() {}
  290. private final function test_private_final() {}
  291. static public abstract function test_static_public_abstract();
  292. protected static final function test_protected_static_final() {}
  293. final protected static function test_final_protected_static() {}
  294. final static public function test_final_static_public() {}
  295. static public function test_static_public() {}
  296. function test_() {}
  297. static abstract public function test_static_abstract_public();
  298. final public function test_final_public() {}
  299. private final static function test_private_final_static() {}
  300. protected final function test_protected_final() {}
  301. public function test_public() {}
  302. }',
  303. ];
  304. yield 'trait method definition arguments' => [
  305. '<?php
  306. trait Foo {
  307. public function foo(
  308. $bar,
  309. $baz
  310. ) {
  311. }
  312. }',
  313. '<?php
  314. trait Foo {
  315. public function foo(
  316. $bar,
  317. $baz
  318. ) {
  319. }
  320. }',
  321. ];
  322. yield 'function call arguments' => [
  323. '<?php
  324. foo(
  325. $bar,
  326. $baz
  327. );',
  328. '<?php
  329. foo(
  330. $bar,
  331. $baz
  332. );',
  333. ];
  334. yield 'variable function call arguments' => [
  335. '<?php
  336. $foo(
  337. $bar,
  338. $baz
  339. );',
  340. '<?php
  341. $foo(
  342. $bar,
  343. $baz
  344. );',
  345. ];
  346. yield 'chained method calls' => [
  347. '<?php
  348. if ($foo) {
  349. $foo
  350. ->bar()
  351. ->baz()
  352. ;
  353. }',
  354. '<?php
  355. if ($foo) {
  356. $foo
  357. ->bar()
  358. ->baz()
  359. ;
  360. }',
  361. ];
  362. yield 'nested arrays (long syntax)' => [
  363. '<?php
  364. if ($foo) {
  365. $foo = array(
  366. $foo,
  367. $bar
  368. ->bar()
  369. ,
  370. array($baz)
  371. )
  372. ;
  373. }',
  374. '<?php
  375. if ($foo) {
  376. $foo = array(
  377. $foo,
  378. $bar
  379. ->bar()
  380. ,
  381. array($baz)
  382. )
  383. ;
  384. }',
  385. ];
  386. yield 'nested arrays (short syntax)' => [
  387. '<?php
  388. if ($foo) {
  389. $foo = [
  390. $foo,
  391. $bar
  392. ->bar()
  393. ,
  394. [$baz]
  395. ]
  396. ;
  397. }',
  398. '<?php
  399. if ($foo) {
  400. $foo = [
  401. $foo,
  402. $bar
  403. ->bar()
  404. ,
  405. [$baz]
  406. ]
  407. ;
  408. }',
  409. ];
  410. yield 'array (long syntax) with function call' => [
  411. '<?php
  412. if ($foo) {
  413. $foo = array(
  414. foo(
  415. $bar,
  416. $baz
  417. )
  418. )
  419. ;
  420. }',
  421. '<?php
  422. if ($foo) {
  423. $foo = array(
  424. foo(
  425. $bar,
  426. $baz
  427. )
  428. )
  429. ;
  430. }',
  431. ];
  432. yield 'array (short syntax) with function call' => [
  433. '<?php
  434. if ($foo) {
  435. $foo = [
  436. foo(
  437. $bar,
  438. $baz
  439. )
  440. ]
  441. ;
  442. }',
  443. '<?php
  444. if ($foo) {
  445. $foo = [
  446. foo(
  447. $bar,
  448. $baz
  449. )
  450. ]
  451. ;
  452. }',
  453. ];
  454. yield 'array (long syntax) with class instantiation' => [
  455. '<?php
  456. if ($foo) {
  457. $foo = array(
  458. new Foo(
  459. $bar,
  460. $baz
  461. )
  462. )
  463. ;
  464. }',
  465. '<?php
  466. if ($foo) {
  467. $foo = array(
  468. new Foo(
  469. $bar,
  470. $baz
  471. )
  472. )
  473. ;
  474. }',
  475. ];
  476. yield 'array (short syntax) with class instantiation' => [
  477. '<?php
  478. if ($foo) {
  479. $foo = [
  480. new Foo(
  481. $bar,
  482. $baz
  483. )
  484. ]
  485. ;
  486. }',
  487. '<?php
  488. if ($foo) {
  489. $foo = [
  490. new Foo(
  491. $bar,
  492. $baz
  493. )
  494. ]
  495. ;
  496. }',
  497. ];
  498. yield 'implements list' => [
  499. '<?php
  500. class Foo implements
  501. Bar,
  502. Baz
  503. {}',
  504. '<?php
  505. class Foo implements
  506. Bar,
  507. Baz
  508. {}',
  509. ];
  510. yield 'extends list' => [
  511. '<?php
  512. interface Foo extends
  513. Bar,
  514. Baz
  515. {}',
  516. '<?php
  517. interface Foo extends
  518. Bar,
  519. Baz
  520. {}',
  521. ];
  522. yield 'use list' => [
  523. '<?php
  524. class Foo {
  525. use Bar,
  526. Baz;
  527. }',
  528. '<?php
  529. class Foo {
  530. use Bar,
  531. Baz;
  532. }',
  533. ];
  534. yield 'chained method call with argument' => [
  535. '<?php
  536. $foo
  537. ->bar(
  538. $baz
  539. );',
  540. '<?php
  541. $foo
  542. ->bar(
  543. $baz
  544. );',
  545. ];
  546. yield 'argument separator on its own line' => [
  547. '<?php
  548. foo(
  549. 1
  550. ,
  551. 2
  552. );',
  553. '<?php
  554. foo(
  555. 1
  556. ,
  557. 2
  558. );',
  559. ];
  560. yield 'statement end on its own line' => [
  561. '<?php
  562. if (true) {
  563. $foo =
  564. $a
  565. && $b
  566. ;
  567. }',
  568. '<?php
  569. if (true) {
  570. $foo =
  571. $a
  572. && $b
  573. ;
  574. }',
  575. ];
  576. yield 'multiline control structure conditions' => [
  577. '<?php
  578. if ($a
  579. && $b) {
  580. foo();
  581. }',
  582. '<?php
  583. if ($a
  584. && $b) {
  585. foo();
  586. }',
  587. ];
  588. yield 'switch' => [
  589. '<?php
  590. switch ($foo) {
  591. case 1:
  592. echo "foo";
  593. break;
  594. case 2:
  595. echo "bar";
  596. break;
  597. case 3:
  598. default:
  599. echo "baz";
  600. }',
  601. '<?php
  602. switch ($foo) {
  603. case 1:
  604. echo "foo";
  605. break;
  606. case 2:
  607. echo "bar";
  608. break;
  609. case 3:
  610. default:
  611. echo "baz";
  612. }',
  613. ];
  614. yield 'array (long syntax) with anonymous class' => [
  615. '<?php
  616. if ($foo) {
  617. $foo = array(
  618. new class (
  619. $bar,
  620. $baz
  621. ) {
  622. private $foo;
  623. public function foo(
  624. $foo
  625. ) {
  626. return $foo;
  627. }
  628. }
  629. )
  630. ;
  631. }',
  632. '<?php
  633. if ($foo) {
  634. $foo = array(
  635. new class (
  636. $bar,
  637. $baz
  638. ) {
  639. private $foo;
  640. public function foo(
  641. $foo
  642. ) {
  643. return $foo;
  644. }
  645. }
  646. )
  647. ;
  648. }',
  649. ];
  650. yield 'array (short syntax) with anonymous class' => [
  651. '<?php
  652. if ($foo) {
  653. $foo = [
  654. new class (
  655. $bar,
  656. $baz
  657. ) {
  658. private $foo;
  659. public function foo(
  660. $foo
  661. ) {
  662. return $foo;
  663. }
  664. }
  665. ]
  666. ;
  667. }',
  668. '<?php
  669. if ($foo) {
  670. $foo = [
  671. new class (
  672. $bar,
  673. $baz
  674. ) {
  675. private $foo;
  676. public function foo(
  677. $foo
  678. ) {
  679. return $foo;
  680. }
  681. }
  682. ]
  683. ;
  684. }',
  685. ];
  686. yield 'expression function call arguments' => [
  687. '<?php
  688. (\'foo\')(
  689. $bar,
  690. $baz
  691. );',
  692. '<?php
  693. (\'foo\')(
  694. $bar,
  695. $baz
  696. );',
  697. ];
  698. yield 'arrow function definition arguments' => [
  699. '<?php
  700. $foo = fn(
  701. $bar,
  702. $baz
  703. ) => null;',
  704. '<?php
  705. $foo = fn(
  706. $bar,
  707. $baz
  708. ) => null;',
  709. ];
  710. yield 'multiline list in foreach' => [
  711. '<?php
  712. foreach ($array as [
  713. "foo" => $foo,
  714. "bar" => $bar,
  715. ]) {
  716. }',
  717. ];
  718. yield 'switch case with control structure' => [
  719. '<?php
  720. switch ($foo) {
  721. case true:
  722. if ($bar) {
  723. bar();
  724. }
  725. return true;
  726. }',
  727. '<?php
  728. switch ($foo) {
  729. case true:
  730. if ($bar) {
  731. bar();
  732. }
  733. return true;
  734. }',
  735. ];
  736. yield 'comment in method calls chain' => [
  737. '<?php
  738. $foo
  739. ->baz()
  740. /* ->baz() */
  741. ;',
  742. ];
  743. yield 'multiple anonymous functions as function arguments' => [
  744. '<?php
  745. foo(function () {
  746. bar();
  747. }, function () {
  748. baz();
  749. });',
  750. ];
  751. yield 'multiple anonymous functions as method arguments' => [
  752. '<?php
  753. $this
  754. ->bar(function ($a) {
  755. echo $a;
  756. }, function ($b) {
  757. echo $b;
  758. })
  759. ;',
  760. ];
  761. yield 'semicolon on a newline inside a switch case without break statement' => [
  762. '<?php
  763. switch (true) {
  764. case $foo:
  765. $foo
  766. ->baz()
  767. ;
  768. }',
  769. ];
  770. yield 'alternative syntax' => [
  771. '<?php if (1): ?>
  772. <div></div>
  773. <?php else: ?>
  774. <?php if (2): ?>
  775. <div></div>
  776. <?php else: ?>
  777. <div></div>
  778. <?php endif; ?>
  779. <?php endif; ?>
  780. ',
  781. ];
  782. yield 'trait import with conflict resolution' => [
  783. '<?php
  784. class Foo {
  785. use Bar,
  786. Baz {
  787. Baz::baz insteadof Bar;
  788. }
  789. }',
  790. '<?php
  791. class Foo {
  792. use Bar,
  793. Baz {
  794. Baz::baz insteadof Bar;
  795. }
  796. }',
  797. ];
  798. yield 'multiline class definition' => [
  799. '<?php
  800. class Foo
  801. extends
  802. BaseFoo
  803. implements Bar,
  804. Baz {
  805. public function foo() {
  806. }
  807. }',
  808. '<?php
  809. class Foo
  810. extends
  811. BaseFoo
  812. implements Bar,
  813. Baz {
  814. public function foo() {
  815. }
  816. }',
  817. ];
  818. yield 'comment at end of switch case' => [
  819. '<?php
  820. switch ($foo) {
  821. case 1:
  822. // Nothing to do
  823. }',
  824. ];
  825. yield 'comment at end of switch default' => [
  826. '<?php
  827. switch ($foo) {
  828. case 1:
  829. break;
  830. case 2:
  831. break;
  832. default:
  833. // Nothing to do
  834. }',
  835. ];
  836. yield 'switch ending with empty case' => [
  837. '<?php
  838. switch ($foo) {
  839. case 1:
  840. }',
  841. ];
  842. yield 'switch ending with empty default' => [
  843. '<?php
  844. switch ($foo) {
  845. default:
  846. }',
  847. ];
  848. yield 'function ending with a comment and followed by a comma' => [
  849. '<?php
  850. foo(function () {
  851. bar();
  852. // comment
  853. }, );',
  854. ];
  855. yield 'multiline arguments starting with "new" keyword' => [
  856. '<?php
  857. $result1 = foo(
  858. new Bar1(),
  859. 1
  860. );
  861. $result2 = ($function)(
  862. new Bar2(),
  863. 2
  864. );
  865. $result3 = (new Argument())(
  866. new Bar3(),
  867. 3
  868. );',
  869. ];
  870. yield 'if with only a comment and followed by else' => [
  871. '<?php
  872. if (true) {
  873. // foo
  874. } else {
  875. // bar
  876. }',
  877. '<?php
  878. if (true) {
  879. // foo
  880. } else {
  881. // bar
  882. }',
  883. ];
  884. yield 'comment before else blocks WITHOUT stick_comment_to_next_continuous_control_statement' => [
  885. '<?php
  886. // foo
  887. if ($foo) {
  888. echo "foo";
  889. // bar
  890. } else {
  891. $aaa = 1;
  892. }',
  893. '<?php
  894. // foo
  895. if ($foo) {
  896. echo "foo";
  897. // bar
  898. } else {
  899. $aaa = 1;
  900. }',
  901. ['stick_comment_to_next_continuous_control_statement' => false],
  902. ];
  903. yield 'comment before else blocks WITH stick_comment_to_next_continuous_control_statement' => [
  904. '<?php
  905. // foo
  906. if ($foo) {
  907. echo "foo";
  908. // bar
  909. } else {
  910. $aaa = 1;
  911. }',
  912. '<?php
  913. // foo
  914. if ($foo) {
  915. echo "foo";
  916. // bar
  917. } else {
  918. $aaa = 1;
  919. }',
  920. ['stick_comment_to_next_continuous_control_statement' => true],
  921. ];
  922. yield 'multiline comment in block - describing next block' => [
  923. '<?php
  924. if (1) {
  925. $b = "a";
  926. // multiline comment line 1
  927. // multiline comment line 2
  928. // multiline comment line 3
  929. } else {
  930. $c = "b";
  931. }',
  932. '<?php
  933. if (1) {
  934. $b = "a";
  935. // multiline comment line 1
  936. // multiline comment line 2
  937. // multiline comment line 3
  938. } else {
  939. $c = "b";
  940. }',
  941. ['stick_comment_to_next_continuous_control_statement' => true],
  942. ];
  943. yield 'multiline comment in block - the only content in block' => [
  944. '<?php
  945. if (1) {
  946. // multiline comment line 1
  947. // multiline comment line 2
  948. // multiline comment line 3
  949. } else {
  950. $c = "b";
  951. }',
  952. '<?php
  953. if (1) {
  954. // multiline comment line 1
  955. // multiline comment line 2
  956. // multiline comment line 3
  957. } else {
  958. $c = "b";
  959. }',
  960. ];
  961. yield 'comment before elseif blocks' => [
  962. '<?php
  963. // foo
  964. if ($foo) {
  965. echo "foo";
  966. // bar
  967. } elseif(1) {
  968. echo "bar";
  969. } elseif(2) {
  970. // do nothing
  971. } elseif(3) {
  972. $aaa = 1;
  973. // end comment in final block
  974. }',
  975. '<?php
  976. // foo
  977. if ($foo) {
  978. echo "foo";
  979. // bar
  980. } elseif(1) {
  981. echo "bar";
  982. } elseif(2) {
  983. // do nothing
  984. } elseif(3) {
  985. $aaa = 1;
  986. // end comment in final block
  987. }',
  988. ['stick_comment_to_next_continuous_control_statement' => true],
  989. ];
  990. yield 'comments at the end of if/elseif/else blocks' => [
  991. '<?php
  992. if ($foo) {
  993. echo "foo";
  994. // foo
  995. } elseif ($bar) {
  996. echo "bar";
  997. // bar
  998. } else {
  999. echo "baz";
  1000. // baz
  1001. }',
  1002. '<?php
  1003. if ($foo) {
  1004. echo "foo";
  1005. // foo
  1006. } elseif ($bar) {
  1007. echo "bar";
  1008. // bar
  1009. } else {
  1010. echo "baz";
  1011. // baz
  1012. }',
  1013. ['stick_comment_to_next_continuous_control_statement' => true],
  1014. ];
  1015. yield 'if-elseif-else without braces' => [
  1016. '<?php
  1017. if ($foo)
  1018. foo();
  1019. elseif ($bar)
  1020. bar();
  1021. else
  1022. baz();',
  1023. '<?php
  1024. if ($foo)
  1025. foo();
  1026. elseif ($bar)
  1027. bar();
  1028. else
  1029. baz();',
  1030. ];
  1031. yield 'for without braces' => [
  1032. '<?php
  1033. for (;;)
  1034. foo();',
  1035. '<?php
  1036. for (;;)
  1037. foo();',
  1038. ];
  1039. yield 'foreach without braces' => [
  1040. '<?php
  1041. foreach ($foo as $bar)
  1042. foo();',
  1043. '<?php
  1044. foreach ($foo as $bar)
  1045. foo();',
  1046. ];
  1047. yield 'while without braces' => [
  1048. '<?php
  1049. while (true)
  1050. foo();',
  1051. '<?php
  1052. while (true)
  1053. foo();',
  1054. ];
  1055. yield 'do-while without braces' => [
  1056. '<?php
  1057. do
  1058. foo();
  1059. while (true);',
  1060. '<?php
  1061. do
  1062. foo();
  1063. while (true);',
  1064. ];
  1065. yield 'nested control structures without braces' => [
  1066. '<?php
  1067. if (true)
  1068. if (true)
  1069. if (true)
  1070. for ($i = 0; $i < 1; ++$i)
  1071. echo 1;
  1072. elseif (true)
  1073. foreach ([] as $foo)
  1074. echo 2;
  1075. else if (true)
  1076. while (true)
  1077. echo 3;
  1078. else
  1079. do
  1080. echo 4;
  1081. while (true);
  1082. else
  1083. echo 5;',
  1084. '<?php
  1085. if (true)
  1086. if (true)
  1087. if (true)
  1088. for ($i = 0; $i < 1; ++$i)
  1089. echo 1;
  1090. elseif (true)
  1091. foreach ([] as $foo)
  1092. echo 2;
  1093. else if (true)
  1094. while (true)
  1095. echo 3;
  1096. else
  1097. do
  1098. echo 4;
  1099. while (true);
  1100. else
  1101. echo 5;',
  1102. ];
  1103. yield 'mixex if-else with and without braces' => [
  1104. '<?php
  1105. if (true)
  1106. if (true) {
  1107. if (true)
  1108. echo 1;
  1109. else
  1110. echo 2;
  1111. }
  1112. else {
  1113. echo 3;
  1114. }
  1115. else
  1116. echo 4;',
  1117. '<?php
  1118. if (true)
  1119. if (true) {
  1120. if (true)
  1121. echo 1;
  1122. else
  1123. echo 2;
  1124. }
  1125. else {
  1126. echo 3;
  1127. }
  1128. else
  1129. echo 4;',
  1130. ];
  1131. yield 'empty if and else without braces' => [
  1132. '<?php
  1133. if (true) {
  1134. if (false);
  1135. elseif (false);
  1136. else if (false);
  1137. else
  1138. echo 1;
  1139. }',
  1140. '<?php
  1141. if (true) {
  1142. if (false);
  1143. elseif (false);
  1144. else if (false);
  1145. else
  1146. echo 1;
  1147. }',
  1148. ];
  1149. yield 'multiline class constant' => [
  1150. '<?php
  1151. class Foo
  1152. {
  1153. const
  1154. FOO = 1;
  1155. }',
  1156. '<?php
  1157. class Foo
  1158. {
  1159. const
  1160. FOO = 1;
  1161. }',
  1162. ];
  1163. yield 'multiline class constant with visibility' => [
  1164. '<?php
  1165. class Foo
  1166. {
  1167. public const
  1168. FOO = 1;
  1169. protected const
  1170. BAR = 1;
  1171. private const
  1172. BAZ = 1;
  1173. }',
  1174. '<?php
  1175. class Foo
  1176. {
  1177. public const
  1178. FOO = 1;
  1179. protected const
  1180. BAR = 1;
  1181. private const
  1182. BAZ = 1;
  1183. }',
  1184. ];
  1185. yield 'multiline comma-separated class constants' => [
  1186. '<?php
  1187. class Foo
  1188. {
  1189. const
  1190. FOO = 1,
  1191. BAR = 2;
  1192. }',
  1193. '<?php
  1194. class Foo
  1195. {
  1196. const
  1197. FOO = 1,
  1198. BAR = 2;
  1199. }',
  1200. ];
  1201. yield 'multiline class constant with array value' => [
  1202. '<?php
  1203. class Foo
  1204. {
  1205. const
  1206. FOO = [
  1207. 1
  1208. ];
  1209. }',
  1210. '<?php
  1211. class Foo
  1212. {
  1213. const
  1214. FOO = [
  1215. 1
  1216. ];
  1217. }',
  1218. ];
  1219. yield 'multiline class constant with semicolon on next line' => [
  1220. '<?php
  1221. class Foo
  1222. {
  1223. public const
  1224. FOO = 1
  1225. ;
  1226. }',
  1227. '<?php
  1228. class Foo
  1229. {
  1230. public const
  1231. FOO = 1
  1232. ;
  1233. }',
  1234. ];
  1235. yield 'multiline class property' => [
  1236. '<?php
  1237. class Foo
  1238. {
  1239. public
  1240. $foo;
  1241. protected
  1242. $bar;
  1243. private
  1244. $baz;
  1245. }',
  1246. '<?php
  1247. class Foo
  1248. {
  1249. public
  1250. $foo;
  1251. protected
  1252. $bar;
  1253. private
  1254. $baz;
  1255. }',
  1256. ];
  1257. yield 'multiline class property with default value' => [
  1258. '<?php
  1259. class Foo
  1260. {
  1261. public
  1262. $foo = 1;
  1263. }',
  1264. '<?php
  1265. class Foo
  1266. {
  1267. public
  1268. $foo = 1;
  1269. }',
  1270. ];
  1271. yield 'multiline class typed property' => [
  1272. '<?php
  1273. class Foo
  1274. {
  1275. public
  1276. int $foo;
  1277. }',
  1278. '<?php
  1279. class Foo
  1280. {
  1281. public
  1282. int $foo;
  1283. }',
  1284. ];
  1285. yield 'multiline class static property' => [
  1286. '<?php
  1287. class Foo
  1288. {
  1289. public static
  1290. $foo;
  1291. static public
  1292. $bar;
  1293. }',
  1294. '<?php
  1295. class Foo
  1296. {
  1297. public static
  1298. $foo;
  1299. static public
  1300. $bar;
  1301. }',
  1302. ];
  1303. yield 'multiline comma-separated class properties' => [
  1304. '<?php
  1305. class Foo
  1306. {
  1307. public
  1308. $foo,
  1309. $bar;
  1310. }',
  1311. '<?php
  1312. class Foo
  1313. {
  1314. public
  1315. $foo,
  1316. $bar;
  1317. }',
  1318. ];
  1319. yield 'multiline class property with array value' => [
  1320. '<?php
  1321. class Foo
  1322. {
  1323. public
  1324. $foo = [
  1325. 1
  1326. ];
  1327. }',
  1328. '<?php
  1329. class Foo
  1330. {
  1331. public
  1332. $foo = [
  1333. 1
  1334. ];
  1335. }',
  1336. ];
  1337. yield 'multiline class property with semicolon on next line' => [
  1338. '<?php
  1339. class Foo
  1340. {
  1341. public
  1342. $foo
  1343. ;
  1344. }',
  1345. '<?php
  1346. class Foo
  1347. {
  1348. public
  1349. $foo
  1350. ;
  1351. }',
  1352. ];
  1353. yield 'multiline class property with var' => [
  1354. '<?php
  1355. class Foo
  1356. {
  1357. var
  1358. $foo;
  1359. }',
  1360. '<?php
  1361. class Foo
  1362. {
  1363. var
  1364. $foo;
  1365. }',
  1366. ];
  1367. yield 'property with multiline array containing explicit keys' => [
  1368. '<?php
  1369. class Foo
  1370. {
  1371. private $foo = [
  1372. \'a\' => 1,
  1373. \'b\' => 2,
  1374. ];
  1375. }',
  1376. ];
  1377. yield 'array with static method call' => [
  1378. '<?php
  1379. $foo = [
  1380. static::createNoErrorReport(),
  1381. 1,
  1382. ];',
  1383. ];
  1384. yield 'ternary operator in property' => [
  1385. <<<'PHP'
  1386. <?php
  1387. class Foo
  1388. {
  1389. public int $bar = BAZ ? -1 : 1;
  1390. }
  1391. PHP,
  1392. ];
  1393. }
  1394. /**
  1395. * @param _AutogeneratedInputConfiguration $configuration
  1396. *
  1397. * @dataProvider provideFixWithTabsCases
  1398. */
  1399. public function testFixWithTabs(string $expected, ?string $input = null, array $configuration = []): void
  1400. {
  1401. $this->fixer->configure($configuration);
  1402. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t"));
  1403. $this->doTest($expected, $input);
  1404. }
  1405. /**
  1406. * @return iterable<array{0: string, 1?: ?string, 2?: array<string, mixed>}>
  1407. */
  1408. public static function provideFixWithTabsCases(): iterable
  1409. {
  1410. yield 'simple' => [
  1411. "<?php
  1412. if (\$foo) {
  1413. \tfoo();
  1414. \tbar();
  1415. }",
  1416. '<?php
  1417. if ($foo) {
  1418. foo();
  1419. bar();
  1420. }',
  1421. ];
  1422. }
  1423. /**
  1424. * @param _AutogeneratedInputConfiguration $configuration
  1425. *
  1426. * @dataProvider provideFixPhp80Cases
  1427. *
  1428. * @requires PHP 8.0
  1429. */
  1430. public function testFixPhp80(string $expected, ?string $input = null, array $configuration = []): void
  1431. {
  1432. $this->fixer->configure($configuration);
  1433. $this->doTest($expected, $input);
  1434. }
  1435. /**
  1436. * @return iterable<array{0: string, 1?: ?string, 2?: array<string, mixed>}>
  1437. */
  1438. public static function provideFixPhp80Cases(): iterable
  1439. {
  1440. yield 'match expression' => [
  1441. '<?php
  1442. return match ($bool) {
  1443. 0 => false,
  1444. 1 => true,
  1445. default => throw new Exception(),
  1446. };',
  1447. '<?php
  1448. return match ($bool) {
  1449. 0 => false,
  1450. 1 => true,
  1451. default => throw new Exception(),
  1452. };',
  1453. ];
  1454. yield 'attribute' => [
  1455. '<?php
  1456. class Foo {
  1457. #[SimpleAttribute]
  1458. #[
  1459. MultilineAttribute
  1460. ]
  1461. #[ComplexAttribute(
  1462. foo: true,
  1463. bar: [
  1464. 1,
  1465. 2,
  1466. 3,
  1467. ]
  1468. )]
  1469. public function bar()
  1470. {
  1471. }
  1472. }',
  1473. '<?php
  1474. class Foo {
  1475. #[SimpleAttribute]
  1476. #[
  1477. MultilineAttribute
  1478. ]
  1479. #[ComplexAttribute(
  1480. foo: true,
  1481. bar: [
  1482. 1,
  1483. 2,
  1484. 3,
  1485. ]
  1486. )]
  1487. public function bar()
  1488. {
  1489. }
  1490. }',
  1491. ];
  1492. }
  1493. /**
  1494. * @param _AutogeneratedInputConfiguration $configuration
  1495. *
  1496. * @dataProvider provideFixPhp81Cases
  1497. *
  1498. * @requires PHP 8.1
  1499. */
  1500. public function testFixPhp81(string $expected, ?string $input = null, array $configuration = []): void
  1501. {
  1502. $this->fixer->configure($configuration);
  1503. $this->doTest($expected, $input);
  1504. }
  1505. /**
  1506. * @return iterable<array{0: string, 1?: ?string, 2?: array<string, mixed>}>
  1507. */
  1508. public static function provideFixPhp81Cases(): iterable
  1509. {
  1510. yield 'simple enum' => [
  1511. '<?php
  1512. enum Color {
  1513. case Red;
  1514. case Green;
  1515. case Blue;
  1516. }',
  1517. '<?php
  1518. enum Color {
  1519. case Red;
  1520. case Green;
  1521. case Blue;
  1522. }',
  1523. ];
  1524. yield 'backend enum' => [
  1525. '<?php
  1526. enum Color: string {
  1527. case Red = "R";
  1528. case Green = "G";
  1529. case Blue = "B";
  1530. }',
  1531. '<?php
  1532. enum Color: string {
  1533. case Red = "R";
  1534. case Green = "G";
  1535. case Blue = "B";
  1536. }',
  1537. ];
  1538. yield 'enum with method' => [
  1539. '<?php
  1540. enum Color {
  1541. case Red;
  1542. case Green;
  1543. case Blue;
  1544. public function foo() {
  1545. return true;
  1546. }
  1547. }',
  1548. '<?php
  1549. enum Color {
  1550. case Red;
  1551. case Green;
  1552. case Blue;
  1553. public function foo() {
  1554. return true;
  1555. }
  1556. }',
  1557. ];
  1558. yield 'multiline class readonly property' => [
  1559. '<?php
  1560. class Foo
  1561. {
  1562. public readonly
  1563. int $foo;
  1564. readonly public
  1565. int $bar;
  1566. }',
  1567. '<?php
  1568. class Foo
  1569. {
  1570. public readonly
  1571. int $foo;
  1572. readonly public
  1573. int $bar;
  1574. }',
  1575. ];
  1576. }
  1577. }