NoPhp4ConstructorFixerTest.php 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  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\ClassNotation;
  13. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  14. /**
  15. * @author Matteo Beccati <matteo@beccati.com>
  16. *
  17. * @internal
  18. *
  19. * @covers \PhpCsFixer\Fixer\ClassNotation\NoPhp4ConstructorFixer
  20. *
  21. * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\ClassNotation\NoPhp4ConstructorFixer>
  22. */
  23. final class NoPhp4ConstructorFixerTest extends AbstractFixerTestCase
  24. {
  25. /**
  26. * @dataProvider provideFixCases
  27. */
  28. public function testFix(string $expected, ?string $input = null): void
  29. {
  30. $this->doTest($expected, $input);
  31. }
  32. /**
  33. * @return iterable<int|string, array{0: string, 1?: string}>
  34. */
  35. public static function provideFixCases(): iterable
  36. {
  37. yield [
  38. '<?php $a = new class {};',
  39. ];
  40. yield [
  41. '<?php $a = new class {}?>',
  42. ];
  43. yield [
  44. '<?php
  45. $a = new Foo() <=> 1;
  46. $a = new Foo <=> 1;
  47. $a = new class() {};
  48. $a = new class() implements Foo{};
  49. $a = new class() /**/ extends Bar1{};
  50. $a = new class() extends Bar2 implements Foo{};
  51. $a = new class() extends Bar3 implements Foo, Foo2{};
  52. $a = new class() {};
  53. $a = new class {};
  54. $a = new class implements Foo{};
  55. $a = new class /**/ extends Bar1{};
  56. $a = new class extends Bar2 implements Foo{};
  57. $a = new class extends Bar3 implements Foo, Foo2{};
  58. $a = new class {}?>
  59. ',
  60. ];
  61. yield 'simple class 1' => [
  62. <<<'EOF'
  63. <?php
  64. class Foo
  65. {
  66. public function __construct($bar)
  67. {
  68. var_dump(1);
  69. }
  70. }
  71. EOF,
  72. <<<'EOF'
  73. <?php
  74. class Foo
  75. {
  76. public function Foo($bar)
  77. {
  78. var_dump(1);
  79. }
  80. }
  81. EOF,
  82. ];
  83. yield 'simple class 2' => [
  84. <<<'EOF'
  85. <?php
  86. class Foo
  87. {
  88. public#
  89. function#
  90. __construct#
  91. (#
  92. $bar#
  93. )#
  94. {}
  95. }
  96. EOF,
  97. <<<'EOF'
  98. <?php
  99. class Foo
  100. {
  101. public#
  102. function#
  103. Foo#
  104. (#
  105. $bar#
  106. )#
  107. {}
  108. }
  109. EOF,
  110. ];
  111. yield 'namespace' => [<<<'EOF'
  112. <?php
  113. namespace Baz\Qux;
  114. class Foo
  115. {
  116. public function __construct($bar)
  117. {
  118. var_dump(1);
  119. }
  120. public function Foo($bar)
  121. {
  122. var_dump(2);
  123. }
  124. }
  125. EOF];
  126. yield 'namespace 2' => [<<<'EOF'
  127. <?php
  128. namespace Baz\Qux
  129. {
  130. class Foo
  131. {
  132. public function __construct($bar)
  133. {
  134. var_dump(1);
  135. }
  136. public function Foo($bar)
  137. {
  138. var_dump(2);
  139. }
  140. }
  141. class Bar
  142. {
  143. public function Bar()
  144. {
  145. var_dump(3);
  146. }
  147. }
  148. }
  149. EOF];
  150. yield 'namespace global' => [
  151. <<<'EOF'
  152. <?php
  153. namespace {
  154. class Foo
  155. {
  156. function __construct($bar)
  157. {
  158. var_dump(1);
  159. }
  160. }
  161. }
  162. EOF,
  163. <<<'EOF'
  164. <?php
  165. namespace {
  166. class Foo
  167. {
  168. function Foo($bar)
  169. {
  170. var_dump(1);
  171. }
  172. }
  173. }
  174. EOF,
  175. ];
  176. yield 'PHP 5 only' => [<<<'EOF'
  177. <?php
  178. class Foo
  179. {
  180. function __construct($bar)
  181. {
  182. var_dump(1);
  183. }
  184. function bar()
  185. {
  186. var_dump(3);
  187. }
  188. }
  189. EOF];
  190. yield 'PHP 4 only' => [
  191. <<<'EOF'
  192. <?php
  193. class Foo
  194. {
  195. /**
  196. * Constructor
  197. */
  198. function __construct($bar)
  199. {
  200. var_dump(1);
  201. }
  202. function bar()
  203. {
  204. var_dump(3);
  205. }
  206. }
  207. EOF,
  208. <<<'EOF'
  209. <?php
  210. class Foo
  211. {
  212. /**
  213. * Constructor
  214. */
  215. function foO($bar)
  216. {
  217. var_dump(1);
  218. }
  219. function bar()
  220. {
  221. var_dump(3);
  222. }
  223. }
  224. EOF,
  225. ];
  226. yield 'both the right way 1' => [
  227. <<<'EOF'
  228. <?php
  229. class Foo
  230. {
  231. /**
  232. * Constructor
  233. */
  234. public function __construct()
  235. {
  236. var_dump(1);
  237. }
  238. public function bar()
  239. {
  240. var_dump(3);
  241. }
  242. }
  243. EOF,
  244. <<<'EOF'
  245. <?php
  246. class Foo
  247. {
  248. /**
  249. * Constructor
  250. */
  251. public function __construct()
  252. {
  253. var_dump(1);
  254. }
  255. /**
  256. * PHP-4 Constructor
  257. */
  258. function Foo()
  259. {
  260. // Call PHP5!
  261. $this->__construct();
  262. }
  263. public function bar()
  264. {
  265. var_dump(3);
  266. }
  267. }
  268. EOF,
  269. ];
  270. yield 'both the right way 2' => [
  271. <<<'EOF'
  272. <?php
  273. class Foo
  274. {
  275. /**
  276. * Constructor
  277. */
  278. public function __construct($bar)
  279. {
  280. var_dump(1);
  281. }
  282. public function bar()
  283. {
  284. var_dump(3);
  285. }
  286. }
  287. EOF,
  288. <<<'EOF'
  289. <?php
  290. class Foo
  291. {
  292. /**
  293. * Constructor
  294. */
  295. public function __construct($bar)
  296. {
  297. var_dump(1);
  298. }
  299. /**
  300. * PHP-4 Constructor
  301. */
  302. function Foo($bar)
  303. {
  304. // Call PHP5!
  305. $this->__construct($bar);
  306. }
  307. public function bar()
  308. {
  309. var_dump(3);
  310. }
  311. }
  312. EOF,
  313. ];
  314. yield 'both the right way 3' => [
  315. <<<'EOF'
  316. <?php
  317. class Foo
  318. {
  319. /**
  320. * Constructor
  321. */
  322. public function __construct($bar = 1, $baz = null)
  323. {
  324. var_dump(1);
  325. }
  326. public function bar()
  327. {
  328. var_dump(3);
  329. }
  330. }
  331. EOF,
  332. <<<'EOF'
  333. <?php
  334. class Foo
  335. {
  336. /**
  337. * Constructor
  338. */
  339. public function __construct($bar = 1, $baz = null)
  340. {
  341. var_dump(1);
  342. }
  343. /**
  344. * PHP-4 Constructor
  345. */
  346. function Foo($bar = 1, $baz = null)
  347. {
  348. // Call PHP5!
  349. $this->__construct($bar, $baz);
  350. }
  351. public function bar()
  352. {
  353. var_dump(3);
  354. }
  355. }
  356. EOF,
  357. ];
  358. yield 'both the other way around 1' => [
  359. <<<'EOF'
  360. <?php
  361. class Foo
  362. {
  363. /**
  364. * PHP-4 Constructor.
  365. *
  366. * This is the real constructor. It's the one that most likely contains any meaningful info in the docblock.
  367. */
  368. private function __construct($bar)
  369. {
  370. var_dump(1);
  371. }
  372. function bar()
  373. {
  374. var_dump(3);
  375. }
  376. }
  377. EOF,
  378. <<<'EOF'
  379. <?php
  380. class Foo
  381. {
  382. /**
  383. * PHP-5 Constructor.
  384. *
  385. * This docblock is removed, along with the entire wrapper method.
  386. */
  387. protected function __construct($bar)
  388. {
  389. // Call The Real Constructor, not the hippy fake one!
  390. $this->Foo($bar);
  391. }
  392. /**
  393. * PHP-4 Constructor.
  394. *
  395. * This is the real constructor. It's the one that most likely contains any meaningful info in the docblock.
  396. */
  397. private function Foo($bar)
  398. {
  399. var_dump(1);
  400. }
  401. function bar()
  402. {
  403. var_dump(3);
  404. }
  405. }
  406. EOF,
  407. ];
  408. yield 'PHP 4 parent' => [
  409. <<<'EOF'
  410. <?php
  411. class Foo extends FooParEnt
  412. {
  413. /**
  414. * Constructor
  415. */
  416. function __construct($bar)
  417. {
  418. parent::__construct(1);
  419. var_dump(9);
  420. }
  421. function bar()
  422. {
  423. var_dump(3);
  424. }
  425. }
  426. EOF,
  427. <<<'EOF'
  428. <?php
  429. class Foo extends FooParEnt
  430. {
  431. /**
  432. * Constructor
  433. */
  434. function Foo($bar)
  435. {
  436. parent::FooPaRent(1);
  437. var_dump(9);
  438. }
  439. function bar()
  440. {
  441. var_dump(3);
  442. }
  443. }
  444. EOF,
  445. ];
  446. yield 'PHP 4 parent init' => [
  447. <<<'EOF'
  448. <?php
  449. class Foo extends FooParent
  450. {
  451. /**
  452. * Constructor
  453. */
  454. function __construct($bar)
  455. {
  456. parent::init(1);
  457. var_dump(9);
  458. }
  459. function bar()
  460. {
  461. var_dump(3);
  462. }
  463. }
  464. EOF,
  465. <<<'EOF'
  466. <?php
  467. class Foo extends FooParent
  468. {
  469. /**
  470. * Constructor
  471. */
  472. function Foo($bar)
  473. {
  474. parent::init(1);
  475. var_dump(9);
  476. }
  477. function bar()
  478. {
  479. var_dump(3);
  480. }
  481. }
  482. EOF,
  483. ];
  484. yield 'mixed parent' => [
  485. <<<'EOF'
  486. <?php
  487. class Foo extends FooParent
  488. {
  489. /**
  490. * Constructor
  491. */
  492. function __construcT($bar)
  493. {
  494. parent::__construct(1);
  495. var_dump(9);
  496. }
  497. function bar()
  498. {
  499. var_dump(3);
  500. }
  501. }
  502. EOF,
  503. <<<'EOF'
  504. <?php
  505. class Foo extends FooParent
  506. {
  507. /**
  508. * Constructor
  509. */
  510. function __construcT($bar)
  511. {
  512. parent::FooParenT(1);
  513. var_dump(9);
  514. }
  515. function bar()
  516. {
  517. var_dump(3);
  518. }
  519. }
  520. EOF,
  521. ];
  522. yield 'mixed parent 2' => [
  523. <<<'EOF'
  524. <?php
  525. class Foo extends FooParent
  526. {
  527. /**
  528. * Constructor
  529. */
  530. function __construcT($bar)
  531. {
  532. parent::__construct(1);
  533. var_dump(9);
  534. }
  535. function bar()
  536. {
  537. var_dump(3);
  538. }
  539. }
  540. EOF,
  541. <<<'EOF'
  542. <?php
  543. class Foo extends FooParent
  544. {
  545. /**
  546. * Constructor
  547. */
  548. function __construcT($bar)
  549. {
  550. $this->FooParenT(1);
  551. var_dump(9);
  552. }
  553. function bar()
  554. {
  555. var_dump(3);
  556. }
  557. }
  558. EOF,
  559. ];
  560. yield 'parent other' => [
  561. <<<'EOF'
  562. <?php
  563. class Foo extends FooParent
  564. {
  565. /**
  566. * Constructor
  567. */
  568. function __construct($bar)
  569. {
  570. parent::__construct(1);
  571. var_dump(9);
  572. }
  573. function bar()
  574. {
  575. var_dump(3);
  576. }
  577. }
  578. EOF,
  579. <<<'EOF'
  580. <?php
  581. class Foo extends FooParent
  582. {
  583. /**
  584. * Constructor
  585. */
  586. function Foo($bar)
  587. {
  588. $this->FooParent(1);
  589. var_dump(9);
  590. }
  591. function bar()
  592. {
  593. var_dump(3);
  594. }
  595. }
  596. EOF,
  597. ];
  598. yield 'parent other 2' => [
  599. <<<'EOF'
  600. <?php
  601. class Foo extends FooParent
  602. {
  603. /**
  604. * Constructor
  605. */
  606. function __construct($bar)
  607. {
  608. parent::__construct(1);
  609. var_dump(9);
  610. }
  611. function bar()
  612. {
  613. var_dump(3);
  614. }
  615. }
  616. EOF,
  617. <<<'EOF'
  618. <?php
  619. class Foo extends FooParent
  620. {
  621. /**
  622. * Constructor
  623. */
  624. function Foo($bar)
  625. {
  626. FooParent::FooParent(1);
  627. var_dump(9);
  628. }
  629. function bar()
  630. {
  631. var_dump(3);
  632. }
  633. }
  634. EOF,
  635. ];
  636. yield 'class with anonymous' => [
  637. <<<'EOF'
  638. <?php
  639. class Foo {
  640. private $bar;
  641. public function __construct()
  642. {
  643. $this->bar = function () {};
  644. }
  645. }
  646. EOF,
  647. <<<'EOF'
  648. <?php
  649. class Foo {
  650. private $bar;
  651. public function Foo()
  652. {
  653. $this->bar = function () {};
  654. }
  655. }
  656. EOF,
  657. ];
  658. yield 'class with comments' => [
  659. <<<'EOF'
  660. <?php
  661. class /* test */
  662. // another
  663. Foo {
  664. public function /* test */ __construct($param) {
  665. }
  666. }
  667. EOF,
  668. <<<'EOF'
  669. <?php
  670. class /* test */
  671. // another
  672. Foo {
  673. public function /* test */ Foo($param) {
  674. }
  675. }
  676. EOF,
  677. ];
  678. yield 'alpha beta' => [<<<'EOF'
  679. <?php
  680. class Foo
  681. {
  682. public function Foo()
  683. {
  684. echo 'alpha';
  685. }
  686. public function __construct()
  687. {
  688. echo 'beta';
  689. }
  690. }
  691. EOF];
  692. yield 'alpha beta trick 1' => [<<<'EOF'
  693. <?php
  694. class Foo
  695. {
  696. public function Foo()
  697. {
  698. // This is not $this->__construct()
  699. echo 'alpha';
  700. }
  701. public function __construct()
  702. {
  703. echo 'beta';
  704. }
  705. }
  706. EOF];
  707. yield 'alpha beta trick 2' => [<<<'EOF'
  708. <?php
  709. class Foo
  710. {
  711. public function Foo()
  712. {
  713. echo 'alpha';
  714. }
  715. public function __construct()
  716. {
  717. // This is not $this->Foo()
  718. echo 'beta';
  719. }
  720. }
  721. EOF];
  722. yield 'alpha beta trick 3' => [<<<'EOF'
  723. <?php
  724. class Foo
  725. {
  726. public function Foo()
  727. {
  728. echo 'alpha';
  729. /* yeah, ok let's construct it anyway */
  730. $this->__construct();
  731. }
  732. public function __construct()
  733. {
  734. echo 'beta';
  735. }
  736. }
  737. EOF];
  738. yield 'alpha beta trick 4 with another class' => [
  739. <<<'EOF'
  740. <?php
  741. class Foo
  742. {
  743. public function Foo()
  744. {
  745. echo 'alpha';
  746. }
  747. public function __construct()
  748. {
  749. $this->Foo();
  750. // Do something more!
  751. echo 'beta';
  752. }
  753. }
  754. Class Bar
  755. {
  756. function __construct()
  757. {
  758. $this->foo = 1;
  759. }
  760. }
  761. EOF,
  762. <<<'EOF'
  763. <?php
  764. class Foo
  765. {
  766. public function Foo()
  767. {
  768. echo 'alpha';
  769. }
  770. public function __construct()
  771. {
  772. $this->Foo();
  773. // Do something more!
  774. echo 'beta';
  775. }
  776. }
  777. Class Bar
  778. {
  779. function bar()
  780. {
  781. $this->foo = 1;
  782. }
  783. }
  784. EOF,
  785. ];
  786. yield 'abstract' => [<<<'EOF'
  787. <?php
  788. abstract class Foo
  789. {
  790. abstract function Foo();
  791. }
  792. EOF];
  793. yield 'abstract trick' => [<<<'EOF'
  794. <?php
  795. abstract class Foo
  796. {
  797. abstract public function Foo();
  798. public function bar()
  799. {
  800. // This is messed up, I know
  801. $this->__construct();
  802. }
  803. public function __construct()
  804. {
  805. $this->baz = 1;
  806. }
  807. }
  808. EOF];
  809. yield 'parent multiple classes' => [
  810. <<<'EOF'
  811. <?php
  812. class Class1 extends Parent1
  813. {
  814. function __construct($foo)
  815. {
  816. parent::__construct();
  817. echo "something";
  818. }
  819. }
  820. class Class2 extends Parent2
  821. {
  822. function __construct($foo)
  823. {
  824. echo "something";
  825. }
  826. }
  827. ?>
  828. EOF,
  829. <<<'EOF'
  830. <?php
  831. class Class1 extends Parent1
  832. {
  833. function __construct($foo)
  834. {
  835. $this->Parent1();
  836. echo "something";
  837. }
  838. }
  839. class Class2 extends Parent2
  840. {
  841. function __construct($foo)
  842. {
  843. echo "something";
  844. }
  845. }
  846. ?>
  847. EOF,
  848. ];
  849. yield 'infinite recursion' => [
  850. <<<'EOF'
  851. <?php
  852. class Parent1
  853. {
  854. function __construct()
  855. {
  856. echo "foobar";
  857. }
  858. }
  859. class Class1 extends Parent1
  860. {
  861. function __construct($foo)
  862. {
  863. parent::__construct();
  864. echo "something";
  865. }
  866. }
  867. ?>
  868. EOF,
  869. <<<'EOF'
  870. <?php
  871. class Parent1
  872. {
  873. function __construct()
  874. {
  875. echo "foobar";
  876. }
  877. }
  878. class Class1 extends Parent1
  879. {
  880. function Class1($foo)
  881. {
  882. $this->__construct();
  883. echo "something";
  884. }
  885. }
  886. ?>
  887. EOF,
  888. ];
  889. }
  890. /**
  891. * @dataProvider provideFix80Cases
  892. *
  893. * @requires PHP 8.0
  894. */
  895. public function testFix80(string $expected, ?string $input = null): void
  896. {
  897. $this->doTest($expected, $input);
  898. }
  899. /**
  900. * @return iterable<array{string, string}>
  901. */
  902. public static function provideFix80Cases(): iterable
  903. {
  904. yield [
  905. <<<'EOF'
  906. <?php
  907. class Foo
  908. {
  909. public function __construct($bar,)
  910. {
  911. var_dump(1);
  912. }
  913. }
  914. EOF,
  915. <<<'EOF'
  916. <?php
  917. class Foo
  918. {
  919. public function Foo($bar,)
  920. {
  921. var_dump(1);
  922. }
  923. }
  924. EOF,
  925. ];
  926. yield [
  927. '<?php
  928. class Foo
  929. {
  930. public function __construct()
  931. {
  932. }
  933. }',
  934. '<?php
  935. class Foo
  936. {
  937. public function Foo()
  938. {
  939. }
  940. }',
  941. ];
  942. yield [
  943. '<?php
  944. class Foo
  945. {
  946. public function __construct()
  947. {
  948. $this?->__construct();
  949. }
  950. }',
  951. '<?php
  952. class Foo
  953. {
  954. public function Foo()
  955. {
  956. $this?->__construct();
  957. }
  958. }',
  959. ];
  960. yield [
  961. '<?php
  962. class Foo extends Bar
  963. {
  964. public function __construct()
  965. {
  966. parent::__construct();
  967. }
  968. }',
  969. '<?php
  970. class Foo extends Bar
  971. {
  972. public function Foo()
  973. {
  974. $this?->Bar();
  975. }
  976. }',
  977. ];
  978. yield [
  979. '<?php
  980. class Foo
  981. {
  982. /**
  983. * Constructor
  984. */
  985. public function __construct($bar = 1, $baz = null)
  986. {
  987. var_dump(1);
  988. }
  989. }
  990. ',
  991. '<?php
  992. class Foo
  993. {
  994. /**
  995. * Constructor
  996. */
  997. public function __construct($bar = 1, $baz = null)
  998. {
  999. var_dump(1);
  1000. }
  1001. /**
  1002. * PHP-4 Constructor
  1003. */
  1004. function Foo($bar = 1, $baz = null)
  1005. {
  1006. $this?->__construct($bar, $baz);
  1007. }
  1008. }
  1009. ',
  1010. ];
  1011. }
  1012. }