FunctionDeclarationFixerTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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\FunctionNotation;
  13. use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException;
  14. use PhpCsFixer\Fixer\FunctionNotation\FunctionDeclarationFixer;
  15. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  16. /**
  17. * @author Denis Sokolov <denis@sokolov.cc>
  18. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  19. *
  20. * @internal
  21. *
  22. * @covers \PhpCsFixer\Fixer\FunctionNotation\FunctionDeclarationFixer
  23. */
  24. final class FunctionDeclarationFixerTest extends AbstractFixerTestCase
  25. {
  26. /**
  27. * @var array<string,string>
  28. */
  29. private static $configurationClosureSpacingNone = ['closure_function_spacing' => FunctionDeclarationFixer::SPACING_NONE];
  30. public function testInvalidConfigurationClosureFunctionSpacing(): void
  31. {
  32. $this->expectException(InvalidFixerConfigurationException::class);
  33. $this->expectExceptionMessageMatches(
  34. '#^\[function_declaration\] Invalid configuration: The option "closure_function_spacing" with value "neither" is invalid\. Accepted values are: "none", "one"\.$#'
  35. );
  36. $this->fixer->configure(['closure_function_spacing' => 'neither']);
  37. }
  38. /**
  39. * @dataProvider provideFixCases
  40. */
  41. public function testFix(string $expected, ?string $input = null, array $configuration = []): void
  42. {
  43. $this->fixer->configure($configuration);
  44. $this->doTest($expected, $input);
  45. }
  46. public function provideFixCases(): array
  47. {
  48. return [
  49. [
  50. // non-PHP test
  51. 'function foo () {}',
  52. ],
  53. [
  54. '<?php function foo() {}',
  55. '<?php function foo() {}',
  56. ],
  57. [
  58. '<?php function foo() {}',
  59. '<?php function foo () {}',
  60. ],
  61. [
  62. '<?php function foo() {}',
  63. '<?php function foo () {}',
  64. ],
  65. [
  66. '<?php function foo() {}',
  67. '<?php function
  68. foo () {}',
  69. ],
  70. [
  71. '<?php function ($i) {};',
  72. '<?php function($i) {};',
  73. ],
  74. [
  75. '<?php function _function() {}',
  76. '<?php function _function () {}',
  77. ],
  78. [
  79. '<?php function foo($a, $b = true) {}',
  80. '<?php function foo($a, $b = true){}',
  81. ],
  82. [
  83. '<?php function foo($a, $b = true) {}',
  84. '<?php function foo($a, $b = true) {}',
  85. ],
  86. [
  87. '<?php function foo($a)
  88. {}',
  89. ],
  90. [
  91. '<?php function ($a) use ($b) {};',
  92. '<?php function ($a) use ($b) {};',
  93. ],
  94. [
  95. '<?php $foo = function ($foo) use ($bar, $baz) {};',
  96. '<?php $foo = function ($foo) use($bar, $baz) {};',
  97. ],
  98. [
  99. '<?php $foo = function ($foo) use ($bar, $baz) {};',
  100. '<?php $foo = function ($foo)use ($bar, $baz) {};',
  101. ],
  102. [
  103. '<?php $foo = function ($foo) use ($bar, $baz) {};',
  104. '<?php $foo = function ($foo)use($bar, $baz) {};',
  105. ],
  106. [
  107. '<?php function &foo($a) {}',
  108. '<?php function &foo( $a ) {}',
  109. ],
  110. [
  111. '<?php function foo($a)
  112. {}',
  113. '<?php function foo( $a)
  114. {}',
  115. ],
  116. [
  117. '<?php
  118. function foo(
  119. $a,
  120. $b,
  121. $c
  122. ) {}',
  123. ],
  124. [
  125. '<?php $function = function () {};',
  126. '<?php $function = function(){};',
  127. ],
  128. [
  129. '<?php $function("");',
  130. ],
  131. [
  132. '<?php function ($a) use ($b) {};',
  133. '<?php function($a)use($b) {};',
  134. ],
  135. [
  136. '<?php function ($a) use ($b) {};',
  137. '<?php function($a) use ($b) {};',
  138. ],
  139. [
  140. '<?php function ($a) use ($b) {};',
  141. '<?php function ($a) use ( $b ) {};',
  142. ],
  143. [
  144. '<?php function &($a) use ($b) {};',
  145. '<?php function &( $a ) use ( $b ) {};',
  146. ],
  147. [
  148. '<?php
  149. interface Foo
  150. {
  151. public function setConfig(ConfigInterface $config);
  152. }',
  153. ],
  154. // do not remove multiline space before { when end of previous line is a comment
  155. [
  156. '<?php
  157. function foo() // bar
  158. { // baz
  159. }',
  160. ],
  161. [
  162. '<?php
  163. function foo() /* bar */
  164. { /* baz */
  165. }',
  166. ],
  167. [
  168. // non-PHP test
  169. 'function foo () {}',
  170. null,
  171. self::$configurationClosureSpacingNone,
  172. ],
  173. [
  174. '<?php function foo() {}',
  175. '<?php function foo() {}',
  176. self::$configurationClosureSpacingNone,
  177. ],
  178. [
  179. '<?php function foo() {}',
  180. '<?php function foo () {}',
  181. self::$configurationClosureSpacingNone,
  182. ],
  183. [
  184. '<?php function foo() {}',
  185. '<?php function foo () {}',
  186. self::$configurationClosureSpacingNone,
  187. ],
  188. [
  189. '<?php function foo() {}',
  190. '<?php function
  191. foo () {}',
  192. self::$configurationClosureSpacingNone,
  193. ],
  194. [
  195. '<?php function($i) {};',
  196. null,
  197. self::$configurationClosureSpacingNone,
  198. ],
  199. [
  200. '<?php function _function() {}',
  201. '<?php function _function () {}',
  202. self::$configurationClosureSpacingNone,
  203. ],
  204. [
  205. '<?php function foo($a, $b = true) {}',
  206. '<?php function foo($a, $b = true){}',
  207. self::$configurationClosureSpacingNone,
  208. ],
  209. [
  210. '<?php function foo($a, $b = true) {}',
  211. '<?php function foo($a, $b = true) {}',
  212. self::$configurationClosureSpacingNone,
  213. ],
  214. [
  215. '<?php function foo($a)
  216. {}',
  217. null,
  218. self::$configurationClosureSpacingNone,
  219. ],
  220. [
  221. '<?php function($a) use ($b) {};',
  222. '<?php function ($a) use ($b) {};',
  223. self::$configurationClosureSpacingNone,
  224. ],
  225. [
  226. '<?php $foo = function($foo) use ($bar, $baz) {};',
  227. '<?php $foo = function ($foo) use($bar, $baz) {};',
  228. self::$configurationClosureSpacingNone,
  229. ],
  230. [
  231. '<?php $foo = function($foo) use ($bar, $baz) {};',
  232. '<?php $foo = function ($foo)use ($bar, $baz) {};',
  233. self::$configurationClosureSpacingNone,
  234. ],
  235. [
  236. '<?php $foo = function($foo) use ($bar, $baz) {};',
  237. '<?php $foo = function ($foo)use($bar, $baz) {};',
  238. self::$configurationClosureSpacingNone,
  239. ],
  240. [
  241. '<?php function &foo($a) {}',
  242. '<?php function &foo( $a ) {}',
  243. self::$configurationClosureSpacingNone,
  244. ],
  245. [
  246. '<?php function foo($a)
  247. {}',
  248. '<?php function foo( $a)
  249. {}',
  250. self::$configurationClosureSpacingNone,
  251. ],
  252. [
  253. '<?php
  254. function foo(
  255. $a,
  256. $b,
  257. $c
  258. ) {}',
  259. null,
  260. self::$configurationClosureSpacingNone,
  261. ],
  262. [
  263. '<?php $function = function() {};',
  264. '<?php $function = function (){};',
  265. self::$configurationClosureSpacingNone,
  266. ],
  267. [
  268. '<?php $function("");',
  269. null,
  270. self::$configurationClosureSpacingNone,
  271. ],
  272. [
  273. '<?php function($a) use ($b) {};',
  274. '<?php function ($a)use($b) {};',
  275. self::$configurationClosureSpacingNone,
  276. ],
  277. [
  278. '<?php function($a) use ($b) {};',
  279. '<?php function ($a) use ($b) {};',
  280. self::$configurationClosureSpacingNone,
  281. ],
  282. [
  283. '<?php function($a) use ($b) {};',
  284. '<?php function ($a) use ( $b ) {};',
  285. self::$configurationClosureSpacingNone,
  286. ],
  287. [
  288. '<?php function&($a) use ($b) {};',
  289. '<?php function &( $a ) use ( $b ) {};',
  290. self::$configurationClosureSpacingNone,
  291. ],
  292. [
  293. '<?php
  294. interface Foo
  295. {
  296. public function setConfig(ConfigInterface $config);
  297. }',
  298. null,
  299. self::$configurationClosureSpacingNone,
  300. ],
  301. // do not remove multiline space before { when end of previous line is a comment
  302. [
  303. '<?php
  304. function foo() // bar
  305. { // baz
  306. }',
  307. null,
  308. self::$configurationClosureSpacingNone,
  309. ],
  310. [
  311. '<?php
  312. function foo() /* bar */
  313. { /* baz */
  314. }',
  315. null,
  316. self::$configurationClosureSpacingNone,
  317. ],
  318. [
  319. '<?php function #
  320. foo#
  321. (#
  322. ) #
  323. {#
  324. }#',
  325. ],
  326. [
  327. '<?php
  328. $b = static function ($a) {
  329. echo $a;
  330. };
  331. ',
  332. '<?php
  333. $b = static function( $a ) {
  334. echo $a;
  335. };
  336. ',
  337. ],
  338. [
  339. '<?php
  340. $b = static function($a) {
  341. echo $a;
  342. };
  343. ',
  344. '<?php
  345. $b = static function ( $a ) {
  346. echo $a;
  347. };
  348. ',
  349. self::$configurationClosureSpacingNone,
  350. ],
  351. ['<?php use function Foo\bar; bar ( 1 );'],
  352. ['<?php use function some\test\{fn_a, fn_b, fn_c};'],
  353. ['<?php use function some\test\{fn_a, fn_b, fn_c} ?>'],
  354. ['<?php use function Foo\bar; bar ( 1 );', null, self::$configurationClosureSpacingNone],
  355. ['<?php use function some\test\{fn_a, fn_b, fn_c};', null, self::$configurationClosureSpacingNone],
  356. ['<?php use function some\test\{fn_a, fn_b, fn_c} ?>', null, self::$configurationClosureSpacingNone],
  357. ];
  358. }
  359. /**
  360. * @dataProvider provideFix74Cases
  361. * @requires PHP 7.4
  362. */
  363. public function test74(string $expected, ?string $input = null, array $configuration = []): void
  364. {
  365. $this->fixer->configure($configuration);
  366. $this->doTest($expected, $input);
  367. }
  368. public function provideFix74Cases(): array
  369. {
  370. return [
  371. [
  372. '<?php fn ($i) => null;',
  373. '<?php fn($i) => null;',
  374. ],
  375. [
  376. '<?php fn ($a) => null;',
  377. '<?php fn ($a) => null;',
  378. ],
  379. [
  380. '<?php $fn = fn () => null;',
  381. '<?php $fn = fn()=> null;',
  382. ],
  383. [
  384. '<?php fn &($a) => null;',
  385. '<?php fn &( $a ) => null;',
  386. ],
  387. [
  388. '<?php fn($i) => null;',
  389. null,
  390. self::$configurationClosureSpacingNone,
  391. ],
  392. [
  393. '<?php fn($a) => null;',
  394. '<?php fn ($a) => null;',
  395. self::$configurationClosureSpacingNone,
  396. ],
  397. [
  398. '<?php $fn = fn() => null;',
  399. '<?php $fn = fn ()=> null;',
  400. self::$configurationClosureSpacingNone,
  401. ],
  402. [
  403. '<?php $fn("");',
  404. null,
  405. self::$configurationClosureSpacingNone,
  406. ],
  407. [
  408. '<?php fn&($a) => null;',
  409. '<?php fn &( $a ) => null;',
  410. self::$configurationClosureSpacingNone,
  411. ],
  412. [
  413. '<?php fn&($a,$b) => null;',
  414. '<?php fn &( $a,$b ) => null;',
  415. self::$configurationClosureSpacingNone,
  416. ],
  417. [
  418. '<?php $b = static fn ($a) => $a;',
  419. '<?php $b = static fn( $a ) => $a;',
  420. ],
  421. [
  422. '<?php $b = static fn($a) => $a;',
  423. '<?php $b = static fn ( $a ) => $a;',
  424. self::$configurationClosureSpacingNone,
  425. ],
  426. ];
  427. }
  428. /**
  429. * @dataProvider provideFixPhp80Cases
  430. * @requires PHP 8.0
  431. */
  432. public function testFixPhp80(string $expected, ?string $input = null, array $configuration = []): void
  433. {
  434. $this->fixer->configure($configuration);
  435. $this->doTest($expected, $input);
  436. }
  437. public function provideFixPhp80Cases(): \Generator
  438. {
  439. yield [
  440. '<?php function ($i,) {};',
  441. '<?php function( $i, ) {};',
  442. ];
  443. yield [
  444. '<?php
  445. $b = static function ($a,$b,) {
  446. echo $a;
  447. };
  448. ',
  449. '<?php
  450. $b = static function( $a,$b, ) {
  451. echo $a;
  452. };
  453. ',
  454. ];
  455. yield [
  456. '<?php fn&($a,$b,) => null;',
  457. '<?php fn &( $a,$b, ) => null;',
  458. self::$configurationClosureSpacingNone,
  459. ];
  460. }
  461. }