VoidReturnFixerTest.php 9.7 KB

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