YodaStyleFixerTest.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065
  1. <?php
  2. /*
  3. * This file is part of PHP CS Fixer.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  7. *
  8. * This source file is subject to the MIT license that is bundled
  9. * with this source code in the file LICENSE.
  10. */
  11. namespace PhpCsFixer\Tests\Fixer\ControlStructure;
  12. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  13. /**
  14. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  15. * @author SpacePossum
  16. *
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer
  20. */
  21. final class YodaStyleFixerTest extends AbstractFixerTestCase
  22. {
  23. /**
  24. * @param string $expected
  25. * @param null|string $input
  26. *
  27. * @dataProvider provideFixCases
  28. */
  29. public function testFix($expected, $input = null, array $extraConfig = [])
  30. {
  31. $this->fixer->configure(['equal' => true, 'identical' => true] + $extraConfig);
  32. $this->doTest($expected, $input);
  33. }
  34. /**
  35. * Test with the inverse config.
  36. *
  37. * @param string $expected
  38. * @param null|string $input
  39. *
  40. * @dataProvider provideFixCases
  41. */
  42. public function testFixInverse($expected, $input = null, array $extraConfig = [])
  43. {
  44. $this->fixer->configure(['equal' => false, 'identical' => false] + $extraConfig);
  45. if (null === $input) {
  46. $this->doTest($expected);
  47. } else {
  48. $this->doTest($input, $expected);
  49. }
  50. }
  51. public function provideFixCases()
  52. {
  53. $tests = [
  54. [
  55. '<?php $a = 1 + ($b + $c) === true ? 1 : 2;',
  56. null,
  57. ['always_move_variable' => true],
  58. ],
  59. [
  60. '<?php $a = true === ($b + $c) ? 1 : 2;',
  61. '<?php $a = ($b + $c) === true ? 1 : 2;',
  62. ['always_move_variable' => true],
  63. ],
  64. [
  65. '<?php
  66. if ((1 === $a) === 1) {
  67. return;
  68. }',
  69. '<?php
  70. if (($a === 1) === 1) {
  71. return;
  72. }',
  73. ['always_move_variable' => false],
  74. ],
  75. [
  76. '<?php
  77. if (true === (1 !== $foo[0])) {
  78. return;
  79. }',
  80. '<?php
  81. if (($foo[0] !== 1) === true) {
  82. return;
  83. }',
  84. ['always_move_variable' => true],
  85. ],
  86. [
  87. '<?php return 1 !== $a [$b];',
  88. '<?php return $a [$b] !== 1;',
  89. ],
  90. [
  91. '<?= 1 === $a ? 5 : 7;',
  92. '<?= $a === 1 ? 5 : 7;',
  93. ],
  94. [
  95. '<?php print 1 === 1343;',
  96. ],
  97. [
  98. '<?php
  99. echo 3 === $a ? 2 : 4;
  100. ',
  101. '<?php
  102. echo $a === 3 ? 2 : 4;
  103. ',
  104. ],
  105. [
  106. '<?php 1 === foo($a) ? 1 : 2;',
  107. '<?php foo($a) === 1 ? 1 : 2;',
  108. ],
  109. [
  110. '<?php 1 === $a::$a ? 1 : 2;',
  111. '<?php $a::$a === 1 ? 1 : 2;',
  112. ],
  113. [
  114. '<?php 1 === (bool) $a ? 8 : 7;',
  115. '<?php (bool) $a === 1 ? 8 : 7;',
  116. ],
  117. [
  118. '<?php 1 === new $a ? 1 : 2;',
  119. '<?php new $a === 1 ? 1 : 2;',
  120. ],
  121. [
  122. '<?php 1 === "a".$a ? 5 : 6;',
  123. '<?php "a".$a === 1 ? 5 : 6;',
  124. ],
  125. [
  126. '<?php 1 === __DIR__.$a ? 5 : 6;',
  127. '<?php __DIR__.$a === 1 ? 5 : 6;',
  128. ],
  129. [
  130. '<?php 1 === $a.$b ? 5 : 6;',
  131. '<?php $a.$b === 1 ? 5 : 6;',
  132. ],
  133. [
  134. '<?php echo 1 === (object) $a ? 8 : 7;',
  135. '<?php echo (object) $a === 1 ? 8 : 7;',
  136. ],
  137. [
  138. '<?php echo 1 === (int) $a ? 8 : 7;',
  139. '<?php echo (int) $a === 1 ? 8 : 7;',
  140. ],
  141. [
  142. '<?php echo 1 === (float) $a ? 8 : 7;',
  143. '<?php echo (float) $a === 1 ? 8 : 7;',
  144. ],
  145. [
  146. '<?php echo 1 === (string) $a ? 8 : 7;',
  147. '<?php echo (string) $a === 1 ? 8 : 7;',
  148. ],
  149. [
  150. '<?php echo 1 === (array) $a ? 8 : 7;',
  151. '<?php echo (array) $a === 1 ? 8 : 7;',
  152. ],
  153. [
  154. '<?php echo 1 === (bool) $a ? 8 : 7;',
  155. '<?php echo (bool) $a === 1 ? 8 : 7;',
  156. ],
  157. [
  158. '<?php
  159. if ($a = true === $obj instanceof A) {
  160. echo \'A\';
  161. }',
  162. '<?php
  163. if ($a = $obj instanceof A === true) {
  164. echo \'A\';
  165. }',
  166. ],
  167. [
  168. '<?php echo 1 === !!$a ? 8 : 7;',
  169. '<?php echo !!$a === 1 ? 8 : 7;',
  170. ],
  171. [
  172. '<?php 1 === new $a ? 1 : 2;',
  173. '<?php new $a === 1 ? 1 : 2;',
  174. ],
  175. [
  176. '<?php $a = 1 === new b ? 1 : 2;',
  177. '<?php $a = new b === 1 ? 1 : 2;',
  178. ],
  179. [
  180. '<?php $a = 1 === empty($a) ? 1 : 2;',
  181. '<?php $a = empty($a) === 1 ? 1 : 2;',
  182. ],
  183. [
  184. '<?php $b = 1 === clone $a ? 5 : 9;',
  185. '<?php $b = clone $a === 1 ? 5 : 9;',
  186. ],
  187. [
  188. '<?php while(1 === $a ? 1 : 2){};',
  189. '<?php while($a === 1 ? 1 : 2){};',
  190. ],
  191. [
  192. '<?php $a = 1 === include_once $a ? 1 : 2;',
  193. '<?php $a = include_once $a === 1 ? 1 : 2;',
  194. ],
  195. [
  196. '<?php echo 1 === include $a ? 1 : 2;',
  197. '<?php echo include $a === 1 ? 1 : 2;',
  198. ],
  199. [
  200. '<?php echo 1 === require_once $a ? 1 : 2;',
  201. '<?php echo require_once $a === 1 ? 1 : 2;',
  202. ],
  203. [
  204. '<?php echo 1 === require $a ? 1 : 2;',
  205. '<?php echo require $a === 1 ? 1 : 2;',
  206. ],
  207. [
  208. '<?php switch(1 === $a){
  209. case true: echo 1;
  210. };',
  211. '<?php switch($a === 1){
  212. case true: echo 1;
  213. };',
  214. ],
  215. [
  216. '<?php echo 1 === $a ? 1 : 2;',
  217. '<?php echo $a === 1 ? 1 : 2;',
  218. ],
  219. // Don't fix cases.
  220. ['<?php $a = 1 === 1;'],
  221. ['<?php $b = $b === $c;'],
  222. ['<?php $c = $$b === $$c;'],
  223. ['<?php $d = count($this->array[$var]) === $a;'],
  224. ['<?php $e = $a === count($this->array[$var]);'],
  225. ['<?php $f = ($a123 & self::MY_BITMASK) === $a;'],
  226. ['<?php $g = $a === ($a456 & self::MY_BITMASK);'],
  227. ['<?php $h = $this->getStuff() === $myVariable;'],
  228. ['<?php $i = $myVariable === $this->getStuff();'],
  229. ['<?php $j = 2 * $myVar % 3 === $a;'],
  230. ['<?php return $k === 2 * $myVar % 3;'],
  231. ['<?php $l = $c > 2;'],
  232. ['<?php return $this->myObject1->{$index}+$b === "";'],
  233. ['<?php return $m[2]+1 == 2;'],
  234. ['<?php return $foo === $bar[$baz][1];'],
  235. ['<?php $a = $b[$key]["1"] === $c["2"];'],
  236. ['<?php return $foo->$a === $foo->$b->$c;'],
  237. ['<?php return $x === 2 - 1;'],
  238. ['<?php return $x === 2-1;'],
  239. // https://github.com/FriendsOfPHP/PHP-CS-Fixer/pull/693
  240. ['<?php return array(2) == $o;'],
  241. ['<?php return $p == array(2);'],
  242. ['<?php return $p == array("2");'],
  243. ['<?php return $p == array(TWO);'],
  244. ['<?php return $p == array(array());'],
  245. ['<?php return $p == [[]];'],
  246. ['<?php return array($q) == $a;'],
  247. ['<?php return $r == array($a);'],
  248. ['<?php $s = ((array(2))) == $a;'],
  249. ['<?php $t = $a == ((array(2)));'],
  250. ['<?php list($a) = $c === array(1) ? $b : $d;'],
  251. ['<?php $b = 7 === list($a) = [7];'],
  252. ['<?php $a = function(){} === array(0);'],
  253. ['<?php $z = $n == list($a) = $b;'],
  254. ['<?php return $n == list($a) = $b;'],
  255. // Fix cases.
  256. 'Array destruct by ternary.' => [
  257. '<?php list($a) = 11 === $c ? $b : $d;',
  258. '<?php list($a) = $c === 11 ? $b : $d;',
  259. ],
  260. 'Less spacing.' => [
  261. '<?php $z=2==$a;$b=$c>1&&$c<=10;',
  262. '<?php $z=$a==2;$b=$c>1&&$c<=10;',
  263. ],
  264. 'Comments.' => [
  265. '<?php $z = /**/ /**/2/**/ /**/
  266. # aa
  267. /**/==/**/$a/***/;',
  268. '<?php $z = /**/ /**/$a/**/ /**/
  269. # aa
  270. /**/==/**/2/***/;',
  271. ],
  272. [
  273. '<?php return 2 == ($a)?>',
  274. ],
  275. [
  276. '<?php return ($a) == 2?>',
  277. ],
  278. [
  279. '<?php return 2 == ($a)?>',
  280. '<?php return ($a) == 2?>',
  281. ['always_move_variable' => true],
  282. ],
  283. [
  284. '<?php $a = ($c === ((null === $b)));',
  285. '<?php $a = ($c === (($b === null)));',
  286. ],
  287. [
  288. '<?php return null == $a[2];',
  289. '<?php return $a[2] == null;',
  290. ],
  291. [
  292. '<?php return "" === $this->myArray[$index];',
  293. '<?php return $this->myArray[$index] === "";',
  294. ],
  295. [
  296. '<?php return "" === $this->myArray[$index]->/*1*//*2*//*3*/a;',
  297. '<?php return $this->myArray[$index]->/*1*//*2*//*3*/a === "";',
  298. ],
  299. [
  300. '<?php return "" === $this->myArray[$index]->a;',
  301. '<?php return $this->myArray[$index]->a === "";',
  302. ],
  303. [
  304. '<?php return "" === $this->myObject2-> {$index};',
  305. '<?php return $this->myObject2-> {$index} === "";',
  306. ],
  307. [
  308. '<?php return "" === $this->myObject3->{$index}->a;',
  309. '<?php return $this->myObject3->{$index}->a === "";',
  310. ],
  311. [
  312. '<?php return "" === $this->myObject4->{$index}->{$index}->a;',
  313. '<?php return $this->myObject4->{$index}->{$index}->a === "";',
  314. ],
  315. [
  316. '<?php return "" === $this->myObject4->$index->a;',
  317. '<?php return $this->myObject4->$index->a === "";',
  318. ],
  319. [
  320. '<?php return self::MY_CONST === self::$myVariable;',
  321. '<?php return self::$myVariable === self::MY_CONST;',
  322. ],
  323. [
  324. '<?php return \A\B\C::MY_CONST === \A\B\C::$myVariable;',
  325. '<?php return \A\B\C::$myVariable === \A\B\C::MY_CONST;',
  326. ],
  327. [
  328. '<?php $a = 1 == $$a?>',
  329. '<?php $a = $$a == 1?>',
  330. ],
  331. 'Nested case' => [
  332. '<?php return null === $a[0 === $b ? $c : $d];',
  333. '<?php return $a[$b === 0 ? $c : $d] === null;',
  334. ],
  335. [
  336. '<?php return null === $this->{null === $a ? "a" : "b"};',
  337. '<?php return $this->{$a === null ? "a" : "b"} === null;',
  338. ],
  339. 'Complex code sample.' => [
  340. '<?php
  341. if ($a == $b) {
  342. return null === $b ? (null === $a ? 0 : 0 === $a->b) : 0 === $b->a;
  343. } else {
  344. if ($c === (null === $b)) {
  345. return false === $d;
  346. }
  347. }',
  348. '<?php
  349. if ($a == $b) {
  350. return $b === null ? ($a === null ? 0 : $a->b === 0) : $b->a === 0;
  351. } else {
  352. if ($c === ($b === null)) {
  353. return $d === false;
  354. }
  355. }',
  356. ],
  357. [
  358. '<?php $b = list($a) = 7 === [7];', // makes no sense, but valid PHP syntax
  359. '<?php $b = list($a) = [7] === 7;',
  360. ],
  361. [
  362. '<?php $a = 1 === function(){};',
  363. '<?php $a = function(){} === 1;',
  364. ],
  365. [
  366. '<?php
  367. $z#1
  368. #2
  369. =
  370. #3
  371. 1#4
  372. #5
  373. ===#6
  374. #7
  375. $a#8
  376. #9
  377. ;#10',
  378. '<?php
  379. $z#1
  380. #2
  381. =
  382. #3
  383. $a#4
  384. #5
  385. ===#6
  386. #7
  387. 1#8
  388. #9
  389. ;#10',
  390. ],
  391. [
  392. '<?php $i = 2 === $this/*a*//*b*//*c*//*d*//*e*//*f*/->getStuff();',
  393. '<?php $i = $this/*a*//*b*//*c*//*d*//*e*//*f*/->getStuff() === 2;',
  394. ],
  395. [
  396. '<?php return "" === $this->myObject5->{$index}->/*1*//*2*/b;',
  397. '<?php return $this->myObject5->{$index}->/*1*//*2*/b === "";',
  398. ],
  399. [
  400. '<?php
  401. function hello() {}
  402. 1 === $a ? b() : c();
  403. ',
  404. '<?php
  405. function hello() {}
  406. $a === 1 ? b() : c();
  407. ',
  408. ],
  409. [
  410. '<?php
  411. class A{}
  412. 1 === $a ? b() : c();
  413. ',
  414. '<?php
  415. class A{}
  416. $a === 1 ? b() : c();
  417. ',
  418. ],
  419. [
  420. '<?php
  421. function foo() {
  422. foreach ($arr as $key => $value) {
  423. false !== uniqid() ? 1 : 2;
  424. }
  425. false !== uniqid() ? 1 : 2;
  426. }',
  427. '<?php
  428. function foo() {
  429. foreach ($arr as $key => $value) {
  430. uniqid() !== false ? 1 : 2;
  431. }
  432. uniqid() !== false ? 1 : 2;
  433. }',
  434. ],
  435. [
  436. '<?php false === $a = array();',
  437. ],
  438. [
  439. '<?php $e = count($this->array[$var]) === $a;',
  440. '<?php $e = $a === count($this->array[$var]);',
  441. ['always_move_variable' => true],
  442. ],
  443. [
  444. '<?php $i = $this->getStuff() === $myVariable;',
  445. '<?php $i = $myVariable === $this->getStuff();',
  446. ['always_move_variable' => true],
  447. ],
  448. [
  449. '<?php $e = count($this->array[$var]) === $a;',
  450. '<?php $e = $a === count($this->array[$var]);',
  451. ['always_move_variable' => true],
  452. ],
  453. [
  454. '<?php $g = ($a789 & self::MY_BITMASK) === $a;',
  455. null,
  456. ['always_move_variable' => true],
  457. ],
  458. [
  459. '<?php return $myVar + 2 === $k;',
  460. '<?php return $k === $myVar + 2;',
  461. ['always_move_variable' => true],
  462. ],
  463. [
  464. '<?php return $myVar . $b === $k;',
  465. '<?php return $k === $myVar . $b;',
  466. ['always_move_variable' => true],
  467. ],
  468. [
  469. '<?php return $myVar - 2 === $k;',
  470. '<?php return $k === $myVar - 2;',
  471. ['always_move_variable' => true],
  472. ],
  473. [
  474. '<?php return $myVar * 2 === $k;',
  475. '<?php return $k === $myVar * 2;',
  476. ['always_move_variable' => true],
  477. ],
  478. [
  479. '<?php return $myVar / 2 === $k;',
  480. '<?php return $k === $myVar / 2;',
  481. ['always_move_variable' => true],
  482. ],
  483. [
  484. '<?php return $myVar % 2 === $k;',
  485. '<?php return $k === $myVar % 2;',
  486. ['always_move_variable' => true],
  487. ],
  488. [
  489. '<?php return $myVar ** 2 === $k;',
  490. '<?php return $k === $myVar ** 2;',
  491. ['always_move_variable' => true],
  492. ],
  493. [
  494. '<?php return $myVar < 2 === $k;',
  495. '<?php return $k === $myVar < 2;',
  496. ['always_move_variable' => true],
  497. ],
  498. [
  499. '<?php return $myVar > 2 === $k;',
  500. '<?php return $k === $myVar > 2;',
  501. ['always_move_variable' => true],
  502. ],
  503. [
  504. '<?php return $myVar <= 2 === $k;',
  505. '<?php return $k === $myVar <= 2;',
  506. ['always_move_variable' => true],
  507. ],
  508. [
  509. '<?php return $myVar >= 2 === $k;',
  510. '<?php return $k === $myVar >= 2;',
  511. ['always_move_variable' => true],
  512. ],
  513. [
  514. '<?php return $myVar . 2 === $k;',
  515. '<?php return $k === $myVar . 2;',
  516. ['always_move_variable' => true],
  517. ],
  518. [
  519. '<?php return $myVar << 2 === $k;',
  520. '<?php return $k === $myVar << 2;',
  521. ['always_move_variable' => true],
  522. ],
  523. [
  524. '<?php return $myVar >> 2 === $k;',
  525. '<?php return $k === $myVar >> 2;',
  526. ['always_move_variable' => true],
  527. ],
  528. [
  529. '<?php return !$myVar === $k;',
  530. '<?php return $k === !$myVar;',
  531. ['always_move_variable' => true],
  532. ],
  533. [
  534. '<?php return $myVar instanceof Foo === $k;',
  535. '<?php return $k === $myVar instanceof Foo;',
  536. ['always_move_variable' => true],
  537. ],
  538. [
  539. '<?php return (bool) $myVar === $k;',
  540. '<?php return $k === (bool) $myVar;',
  541. ['always_move_variable' => true],
  542. ],
  543. [
  544. '<?php return (int) $myVar === $k;',
  545. '<?php return $k === (int) $myVar;',
  546. ['always_move_variable' => true],
  547. ],
  548. [
  549. '<?php return (float) $myVar === $k;',
  550. '<?php return $k === (float) $myVar;',
  551. ['always_move_variable' => true],
  552. ],
  553. [
  554. '<?php return (string) $myVar === $k;',
  555. '<?php return $k === (string) $myVar;',
  556. ['always_move_variable' => true],
  557. ],
  558. [
  559. '<?php return (array) $myVar === $k;',
  560. '<?php return $k === (array) $myVar;',
  561. ['always_move_variable' => true],
  562. ],
  563. [
  564. '<?php return (object) $myVar === $k;',
  565. '<?php return $k === (object) $myVar;',
  566. ['always_move_variable' => true],
  567. ],
  568. [
  569. '<?php $a = null === foo();',
  570. '<?php $a = foo() === null;',
  571. ],
  572. [
  573. '<?php $a = \'foo\' === foo();',
  574. '<?php $a = foo() === \'foo\';',
  575. ],
  576. [
  577. '<?php $a = "foo" === foo();',
  578. '<?php $a = foo() === "foo";',
  579. ],
  580. [
  581. '<?php $a = 1 === foo();',
  582. '<?php $a = foo() === 1;',
  583. ],
  584. [
  585. '<?php $a = 1.2 === foo();',
  586. '<?php $a = foo() === 1.2;',
  587. ],
  588. [
  589. '<?php $a = true === foo();',
  590. '<?php $a = foo() === true;',
  591. ],
  592. [
  593. '<?php $a = false === foo();',
  594. '<?php $a = foo() === false;',
  595. ],
  596. [
  597. '<?php $a = -1 === reset($foo);',
  598. '<?php $a = reset($foo) === -1;',
  599. ],
  600. [
  601. '<?php $a = - 1 === reset($foo);',
  602. '<?php $a = reset($foo) === - 1;',
  603. ],
  604. [
  605. '<?php $a = -/* bar */1 === reset($foo);',
  606. '<?php $a = reset($foo) === -/* bar */1;',
  607. ],
  608. [
  609. '<?php $a %= 4 === $b ? 2 : 3;',
  610. '<?php $a %= $b === 4 ? 2 : 3;',
  611. ],
  612. [
  613. '<?php return array() === $array;',
  614. '<?php return $array === array();',
  615. ],
  616. [
  617. '<?php return [] === $array;',
  618. '<?php return $array === [];',
  619. ],
  620. [
  621. '<?php return array(/* foo */) === $array;',
  622. '<?php return $array === array(/* foo */);',
  623. ],
  624. [
  625. '<?php return [
  626. // 1
  627. ] === $array;',
  628. '<?php return $array === [
  629. // 1
  630. ];',
  631. ],
  632. [
  633. '<?php $a = $b = null === $c;',
  634. '<?php $a = $b = $c === null;',
  635. ],
  636. ];
  637. foreach ($tests as $index => $test) {
  638. yield $index => $test;
  639. }
  640. $template = '<?php $a = ($b + $c) %s 1 === true ? 1 : 2;';
  641. $operators = ['||', '&&'];
  642. foreach ($operators as $operator) {
  643. yield [
  644. sprintf($template, $operator),
  645. null,
  646. ['always_move_variable' => true],
  647. ];
  648. }
  649. $templateExpected = '<?php $a %s 4 === $b ? 2 : 3;';
  650. $templateInput = '<?php $a %s $b === 4 ? 2 : 3;';
  651. $operators = ['**=', '*=', '|=', '+=', '-=', '^=', 'xor', 'or', 'and', '<<=', '>>=', '&=', '.=', '/=', '-=', '||', '&&'];
  652. foreach ($operators as $operator) {
  653. yield [
  654. sprintf($templateExpected, $operator),
  655. sprintf($templateInput, $operator),
  656. ];
  657. }
  658. }
  659. /**
  660. * @param string $expected
  661. * @param string $input
  662. *
  663. * @dataProvider provideLessGreaterCases
  664. */
  665. public function testFixLessGreater($expected, $input)
  666. {
  667. $this->fixer->configure(['less_and_greater' => true]);
  668. $this->doTest($expected, $input);
  669. }
  670. /**
  671. * Test with the inverse config.
  672. *
  673. * @param string $expected
  674. * @param string $input
  675. *
  676. * @dataProvider provideLessGreaterCases
  677. */
  678. public function testFixLessGreaterInverse($expected, $input)
  679. {
  680. $this->fixer->configure(['less_and_greater' => false]);
  681. $this->doTest($input, $expected);
  682. }
  683. public function provideLessGreaterCases()
  684. {
  685. return [
  686. [
  687. '<?php $a = 3 <= $b;',
  688. '<?php $a = $b >= 3;',
  689. ],
  690. [
  691. '<?php $a = 3 > $b;',
  692. '<?php $a = $b < 3;',
  693. ],
  694. [
  695. '<?php $a = (3 > $b) || $d;',
  696. '<?php $a = ($b < 3) || $d;',
  697. ],
  698. ];
  699. }
  700. public function testComplexConfiguration()
  701. {
  702. $this->fixer->configure([
  703. 'equal' => null,
  704. 'identical' => true,
  705. 'less_and_greater' => false,
  706. ]);
  707. $this->doTest(
  708. '<?php
  709. $a = 1 === $b;
  710. $b = $c != 1;
  711. $c = $c > 3;
  712. ',
  713. '<?php
  714. $a = $b === 1;
  715. $b = $c != 1;
  716. $c = $c > 3;
  717. '
  718. );
  719. }
  720. /**
  721. * @param string $expectedMessage
  722. *
  723. * @dataProvider provideInvalidConfigurationCases
  724. */
  725. public function testInvalidConfig(array $config, $expectedMessage)
  726. {
  727. $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class);
  728. $this->expectExceptionMessageMatches("#^\\[{$this->fixer->getName()}\\] {$expectedMessage}$#");
  729. $this->fixer->configure($config);
  730. }
  731. /**
  732. * @return array
  733. */
  734. public function provideInvalidConfigurationCases()
  735. {
  736. return [
  737. [['equal' => 2], 'Invalid configuration: The option "equal" with value 2 is expected to be of type "bool" or "null", but is of type "(int|integer)"\.'],
  738. [['_invalid_' => true], 'Invalid configuration: The option "_invalid_" does not exist\. Defined options are: "always_move_variable", "equal", "identical", "less_and_greater"\.'],
  739. ];
  740. }
  741. public function testDefinition()
  742. {
  743. static::assertInstanceOf(\PhpCsFixer\FixerDefinition\FixerDefinitionInterface::class, $this->fixer->getDefinition());
  744. }
  745. /**
  746. * @param string $expected
  747. * @param null|string $input
  748. *
  749. * @dataProvider providePHP70Cases
  750. * @requires PHP 7.0
  751. */
  752. public function testPHP70Cases($expected, $input = null)
  753. {
  754. $this->fixer->configure(['equal' => true, 'identical' => true]);
  755. $this->doTest($expected, $input);
  756. }
  757. /**
  758. * Test with the inverse config.
  759. *
  760. * @param string $expected
  761. * @param null|string $input
  762. *
  763. * @dataProvider providePHP70Cases
  764. * @requires PHP 7.0
  765. */
  766. public function testPHP70CasesInverse($expected, $input = null)
  767. {
  768. $this->fixer->configure(['equal' => false, 'identical' => false]);
  769. if (null === $input) {
  770. $this->doTest($expected);
  771. } else {
  772. $this->doTest($input, $expected);
  773. }
  774. }
  775. public function providePHP70Cases()
  776. {
  777. return [
  778. ['<?php $a = $b + 1 <=> $d;'],
  779. [
  780. '<?php $a = new class(10) extends SomeClass implements SomeInterface {} === $a;/**/',
  781. ],
  782. [
  783. '<?php $a = $b ?? 1 ?? 2 == $d;',
  784. '<?php $a = $b ?? 1 ?? $d == 2;',
  785. ],
  786. [
  787. '<?php $a = 1 === new class(10) extends SomeClass implements SomeInterface {};/**/',
  788. '<?php $a = new class(10) extends SomeClass implements SomeInterface {} === 1;/**/',
  789. ],
  790. [
  791. '<?php
  792. function a() {
  793. for ($i = 1; $i <= 3; $i++) {
  794. echo yield 1 === $i ? 1 : 2;
  795. }
  796. }
  797. ',
  798. ],
  799. ];
  800. }
  801. /**
  802. * @param string $expected
  803. * @param null|string $input
  804. *
  805. * @dataProvider providePHP71Cases
  806. * @requires PHP 7.1
  807. */
  808. public function testPHP71Cases($expected, $input = null)
  809. {
  810. $this->fixer->configure(['equal' => true, 'identical' => true]);
  811. $this->doTest($expected, $input);
  812. }
  813. /**
  814. * Test with the inverse config.
  815. *
  816. * @param string $expected
  817. * @param null|string $input
  818. *
  819. * @dataProvider providePHP71Cases
  820. * @requires PHP 7.1
  821. */
  822. public function testPHP71CasesInverse($expected, $input = null)
  823. {
  824. $this->fixer->configure(['equal' => false, 'identical' => false]);
  825. if (null === $input) {
  826. $this->doTest($expected);
  827. } else {
  828. $this->doTest($input, $expected);
  829. }
  830. }
  831. public function providePHP71Cases()
  832. {
  833. return [
  834. // no fix cases
  835. ['<?php list("a" => $a, "b" => $b, "c" => $c) = $c === array(1) ? $b : $d;'],
  836. ['<?php list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = $points;'],
  837. ['<?php list("first" => list($x1, $y1), "second" => list($x2, $y2)) = $points;'],
  838. ['<?php [$a, $b, $c] = [1, 2, 3];'],
  839. ['<?php ["a" => $a, "b" => $b, "c" => $c] = $a[0];'],
  840. ['<?php list("a" => $a, "b" => $b, "c" => $c) = $c === array(1) ? $b : $d;'],
  841. ['<?php $b = 7 === [$a] = [7];'], // makes no sense, but valid PHP syntax
  842. ['<?php $b = 7 === [$a] = [7];'],
  843. ['<?php [$a] = $c === array(1) ? $b : $d;'],
  844. ['<?php $b = 7 === [$a] = [7];'],
  845. ['<?php $z = $n == [$a] = $b;'],
  846. ['<?php return $n == [$a] = $b;'],
  847. // fix cases
  848. [
  849. '<?php list("a" => $a, "b" => $b, "c" => $c) = 1 === $c ? $b : $d;',
  850. '<?php list("a" => $a, "b" => $b, "c" => $c) = $c === 1 ? $b : $d;',
  851. ],
  852. [
  853. '<?php list("a" => $a, "b" => $b, "c" => $c) = A::B === $c ? $b : $d;',
  854. '<?php list("a" => $a, "b" => $b, "c" => $c) = $c === A::B ? $b : $d;',
  855. ],
  856. [
  857. '<?php list( (2 === $c ? "a" : "b") => $b) = ["a" => 7 === $c ? 5 : 1, "b" => 7];',
  858. '<?php list( ($c === 2 ? "a" : "b") => $b) = ["a" => $c === 7 ? 5 : 1, "b" => 7];',
  859. ],
  860. [
  861. '<?php [ (ABC::A === $c ? "a" : "b") => $b] = ["a" => 7 === $c ? 5 : 1, "b" => 7];',
  862. '<?php [ ($c === ABC::A ? "a" : "b") => $b] = ["a" => $c === 7 ? 5 : 1, "b" => 7];',
  863. ],
  864. 'Array destruct by ternary.' => [
  865. '<?php [$a] = 11 === $c ? $b : $d;',
  866. '<?php [$a] = $c === 11 ? $b : $d;',
  867. ],
  868. [
  869. '<?php $b = [$a] = 7 === [7];', // makes no sense, but valid PHP syntax
  870. '<?php $b = [$a] = [7] === 7;',
  871. ],
  872. ];
  873. }
  874. /**
  875. * @param string $expected
  876. *
  877. * @dataProvider provideFixWithConfigCases
  878. */
  879. public function testWithConfig(array $config, $expected)
  880. {
  881. $this->fixer->configure($config);
  882. $this->doTest($expected);
  883. }
  884. public function provideFixWithConfigCases()
  885. {
  886. return [
  887. [
  888. [
  889. 'identical' => false,
  890. ],
  891. '<?php
  892. $a = [1, 2, 3];
  893. while (2 !== $b = array_pop($c));
  894. ',
  895. ],
  896. [
  897. [
  898. 'equal' => false,
  899. 'identical' => false,
  900. ],
  901. '<?php
  902. if ($revision->event == \'created\') {
  903. foreach ($revision->getModified() as $col => $data) {
  904. $model->$col = $data[\'new\'];
  905. }
  906. } else {
  907. foreach ($revision->getModified() as $col => $data) {
  908. $model->$col = $data[\'old\'];
  909. }
  910. }',
  911. ],
  912. ];
  913. }
  914. /**
  915. * @param string $expected
  916. * @param null|string $input
  917. *
  918. * @dataProvider provideFixPhp74Cases
  919. * @requires PHP 7.4
  920. */
  921. public function testFixPhp74($expected, $input)
  922. {
  923. $this->doTest($expected, $input);
  924. }
  925. public function provideFixPhp74Cases()
  926. {
  927. yield [
  928. '<?php if (1_000 === $b);',
  929. '<?php if ($b === 1_000);',
  930. ];
  931. }
  932. /**
  933. * Test with the inverse config.
  934. *
  935. * @param string $expected
  936. * @param null|string $input
  937. *
  938. * @dataProvider providePHP74Cases
  939. * @requires PHP 7.4
  940. */
  941. public function testPHP74CasesInverse($expected, $input = null, array $configuration = null)
  942. {
  943. if (null !== $configuration) {
  944. $this->fixer->configure($configuration);
  945. }
  946. $this->doTest($expected, $input);
  947. }
  948. public function providePHP74Cases()
  949. {
  950. return [
  951. [
  952. '<?php fn() => $c === array(1) ? $b : $d;',
  953. null,
  954. [
  955. 'less_and_greater' => false,
  956. ],
  957. ],
  958. [
  959. '<?php $a ??= 4 === $b ? 2 : 3;',
  960. '<?php $a ??= $b === 4 ? 2 : 3;',
  961. ],
  962. ];
  963. }
  964. /**
  965. * @param string $expected
  966. * @param null|string $input
  967. *
  968. * @dataProvider provideFixPrePHP80Cases
  969. *
  970. * @requires PHP <8.0
  971. */
  972. public function testFixPrePHP80($expected, $input = null)
  973. {
  974. $this->doTest($expected, $input);
  975. }
  976. public function provideFixPrePHP80Cases()
  977. {
  978. yield [
  979. '<?php return \A/*5*/\/*6*/B\/*7*/C::MY_CONST === \A/*1*//*1*//*1*//*1*//*1*/\/*2*/B/*3*/\C/*4*/::$myVariable;',
  980. '<?php return \A/*1*//*1*//*1*//*1*//*1*/\/*2*/B/*3*/\C/*4*/::$myVariable === \A/*5*/\/*6*/B\/*7*/C::MY_CONST;',
  981. ];
  982. yield [
  983. '<?php return A\/**//**//**/B/*a*//*a*//*a*//*a*/::MY_CONST === B\C::$myVariable;',
  984. '<?php return B\C::$myVariable === A\/**//**//**/B/*a*//*a*//*a*//*a*/::MY_CONST;',
  985. ];
  986. yield ['<?php return $foo === $bar[$baz]{1};'];
  987. yield ['<?php return $foo->$a[1] === $bar[$baz]{1}->$a[1][2][3]->$d[$z]{1};'];
  988. yield ['<?php return $m->a{2}+1 == 2;'];
  989. yield ['<?php return $m{2}+1 == 2;'];
  990. yield [
  991. '<?php echo 1 === (unset) $a ? 8 : 7;',
  992. '<?php echo (unset) $a === 1 ? 8 : 7;',
  993. ];
  994. }
  995. /**
  996. * @param string $expected
  997. * @param string $input
  998. *
  999. * @dataProvider provideFix80Cases
  1000. * @requires PHP 8.0
  1001. */
  1002. public function testFix80($expected, $input)
  1003. {
  1004. $this->doTest($expected, $input);
  1005. }
  1006. public function provideFix80Cases()
  1007. {
  1008. yield [
  1009. '<?php
  1010. if ($a = true === $obj instanceof (foo())) {
  1011. echo 1;
  1012. }',
  1013. '<?php
  1014. if ($a = $obj instanceof (foo()) === true) {
  1015. echo 1;
  1016. }',
  1017. ];
  1018. }
  1019. }