TernaryToElvisOperatorFixerTest.php 12 KB

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