RegularCallableCallFixerTest.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  16. *
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\FunctionNotation\RegularCallableCallFixer
  20. */
  21. final class RegularCallableCallFixerTest extends AbstractFixerTestCase
  22. {
  23. /**
  24. * @dataProvider provideFixCases
  25. */
  26. public function testFix(string $expected, ?string $input = null): void
  27. {
  28. $this->doTest($expected, $input);
  29. }
  30. public static function provideFixCases(): iterable
  31. {
  32. yield 'call by name - list' => [
  33. '<?php
  34. dont_touch_me(1, 2);
  35. foo();
  36. foo();
  37. call_user_func("foo" . "bar"); // not (yet?) supported by Fixer, possible since PHP 7+
  38. var_dump(1, 2);
  39. Bar\Baz::d(1, 2);
  40. \Bar\Baz::d(1, 2);',
  41. '<?php
  42. dont_touch_me(1, 2);
  43. call_user_func(\'foo\');
  44. call_user_func("foo");
  45. call_user_func("foo" . "bar"); // not (yet?) supported by Fixer, possible since PHP 7+
  46. call_user_func("var_dump", 1, 2);
  47. call_user_func("Bar\Baz::d", 1, 2);
  48. call_user_func("\Bar\Baz::d", 1, 2);',
  49. ];
  50. yield 'call by name - array' => [
  51. '<?php Bar\Baz::d(...[1, 2]);',
  52. '<?php call_user_func_array("Bar\Baz::d", [1, 2]);',
  53. ];
  54. yield 'call by array-as-name, not supported' => [
  55. '<?php
  56. call_user_func(array("Bar\baz", "myCallbackMethod"), 1, 2);
  57. call_user_func(["Bar\baz", "myCallbackMethod"], 1, 2);
  58. call_user_func([$obj, "myCallbackMethod"], 1, 2);
  59. call_user_func([$obj, $cb."Method"], 1, 2);
  60. call_user_func(array(__NAMESPACE__ ."Foo", "test"), 1, 2);
  61. call_user_func(array("Foo", "parent::method"), 1, 2); // no way to convert `parent::`
  62. ',
  63. ];
  64. yield 'call by variable' => [
  65. '<?php
  66. $c(1, 2);
  67. $a["b"]["c"](1, 2);
  68. ',
  69. '<?php
  70. call_user_func($c, 1, 2);
  71. call_user_func($a["b"]["c"], 1, 2);
  72. ',
  73. ];
  74. yield 'call with comments' => [
  75. '<?php
  76. dont_touch_me(/* a */1, 2/** b */);
  77. foo();
  78. foo(/* a */1, 2/** b */);
  79. foo(/* a *//** b *//** c */1/** d */,/** e */ 2);
  80. call_user_func("foo" . "bar"); // not (yet?) supported by Fixer, possible since PHP 7+
  81. var_dump(1, /*
  82. aaa
  83. */ 2);
  84. var_dump(3 /*
  85. aaa
  86. */, 4);
  87. Bar\Baz::d(1, 2);
  88. \Bar\Baz::d(1, 2);',
  89. '<?php
  90. dont_touch_me(/* a */1, 2/** b */);
  91. call_user_func(\'foo\');
  92. call_user_func("foo", /* a */1, 2/** b */);
  93. call_user_func("foo"/* a *//** b */, /** c */1/** d */,/** e */ 2);
  94. call_user_func("foo" . "bar"); // not (yet?) supported by Fixer, possible since PHP 7+
  95. call_user_func("var_dump", 1, /*
  96. aaa
  97. */ 2);
  98. call_user_func("var_dump", 3 /*
  99. aaa
  100. */, 4);
  101. call_user_func("Bar\Baz::d", 1, 2);
  102. call_user_func("\Bar\Baz::d", 1, 2);',
  103. ];
  104. yield 'single var' => [
  105. '<?php $foo() ?>',
  106. '<?php \call_user_func($foo) ?>',
  107. ];
  108. yield 'unsafe repeated variable' => [
  109. '<?php call_user_func($foo, $foo = "bar");',
  110. ];
  111. if (\PHP_VERSION_ID < 8_00_00) {
  112. yield 'call by variable (PHP < 8.0)' => [
  113. '<?php
  114. $a{"b"}{"c"}(1, 2);
  115. ',
  116. '<?php
  117. call_user_func($a{"b"}{"c"}, 1, 2);
  118. ',
  119. ];
  120. }
  121. yield 'call by property' => [
  122. '<?php
  123. ($f->c)(1, 2);
  124. ($f->{c})(1, 2);
  125. ($x["y"]->c)(1, 2);
  126. ($x["y"]->{"c"})(1, 2);
  127. ',
  128. '<?php
  129. call_user_func($f->c, 1, 2);
  130. call_user_func($f->{c}, 1, 2);
  131. call_user_func($x["y"]->c, 1, 2);
  132. call_user_func($x["y"]->{"c"}, 1, 2);
  133. ',
  134. ];
  135. yield 'call by anon-function' => [
  136. '<?php
  137. (function ($a, $b) { var_dump($a, $b); })(1, 2);
  138. (static function ($a, $b) { var_dump($a, $b); })(1, 2);
  139. ',
  140. '<?php
  141. call_user_func(function ($a, $b) { var_dump($a, $b); }, 1, 2);
  142. call_user_func(static function ($a, $b) { var_dump($a, $b); }, 1, 2);
  143. ',
  144. ];
  145. yield 'complex cases' => [
  146. '<?php
  147. call_user_func(\'a\'.$a.$b, 1, 2);
  148. ($a/**/.$b)(1, 2);
  149. (function (){})();
  150. ($a["b"]["c"]->a)(1, 2, 3, 4);
  151. ($a::$b)(1, 2);
  152. ($a[1]::$b[2][3])([&$c], array(&$d));
  153. ',
  154. '<?php
  155. call_user_func(\'a\'.$a.$b, 1, 2);
  156. call_user_func($a/**/.$b, 1, 2);
  157. \call_user_func(function (){});
  158. call_user_func($a["b"]["c"]->a, 1, 2, 3, 4);
  159. call_user_func($a::$b, 1, 2);
  160. call_user_func($a[1]::$b[2][3], [&$c], array(&$d));
  161. ',
  162. ];
  163. yield [
  164. '<?php ($a(1, 2))([&$x], array(&$z));',
  165. '<?php call_user_func($a(1, 2), [&$x], array(&$z));',
  166. ];
  167. yield 'redeclare/override' => [
  168. '<?php
  169. if (!function_exists("call_user_func")) {
  170. function call_user_func($foo){}
  171. }
  172. ',
  173. ];
  174. yield 'function name with escaped slash' => [
  175. '<?php \pack(...$args);',
  176. '<?php call_user_func_array("\\\\pack", $args);',
  177. ];
  178. yield 'function call_user_func_array with leading slash' => [
  179. '<?php \pack(...$args);',
  180. '<?php \call_user_func_array("\\\\pack", $args);',
  181. ];
  182. yield 'function call_user_func_array caps' => [
  183. '<?php \pack(...$args);',
  184. '<?php \CALL_USER_FUNC_ARRAY("\\\\pack", $args);',
  185. ];
  186. yield [
  187. '<?php foo(1,);',
  188. '<?php call_user_func("foo", 1,);',
  189. ];
  190. yield 'empty string double quote' => [
  191. '<?php call_user_func("", 1,);',
  192. ];
  193. yield 'empty string single quote' => [
  194. '<?php call_user_func(\' \', 1,);',
  195. ];
  196. yield 'string with padding' => [
  197. '<?php call_user_func(" padded ", 1,);',
  198. ];
  199. yield 'binary string lower double quote' => [
  200. '<?php call_user_func(b"foo", 1,);',
  201. ];
  202. yield 'binary string upper single quote' => [
  203. '<?php call_user_func(B"foo", 1,);',
  204. ];
  205. yield 'static property as first argument' => [
  206. '<?php
  207. class Foo {
  208. public static $factory;
  209. public static function createFromFactory(...$args) {
  210. return call_user_func_array(static::$factory, $args);
  211. }
  212. }',
  213. ];
  214. }
  215. /**
  216. * @dataProvider provideFix81Cases
  217. *
  218. * @requires PHP 8.1
  219. */
  220. public function testFix81(string $expected, ?string $input = null): void
  221. {
  222. $this->doTest($expected, $input);
  223. }
  224. public static function provideFix81Cases(): iterable
  225. {
  226. yield [
  227. '<?php \call_user_func(...) ?>',
  228. ];
  229. }
  230. }