VoidReturnFixerTest.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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. use PhpCsFixer\Tokenizer\Tokens;
  15. /**
  16. * @author Mark Nielsen
  17. *
  18. * @internal
  19. *
  20. * @covers \PhpCsFixer\Fixer\FunctionNotation\VoidReturnFixer
  21. */
  22. final class VoidReturnFixerTest extends AbstractFixerTestCase
  23. {
  24. /**
  25. * @dataProvider provideFixCases
  26. */
  27. public function testFix(string $expected, ?string $input = null): void
  28. {
  29. $this->doTest($expected, $input);
  30. }
  31. public static function provideFixCases(): iterable
  32. {
  33. return [
  34. ['<?php class Test { public function __construct() {} }'],
  35. ['<?php class Test { public function __destruct() {} }'],
  36. ['<?php class Test { public function __clone() {} }'],
  37. ['<?php function foo($param) { return $param; }'],
  38. ['<?php function foo($param) { return null; }'],
  39. ['<?php function foo($param) { yield; }'],
  40. ['<?php function foo($param) { yield $param; }'],
  41. ['<?php function foo($param) { yield from test(); }'],
  42. ['<?php function foo($param): Void {}'],
  43. ['<?php interface Test { public function foo($param); }'],
  44. ['<?php function foo($param) { return function($a) use ($param): string {}; }'],
  45. ['<?php abstract class Test { abstract public function foo($param); }'],
  46. ['<?php use Foo\ { function Bar }; function test() { return Bar(); }'],
  47. ['<?php
  48. /**
  49. * @return array
  50. */
  51. function foo($param) {}
  52. '],
  53. ['<?php
  54. interface Test {
  55. /**
  56. * @return array
  57. */
  58. public function foo($param);
  59. }
  60. '],
  61. [
  62. '<?php function foo($param): void { return; }',
  63. '<?php function foo($param) { return; }',
  64. ],
  65. [
  66. '<?php function foo($param): void {}',
  67. '<?php function foo($param) {}',
  68. ],
  69. [
  70. '<?php class Test { public function foo($param): void { return; } }',
  71. '<?php class Test { public function foo($param) { return; } }',
  72. ],
  73. [
  74. '<?php class Test { public function foo($param): void {} }',
  75. '<?php class Test { public function foo($param) {} }',
  76. ],
  77. [
  78. '<?php trait Test { public function foo($param): void { return; } }',
  79. '<?php trait Test { public function foo($param) { return; } }',
  80. ],
  81. [
  82. '<?php trait Test { public function foo($param): void {} }',
  83. '<?php trait Test { public function foo($param) {} }',
  84. ],
  85. [
  86. '<?php $arr = []; usort($arr, function ($a, $b): void {});',
  87. '<?php $arr = []; usort($arr, function ($a, $b) {});',
  88. ],
  89. [
  90. '<?php $arr = []; $param = 1; usort($arr, function ($a, $b) use ($param): void {});',
  91. '<?php $arr = []; $param = 1; usort($arr, function ($a, $b) use ($param) {});',
  92. ],
  93. [
  94. '<?php function foo($param) { return function($a) use ($param): void {}; }',
  95. '<?php function foo($param) { return function($a) use ($param) {}; }',
  96. ],
  97. [
  98. '<?php function foo($param): void { $arr = []; usort($arr, function ($a, $b) use ($param): void {}); }',
  99. '<?php function foo($param) { $arr = []; usort($arr, function ($a, $b) use ($param) {}); }',
  100. ],
  101. [
  102. '<?php function foo() { $arr = []; return usort($arr, new class { public function __invoke($a, $b): void {} }); }',
  103. '<?php function foo() { $arr = []; return usort($arr, new class { public function __invoke($a, $b) {} }); }',
  104. ],
  105. [
  106. '<?php function foo(): void { $arr = []; usort($arr, new class { public function __invoke($a, $b): void {} }); }',
  107. '<?php function foo() { $arr = []; usort($arr, new class { public function __invoke($a, $b) {} }); }',
  108. ],
  109. [
  110. '<?php
  111. function foo(): void {
  112. $a = function (): void {};
  113. }',
  114. '<?php
  115. function foo() {
  116. $a = function () {};
  117. }',
  118. ],
  119. [
  120. '<?php
  121. function foo(): void {
  122. (function (): void {
  123. return;
  124. })();
  125. }',
  126. '<?php
  127. function foo() {
  128. (function () {
  129. return;
  130. })();
  131. }',
  132. ],
  133. [
  134. '<?php
  135. function foo(): void {
  136. (function () {
  137. return 1;
  138. })();
  139. }',
  140. '<?php
  141. function foo() {
  142. (function () {
  143. return 1;
  144. })();
  145. }',
  146. ],
  147. [
  148. '<?php
  149. function foo(): void {
  150. $b = new class {
  151. public function b1(): void {}
  152. public function b2() { return 2; }
  153. };
  154. }',
  155. '<?php
  156. function foo() {
  157. $b = new class {
  158. public function b1() {}
  159. public function b2() { return 2; }
  160. };
  161. }',
  162. ],
  163. [
  164. '<?php
  165. /**
  166. * @return void
  167. */
  168. function foo($param): void {}',
  169. '<?php
  170. /**
  171. * @return void
  172. */
  173. function foo($param) {}',
  174. ],
  175. [
  176. '<?php
  177. interface Test {
  178. /**
  179. * @return void
  180. */
  181. public function foo($param): void;
  182. }',
  183. '<?php
  184. interface Test {
  185. /**
  186. * @return void
  187. */
  188. public function foo($param);
  189. }',
  190. ],
  191. [
  192. '<?php
  193. abstract class Test {
  194. /**
  195. * @return void
  196. */
  197. abstract protected function foo($param): void;
  198. }',
  199. '<?php
  200. abstract class Test {
  201. /**
  202. * @return void
  203. */
  204. abstract protected function foo($param);
  205. }',
  206. ],
  207. [
  208. '<?php fn($a) => null;',
  209. ],
  210. [
  211. '<?php fn($a) => 1;',
  212. ],
  213. [
  214. '<?php fn($a) => var_dump($a);',
  215. ],
  216. ];
  217. }
  218. /**
  219. * @dataProvider provideFix80Cases
  220. *
  221. * @requires PHP 8.0
  222. */
  223. public function testFix80(string $expected, ?string $input = null): void
  224. {
  225. $this->doTest($expected, $input);
  226. }
  227. /**
  228. * @return iterable<array<string>>
  229. */
  230. public static function provideFix80Cases(): iterable
  231. {
  232. yield [
  233. '<?php
  234. class Foo
  235. {
  236. /**
  237. * @return int|false
  238. */
  239. #[\ReturnTypeWillChange]
  240. public function test() {}
  241. }
  242. ',
  243. ];
  244. yield [
  245. '<?php
  246. /**
  247. * @return void
  248. */
  249. #[\Deprecated]
  250. function test(): void {};
  251. ',
  252. '<?php
  253. /**
  254. * @return void
  255. */
  256. #[\Deprecated]
  257. function test() {};
  258. ',
  259. ];
  260. }
  261. /**
  262. * Test if magic method is handled without causing syntax error.
  263. *
  264. * @dataProvider provideMethodWillNotCauseSyntaxErrorCases
  265. */
  266. public function testMethodWillNotCauseSyntaxError(string $method, int $arguments = 0, bool $static = false): void
  267. {
  268. $tokens = Tokens::fromCode(sprintf(
  269. '<?php class Test { public%s function %s(%s) {} }',
  270. $static ? ' static' : '',
  271. $method,
  272. implode(',', array_map(
  273. static fn (int $n): string => sprintf('$x%d', $n),
  274. array_keys(array_fill(0, $arguments, true)),
  275. ))
  276. ));
  277. $this->fixer->fix(self::getTestFile(), $tokens);
  278. self::assertNull($this->lintSource($tokens->generateCode()));
  279. }
  280. public static function provideMethodWillNotCauseSyntaxErrorCases(): iterable
  281. {
  282. // List: https://www.php.net/manual/en/language.oop5.magic.php
  283. yield ['__construct'];
  284. yield ['__destruct'];
  285. yield ['__call', 2];
  286. yield ['__callStatic', 2, true];
  287. yield ['__get', 1];
  288. yield ['__set', 2];
  289. yield ['__isset', 1];
  290. yield ['__unset', 1];
  291. yield ['__sleep'];
  292. yield ['__wakeup'];
  293. yield ['__serialize'];
  294. yield ['__unserialize', 1];
  295. yield ['__toString'];
  296. yield ['__invoke'];
  297. yield ['__set_state', 1, true];
  298. yield ['__clone'];
  299. yield ['__debugInfo'];
  300. }
  301. }