TernaryToElvisOperatorFixerTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  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\Operator;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @internal
  16. *
  17. * @covers \PhpCsFixer\Fixer\Operator\TernaryToElvisOperatorFixer
  18. */
  19. final class TernaryToElvisOperatorFixerTest extends AbstractFixerTestCase
  20. {
  21. /**
  22. * @dataProvider provideFixCases
  23. */
  24. public function testFix(string $expected, ?string $input = null): void
  25. {
  26. $this->doTest($expected, $input);
  27. }
  28. public static function provideFixCases(): iterable
  29. {
  30. $operators = ['+=', '-=', '*=', '**=', '/=', '.=', '%=', '&=', '|=', '^=', '<<=', '>>='];
  31. foreach ($operators as $operator) {
  32. yield sprintf('Test with operator "%s".', $operator) => [
  33. sprintf('<?php $z = $a %s $b ? : $c;', $operator),
  34. sprintf('<?php $z = $a %s $b ? $b : $c;', $operator),
  35. ];
  36. }
  37. yield 'multiple fixes' => [
  38. '<?php $a ? : 1; $a ? : 1; $a ? : 1; $a ? : 1; $a ? : 1; $a ? : 1; $a ? : 1;',
  39. '<?php $a ? $a : 1; $a ? $a : 1; $a ? $a : 1; $a ? $a : 1; $a ? $a : 1; $a ? $a : 1; $a ? $a : 1;',
  40. ];
  41. yield [
  42. '<?php $z = $z ? : "a";',
  43. '<?php $z = $z ? $z : "a";',
  44. ];
  45. yield [
  46. '<?php ${"foo"} ? : "a";',
  47. '<?php ${"foo"} ? ${"foo"} : "a";',
  48. ];
  49. yield [
  50. '<?php $z::$a()[1] ? : 1;',
  51. '<?php $z::$a()[1] ? $z::$a()[1] : 1;',
  52. ];
  53. yield [
  54. '<?php $z->$a ? : 1;',
  55. '<?php $z->$a ? $z->$a : 1;',
  56. ];
  57. yield [
  58. '<?php $z = $z ? : 1;',
  59. '<?php $z = $z ? $z : 1;',
  60. ];
  61. yield [
  62. '<?php $z = $z ? : 1.1;',
  63. '<?php $z = $z ? $z : 1.1;',
  64. ];
  65. yield [
  66. '<?php $z = $a ? : foo();',
  67. '<?php $z = $a ? $a : foo();',
  68. ];
  69. yield [
  70. '<?php $z = $a ? : \foo();',
  71. '<?php $z = $a ? $a : \foo();',
  72. ];
  73. yield [
  74. '<?php $z = 1 ? : $z;',
  75. '<?php $z = 1 ? 1 : $z;',
  76. ];
  77. yield [
  78. '<?php $z = 1.1 ? : $z;',
  79. '<?php $z = 1.1 ? 1.1 : $z;',
  80. ];
  81. yield [
  82. '<?php $z = "a" ? : "b";',
  83. '<?php $z = "a" ? "a" : "b";',
  84. ];
  85. yield [
  86. '<?php $z = foo() ? : $a;',
  87. '<?php $z = foo() ? foo() : $a;',
  88. ];
  89. yield [
  90. '<?php $z = \foo() ? : $a;',
  91. '<?php $z = \foo() ? \foo() : $a;',
  92. ];
  93. yield [
  94. '<?php 1 ? : $z->$a;',
  95. '<?php 1 ? 1 : $z->$a;',
  96. ];
  97. yield [
  98. '<?php 1 ? : $z::$a()[1];',
  99. '<?php 1 ? 1 : $z::$a()[1];',
  100. ];
  101. yield [
  102. '<?php $a ? : ${"foo"};',
  103. '<?php $a ? $a : ${"foo"};',
  104. ];
  105. yield [
  106. '<?php {$b ? : 1;}',
  107. '<?php {$b ? $b : 1;}',
  108. ];
  109. yield [
  110. '<?php {echo 1;} $c = $c ? : 1;',
  111. '<?php {echo 1;} $c = $c ? $c : 1;',
  112. ];
  113. yield [
  114. '<?php $d ? : 1;',
  115. '<?php $d ? ($d) : 1;',
  116. ];
  117. yield [
  118. '<?php $d ? : 1;',
  119. '<?php $d ? (($d)) : 1;',
  120. ];
  121. yield [
  122. '<?php ($d) ? : 1;',
  123. '<?php ($d) ? $d : 1;',
  124. ];
  125. yield [
  126. '<?php ($d) ? : 1;',
  127. '<?php ($d) ? (($d)) : 1;',
  128. ];
  129. yield [
  130. '<?php
  131. a($d) ? $d : 1;
  132. $d ? a($d) : 1;
  133. ',
  134. ];
  135. yield [
  136. '<?php ; $e ? : 1;',
  137. '<?php ; $e ? $e : 1;',
  138. ];
  139. yield [
  140. '<?php $foo8 = $bar[0] ? : $foo;',
  141. '<?php $foo8 = $bar[0] ? $bar[0] : $foo;',
  142. ];
  143. yield [
  144. '<?php $foo7 = $_GET[$a] ? : $foo;',
  145. '<?php $foo7 = $_GET[$a] ? $_GET[$a] : $foo;',
  146. ];
  147. yield [
  148. '<?php $foo6 = $bar[$a][0][$a ? 1 : 2][2] ? /* 1 *//* 2 *//* 3 */ /* 4 */ : $foo;',
  149. '<?php $foo6 = $bar[$a][0][$a ? 1 : 2][2] ? $bar/* 1 */[$a]/* 2 */[0]/* 3 */[$a ? 1 : 2]/* 4 */[2] : $foo;',
  150. ];
  151. yield [
  152. '<?php ; 2 ? : 1;',
  153. '<?php ; 2 ? 2 : 1;',
  154. ];
  155. yield [
  156. '<?php
  157. $bar1[0][1] = $bar[0][1] ? $bar[0][1] + 1 : $bar[0][1];
  158. $bar2[0] = $bar[0] ? $bar[0] + 1 : $bar[0];
  159. $bar3[0][1] = $bar[0][1] ? ++$bar[0][1] : $bar[0][1];
  160. $bar4[0] = $bar[0] ? --$bar[0] : $bar[0];
  161. ',
  162. ];
  163. yield [
  164. '<?php
  165. $foo77 = $foo ? "$foo" : $foo;
  166. $foo77 = $foo ? \'$foo\' : $foo;
  167. ',
  168. ];
  169. yield 'comments 1' => [
  170. '<?php $a /* a */ = /* b */ $a /* c */ ? /* d */ /* e */ : /* f */ 1;',
  171. '<?php $a /* a */ = /* b */ $a /* c */ ? /* d */ $a /* e */ : /* f */ 1;',
  172. ];
  173. yield 'comments 2' => [
  174. '<?php $foo = $bar/* a */?/* b *//* c */:/* d */$baz;',
  175. '<?php $foo = $bar/* a */?/* b */$bar/* c */:/* d */$baz;',
  176. ];
  177. yield 'minimal' => [
  178. '<?php $b?:$c;',
  179. '<?php $b?$b:$c;',
  180. ];
  181. yield 'minimal 2x' => [
  182. '<?php $b?:$c;$f=$b?:$c;',
  183. '<?php $b?$b:$c;$f=$b?$b:$c;',
  184. ];
  185. yield [
  186. '<?php
  187. $foo = $bar
  188. ? '.'
  189. : $foo;
  190. ',
  191. '<?php
  192. $foo = $bar
  193. ? $bar
  194. : $foo;
  195. ',
  196. ];
  197. yield [
  198. '<?php
  199. $foo = $bar # 1
  200. ? # 2
  201. : $foo; # 3
  202. ',
  203. '<?php
  204. $foo = $bar # 1
  205. ? $bar # 2
  206. : $foo; # 3
  207. ',
  208. ];
  209. yield [
  210. '<?php foo($a ? : $b, $c ? : $d);',
  211. '<?php foo($a ? $a : $b, $c ? $c : $d);',
  212. ];
  213. yield [
  214. '<?php $j[$b ? : $c];',
  215. '<?php $j[$b ? $b : $c];',
  216. ];
  217. yield [
  218. '<?php foo($a[0] ? : $b[0], $c[0] ? : $d[0]);',
  219. '<?php foo($a[0] ? $a[0] : $b[0], $c[0] ? $c[0] : $d[0]);',
  220. ];
  221. yield [
  222. '<?php $a + 1 ? : $b;',
  223. '<?php $a + 1 ? $a + 1 : $b;',
  224. ];
  225. yield [
  226. '<?php
  227. $a ? : <<<EOT
  228. EOT;
  229. $a ? : <<<\'EOT\'
  230. EOT;
  231. <<<EOT
  232. EOT
  233. ? '.'
  234. : $a
  235. ;
  236. <<<\'EOT\'
  237. EOT
  238. ? '.'
  239. : $a
  240. ;
  241. ',
  242. '<?php
  243. $a ? $a : <<<EOT
  244. EOT;
  245. $a ? $a : <<<\'EOT\'
  246. EOT;
  247. <<<EOT
  248. EOT
  249. ? <<<EOT
  250. EOT
  251. : $a
  252. ;
  253. <<<\'EOT\'
  254. EOT
  255. ? <<<\'EOT\'
  256. EOT
  257. : $a
  258. ;
  259. ',
  260. ];
  261. yield [
  262. '<?php @foo() ? : 1;',
  263. '<?php @foo() ? @foo() : 1;',
  264. ];
  265. yield [
  266. '<?php
  267. $f = !foo() ? : 1;
  268. $f = !$a ? : 1;
  269. $f = $a[1][!$a][@foo()] ? : 1;
  270. $f = !foo() ? : 1;
  271. ',
  272. '<?php
  273. $f = !foo() ? !foo() : 1;
  274. $f = !$a ? !$a : 1;
  275. $f = $a[1][!$a][@foo()] ? $a[1][!$a][@foo()] : 1;
  276. $f = !foo() ? !foo() : 1;
  277. ',
  278. ];
  279. yield [
  280. '<?php $foo = $foo ? $bar : $foo;',
  281. ];
  282. yield [
  283. '<?php $foo1 = $bar[$a][0][1][2] ? 123 : $foo;',
  284. ];
  285. yield [
  286. '<?php $foo2 = $bar[$a] ? $bar[$b] : $foo;',
  287. ];
  288. yield [
  289. '<?php $foo2a = $bar[$a] ? $bar[$a][1] : $foo;',
  290. ];
  291. yield [
  292. '<?php $foo2b = $bar[$a][1] ? $bar[$a] : $foo;',
  293. ];
  294. yield [
  295. '<?php $foo3 = $bar[$a][1] ? $bar[$a][2] : $foo;',
  296. ];
  297. yield [
  298. '<?php $foo4 = 1 + $bar[0] ? $bar[0] : $foo;',
  299. ];
  300. yield [
  301. '<?php $foo = $bar ? $$bar : 1;',
  302. ];
  303. yield 'complex case 1 left out by design' => [
  304. '<?php $foo = !empty($bar) ? $bar : $baz;',
  305. ];
  306. yield 'complex case 2 left out by design' => [
  307. '<?php $foo = !!$bar ? $bar : $baz;',
  308. ];
  309. yield [
  310. '<?php $f = 1 + $f ? $f : 1;',
  311. ];
  312. yield [
  313. '<?php $g = $g ? $g - 1 : 1;',
  314. ];
  315. yield [
  316. '<?php
  317. $c = ++$a ? ++$a : $b;
  318. $c = (++$a) ? (++$a) : $b;
  319. $c = ($a++) ? ($a++) : $b;
  320. $c = fooBar(++$a) ? fooBar(++$a) : $b;
  321. $c = [++$a] ? [++$a] : $b;
  322. ',
  323. ];
  324. yield [
  325. '<?php
  326. $c = --$a ? --$a : $b;
  327. $c = (--$a) ? (--$a) : $b;
  328. $c = ($a--) ? ($a--) : $b;
  329. $c = fooBar(--$a) ? fooBar(--$a) : $b;
  330. $c = [--$a] ? [--$a] : $b;
  331. ',
  332. ];
  333. yield [
  334. '<?= $a ? : $b ?>',
  335. '<?= $a ? $a : $b ?>',
  336. ];
  337. yield [
  338. '<?php new class() extends Foo {} ? new class{} : $a;',
  339. ];
  340. yield [
  341. '<?php $a ? : new class{};',
  342. '<?php $a ? $a : new class{};',
  343. ];
  344. yield [
  345. '<?php $a ? : new class($a) extends Foo {};',
  346. '<?php $a ? $a : new class($a) extends Foo {};',
  347. ];
  348. }
  349. /**
  350. * @dataProvider provideFixPre80Cases
  351. *
  352. * @requires PHP <8.0
  353. */
  354. public function testFixPre80(string $expected, string $input = null): void
  355. {
  356. $this->doTest($expected, $input);
  357. }
  358. public static function provideFixPre80Cases(): iterable
  359. {
  360. yield [
  361. '<?php $foo = $a->{$b} ? $bar{0} : $foo;',
  362. ];
  363. yield [
  364. '<?php $l[$b[0] ? : $c[0]];',
  365. '<?php $l[$b[0] ? $b{0} : $c[0]];',
  366. ];
  367. yield [
  368. '<?php $l{$b{0} ? : $c{0}};',
  369. '<?php $l{$b{0} ? $b{0} : $c{0}};',
  370. ];
  371. yield [
  372. '<?php $z = $a[1][2] ? : 1;',
  373. '<?php $z = $a[1][2] ? $a[1][2] : 1;',
  374. ];
  375. yield [
  376. '<?php $i = $bar{0}[1]{2}[3] ? : $foo;',
  377. '<?php $i = $bar{0}[1]{2}[3] ? $bar{0}[1]{2}[3] : $foo;',
  378. ];
  379. yield [
  380. '<?php $fooX = $bar{0}[1]{2}[3] ? : $foo;',
  381. '<?php $fooX = $bar{0}[1]{2}[3] ? $bar{0}[1]{2}[3] : $foo;',
  382. ];
  383. yield [
  384. '<?php $k = $bar{0} ? : $foo;',
  385. '<?php $k = $bar{0} ? $bar{0} : $foo;',
  386. ];
  387. yield 'ignore different type of index braces' => [
  388. '<?php $z = $a[1] ? : 1;',
  389. '<?php $z = $a[1] ? $a{1} : 1;',
  390. ];
  391. yield [
  392. '<?php __FILE__.$a.$b{2}.$c->$a[0] ? : 1;',
  393. '<?php __FILE__.$a.$b{2}.$c->$a[0] ? __FILE__.$a.$b{2}.$c->$a[0] : 1;',
  394. ];
  395. }
  396. /**
  397. * @dataProvider provideDoNotFix80Cases
  398. *
  399. * @requires PHP 8.0
  400. */
  401. public function testDoNotFix80(string $input): void
  402. {
  403. $this->doTest($input);
  404. }
  405. public static function provideDoNotFix80Cases(): iterable
  406. {
  407. yield ['<?php
  408. function test(#[TestAttribute] ?User $user) {}
  409. '];
  410. yield ['<?php
  411. function test(#[TestAttribute] ?User $user = null) {}
  412. '];
  413. }
  414. }