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. * @dataProvider provideFixSpaceOutsideOffsetCases
  37. */
  38. public function testFixSpaceOutsideOffset(string $expected, ?string $input = null): void
  39. {
  40. $this->doTest($expected, $input);
  41. }
  42. public function testLeaveNewLinesAlone(): void
  43. {
  44. $expected = <<<'EOF'
  45. <?php
  46. class Foo
  47. {
  48. private function bar()
  49. {
  50. if ([1, 2, 3] && [
  51. 'foo',
  52. 'bar' ,
  53. 'baz'// a comment just to mix things up
  54. ]) {
  55. return 1;
  56. };
  57. }
  58. }
  59. EOF;
  60. $this->doTest($expected);
  61. }
  62. /**
  63. * @dataProvider provideCommentsCases
  64. */
  65. public function testComments(string $expected, ?string $input = null): void
  66. {
  67. $this->doTest($expected, $input);
  68. }
  69. /**
  70. * @return iterable<array{0: string, 1?: string}>
  71. */
  72. public static function provideCommentsCases(): iterable
  73. {
  74. yield [
  75. '<?php
  76. $withComments[0] // here is a comment
  77. [1] // and here is another
  78. [2] = 3;',
  79. ];
  80. yield [
  81. '<?php
  82. $a = $b[# z
  83. 1#z
  84. ];',
  85. '<?php
  86. $a = $b[ # z
  87. 1#z
  88. ];',
  89. ];
  90. }
  91. public function testLeaveComplexString(): void
  92. {
  93. $expected = <<<'EOF'
  94. <?php
  95. echo "I am printing some spaces here {$foo->bar[1]} {$foo->bar[1]}.";
  96. EOF;
  97. $this->doTest($expected);
  98. }
  99. public function testLeaveFunctions(): void
  100. {
  101. $expected = <<<'EOF'
  102. <?php
  103. function someFunc() { $someVar = []; }
  104. EOF;
  105. $this->doTest($expected);
  106. }
  107. /**
  108. * @return iterable<array{string, string}>
  109. */
  110. public static function provideFixSpaceOutsideOffsetCases(): iterable
  111. {
  112. yield [
  113. '<?php
  114. $a = $b[0] ;',
  115. '<?php
  116. $a = $b [0] ;',
  117. ];
  118. yield [
  119. '<?php
  120. $a = array($b[0] , $b[0] );',
  121. '<?php
  122. $a = array($b [0] , $b [0] );',
  123. ];
  124. yield [
  125. '<?php
  126. $withComments[0] // here is a comment
  127. [1] // and here is another
  128. [2][3] = 4;',
  129. '<?php
  130. $withComments [0] // here is a comment
  131. [1] // and here is another
  132. [2] [3] = 4;',
  133. ];
  134. yield [
  135. '<?php
  136. $c = SOME_CONST[0][1][2];',
  137. '<?php
  138. $c = SOME_CONST [0] [1] [2];',
  139. ];
  140. yield [
  141. '<?php
  142. $f = someFunc()[0][1][2];',
  143. '<?php
  144. $f = someFunc() [0] [1] [2];',
  145. ];
  146. yield [
  147. '<?php
  148. $foo[][0][1][2] = 3;',
  149. '<?php
  150. $foo [] [0] [1] [2] = 3;',
  151. ];
  152. yield [
  153. '<?php
  154. $foo[0][1][2] = 3;',
  155. '<?php
  156. $foo [0] [1] [2] = 3;',
  157. ];
  158. yield [
  159. '<?php
  160. $bar = $foo[0][1][2];',
  161. '<?php
  162. $bar = $foo [0] [1] [2];',
  163. ];
  164. yield [
  165. '<?php
  166. $baz[0][1][2] = 3;',
  167. '<?php
  168. $baz [0]
  169. [1]
  170. [2] = 3;',
  171. ];
  172. }
  173. /**
  174. * @return iterable<array{string, string}>
  175. */
  176. public static function provideFixSpaceInsideOffsetCases(): iterable
  177. {
  178. yield [
  179. '<?php
  180. $foo = array(1, 2, 3);
  181. $var = $foo[1];',
  182. '<?php
  183. $foo = array(1, 2, 3);
  184. $var = $foo[ 1 ];',
  185. ];
  186. yield [
  187. '<?php
  188. $arr = [2, 2 , ];
  189. $var = $arr[0];',
  190. '<?php
  191. $arr = [2, 2 , ];
  192. $var = $arr[ 0 ];',
  193. ];
  194. yield [
  195. '<?php
  196. $arr[2] = 3;',
  197. '<?php
  198. $arr[ 2 ] = 3;',
  199. ];
  200. yield [
  201. '<?php
  202. $arr[] = 3;',
  203. '<?php
  204. $arr[ ] = 3;',
  205. ];
  206. yield [
  207. '<?php
  208. $arr[]["some_offset"][] = 3;',
  209. '<?php
  210. $arr[ ][ "some_offset" ][ ] = 3;',
  211. ];
  212. yield [
  213. '<?php
  214. $arr[]["some offset with spaces"][] = 3;',
  215. '<?php
  216. $arr[ ][ "some offset with spaces" ][ ] = 3;',
  217. ];
  218. yield [
  219. '<?php
  220. $var = $arr[0];',
  221. '<?php
  222. $var = $arr[ 0 ];',
  223. ];
  224. yield [
  225. '<?php
  226. $var = $arr[0][0];',
  227. '<?php
  228. $var = $arr[ 0 ][ 0 ];',
  229. ];
  230. yield [
  231. '<?php
  232. $var = $arr[$a[$b]];',
  233. '<?php
  234. $var = $arr[ $a [ $b ] ];',
  235. ];
  236. yield [
  237. '<?php
  238. $var = $arr[$a[$b]];',
  239. '<?php
  240. $var = $arr[ $a [ $b ] ];',
  241. ];
  242. yield [
  243. '<?php
  244. $var = $arr[0][
  245. 0];',
  246. '<?php
  247. $var = $arr[0][
  248. 0 ];',
  249. ];
  250. yield [
  251. '<?php
  252. $var = $arr[0][0
  253. ];',
  254. '<?php
  255. $var = $arr[0][ 0
  256. ];',
  257. ];
  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. /**
  293. * @param _AutogeneratedInputConfiguration $configuration
  294. *
  295. * @dataProvider provideFixPre80Cases
  296. *
  297. * @requires PHP <8.0
  298. */
  299. public function testFixPre80(string $expected, ?string $input = null, array $configuration = []): void
  300. {
  301. $this->fixer->configure($configuration);
  302. $this->doTest($expected, $input);
  303. }
  304. public static function provideFixPre80Cases(): iterable
  305. {
  306. yield [
  307. '<?php
  308. $foo{0}{1}{2} = 3;',
  309. '<?php
  310. $foo {0} {1} {2} = 3;',
  311. ];
  312. yield [
  313. '<?php
  314. $foobar = $foo{0}[1]{2};',
  315. '<?php
  316. $foobar = $foo {0} [1] {2};',
  317. ];
  318. yield [
  319. '<?php
  320. $var = $arr[0]{0
  321. };',
  322. '<?php
  323. $var = $arr[0]{ 0
  324. };',
  325. ];
  326. yield from self::provideMultiDimensionalArrayCases();
  327. }
  328. /**
  329. * @param _AutogeneratedInputConfiguration $configuration
  330. *
  331. * @dataProvider provideFix80Cases
  332. *
  333. * @requires PHP 8.0
  334. */
  335. public function testFix80(string $expected, ?string $input, array $configuration): void
  336. {
  337. $this->fixer->configure($configuration);
  338. $this->doTest($expected, $input);
  339. }
  340. /**
  341. * @return iterable<array{string, string, _AutogeneratedInputConfiguration}>
  342. */
  343. public static function provideFix80Cases(): iterable
  344. {
  345. foreach (self::provideMultiDimensionalArrayCases() as $index => $test) {
  346. $test[0] = str_replace('{', '[', $test[0]);
  347. $test[0] = str_replace('}', ']', $test[0]);
  348. $test[1] = str_replace('{', '[', $test[1]);
  349. $test[1] = str_replace('}', ']', $test[1]);
  350. yield $index => $test;
  351. }
  352. }
  353. public function testWrongConfig(): void
  354. {
  355. $this->expectException(InvalidFixerConfigurationException::class);
  356. $this->expectExceptionMessageMatches('/^\[no_spaces_around_offset\] Invalid configuration: The option "positions" .*\.$/');
  357. $this->fixer->configure(['positions' => ['foo']]); // @phpstan-ignore-line
  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. }