IsNullFixerTest.php 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @author Vladimir Reznichenko <kalessil@gmail.com>
  16. *
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\LanguageConstruct\IsNullFixer
  20. *
  21. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\LanguageConstruct\IsNullFixer>
  22. */
  23. final class IsNullFixerTest extends AbstractFixerTestCase
  24. {
  25. /**
  26. * @dataProvider provideFixCases
  27. */
  28. public function testFix(string $expected, ?string $input = null): void
  29. {
  30. $this->doTest($expected, $input);
  31. }
  32. /**
  33. * @return iterable<array{0: string, 1?: string}>
  34. */
  35. public static function provideFixCases(): iterable
  36. {
  37. $multiLinePatternToFix = <<<'FIX'
  38. <?php $x =
  39. is_null
  40. (
  41. json_decode
  42. (
  43. $x
  44. )
  45. )
  46. ;
  47. FIX;
  48. $multiLinePatternFixed = <<<'FIXED'
  49. <?php $x =
  50. null === json_decode
  51. (
  52. $x
  53. )
  54. ;
  55. FIXED;
  56. yield ['<?php $x = "is_null";'];
  57. yield ['<?php $x = ClassA::is_null(json_decode($x));'];
  58. yield ['<?php $x = ScopeA\is_null(json_decode($x));'];
  59. yield ['<?php $x = namespace\is_null(json_decode($x));'];
  60. yield ['<?php $x = $object->is_null(json_decode($x));'];
  61. yield ['<?php $x = new \is_null(json_decode($x));'];
  62. yield ['<?php $x = new is_null(json_decode($x));'];
  63. yield ['<?php $x = new ScopeB\is_null(json_decode($x));'];
  64. yield ['<?php is_nullSmth(json_decode($x));'];
  65. yield ['<?php smth_is_null(json_decode($x));'];
  66. yield ['<?php namespace Foo; function &is_null($x) { return null === $x; }'];
  67. yield ['<?php "SELECT ... is_null(json_decode($x)) ...";'];
  68. yield ['<?php "test" . "is_null" . "in concatenation";'];
  69. yield ['<?php $x = null === json_decode($x);', '<?php $x = is_null(json_decode($x));'];
  70. yield ['<?php $x = null !== json_decode($x);', '<?php $x = !is_null(json_decode($x));'];
  71. yield ['<?php $x = null !== json_decode($x);', '<?php $x = ! is_null(json_decode($x));'];
  72. yield ['<?php $x = null !== json_decode($x);', '<?php $x = ! is_null( json_decode($x) );'];
  73. yield ['<?php $x = null === json_decode($x);', '<?php $x = \is_null(json_decode($x));'];
  74. yield ['<?php $x = null !== json_decode($x);', '<?php $x = !\is_null(json_decode($x));'];
  75. yield ['<?php $x = null !== json_decode($x);', '<?php $x = ! \is_null(json_decode($x));'];
  76. yield ['<?php $x = null !== json_decode($x);', '<?php $x = ! \is_null( json_decode($x) );'];
  77. yield ['<?php $x = null === json_decode($x).".dist";', '<?php $x = is_null(json_decode($x)).".dist";'];
  78. yield ['<?php $x = null !== json_decode($x).".dist";', '<?php $x = !is_null(json_decode($x)).".dist";'];
  79. yield ['<?php $x = null === json_decode($x).".dist";', '<?php $x = \is_null(json_decode($x)).".dist";'];
  80. yield ['<?php $x = null !== json_decode($x).".dist";', '<?php $x = !\is_null(json_decode($x)).".dist";'];
  81. yield [$multiLinePatternFixed, $multiLinePatternToFix];
  82. yield [
  83. '<?php $x = /**/null === /**/ /** x*//**//** */json_decode($x)/***//*xx*/;',
  84. '<?php $x = /**/is_null/**/ /** x*/(/**//** */json_decode($x)/***/)/*xx*/;',
  85. ];
  86. yield [
  87. '<?php $x = null === (null === $x ? z(null === $y) : z(null === $z));',
  88. '<?php $x = is_null(is_null($x) ? z(is_null($y)) : z(is_null($z)));',
  89. ];
  90. yield [
  91. '<?php $x = null === ($x = array());',
  92. '<?php $x = is_null($x = array());',
  93. ];
  94. yield [
  95. '<?php null === a(null === a(null === a(null === b())));',
  96. '<?php \is_null(a(\is_null(a(\is_null(a(\is_null(b())))))));',
  97. ];
  98. yield [
  99. '<?php $d= null === ($a)/*=?*/?>',
  100. "<?php \$d= is_null(\n(\$a)/*=?*/\n)?>",
  101. ];
  102. yield [
  103. '<?php is_null()?>',
  104. ];
  105. // edge cases: is_null wrapped into a binary operations
  106. yield [
  107. '<?php $result = (false === (null === $a)); ?>',
  108. '<?php $result = (false === is_null($a)); ?>',
  109. ];
  110. yield [
  111. '<?php $result = ((null === $a) === false); ?>',
  112. '<?php $result = (is_null($a) === false); ?>',
  113. ];
  114. yield [
  115. '<?php $result = (false !== (null === $a)); ?>',
  116. '<?php $result = (false !== is_null($a)); ?>',
  117. ];
  118. yield [
  119. '<?php $result = ((null === $a) !== false); ?>',
  120. '<?php $result = (is_null($a) !== false); ?>',
  121. ];
  122. yield [
  123. '<?php $result = (false == (null === $a)); ?>',
  124. '<?php $result = (false == is_null($a)); ?>',
  125. ];
  126. yield [
  127. '<?php $result = ((null === $a) == false); ?>',
  128. '<?php $result = (is_null($a) == false); ?>',
  129. ];
  130. yield [
  131. '<?php $result = (false != (null === $a)); ?>',
  132. '<?php $result = (false != is_null($a)); ?>',
  133. ];
  134. yield [
  135. '<?php $result = ((null === $a) != false); ?>',
  136. '<?php $result = (is_null($a) != false); ?>',
  137. ];
  138. yield [
  139. '<?php $result = (false <> (null === $a)); ?>',
  140. '<?php $result = (false <> is_null($a)); ?>',
  141. ];
  142. yield [
  143. '<?php $result = ((null === $a) <> false); ?>',
  144. '<?php $result = (is_null($a) <> false); ?>',
  145. ];
  146. yield [
  147. '<?php if (null === $x) echo "foo"; ?>',
  148. '<?php if (is_null($x)) echo "foo"; ?>',
  149. ];
  150. // check with logical operator
  151. yield [
  152. '<?php if (null === $x && $y) echo "foo"; ?>',
  153. '<?php if (is_null($x) && $y) echo "foo"; ?>',
  154. ];
  155. yield [
  156. '<?php if (null === $x || $y) echo "foo"; ?>',
  157. '<?php if (is_null($x) || $y) echo "foo"; ?>',
  158. ];
  159. yield [
  160. '<?php if (null === $x xor $y) echo "foo"; ?>',
  161. '<?php if (is_null($x) xor $y) echo "foo"; ?>',
  162. ];
  163. yield [
  164. '<?php if (null === $x and $y) echo "foo"; ?>',
  165. '<?php if (is_null($x) and $y) echo "foo"; ?>',
  166. ];
  167. yield [
  168. '<?php if (null === $x or $y) echo "foo"; ?>',
  169. '<?php if (is_null($x) or $y) echo "foo"; ?>',
  170. ];
  171. yield [
  172. '<?php if ((null === $u or $v) and ($w || null === $x) xor (null !== $y and $z)) echo "foo"; ?>',
  173. '<?php if ((is_null($u) or $v) and ($w || is_null($x)) xor (!is_null($y) and $z)) echo "foo"; ?>',
  174. ];
  175. // edge cases: $isContainingDangerousConstructs, $wrapIntoParentheses
  176. yield [
  177. '<?php null === ($a ? $x : $y);',
  178. '<?php is_null($a ? $x : $y);',
  179. ];
  180. yield [
  181. '<?php $a === (null === $x);',
  182. '<?php $a === is_null($x);',
  183. ];
  184. yield [
  185. '<?php $a === (null === ($a ? $x : $y));',
  186. '<?php $a === is_null($a ? $x : $y);',
  187. ];
  188. yield [
  189. '<?php null !== ($a ?? null);',
  190. '<?php !is_null($a ?? null);',
  191. ];
  192. yield [
  193. '<?php null === $x;',
  194. '<?php is_null($x, );',
  195. ];
  196. yield [
  197. '<?php null === $x;',
  198. '<?php is_null( $x , );',
  199. ];
  200. yield [
  201. '<?php null === a(null === a(null === a(null === b(), ), ), );',
  202. '<?php \is_null(a(\is_null(a(\is_null(a(\is_null(b(), ), ), ), ), ), ), );',
  203. ];
  204. yield [
  205. '<?php if ((null === $u or $v) and ($w || null === $x) xor (null !== $y and $z)) echo "foo"; ?>',
  206. '<?php if ((is_null($u, ) or $v) and ($w || is_null($x, )) xor (!is_null($y, ) and $z)) echo "foo"; ?>',
  207. ];
  208. // edge cases: $isContainingDangerousConstructs, $wrapIntoParentheses
  209. yield [
  210. '<?php null === ($a ? $x : $y );',
  211. '<?php is_null($a ? $x : $y, );',
  212. ];
  213. yield [
  214. '<?php $a === (null === $x);',
  215. '<?php $a === is_null($x, );',
  216. ];
  217. yield [
  218. '<?php $a === (null === ($a ? $x : $y ));',
  219. '<?php $a === is_null($a ? $x : $y, );',
  220. ];
  221. yield [
  222. '<?php $a === (int) (null === $x) + (int) (null !== $y);',
  223. '<?php $a === (int) is_null($x) + (int) !is_null($y);',
  224. ];
  225. }
  226. /**
  227. * @dataProvider provideFix81Cases
  228. *
  229. * @requires PHP 8.1
  230. */
  231. public function testFix81(string $expected, ?string $input = null): void
  232. {
  233. $this->doTest($expected, $input);
  234. }
  235. /**
  236. * @return iterable<string, array{string}>
  237. */
  238. public static function provideFix81Cases(): iterable
  239. {
  240. yield 'first-class callable' => [
  241. '<?php array_filter([], is_null(...));',
  242. ];
  243. yield 'first-class callable with leading slash' => [
  244. '<?php array_filter([], \is_null(...));',
  245. ];
  246. }
  247. }