YodaStyleFixerTest.php 30 KB

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