FunctionDeclarationFixerTest.php 15 KB

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