FunctionToConstantFixerTest.php 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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\LanguageConstruct;
  13. use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException;
  14. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  15. /**
  16. * @internal
  17. *
  18. * @covers \PhpCsFixer\Fixer\LanguageConstruct\FunctionToConstantFixer
  19. */
  20. final class FunctionToConstantFixerTest extends AbstractFixerTestCase
  21. {
  22. /**
  23. * @dataProvider provideTestCases
  24. */
  25. public function testFix(string $expected, ?string $input = null, array $config = []): void
  26. {
  27. $this->fixer->configure($config);
  28. $this->doTest($expected, $input);
  29. }
  30. public function provideTestCases(): array
  31. {
  32. return [
  33. 'Minimal case, alternative casing, alternative statement end.' => [
  34. '<?php echo PHP_VERSION?>',
  35. '<?php echo PHPversion()?>',
  36. ],
  37. 'With embedded comment.' => [
  38. '<?php echo PHP_VERSION/**/?>',
  39. '<?php echo phpversion(/**/)?>',
  40. ],
  41. 'With white space.' => [
  42. '<?php echo PHP_VERSION ;',
  43. '<?php echo phpversion ( ) ;',
  44. ],
  45. 'With multi line whitespace.' => [
  46. '<?php echo
  47. PHP_VERSION
  48. '.'
  49. '.'
  50. ;',
  51. '<?php echo
  52. phpversion
  53. (
  54. )
  55. ;',
  56. ],
  57. 'Global namespaced.' => [
  58. '<?php echo \PHP_VERSION;',
  59. '<?php echo \phpversion();',
  60. ],
  61. 'Wrong number of arguments.' => [
  62. '<?php phpversion($a);',
  63. ],
  64. 'Wrong namespace.' => [
  65. '<?php A\B\phpversion();',
  66. ],
  67. 'Class creating.' => [
  68. '<?php new phpversion();',
  69. ],
  70. 'Class static method call.' => [
  71. '<?php A::phpversion();',
  72. ],
  73. 'Class method call.' => [
  74. '<?php $a->phpversion();',
  75. ],
  76. 'Overridden function.' => [
  77. '<?php if (!function_exists("phpversion")){function phpversion(){}}?>',
  78. ],
  79. 'phpversion only' => [
  80. '<?php echo PHP_VERSION; echo php_sapi_name(); echo pi();',
  81. '<?php echo phpversion(); echo php_sapi_name(); echo pi();',
  82. ['functions' => ['phpversion']],
  83. ],
  84. 'php_sapi_name only' => [
  85. '<?php echo phpversion(); echo PHP_SAPI; echo pi();',
  86. '<?php echo phpversion(); echo php_sapi_name(); echo pi();',
  87. ['functions' => ['php_sapi_name']],
  88. ],
  89. 'php_sapi_name in conditional' => [
  90. '<?php if ("cli" === PHP_SAPI && $a){ echo 123;}',
  91. '<?php if ("cli" === php_sapi_name() && $a){ echo 123;}',
  92. ['functions' => ['php_sapi_name']],
  93. ],
  94. 'pi only' => [
  95. '<?php echo phpversion(); echo php_sapi_name(); echo M_PI;',
  96. '<?php echo phpversion(); echo php_sapi_name(); echo pi();',
  97. ['functions' => ['pi']],
  98. ],
  99. 'multi line pi' => [
  100. '<?php
  101. $a =
  102. $b
  103. || $c < M_PI
  104. ;',
  105. '<?php
  106. $a =
  107. $b
  108. || $c < pi()
  109. ;',
  110. ['functions' => ['pi']],
  111. ],
  112. 'phpversion and pi' => [
  113. '<?php echo PHP_VERSION; echo php_sapi_name(); echo M_PI;',
  114. '<?php echo phpversion(); echo php_sapi_name(); echo M_PI;',
  115. ['functions' => ['pi', 'phpversion']],
  116. ],
  117. 'diff argument count than native allows' => [
  118. '<?php
  119. echo phpversion(1);
  120. echo php_sapi_name(1,2);
  121. echo pi(1);
  122. ',
  123. ],
  124. 'get_class => T_CLASS' => [
  125. '<?php
  126. class A
  127. {
  128. public function echoClassName($notMe)
  129. {
  130. echo get_class($notMe);
  131. echo __CLASS__/** 1 *//* 2 */;
  132. echo __CLASS__;
  133. }
  134. }
  135. class B
  136. {
  137. use A;
  138. }
  139. ',
  140. '<?php
  141. class A
  142. {
  143. public function echoClassName($notMe)
  144. {
  145. echo get_class($notMe);
  146. echo get_class(/** 1 *//* 2 */);
  147. echo GET_Class();
  148. }
  149. }
  150. class B
  151. {
  152. use A;
  153. }
  154. ',
  155. ],
  156. 'get_class with leading backslash' => [
  157. '<?php __CLASS__;',
  158. '<?php \get_class();',
  159. ],
  160. [
  161. '<?php class A { function B(){ echo static::class; }}',
  162. '<?php class A { function B(){ echo get_called_class(); }}',
  163. ['functions' => ['get_called_class']],
  164. ],
  165. [
  166. '<?php class A { function B(){
  167. echo#.
  168. #0
  169. static::class#1
  170. #2
  171. #3
  172. #4
  173. #5
  174. #6
  175. ;#7
  176. }}
  177. ',
  178. '<?php class A { function B(){
  179. echo#.
  180. #0
  181. get_called_class#1
  182. #2
  183. (#3
  184. #4
  185. )#5
  186. #6
  187. ;#7
  188. }}
  189. ',
  190. ['functions' => ['get_called_class']],
  191. ],
  192. 'get_called_class with leading backslash' => [
  193. '<?php class A { function B(){echo static::class; }}',
  194. '<?php class A { function B(){echo \get_called_class(); }}',
  195. ['functions' => ['get_called_class']],
  196. ],
  197. 'get_called_class overridden' => [
  198. '<?php echo get_called_class(1);',
  199. null,
  200. ['functions' => ['get_called_class']],
  201. ],
  202. [
  203. '<?php class Foo{ public function Bar(){ echo static::class ; }}',
  204. '<?php class Foo{ public function Bar(){ echo get_class( $This ); }}',
  205. ['functions' => ['get_class_this']],
  206. ],
  207. [
  208. '<?php class Foo{ public function Bar(){ echo static::class; get_class(1, 2); get_class($a); get_class($a, $b);}}',
  209. '<?php class Foo{ public function Bar(){ echo get_class($this); get_class(1, 2); get_class($a); get_class($a, $b);}}',
  210. ['functions' => ['get_class_this']],
  211. ],
  212. [
  213. '<?php class Foo{ public function Bar(){ echo static::class /* 0 */ /* 1 */ ;}}',
  214. '<?php class Foo{ public function Bar(){ echo \get_class( /* 0 */ $this /* 1 */ );}}',
  215. ['functions' => ['get_class_this']],
  216. ],
  217. [
  218. '<?php class Foo{ public function Bar(){ echo static::class; echo __CLASS__; }}',
  219. '<?php class Foo{ public function Bar(){ echo \get_class((($this))); echo get_class(); }}',
  220. ['functions' => ['get_class_this', 'get_class']],
  221. ],
  222. [
  223. '<?php
  224. class Foo{ public function Bar(){ echo $reflection = new \ReflectionClass(get_class($this->extension)); }}
  225. class Foo{ public function Bar(){ echo $reflection = new \ReflectionClass(get_class($this() )); }}
  226. ',
  227. null,
  228. ['functions' => ['get_class_this']],
  229. ],
  230. [
  231. "<?php namespace Foo;\nfunction &PHPversion(){}",
  232. ],
  233. ];
  234. }
  235. /**
  236. * @dataProvider provideInvalidConfigurationKeysCases
  237. */
  238. public function testInvalidConfigurationKeys(array $config): void
  239. {
  240. $this->expectException(InvalidFixerConfigurationException::class);
  241. $this->expectExceptionMessageMatches('#^\[function_to_constant\] Invalid configuration: The option "functions" with value array is invalid\.$#');
  242. $this->fixer->configure($config);
  243. }
  244. public function provideInvalidConfigurationKeysCases(): array
  245. {
  246. return [
  247. [['functions' => ['a']]],
  248. [['functions' => [false => 1]]],
  249. [['functions' => ['abc' => true]]],
  250. ];
  251. }
  252. public function testInvalidConfigurationValue(): void
  253. {
  254. $this->expectException(InvalidFixerConfigurationException::class);
  255. $this->expectExceptionMessageMatches('#^\[function_to_constant\] Invalid configuration: The option "0" does not exist\. Defined options are: "functions"\.$#');
  256. $this->fixer->configure(['pi123']);
  257. }
  258. /**
  259. * @dataProvider provideFix81Cases
  260. * @requires PHP 8.1
  261. */
  262. public function testFix81(string $expected, string $input = null): void
  263. {
  264. $this->doTest($expected, $input);
  265. }
  266. public function provideFix81Cases(): \Generator
  267. {
  268. yield 'first callable class' => [
  269. '<?php $a = get_class(...);',
  270. ];
  271. }
  272. }