YodaStyleFixerTest.php 30 KB

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