StatementIndentationFixerTest.php 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688
  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. yield 'braceless if with return' => [
  1394. <<<'PHP'
  1395. <?php
  1396. if (1 == 2)
  1397. return;
  1398. if (1 == 2)
  1399. return false;
  1400. PHP,
  1401. ];
  1402. }
  1403. /**
  1404. * @param _AutogeneratedInputConfiguration $configuration
  1405. *
  1406. * @dataProvider provideFixWithTabsCases
  1407. */
  1408. public function testFixWithTabs(string $expected, ?string $input = null, array $configuration = []): void
  1409. {
  1410. $this->fixer->configure($configuration);
  1411. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t"));
  1412. $this->doTest($expected, $input);
  1413. }
  1414. /**
  1415. * @return iterable<array{0: string, 1?: ?string, 2?: array<string, mixed>}>
  1416. */
  1417. public static function provideFixWithTabsCases(): iterable
  1418. {
  1419. yield 'simple' => [
  1420. "<?php
  1421. if (\$foo) {
  1422. \tfoo();
  1423. \tbar();
  1424. }",
  1425. '<?php
  1426. if ($foo) {
  1427. foo();
  1428. bar();
  1429. }',
  1430. ];
  1431. }
  1432. /**
  1433. * @param _AutogeneratedInputConfiguration $configuration
  1434. *
  1435. * @dataProvider provideFixPhp80Cases
  1436. *
  1437. * @requires PHP 8.0
  1438. */
  1439. public function testFixPhp80(string $expected, ?string $input = null, array $configuration = []): void
  1440. {
  1441. $this->fixer->configure($configuration);
  1442. $this->doTest($expected, $input);
  1443. }
  1444. /**
  1445. * @return iterable<array{0: string, 1?: ?string, 2?: array<string, mixed>}>
  1446. */
  1447. public static function provideFixPhp80Cases(): iterable
  1448. {
  1449. yield 'match expression' => [
  1450. '<?php
  1451. return match ($bool) {
  1452. 0 => false,
  1453. 1 => true,
  1454. default => throw new Exception(),
  1455. };',
  1456. '<?php
  1457. return match ($bool) {
  1458. 0 => false,
  1459. 1 => true,
  1460. default => throw new Exception(),
  1461. };',
  1462. ];
  1463. yield 'attribute' => [
  1464. '<?php
  1465. class Foo {
  1466. #[SimpleAttribute]
  1467. #[
  1468. MultilineAttribute
  1469. ]
  1470. #[ComplexAttribute(
  1471. foo: true,
  1472. bar: [
  1473. 1,
  1474. 2,
  1475. 3,
  1476. ]
  1477. )]
  1478. public function bar()
  1479. {
  1480. }
  1481. }',
  1482. '<?php
  1483. class Foo {
  1484. #[SimpleAttribute]
  1485. #[
  1486. MultilineAttribute
  1487. ]
  1488. #[ComplexAttribute(
  1489. foo: true,
  1490. bar: [
  1491. 1,
  1492. 2,
  1493. 3,
  1494. ]
  1495. )]
  1496. public function bar()
  1497. {
  1498. }
  1499. }',
  1500. ];
  1501. }
  1502. /**
  1503. * @param _AutogeneratedInputConfiguration $configuration
  1504. *
  1505. * @dataProvider provideFixPhp81Cases
  1506. *
  1507. * @requires PHP 8.1
  1508. */
  1509. public function testFixPhp81(string $expected, ?string $input = null, array $configuration = []): void
  1510. {
  1511. $this->fixer->configure($configuration);
  1512. $this->doTest($expected, $input);
  1513. }
  1514. /**
  1515. * @return iterable<array{0: string, 1?: ?string, 2?: array<string, mixed>}>
  1516. */
  1517. public static function provideFixPhp81Cases(): iterable
  1518. {
  1519. yield 'simple enum' => [
  1520. '<?php
  1521. enum Color {
  1522. case Red;
  1523. case Green;
  1524. case Blue;
  1525. }',
  1526. '<?php
  1527. enum Color {
  1528. case Red;
  1529. case Green;
  1530. case Blue;
  1531. }',
  1532. ];
  1533. yield 'backend enum' => [
  1534. '<?php
  1535. enum Color: string {
  1536. case Red = "R";
  1537. case Green = "G";
  1538. case Blue = "B";
  1539. }',
  1540. '<?php
  1541. enum Color: string {
  1542. case Red = "R";
  1543. case Green = "G";
  1544. case Blue = "B";
  1545. }',
  1546. ];
  1547. yield 'enum with method' => [
  1548. '<?php
  1549. enum Color {
  1550. case Red;
  1551. case Green;
  1552. case Blue;
  1553. public function foo() {
  1554. return true;
  1555. }
  1556. }',
  1557. '<?php
  1558. enum Color {
  1559. case Red;
  1560. case Green;
  1561. case Blue;
  1562. public function foo() {
  1563. return true;
  1564. }
  1565. }',
  1566. ];
  1567. yield 'multiline class readonly property' => [
  1568. '<?php
  1569. class Foo
  1570. {
  1571. public readonly
  1572. int $foo;
  1573. readonly public
  1574. int $bar;
  1575. }',
  1576. '<?php
  1577. class Foo
  1578. {
  1579. public readonly
  1580. int $foo;
  1581. readonly public
  1582. int $bar;
  1583. }',
  1584. ];
  1585. }
  1586. }