ArrayIndentationFixerTest.php 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  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\ArrayIndentationFixer
  19. *
  20. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Whitespace\ArrayIndentationFixer>
  21. */
  22. final class ArrayIndentationFixerTest extends AbstractFixerTestCase
  23. {
  24. /**
  25. * @dataProvider provideFixCases
  26. */
  27. public function testFix(string $expected, ?string $input = null): void
  28. {
  29. $this->doTest($expected, $input);
  30. }
  31. /**
  32. * @return iterable<int|string, array{0: string, 1?: string}>
  33. */
  34. public static function provideFixCases(): iterable
  35. {
  36. yield from self::withLongArraySyntaxCases([
  37. [
  38. <<<'EXPECTED'
  39. <?php
  40. $foo = [
  41. 'foo',
  42. 'bar' => 'baz',
  43. ];
  44. EXPECTED,
  45. <<<'INPUT'
  46. <?php
  47. $foo = [
  48. 'foo',
  49. 'bar' => 'baz',
  50. ];
  51. INPUT,
  52. ],
  53. [
  54. <<<'EXPECTED'
  55. <?php
  56. $foo = [
  57. 'foo',
  58. 'bar' => 'baz',
  59. ];
  60. EXPECTED,
  61. <<<'INPUT'
  62. <?php
  63. $foo = [
  64. 'foo',
  65. 'bar' => 'baz',
  66. ];
  67. INPUT,
  68. ],
  69. [
  70. <<<'EXPECTED'
  71. <?php
  72. $foo = [
  73. ['bar', 'baz'],
  74. [
  75. 'bar',
  76. 'baz'
  77. ],
  78. ];
  79. EXPECTED,
  80. <<<'INPUT'
  81. <?php
  82. $foo = [
  83. ['bar', 'baz'],
  84. [
  85. 'bar',
  86. 'baz'
  87. ],
  88. ];
  89. INPUT,
  90. ],
  91. [
  92. <<<'EXPECTED'
  93. <?php
  94. $foo = [
  95. ['foo',
  96. 'bar',
  97. ['foo',
  98. 'bar',
  99. ['foo',
  100. 'bar',
  101. 'baz']],
  102. 'baz'],
  103. ];
  104. EXPECTED,
  105. <<<'INPUT'
  106. <?php
  107. $foo = [
  108. ['foo',
  109. 'bar',
  110. ['foo',
  111. 'bar',
  112. ['foo',
  113. 'bar',
  114. 'baz']],
  115. 'baz'],
  116. ];
  117. INPUT,
  118. ],
  119. [
  120. <<<'EXPECTED'
  121. <?php
  122. class Foo
  123. {
  124. public $foo = [
  125. ['bar', 'baz'],
  126. [
  127. 'bar',
  128. 'baz'
  129. ],
  130. ];
  131. public function bar()
  132. {
  133. return [
  134. ['bar', 'baz'],
  135. [
  136. 'bar',
  137. 'baz'
  138. ],
  139. ];
  140. }
  141. }
  142. EXPECTED,
  143. <<<'INPUT'
  144. <?php
  145. class Foo
  146. {
  147. public $foo = [
  148. ['bar', 'baz'],
  149. [
  150. 'bar',
  151. 'baz'
  152. ],
  153. ];
  154. public function bar()
  155. {
  156. return [
  157. ['bar', 'baz'],
  158. [
  159. 'bar',
  160. 'baz'
  161. ],
  162. ];
  163. }
  164. }
  165. INPUT,
  166. ],
  167. [
  168. <<<'EXPECTED'
  169. <?php
  170. $foo = [
  171. 'foo' => foo(
  172. 1,
  173. 2
  174. ),
  175. 'bar' => bar(
  176. 1,
  177. 2
  178. ),
  179. 'baz' => baz(
  180. 1,
  181. 2
  182. ),
  183. ];
  184. EXPECTED,
  185. <<<'INPUT'
  186. <?php
  187. $foo = [
  188. 'foo' => foo(
  189. 1,
  190. 2
  191. ),
  192. 'bar' => bar(
  193. 1,
  194. 2
  195. ),
  196. 'baz' => baz(
  197. 1,
  198. 2
  199. ),
  200. ];
  201. INPUT,
  202. ],
  203. [
  204. <<<'EXPECTED'
  205. <?php
  206. $foo = [
  207. 'foo' => ['bar' => [
  208. 'baz',
  209. ]],
  210. 'qux',
  211. ];
  212. EXPECTED,
  213. <<<'INPUT'
  214. <?php
  215. $foo = [
  216. 'foo' => ['bar' => [
  217. 'baz',
  218. ]],
  219. 'qux',
  220. ];
  221. INPUT,
  222. ],
  223. [
  224. <<<'EXPECTED'
  225. <?php
  226. $foo = [
  227. 'foo' => [
  228. (new Foo())
  229. ->foo(),
  230. ],
  231. ];
  232. EXPECTED,
  233. <<<'INPUT'
  234. <?php
  235. $foo = [
  236. 'foo' => [
  237. (new Foo())
  238. ->foo(),
  239. ],
  240. ];
  241. INPUT,
  242. ],
  243. [
  244. <<<'EXPECTED'
  245. <?php
  246. $foo = [
  247. [new Foo(
  248. )],
  249. [new Foo(
  250. )],
  251. ];
  252. EXPECTED,
  253. <<<'INPUT'
  254. <?php
  255. $foo = [
  256. [new Foo(
  257. )],
  258. [new Foo(
  259. )],
  260. ];
  261. INPUT,
  262. ],
  263. [
  264. <<<'EXPECTED'
  265. <?php
  266. $foo = new Foo([
  267. (new Bar())
  268. ->foo([
  269. 'foo',
  270. 'foo',
  271. ])
  272. ->bar(['bar', 'bar'])
  273. ->baz([
  274. 'baz',
  275. 'baz',
  276. ])
  277. ,
  278. ]);
  279. EXPECTED,
  280. <<<'INPUT'
  281. <?php
  282. $foo = new Foo([
  283. (new Bar())
  284. ->foo([
  285. 'foo',
  286. 'foo',
  287. ])
  288. ->bar(['bar', 'bar'])
  289. ->baz([
  290. 'baz',
  291. 'baz',
  292. ])
  293. ,
  294. ]);
  295. INPUT,
  296. ],
  297. [
  298. <<<'EXPECTED'
  299. <?php
  300. class Foo
  301. {
  302. public function bar()
  303. {
  304. $foo = [
  305. 'foo',
  306. 'foo',
  307. ];
  308. $bar = [
  309. 'bar',
  310. 'bar',
  311. ];
  312. }
  313. }
  314. EXPECTED,
  315. <<<'INPUT'
  316. <?php
  317. class Foo
  318. {
  319. public function bar()
  320. {
  321. $foo = [
  322. 'foo',
  323. 'foo',
  324. ];
  325. $bar = [
  326. 'bar',
  327. 'bar',
  328. ];
  329. }
  330. }
  331. INPUT,
  332. ],
  333. [
  334. <<<'EXPECTED'
  335. <?php
  336. class Foo
  337. {
  338. public function bar()
  339. {
  340. return new Bar([
  341. (new Baz())
  342. ->qux([function ($a) {
  343. foreach ($a as $b) {
  344. if ($b) {
  345. throw new Exception(sprintf(
  346. 'Oops: %s',
  347. $b
  348. ));
  349. }
  350. }
  351. }]),
  352. ]);
  353. }
  354. }
  355. EXPECTED,
  356. <<<'INPUT'
  357. <?php
  358. class Foo
  359. {
  360. public function bar()
  361. {
  362. return new Bar([
  363. (new Baz())
  364. ->qux([function ($a) {
  365. foreach ($a as $b) {
  366. if ($b) {
  367. throw new Exception(sprintf(
  368. 'Oops: %s',
  369. $b
  370. ));
  371. }
  372. }
  373. }]),
  374. ]);
  375. }
  376. }
  377. INPUT,
  378. ],
  379. [
  380. <<<'EXPECTED'
  381. <?php
  382. $foo = [
  383. 'Foo'.
  384. foo()
  385. .bar()
  386. ,
  387. ];
  388. EXPECTED,
  389. <<<'INPUT'
  390. <?php
  391. $foo = [
  392. 'Foo'.
  393. foo()
  394. .bar()
  395. ,
  396. ];
  397. INPUT,
  398. ],
  399. [
  400. <<<'EXPECTED'
  401. <?php
  402. $foo = [
  403. [new \stdClass()],
  404. 'foo',
  405. ];
  406. EXPECTED,
  407. <<<'INPUT'
  408. <?php
  409. $foo = [
  410. [new \stdClass()],
  411. 'foo',
  412. ];
  413. INPUT,
  414. ],
  415. [
  416. <<<'EXPECTED'
  417. <?php
  418. $foo = [
  419. $bar
  420. ? 'bar'
  421. : 'foo'
  422. ,
  423. ];
  424. EXPECTED,
  425. <<<'INPUT'
  426. <?php
  427. $foo = [
  428. $bar
  429. ? 'bar'
  430. : 'foo'
  431. ,
  432. ];
  433. INPUT,
  434. ],
  435. [
  436. <<<'EXPECTED'
  437. <?php
  438. $foo = [
  439. $bar ?
  440. 'bar' :
  441. 'foo'
  442. ,
  443. ];
  444. EXPECTED,
  445. <<<'INPUT'
  446. <?php
  447. $foo = [
  448. $bar ?
  449. 'bar' :
  450. 'foo'
  451. ,
  452. ];
  453. INPUT,
  454. ],
  455. [
  456. <<<'EXPECTED'
  457. <?php
  458. $foo = [
  459. [
  460. 'foo',
  461. ], [
  462. 'bar',
  463. ],
  464. ];
  465. EXPECTED,
  466. <<<'INPUT'
  467. <?php
  468. $foo = [
  469. [
  470. 'foo',
  471. ], [
  472. 'bar',
  473. ],
  474. ];
  475. INPUT,
  476. ],
  477. [
  478. <<<'EXPECTED'
  479. <?php
  480. $foo = [
  481. 'foo', // comment
  482. 'bar',
  483. ];
  484. EXPECTED,
  485. <<<'INPUT'
  486. <?php
  487. $foo = [
  488. 'foo', // comment
  489. 'bar',
  490. ];
  491. INPUT,
  492. ],
  493. [
  494. <<<'EXPECTED'
  495. <?php
  496. $foo = [[[
  497. 'foo',
  498. 'bar',
  499. ],
  500. ],
  501. ];
  502. EXPECTED,
  503. <<<'INPUT'
  504. <?php
  505. $foo = [[[
  506. 'foo',
  507. 'bar',
  508. ],
  509. ],
  510. ];
  511. INPUT,
  512. ],
  513. [
  514. <<<'EXPECTED'
  515. <?php
  516. $foo = [
  517. [
  518. [
  519. 'foo',
  520. 'bar',
  521. ]]];
  522. EXPECTED,
  523. <<<'INPUT'
  524. <?php
  525. $foo = [
  526. [
  527. [
  528. 'foo',
  529. 'bar',
  530. ]]];
  531. INPUT,
  532. ],
  533. [
  534. <<<'EXPECTED'
  535. <?php
  536. $foo = [
  537. [
  538. [[
  539. [[[
  540. 'foo',
  541. 'bar',
  542. ]
  543. ]]
  544. ]
  545. ]
  546. ]];
  547. EXPECTED,
  548. <<<'INPUT'
  549. <?php
  550. $foo = [
  551. [
  552. [[
  553. [[[
  554. 'foo',
  555. 'bar',
  556. ]
  557. ]]
  558. ]
  559. ]
  560. ]];
  561. INPUT,
  562. ],
  563. [
  564. <<<'EXPECTED'
  565. <?php
  566. $foo = [[
  567. [
  568. [[[],[[
  569. [[[
  570. 'foo',
  571. 'bar',
  572. ],[[],[]]]
  573. ]],[
  574. 'baz',
  575. ]]
  576. ],[]],[]]
  577. ]
  578. ];
  579. EXPECTED,
  580. <<<'INPUT'
  581. <?php
  582. $foo = [[
  583. [
  584. [[[],[[
  585. [[[
  586. 'foo',
  587. 'bar',
  588. ],[[],[]]]
  589. ]],[
  590. 'baz',
  591. ]]
  592. ],[]],[]]
  593. ]
  594. ];
  595. INPUT,
  596. ],
  597. [
  598. <<<'EXPECTED'
  599. <?php if ($foo): ?>
  600. <?php foo([
  601. 'bar',
  602. 'baz',
  603. ]) ?>
  604. <?php endif ?>
  605. EXPECTED,
  606. <<<'INPUT'
  607. <?php if ($foo): ?>
  608. <?php foo([
  609. 'bar',
  610. 'baz',
  611. ]) ?>
  612. <?php endif ?>
  613. INPUT,
  614. ],
  615. [
  616. <<<'EXPECTED'
  617. <div>
  618. <a
  619. class="link"
  620. href="<?= Url::to([
  621. '/site/page',
  622. 'id' => 123,
  623. ]); ?>"
  624. >
  625. Link text
  626. </a>
  627. </div>
  628. EXPECTED,
  629. <<<'INPUT'
  630. <div>
  631. <a
  632. class="link"
  633. href="<?= Url::to([
  634. '/site/page',
  635. 'id' => 123,
  636. ]); ?>"
  637. >
  638. Link text
  639. </a>
  640. </div>
  641. INPUT,
  642. ],
  643. [
  644. <<<'EXPECTED'
  645. <?php
  646. $arr = [
  647. 'a' => 'b',
  648. // 'c' => 'd',
  649. ];
  650. EXPECTED,
  651. <<<'INPUT'
  652. <?php
  653. $arr = [
  654. 'a' => 'b',
  655. // 'c' => 'd',
  656. ];
  657. INPUT,
  658. ],
  659. [
  660. '<?php
  661. '.'
  662. $foo = [
  663. "foo",
  664. "bar",
  665. ];',
  666. ],
  667. [
  668. <<<'EXPECTED'
  669. <?php
  670. $foo = [
  671. 'foo' =>
  672. 'Some'
  673. .' long'
  674. .' string',
  675. 'bar' =>
  676. 'Another'
  677. .' long'
  678. .' string'
  679. ];
  680. EXPECTED,
  681. <<<'INPUT'
  682. <?php
  683. $foo = [
  684. 'foo' =>
  685. 'Some'
  686. .' long'
  687. .' string',
  688. 'bar' =>
  689. 'Another'
  690. .' long'
  691. .' string'
  692. ];
  693. INPUT,
  694. ],
  695. [
  696. <<<'EXPECTED'
  697. <?php
  698. $foo = [
  699. $test
  700. ? [
  701. 123,
  702. ]
  703. : [
  704. 321,
  705. ],
  706. ];
  707. EXPECTED,
  708. <<<'INPUT'
  709. <?php
  710. $foo = [
  711. $test
  712. ? [
  713. 123,
  714. ]
  715. : [
  716. 321,
  717. ],
  718. ];
  719. INPUT,
  720. ],
  721. [
  722. <<<'EXPECTED'
  723. <?php
  724. $foo = [[
  725. new Foo(
  726. 'foo'
  727. ),
  728. ]];
  729. EXPECTED,
  730. <<<'INPUT'
  731. <?php
  732. $foo = [[
  733. new Foo(
  734. 'foo'
  735. ),
  736. ]];
  737. INPUT,
  738. ],
  739. [
  740. <<<'EXPECTED'
  741. <?php
  742. $array = [
  743. 'foo' => [
  744. 'bar' => [
  745. 'baz',
  746. ],
  747. ], // <- this one
  748. ];
  749. EXPECTED,
  750. <<<'INPUT'
  751. <?php
  752. $array = [
  753. 'foo' => [
  754. 'bar' => [
  755. 'baz',
  756. ],
  757. ], // <- this one
  758. ];
  759. INPUT,
  760. ],
  761. [
  762. <<<'EXPECTED'
  763. <?php
  764. $foo = [
  765. ...$foo,
  766. ...$bar,
  767. ];
  768. EXPECTED,
  769. <<<'INPUT'
  770. <?php
  771. $foo = [
  772. ...$foo,
  773. ...$bar,
  774. ];
  775. INPUT,
  776. ],
  777. ]);
  778. yield 'array destructuring' => [
  779. <<<'EXPECTED'
  780. <?php
  781. [
  782. $foo,
  783. $bar,
  784. $baz
  785. ] = $arr;
  786. EXPECTED,
  787. <<<'INPUT'
  788. <?php
  789. [
  790. $foo,
  791. $bar,
  792. $baz
  793. ] = $arr;
  794. INPUT,
  795. ];
  796. yield 'array destructuring using list' => [
  797. <<<'EXPECTED'
  798. <?php
  799. list(
  800. $foo,
  801. $bar,
  802. $baz
  803. ) = $arr;
  804. EXPECTED,
  805. <<<'INPUT'
  806. <?php
  807. list(
  808. $foo,
  809. $bar,
  810. $baz
  811. ) = $arr;
  812. INPUT,
  813. ];
  814. }
  815. /**
  816. * @dataProvider provideWithWhitespacesConfigCases
  817. */
  818. public function testWithWhitespacesConfig(string $expected, ?string $input = null): void
  819. {
  820. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t"));
  821. $this->doTest($expected, $input);
  822. }
  823. /**
  824. * @return iterable<int|string, array{0: string, 1?: string}>
  825. */
  826. public static function provideWithWhitespacesConfigCases(): iterable
  827. {
  828. yield from self::withLongArraySyntaxCases([
  829. [
  830. <<<EXPECTED
  831. <?php
  832. \$foo = [
  833. \t'foo',
  834. \t'bar' => 'baz',
  835. ];
  836. EXPECTED,
  837. <<<'INPUT'
  838. <?php
  839. $foo = [
  840. 'foo',
  841. 'bar' => 'baz',
  842. ];
  843. INPUT,
  844. ],
  845. [
  846. <<<EXPECTED
  847. <?php
  848. \$foo = [
  849. \t'foo',
  850. \t'bar' => 'baz',
  851. ];
  852. EXPECTED,
  853. <<<INPUT
  854. <?php
  855. \$foo = [
  856. \t\t\t'foo',
  857. \t\t'bar' => 'baz',
  858. ];
  859. INPUT,
  860. ],
  861. ]);
  862. yield 'array destructuring' => [
  863. <<<EXPECTED
  864. <?php
  865. [
  866. \t\$foo,
  867. \t\$bar,
  868. \t\$baz
  869. ] = \$arr;
  870. EXPECTED,
  871. <<<'INPUT'
  872. <?php
  873. [
  874. $foo,
  875. $bar,
  876. $baz
  877. ] = $arr;
  878. INPUT,
  879. ];
  880. yield 'array destructuring using list' => [
  881. <<<EXPECTED
  882. <?php
  883. list(
  884. \t\$foo,
  885. \t\$bar,
  886. \t\$baz
  887. ) = \$arr;
  888. EXPECTED,
  889. <<<'INPUT'
  890. <?php
  891. list(
  892. $foo,
  893. $bar,
  894. $baz
  895. ) = $arr;
  896. INPUT,
  897. ];
  898. }
  899. /**
  900. * @dataProvider provideFix80Cases
  901. *
  902. * @requires PHP 8.0
  903. */
  904. public function testFix80(string $expected, ?string $input = null): void
  905. {
  906. $this->doTest($expected, $input);
  907. }
  908. /**
  909. * @return iterable<string, array{string, string}>
  910. */
  911. public static function provideFix80Cases(): iterable
  912. {
  913. yield 'attribute' => [
  914. '<?php
  915. class Foo {
  916. #[SimpleAttribute]
  917. #[ComplexAttribute(
  918. foo: true,
  919. bar: [
  920. 1,
  921. 2,
  922. 3,
  923. ]
  924. )]
  925. public function bar()
  926. {
  927. }
  928. }',
  929. '<?php
  930. class Foo {
  931. #[SimpleAttribute]
  932. #[ComplexAttribute(
  933. foo: true,
  934. bar: [
  935. 1,
  936. 2,
  937. 3,
  938. ]
  939. )]
  940. public function bar()
  941. {
  942. }
  943. }',
  944. ];
  945. }
  946. /**
  947. * @param list<array{0: string, 1?: string}> $cases
  948. *
  949. * @return list<array{0: string, 1?: string}>
  950. */
  951. private static function withLongArraySyntaxCases(array $cases): array
  952. {
  953. $longSyntaxCases = [];
  954. foreach ($cases as $case) {
  955. $case[0] = self::toLongArraySyntax($case[0]);
  956. if (isset($case[1])) {
  957. $case[1] = self::toLongArraySyntax($case[1]);
  958. }
  959. $longSyntaxCases[] = $case;
  960. }
  961. return [...$cases, ...$longSyntaxCases];
  962. }
  963. private static function toLongArraySyntax(string $php): string
  964. {
  965. return strtr($php, [
  966. '[' => 'array(',
  967. ']' => ')',
  968. ]);
  969. }
  970. }