NoSpacesAroundOffsetFixerTest.php 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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\ConfigurationException\InvalidFixerConfigurationException;
  14. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  15. /**
  16. * @author Javier Spagnoletti <phansys@gmail.com>
  17. *
  18. * @internal
  19. *
  20. * @covers \PhpCsFixer\Fixer\Whitespace\NoSpacesAroundOffsetFixer
  21. *
  22. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Whitespace\NoSpacesAroundOffsetFixer>
  23. *
  24. * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\Whitespace\NoSpacesAroundOffsetFixer
  25. */
  26. final class NoSpacesAroundOffsetFixerTest extends AbstractFixerTestCase
  27. {
  28. /**
  29. * @dataProvider provideFixSpaceInsideOffsetCases
  30. */
  31. public function testFixSpaceInsideOffset(string $expected, ?string $input = null): void
  32. {
  33. $this->doTest($expected, $input);
  34. }
  35. /**
  36. * @return iterable<array{string, string}>
  37. */
  38. public static function provideFixSpaceInsideOffsetCases(): iterable
  39. {
  40. yield [
  41. '<?php
  42. $foo = array(1, 2, 3);
  43. $var = $foo[1];',
  44. '<?php
  45. $foo = array(1, 2, 3);
  46. $var = $foo[ 1 ];',
  47. ];
  48. yield [
  49. '<?php
  50. $arr = [2, 2 , ];
  51. $var = $arr[0];',
  52. '<?php
  53. $arr = [2, 2 , ];
  54. $var = $arr[ 0 ];',
  55. ];
  56. yield [
  57. '<?php
  58. $arr[2] = 3;',
  59. '<?php
  60. $arr[ 2 ] = 3;',
  61. ];
  62. yield [
  63. '<?php
  64. $arr[] = 3;',
  65. '<?php
  66. $arr[ ] = 3;',
  67. ];
  68. yield [
  69. '<?php
  70. $arr[]["some_offset"][] = 3;',
  71. '<?php
  72. $arr[ ][ "some_offset" ][ ] = 3;',
  73. ];
  74. yield [
  75. '<?php
  76. $arr[]["some offset with spaces"][] = 3;',
  77. '<?php
  78. $arr[ ][ "some offset with spaces" ][ ] = 3;',
  79. ];
  80. yield [
  81. '<?php
  82. $var = $arr[0];',
  83. '<?php
  84. $var = $arr[ 0 ];',
  85. ];
  86. yield [
  87. '<?php
  88. $var = $arr[0][0];',
  89. '<?php
  90. $var = $arr[ 0 ][ 0 ];',
  91. ];
  92. yield [
  93. '<?php
  94. $var = $arr[$a[$b]];',
  95. '<?php
  96. $var = $arr[ $a [ $b ] ];',
  97. ];
  98. yield [
  99. '<?php
  100. $var = $arr[$a[$b]];',
  101. '<?php
  102. $var = $arr[ $a [ $b ] ];',
  103. ];
  104. yield [
  105. '<?php
  106. $var = $arr[0][
  107. 0];',
  108. '<?php
  109. $var = $arr[0][
  110. 0 ];',
  111. ];
  112. yield [
  113. '<?php
  114. $var = $arr[0][0
  115. ];',
  116. '<?php
  117. $var = $arr[0][ 0
  118. ];',
  119. ];
  120. }
  121. /**
  122. * @dataProvider provideFixSpaceOutsideOffsetCases
  123. */
  124. public function testFixSpaceOutsideOffset(string $expected, ?string $input = null): void
  125. {
  126. $this->doTest($expected, $input);
  127. }
  128. /**
  129. * @return iterable<array{string, string}>
  130. */
  131. public static function provideFixSpaceOutsideOffsetCases(): iterable
  132. {
  133. yield [
  134. '<?php
  135. $a = $b[0] ;',
  136. '<?php
  137. $a = $b [0] ;',
  138. ];
  139. yield [
  140. '<?php
  141. $a = array($b[0] , $b[0] );',
  142. '<?php
  143. $a = array($b [0] , $b [0] );',
  144. ];
  145. yield [
  146. '<?php
  147. $withComments[0] // here is a comment
  148. [1] // and here is another
  149. [2][3] = 4;',
  150. '<?php
  151. $withComments [0] // here is a comment
  152. [1] // and here is another
  153. [2] [3] = 4;',
  154. ];
  155. yield [
  156. '<?php
  157. $c = SOME_CONST[0][1][2];',
  158. '<?php
  159. $c = SOME_CONST [0] [1] [2];',
  160. ];
  161. yield [
  162. '<?php
  163. $f = someFunc()[0][1][2];',
  164. '<?php
  165. $f = someFunc() [0] [1] [2];',
  166. ];
  167. yield [
  168. '<?php
  169. $foo[][0][1][2] = 3;',
  170. '<?php
  171. $foo [] [0] [1] [2] = 3;',
  172. ];
  173. yield [
  174. '<?php
  175. $foo[0][1][2] = 3;',
  176. '<?php
  177. $foo [0] [1] [2] = 3;',
  178. ];
  179. yield [
  180. '<?php
  181. $bar = $foo[0][1][2];',
  182. '<?php
  183. $bar = $foo [0] [1] [2];',
  184. ];
  185. yield [
  186. '<?php
  187. $baz[0][1][2] = 3;',
  188. '<?php
  189. $baz [0]
  190. [1]
  191. [2] = 3;',
  192. ];
  193. }
  194. public function testLeaveNewLinesAlone(): void
  195. {
  196. $expected = <<<'EOF'
  197. <?php
  198. class Foo
  199. {
  200. private function bar()
  201. {
  202. if ([1, 2, 3] && [
  203. 'foo',
  204. 'bar' ,
  205. 'baz'// a comment just to mix things up
  206. ]) {
  207. return 1;
  208. };
  209. }
  210. }
  211. EOF;
  212. $this->doTest($expected);
  213. }
  214. /**
  215. * @dataProvider provideCommentsCases
  216. */
  217. public function testComments(string $expected, ?string $input = null): void
  218. {
  219. $this->doTest($expected, $input);
  220. }
  221. /**
  222. * @return iterable<array{0: string, 1?: string}>
  223. */
  224. public static function provideCommentsCases(): iterable
  225. {
  226. yield [
  227. '<?php
  228. $withComments[0] // here is a comment
  229. [1] // and here is another
  230. [2] = 3;',
  231. ];
  232. yield [
  233. '<?php
  234. $a = $b[# z
  235. 1#z
  236. ];',
  237. '<?php
  238. $a = $b[ # z
  239. 1#z
  240. ];',
  241. ];
  242. }
  243. public function testLeaveComplexString(): void
  244. {
  245. $expected = <<<'EOF'
  246. <?php
  247. echo "I am printing some spaces here {$foo->bar[1]} {$foo->bar[1]}.";
  248. EOF;
  249. $this->doTest($expected);
  250. }
  251. public function testLeaveFunctions(): void
  252. {
  253. $expected = <<<'EOF'
  254. <?php
  255. function someFunc() { $someVar = []; }
  256. EOF;
  257. $this->doTest($expected);
  258. }
  259. /**
  260. * @param _AutogeneratedInputConfiguration $configuration
  261. *
  262. * @dataProvider provideFixWithConfigurationCases
  263. */
  264. public function testFixWithConfiguration(string $expected, string $input, array $configuration): void
  265. {
  266. $this->fixer->configure($configuration);
  267. $this->doTest($expected, $input);
  268. }
  269. /**
  270. * @return iterable<array{string, string, _AutogeneratedInputConfiguration}>
  271. */
  272. public static function provideFixWithConfigurationCases(): iterable
  273. {
  274. yield 'Config "default".' => [
  275. '<?php [ $a ] = $a;
  276. if ($controllerName = $request->attributes->get(1)) {
  277. return false;
  278. }
  279. [ $class , $method ] = $this->splitControllerClassAndMethod($controllerName);
  280. $a = $b[0];
  281. ',
  282. '<?php [ $a ] = $a;
  283. if ($controllerName = $request->attributes->get(1)) {
  284. return false;
  285. }
  286. [ $class , $method ] = $this->splitControllerClassAndMethod($controllerName);
  287. $a = $b [0];
  288. ',
  289. ['positions' => ['inside', 'outside']],
  290. ];
  291. }
  292. public function testWrongConfig(): void
  293. {
  294. $this->expectException(InvalidFixerConfigurationException::class);
  295. $this->expectExceptionMessageMatches('/^\[no_spaces_around_offset\] Invalid configuration: The option "positions" .*\.$/');
  296. $this->fixer->configure(['positions' => ['foo']]); // @phpstan-ignore-line
  297. }
  298. /**
  299. * @param _AutogeneratedInputConfiguration $configuration
  300. *
  301. * @dataProvider provideFixPre80Cases
  302. *
  303. * @requires PHP <8.0
  304. */
  305. public function testFixPre80(string $expected, ?string $input = null, array $configuration = []): void
  306. {
  307. $this->fixer->configure($configuration);
  308. $this->doTest($expected, $input);
  309. }
  310. public static function provideFixPre80Cases(): iterable
  311. {
  312. yield [
  313. '<?php
  314. $foo{0}{1}{2} = 3;',
  315. '<?php
  316. $foo {0} {1} {2} = 3;',
  317. ];
  318. yield [
  319. '<?php
  320. $foobar = $foo{0}[1]{2};',
  321. '<?php
  322. $foobar = $foo {0} [1] {2};',
  323. ];
  324. yield [
  325. '<?php
  326. $var = $arr[0]{0
  327. };',
  328. '<?php
  329. $var = $arr[0]{ 0
  330. };',
  331. ];
  332. yield from self::provideMultiDimensionalArrayCases();
  333. }
  334. /**
  335. * @param _AutogeneratedInputConfiguration $configuration
  336. *
  337. * @dataProvider provideFix80Cases
  338. *
  339. * @requires PHP 8.0
  340. */
  341. public function testFix80(string $expected, ?string $input, array $configuration): void
  342. {
  343. $this->fixer->configure($configuration);
  344. $this->doTest($expected, $input);
  345. }
  346. /**
  347. * @return iterable<array{string, string, _AutogeneratedInputConfiguration}>
  348. */
  349. public static function provideFix80Cases(): iterable
  350. {
  351. foreach (self::provideMultiDimensionalArrayCases() as $index => $test) {
  352. $test[0] = str_replace('{', '[', $test[0]);
  353. $test[0] = str_replace('}', ']', $test[0]);
  354. $test[1] = str_replace('{', '[', $test[1]);
  355. $test[1] = str_replace('}', ']', $test[1]);
  356. yield $index => $test;
  357. }
  358. }
  359. /**
  360. * @return iterable<array{string, string, _AutogeneratedInputConfiguration}>
  361. */
  362. private static function provideMultiDimensionalArrayCases(): iterable
  363. {
  364. yield [
  365. <<<'EOT'
  366. <?php
  367. $arr1[] ["some_offset"] [] {"foo"} = 3;
  368. EOT,
  369. <<<'EOT'
  370. <?php
  371. $arr1[ ] [ "some_offset" ] [ ] { "foo" } = 3;
  372. EOT,
  373. ['positions' => ['inside']],
  374. ];
  375. yield [
  376. <<<'EOT'
  377. <?php
  378. $arr1[ ][ "some_offset" ][ ]{ "foo" } = 3;
  379. EOT,
  380. <<<'EOT'
  381. <?php
  382. $arr1[ ] [ "some_offset" ] [ ] { "foo" } = 3;
  383. EOT,
  384. ['positions' => ['outside']],
  385. ];
  386. }
  387. }