NoUnsetOnPropertyFixerTest.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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 Gert de Pagter <BackEndTea@gmail.com>
  16. *
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\LanguageConstruct\NoUnsetOnPropertyFixer
  20. *
  21. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\LanguageConstruct\NoUnsetOnPropertyFixer>
  22. */
  23. final class NoUnsetOnPropertyFixerTest 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<int|string, array{0: string, 1?: string}>
  34. */
  35. public static function provideFixCases(): iterable
  36. {
  37. yield 'It replaces an unset on a property with = null' => [
  38. '<?php $foo->bar = null;',
  39. '<?php unset($foo->bar);',
  40. ];
  41. yield 'It replaces an unset on a property with = null II' => [
  42. '<?php $foo->bar = null ;',
  43. '<?php unset($foo->bar );',
  44. ];
  45. yield 'It replaces an unset on a static property with = null' => [
  46. '<?php TestClass::$bar = null;',
  47. '<?php unset(TestClass::$bar);',
  48. ];
  49. yield 'It does not replace unset on a variable with = null' => [
  50. '<?php $b->a; unset($foo);',
  51. ];
  52. yield 'It replaces multiple unsets on variables with = null' => [
  53. '<?php $foo->bar = null; $bar->foo = null; $bar->baz = null; $a->ba = null;',
  54. '<?php unset($foo->bar, $bar->foo, $bar->baz, $a->ba);',
  55. ];
  56. yield 'It replaces multiple unsets, but not those that arent properties' => [
  57. '<?php $foo->bar = null; $bar->foo = null; unset($bar);',
  58. '<?php unset($foo->bar, $bar->foo, $bar);',
  59. ];
  60. yield 'It replaces multiple unsets, but not those that arent properties in multiple places' => [
  61. '<?php unset($foo); $bar->foo = null; unset($bar);',
  62. '<?php unset($foo, $bar->foo, $bar);',
  63. ];
  64. yield 'It replaces $this -> and self:: replacements' => [
  65. '<?php $this->bar = null; self::$foo = null; unset($bar);',
  66. '<?php unset($this->bar, self::$foo, $bar);',
  67. ];
  68. yield 'It does not replace unsets on arrays' => [
  69. '<?php unset($bar->foo[0]);',
  70. ];
  71. yield 'It works in a more complex unset' => [
  72. '<?php unset($bar->foo[0]); self::$foo = null; \Test\Baz::$fooBar = null; unset($bar->foo[0]); $this->foo = null; unset($a); unset($b);',
  73. '<?php unset($bar->foo[0], self::$foo, \Test\Baz::$fooBar, $bar->foo[0], $this->foo, $a, $b);',
  74. ];
  75. yield 'It works with consecutive unsets' => [
  76. '<?php $foo->bar = null; unset($foo); unset($bar); unset($baz); $this->ab = null;',
  77. '<?php unset($foo->bar, $foo, $bar, $baz, $this->ab);',
  78. ];
  79. yield 'It works when around messy whitespace' => [
  80. '<?php
  81. unset($a); $this->b = null;
  82. $this->a = null; unset($b);
  83. ',
  84. '<?php
  85. unset($a, $this->b);
  86. unset($this->a, $b);
  87. ',
  88. ];
  89. yield 'It works with weirdly placed comments' => [
  90. '<?php unset/*foo*/(/*bar*/$bar->foo[0]); self::$foo = null/*baz*/; /*hello*/\Test\Baz::$fooBar = null/*comment*/; unset($bar->foo[0]); $this->foo = null; unset($a); unset($b);
  91. unset/*foo*/(/*bar*/$bar);',
  92. '<?php unset/*foo*/(/*bar*/$bar->foo[0], self::$foo/*baz*/, /*hello*/\Test\Baz::$fooBar/*comment*/, $bar->foo[0], $this->foo, $a, $b);
  93. unset/*foo*/(/*bar*/$bar);',
  94. ];
  95. yield 'It does not mess with consecutive unsets' => [
  96. '<?php unset($a, $b, $c);
  97. $this->a = null;',
  98. '<?php unset($a, $b, $c);
  99. unset($this->a);',
  100. ];
  101. yield 'It does not replace function call with class constant inside' => [
  102. '<?php unset($foos[array_search(BadFoo::NAME, $foos)]);',
  103. ];
  104. yield 'It does not replace function call with class constant and property inside' => [
  105. '<?php unset($this->property[array_search(\Types::TYPE_RANDOM, $this->property)]);',
  106. ];
  107. yield 'It does not break complex expressions' => [
  108. '<?php
  109. unset(a()[b()["a"]]);
  110. unset(a()[b()]);
  111. unset(a()["a"]);
  112. unset(c($a)->a);
  113. ',
  114. ];
  115. yield 'It replaces an unset on a property with = null 1' => [
  116. '<?php $foo->bar = null;',
  117. '<?php unset($foo->bar,);',
  118. ];
  119. yield 'It replaces multiple unsets, but not those that arent properties 1' => [
  120. '<?php $foo->bar = null; $bar->foo = null; unset($bar,);',
  121. '<?php unset($foo->bar, $bar->foo, $bar,);',
  122. ];
  123. yield 'It replaces an unset on a static property with = null 1' => [
  124. '<?php TestClass::$bar = null;',
  125. '<?php unset(TestClass::$bar,);',
  126. ];
  127. yield 'It does not replace unset on a variable with = null 1' => [
  128. '<?php $b->a; unset($foo,);',
  129. ];
  130. yield 'It replaces multiple unsets on variables with = null 1' => [
  131. '<?php $foo->bar = null; $bar->foo = null; $bar->baz = null; $a->ba = null;',
  132. '<?php unset($foo->bar, $bar->foo, $bar->baz, $a->ba,);',
  133. ];
  134. yield 'It replaces multiple unsets, but not those that arent properties in multiple places 1' => [
  135. '<?php unset($foo); $bar->foo = null; unset($bar,);',
  136. '<?php unset($foo, $bar->foo, $bar,);',
  137. ];
  138. yield 'It replaces $this -> and self:: replacements 1' => [
  139. '<?php $this->bar = null; self::$foo = null; unset($bar,);',
  140. '<?php unset($this->bar, self::$foo, $bar,);',
  141. ];
  142. yield 'It does not replace unsets on arrays 1' => [
  143. '<?php unset($bar->foo[0],);',
  144. ];
  145. yield 'It works in a more complex unset 1' => [
  146. '<?php unset($bar->foo[0]); self::$foo = null; \Test\Baz::$fooBar = null; unset($bar->foo[0]); $this->foo = null; unset($a); unset($b,);',
  147. '<?php unset($bar->foo[0], self::$foo, \Test\Baz::$fooBar, $bar->foo[0], $this->foo, $a, $b,);',
  148. ];
  149. yield 'It works with consecutive unsets 1' => [
  150. '<?php $foo->bar = null; unset($foo); unset($bar); unset($baz); $this->ab = null;',
  151. '<?php unset($foo->bar, $foo, $bar, $baz, $this->ab,);',
  152. ];
  153. yield 'It works when around messy whitespace 1' => [
  154. '<?php
  155. unset($a); $this->b = null;
  156. $this->a = null; unset($b,);
  157. ',
  158. '<?php
  159. unset($a, $this->b,);
  160. unset($this->a, $b,);
  161. ',
  162. ];
  163. yield 'It works with weirdly placed comments 11' => [
  164. '<?php unset/*foo*/(/*bar*/$bar->foo[0]); self::$foo = null/*baz*/; /*hello*/\Test\Baz::$fooBar = null/*comment*/; unset($bar->foo[0]); $this->foo = null; unset($a); unset($b,);
  165. unset/*foo*/(/*bar*/$bar,);',
  166. '<?php unset/*foo*/(/*bar*/$bar->foo[0], self::$foo/*baz*/, /*hello*/\Test\Baz::$fooBar/*comment*/, $bar->foo[0], $this->foo, $a, $b,);
  167. unset/*foo*/(/*bar*/$bar,);',
  168. ];
  169. yield 'It does not mess with consecutive unsets 1' => [
  170. '<?php unset($a, $b, $c,);
  171. $this->a = null;',
  172. '<?php unset($a, $b, $c,);
  173. unset($this->a,);',
  174. ];
  175. yield 'It does not replace function call with class constant inside 1' => [
  176. '<?php unset($foos[array_search(BadFoo::NAME, $foos)],);',
  177. ];
  178. yield 'It does not replace function call with class constant and property inside 1' => [
  179. '<?php unset($this->property[array_search(\Types::TYPE_RANDOM, $this->property)],);',
  180. ];
  181. yield [
  182. '<?php $foo->bar = null ;',
  183. '<?php unset($foo->bar, );',
  184. ];
  185. yield [
  186. '<?php $foo->bar = null ;',
  187. '<?php unset($foo->bar ,);',
  188. ];
  189. yield [
  190. '<?php $foo->bar = null ;',
  191. '<?php unset($foo->bar , );',
  192. ];
  193. }
  194. /**
  195. * @dataProvider provideFixPre80Cases
  196. *
  197. * @requires PHP <8.0
  198. */
  199. public function testFixPre80(string $expected, ?string $input = null): void
  200. {
  201. $this->doTest($expected, $input);
  202. }
  203. /**
  204. * @return iterable<array{string}>
  205. */
  206. public static function provideFixPre80Cases(): iterable
  207. {
  208. yield 'It does not replace unsets on arrays with special notation' => [
  209. '<?php unset($bar->foo{0});',
  210. ];
  211. yield 'It does not replace unsets on arrays with special notation 1' => [
  212. '<?php unset($bar->foo{0},);',
  213. ];
  214. yield 'It does not break curly access expressions' => [
  215. '<?php unset(a(){"a"});',
  216. ];
  217. }
  218. }