ClassDefinitionFixerTest.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  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\Fixer\ClassNotation\ClassDefinitionFixer;
  14. use PhpCsFixer\Tests\Test\AbstractFixerTestCase;
  15. use PhpCsFixer\Tokenizer\Tokens;
  16. use PhpCsFixer\WhitespacesFixerConfig;
  17. /**
  18. * @author SpacePossum
  19. *
  20. * @internal
  21. *
  22. * @covers \PhpCsFixer\Fixer\ClassNotation\ClassDefinitionFixer
  23. */
  24. final class ClassDefinitionFixerTest extends AbstractFixerTestCase
  25. {
  26. public function testConfigureDefaultToNull(): void
  27. {
  28. $defaultConfig = [
  29. 'multi_line_extends_each_single_line' => false,
  30. 'single_item_single_line' => false,
  31. 'single_line' => false,
  32. ];
  33. $fixer = new ClassDefinitionFixer();
  34. $fixer->configure($defaultConfig);
  35. static::assertConfigurationSame($defaultConfig, $fixer);
  36. $fixer->configure([]);
  37. static::assertConfigurationSame($defaultConfig, $fixer);
  38. }
  39. /**
  40. * @param string $expected PHP source code
  41. * @param string $input PHP source code
  42. * @param array<string, bool> $config
  43. *
  44. * @dataProvider provideAnonymousClassesCases
  45. *
  46. * @requires PHP 7.0
  47. */
  48. public function testFixingAnonymousClasses(string $expected, string $input, array $config = []): void
  49. {
  50. $this->fixer->configure($config);
  51. $this->doTest($expected, $input);
  52. }
  53. /**
  54. * @param string $expected PHP source code
  55. * @param string $input PHP source code
  56. *
  57. * @dataProvider provideClassesCases
  58. */
  59. public function testFixingClasses(string $expected, string $input): void
  60. {
  61. $this->fixer->configure([]);
  62. $this->doTest($expected, $input);
  63. }
  64. /**
  65. * @param string $expected PHP source code
  66. * @param string $input PHP source code
  67. * @param array<string, bool> $config
  68. *
  69. * @dataProvider provideClassesWithConfigCases
  70. */
  71. public function testFixingClassesWithConfig(string $expected, string $input, array $config): void
  72. {
  73. $this->fixer->configure($config);
  74. $this->doTest($expected, $input);
  75. }
  76. /**
  77. * @param string $expected PHP source code
  78. * @param string $input PHP source code
  79. *
  80. * @dataProvider provideInterfacesCases
  81. */
  82. public function testFixingInterfaces(string $expected, string $input): void
  83. {
  84. $this->fixer->configure([]);
  85. $this->doTest($expected, $input);
  86. }
  87. /**
  88. * @param string $expected PHP source code
  89. * @param string $input PHP source code
  90. *
  91. * @dataProvider provideTraitsCases
  92. */
  93. public function testFixingTraits(string $expected, string $input): void
  94. {
  95. $this->fixer->configure([]);
  96. $this->doTest($expected, $input);
  97. }
  98. public function testInvalidConfigurationKey(): void
  99. {
  100. $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class);
  101. $this->expectExceptionMessageMatches(
  102. '/^\[class_definition\] Invalid configuration: The option "a" does not exist\. Defined options are: "multi_line_extends_each_single_line", "single_item_single_line", "single_line"\.$/'
  103. );
  104. $fixer = new ClassDefinitionFixer();
  105. $fixer->configure(['a' => false]);
  106. }
  107. public function testInvalidConfigurationValueType(): void
  108. {
  109. $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class);
  110. $this->expectExceptionMessageMatches(
  111. '/^\[class_definition\] Invalid configuration: The option "single_line" with value "z" is expected to be of type "bool", but is of type "string"\.$/'
  112. );
  113. $fixer = new ClassDefinitionFixer();
  114. $fixer->configure(['single_line' => 'z']);
  115. }
  116. public function provideAnonymousClassesCases()
  117. {
  118. return [
  119. [
  120. '<?php $a = new class(0) extends SomeClass implements SomeInterface, D {};',
  121. "<?php \$a = new class(0) extends\nSomeClass\timplements SomeInterface, D {};",
  122. ],
  123. [
  124. '<?php $a = new class(1) extends SomeClass implements SomeInterface, D {};',
  125. "<?php \$a = new class(1) extends\nSomeClass\timplements SomeInterface, D {};",
  126. ['single_line' => true],
  127. ],
  128. [
  129. "<?php \$a = new class('1a') implements\nA\n{};",
  130. "<?php \$a = new class('1a') implements\nA{};",
  131. ],
  132. [
  133. "<?php \$a = new class('1a') implements A {};",
  134. "<?php \$a = new class('1a') implements\nA{};",
  135. ['single_item_single_line' => true],
  136. ],
  137. [
  138. '<?php $a = new class {};',
  139. '<?php $a = new class{};',
  140. ],
  141. [
  142. '<?php $a = new class {};',
  143. "<?php \$a = new class\n{};",
  144. ],
  145. [
  146. '<?php $a = new class() {};',
  147. "<?php \$a = new\n class ( ){};",
  148. ],
  149. [
  150. '<?php $a = new class(10, 1, /**/ 2) {};',
  151. '<?php $a = new class( 10, 1,/**/2 ){};',
  152. ],
  153. [
  154. '<?php $a = new class(2) {};',
  155. '<?php $a = new class(2){};',
  156. ],
  157. [
  158. '<?php $a = new class($this->prop) {};',
  159. '<?php $a = new class( $this->prop ){};',
  160. ],
  161. [
  162. '<?php $a = new class($this->prop, $v[3], 4) {};',
  163. '<?php $a = new class( $this->prop,$v[3], 4) {};',
  164. ],
  165. 'PSR-12 Extends/Implements Parenthesis on the next line.' => [
  166. '<?php
  167. $instance = new class extends \Foo implements
  168. \ArrayAccess,
  169. \Countable,
  170. \Serializable
  171. {};',
  172. '<?php
  173. $instance = new class extends \Foo implements
  174. \ArrayAccess,\Countable,\Serializable{};',
  175. ],
  176. 'PSR-12 Implements Parenthesis on the next line.' => [
  177. '<?php
  178. $instance = new class implements
  179. \ArrayAccess,
  180. \Countable,
  181. \Serializable
  182. {};',
  183. '<?php
  184. $instance = new class implements
  185. \ArrayAccess,\Countable,\Serializable{};',
  186. ],
  187. 'PSR-12 Extends Parenthesis on the next line.' => [
  188. '<?php
  189. $instance = new class extends
  190. ArrayAccess
  191. {};',
  192. '<?php
  193. $instance = new class
  194. extends
  195. ArrayAccess
  196. {};',
  197. ],
  198. [
  199. "<?php \$a = new #
  200. class #
  201. ( #
  202. '1a', #
  203. 1 #
  204. ) #
  205. implements#
  206. A, #
  207. B,
  208. C #
  209. {#
  210. #
  211. }#
  212. ;",
  213. "<?php \$a = new#
  214. class#
  215. (#
  216. '1a',#
  217. 1 #
  218. )#
  219. implements#
  220. A, #
  221. B,C#
  222. {#
  223. #
  224. }#
  225. ;",
  226. ],
  227. [
  228. "<?php \$a = new #
  229. class #
  230. ( #
  231. '1a', #
  232. 1 #
  233. ) #
  234. implements #
  235. A #
  236. {#
  237. #
  238. }#
  239. ;",
  240. "<?php \$a = new#
  241. class#
  242. (#
  243. '1a',#
  244. 1 #
  245. )#
  246. implements#
  247. A#
  248. {#
  249. #
  250. }#
  251. ;",
  252. ['single_item_single_line' => true],
  253. ],
  254. [
  255. '<?php $a = new class() #
  256. {};',
  257. '<?php $a = new class()#
  258. {};',
  259. ],
  260. ];
  261. }
  262. public function provideClassesCases()
  263. {
  264. return array_merge(
  265. $this->provideClassyCases('class'),
  266. $this->provideClassyExtendingCases('class'),
  267. $this->provideClassyImplementsCases()
  268. );
  269. }
  270. public function provideClassesWithConfigCases()
  271. {
  272. return [
  273. [
  274. "<?php class configA implements B, C\n{}",
  275. "<?php class configA implements\nB, C{}",
  276. ['single_line' => true],
  277. ],
  278. [
  279. "<?php class configA1 extends B\n{}",
  280. "<?php class configA1\n extends\nB{}",
  281. ['single_line' => true],
  282. ],
  283. [
  284. "<?php class configA1a extends B\n{}",
  285. "<?php class configA1a\n extends\nB{}",
  286. ['single_line' => false, 'single_item_single_line' => true],
  287. ],
  288. [
  289. "<?php class configA2 extends D implements B, C\n{}",
  290. "<?php class configA2 extends D implements\nB,\nC{}",
  291. ['single_line' => true],
  292. ],
  293. [
  294. "<?php class configA3 extends D implements B, C\n{}",
  295. "<?php class configA3\n extends\nD\n\t implements\nB,\nC{}",
  296. ['single_line' => true],
  297. ],
  298. [
  299. "<?php class configA4 extends D implements B, #\nC\n{}",
  300. "<?php class configA4\n extends\nD\n\t implements\nB,#\nC{}",
  301. ['single_line' => true],
  302. ],
  303. [
  304. "<?php class configA5 implements A\n{}",
  305. "<?php class configA5 implements\nA{}",
  306. ['single_line' => false, 'single_item_single_line' => true],
  307. ],
  308. [
  309. "<?php interface TestWithMultiExtendsMultiLine extends\n A,\nAb,\n C,\n D\n{}",
  310. "<?php interface TestWithMultiExtendsMultiLine extends A,\nAb,C,D\n{}",
  311. [
  312. 'single_line' => false,
  313. 'single_item_single_line' => false,
  314. 'multi_line_extends_each_single_line' => true,
  315. ],
  316. ],
  317. ];
  318. }
  319. public function provideInterfacesCases()
  320. {
  321. $cases = array_merge(
  322. $this->provideClassyCases('interface'),
  323. $this->provideClassyExtendingCases('interface')
  324. );
  325. $cases[] = [
  326. '<?php
  327. interface Test extends
  328. /*a*/ /*b*/TestInterface1 , \A\B\C , /* test */
  329. TestInterface2 , // test
  330. '.'
  331. // Note: PSR does not have a rule for multiple extends
  332. TestInterface3, /**/ TestInterface4 ,
  333. TestInterface5 , '.'
  334. /**/TestInterface65
  335. {}
  336. ',
  337. '<?php
  338. interface Test
  339. extends
  340. /*a*/ /*b*/TestInterface1 , \A\B\C , /* test */
  341. TestInterface2 , // test
  342. '.'
  343. // Note: PSR does not have a rule for multiple extends
  344. TestInterface3, /**/ TestInterface4 ,
  345. TestInterface5 , '.'
  346. /**/TestInterface65 {}
  347. ',
  348. ];
  349. return $cases;
  350. }
  351. public function provideTraitsCases()
  352. {
  353. return $this->provideClassyCases('trait');
  354. }
  355. /**
  356. * @param string $source PHP source code
  357. *
  358. * @dataProvider provideClassyDefinitionInfoCases
  359. */
  360. public function testClassyDefinitionInfo(string $source, array $expected): void
  361. {
  362. Tokens::clearCache();
  363. $tokens = Tokens::fromCode($source);
  364. $method = new \ReflectionMethod($this->fixer, 'getClassyDefinitionInfo');
  365. $method->setAccessible(true);
  366. $result = $method->invoke($this->fixer, $tokens, $expected['classy']);
  367. static::assertSame($expected, $result);
  368. }
  369. public function provideClassyDefinitionInfoCases()
  370. {
  371. return [
  372. [
  373. '<?php class A{}',
  374. [
  375. 'start' => 1,
  376. 'classy' => 1,
  377. 'open' => 4,
  378. 'extends' => false,
  379. 'implements' => false,
  380. 'anonymousClass' => false,
  381. ],
  382. ],
  383. [
  384. '<?php final class A{}',
  385. [
  386. 'start' => 1,
  387. 'classy' => 3,
  388. 'open' => 6,
  389. 'extends' => false,
  390. 'implements' => false,
  391. 'anonymousClass' => false,
  392. ],
  393. ],
  394. [
  395. '<?php abstract /**/ class A{}',
  396. [
  397. 'start' => 1,
  398. 'classy' => 5,
  399. 'open' => 8,
  400. 'extends' => false,
  401. 'implements' => false,
  402. 'anonymousClass' => false,
  403. ],
  404. ],
  405. [
  406. '<?php class A extends B {}',
  407. [
  408. 'start' => 1,
  409. 'classy' => 1,
  410. 'open' => 9,
  411. 'extends' => [
  412. 'start' => 5,
  413. 'numberOfExtends' => 1,
  414. 'multiLine' => false,
  415. ],
  416. 'implements' => false,
  417. 'anonymousClass' => false,
  418. ],
  419. ],
  420. [
  421. '<?php interface A extends B,C,D {}',
  422. [
  423. 'start' => 1,
  424. 'classy' => 1,
  425. 'open' => 13,
  426. 'extends' => [
  427. 'start' => 5,
  428. 'numberOfExtends' => 3,
  429. 'multiLine' => false,
  430. ],
  431. 'implements' => false,
  432. 'anonymousClass' => false,
  433. ],
  434. ],
  435. ];
  436. }
  437. /**
  438. * @param string $source PHP source code
  439. *
  440. * @dataProvider provideClassyImplementsInfoCases
  441. */
  442. public function testClassyInheritanceInfo(string $source, string $label, array $expected): void
  443. {
  444. $this->doTestClassyInheritanceInfo($source, $label, $expected);
  445. }
  446. /**
  447. * @param string $source PHP source code
  448. *
  449. * @requires PHP 7.0
  450. * @dataProvider provideClassyInheritanceInfo7Cases
  451. */
  452. public function testClassyInheritanceInfo7(string $source, string $label, array $expected): void
  453. {
  454. $this->doTestClassyInheritanceInfo($source, $label, $expected);
  455. }
  456. public function provideClassyImplementsInfoCases()
  457. {
  458. $tests = [
  459. '1' => [
  460. '<?php
  461. class X11 implements Z , T,R
  462. {
  463. }',
  464. 'numberOfImplements',
  465. ['start' => 5, 'numberOfImplements' => 3, 'multiLine' => false],
  466. ],
  467. '2' => [
  468. '<?php
  469. class X10 implements Z , T,R //
  470. {
  471. }',
  472. 'numberOfImplements',
  473. ['start' => 5, 'numberOfImplements' => 3, 'multiLine' => false],
  474. ],
  475. '3' => [
  476. '<?php class A implements B {}',
  477. 'numberOfImplements',
  478. ['start' => 5, 'numberOfImplements' => 1, 'multiLine' => false],
  479. ],
  480. '4' => [
  481. "<?php class A implements B,\n I{}",
  482. 'numberOfImplements',
  483. ['start' => 5, 'numberOfImplements' => 2, 'multiLine' => true],
  484. ],
  485. '5' => [
  486. "<?php class A implements Z\\C\\B,C,D {\n\n\n}",
  487. 'numberOfImplements',
  488. ['start' => 5, 'numberOfImplements' => 3, 'multiLine' => false],
  489. ],
  490. ];
  491. foreach ($tests as $index => $test) {
  492. yield $index => $test;
  493. }
  494. if (\PHP_VERSION_ID < 80000) {
  495. $multiLine = true;
  496. $code = '<?php
  497. namespace A {
  498. interface X {}
  499. }
  500. namespace {
  501. class B{}
  502. class A extends //
  503. B implements /* */ \A
  504. \C, Z{
  505. public function test()
  506. {
  507. echo 1;
  508. }
  509. }
  510. $a = new A();
  511. $a->test();
  512. }';
  513. } else {
  514. $multiLine = false;
  515. $code = '<?php
  516. namespace A {
  517. interface X {}
  518. }
  519. namespace {
  520. class B{}
  521. class A extends //
  522. B implements /* */ \A\C, Z{
  523. public function test()
  524. {
  525. echo 1;
  526. }
  527. }
  528. $a = new A();
  529. $a->test();
  530. }';
  531. }
  532. yield [
  533. $code,
  534. 'numberOfImplements',
  535. ['start' => 36, 'numberOfImplements' => 2, 'multiLine' => $multiLine],
  536. ];
  537. }
  538. public function provideClassyInheritanceInfo7Cases()
  539. {
  540. return [
  541. [
  542. "<?php \$a = new class(3) extends\nSomeClass\timplements SomeInterface, D {};",
  543. 'numberOfExtends',
  544. ['start' => 12, 'numberOfExtends' => 1, 'multiLine' => true],
  545. ],
  546. [
  547. "<?php \$a = new class(4) extends\nSomeClass\timplements SomeInterface, D\n\n{};",
  548. 'numberOfImplements',
  549. ['start' => 16, 'numberOfImplements' => 2, 'multiLine' => false],
  550. ],
  551. [
  552. "<?php \$a = new class(5) extends SomeClass\nimplements SomeInterface, D {};",
  553. 'numberOfExtends',
  554. ['start' => 12, 'numberOfExtends' => 1, 'multiLine' => true],
  555. ],
  556. ];
  557. }
  558. /**
  559. * @dataProvider providePHP7Cases
  560. * @requires PHP 7.0
  561. */
  562. public function testFixPHP7(string $expected, ?string $input = null): void
  563. {
  564. $this->fixer->configure([]);
  565. $this->doTest($expected, $input);
  566. }
  567. public function providePHP7Cases()
  568. {
  569. return [
  570. [
  571. '<?php
  572. $a = new class implements
  573. \RFb,
  574. \Fcc,
  575. \GFddZz
  576. {
  577. };',
  578. '<?php
  579. $a = new class implements
  580. \RFb,
  581. \Fcc, \GFddZz
  582. {
  583. };',
  584. ],
  585. [
  586. '<?php
  587. $a = new class implements
  588. \RFb,
  589. \Fcc,
  590. \GFddZz
  591. {
  592. }?>',
  593. '<?php
  594. $a = new class implements
  595. \RFb,
  596. \Fcc, \GFddZz
  597. {
  598. }?>',
  599. ],
  600. ];
  601. }
  602. /**
  603. * @dataProvider provideMessyWhitespacesCases
  604. */
  605. public function testMessyWhitespaces(string $expected, ?string $input = null): void
  606. {
  607. $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t", "\r\n"));
  608. $this->fixer->configure([]);
  609. $this->doTest($expected, $input);
  610. }
  611. public function provideMessyWhitespacesCases()
  612. {
  613. return [
  614. [
  615. "<?php\r\nclass Aaa implements\r\n\tBbb,\r\n\tCcc,\r\n\tDdd\r\n\t{\r\n\t}",
  616. "<?php\r\nclass Aaa implements\r\n\tBbb, Ccc,\r\n\tDdd\r\n\t{\r\n\t}",
  617. ],
  618. ];
  619. }
  620. private static function assertConfigurationSame(array $expected, ClassDefinitionFixer $fixer): void
  621. {
  622. $reflectionProperty = new \ReflectionProperty($fixer, 'configuration');
  623. $reflectionProperty->setAccessible(true);
  624. static::assertSame($expected, $reflectionProperty->getValue($fixer));
  625. }
  626. private function doTestClassyInheritanceInfo(string $source, string $label, array $expected): void
  627. {
  628. Tokens::clearCache();
  629. $tokens = Tokens::fromCode($source);
  630. static::assertTrue($tokens[$expected['start']]->isGivenKind([T_IMPLEMENTS, T_EXTENDS]), sprintf('Token must be "implements" or "extends", got "%s".', $tokens[$expected['start']]->getContent()));
  631. $method = new \ReflectionMethod($this->fixer, 'getClassyInheritanceInfo');
  632. $method->setAccessible(true);
  633. $result = $method->invoke($this->fixer, $tokens, $expected['start'], $label);
  634. static::assertSame($expected, $result);
  635. }
  636. private function provideClassyCases(string $classy)
  637. {
  638. return [
  639. [
  640. sprintf("<?php %s A\n{}", $classy),
  641. sprintf('<?php %s A {}', $classy),
  642. ],
  643. [
  644. sprintf("<?php %s B\n{}", $classy),
  645. sprintf('<?php %s B{}', $classy),
  646. ],
  647. [
  648. sprintf("<?php %s C\n{}", $classy),
  649. sprintf("<?php %s\n\tC{}", $classy),
  650. ],
  651. [
  652. sprintf("<?php %s D //\n{}", $classy),
  653. sprintf("<?php %s D//\n{}", $classy),
  654. ],
  655. [
  656. sprintf("<?php %s /**/ E //\n{}", $classy),
  657. sprintf("<?php %s/**/E//\n{}", $classy),
  658. ],
  659. [
  660. sprintf(
  661. "<?php
  662. %s A
  663. {}
  664. %s /**/ B //
  665. /**/\n{}",
  666. $classy,
  667. $classy
  668. ),
  669. sprintf(
  670. '<?php
  671. %s
  672. A
  673. {}
  674. %s/**/B //
  675. /**/ {}',
  676. $classy,
  677. $classy
  678. ),
  679. ],
  680. [
  681. sprintf(
  682. '<?php
  683. namespace {
  684. %s IndentedNameSpacedClass
  685. {
  686. }
  687. }',
  688. $classy
  689. ),
  690. sprintf(
  691. '<?php
  692. namespace {
  693. %s IndentedNameSpacedClass {
  694. }
  695. }',
  696. $classy
  697. ),
  698. ],
  699. ];
  700. }
  701. private function provideClassyExtendingCases(string $classy)
  702. {
  703. return [
  704. [
  705. sprintf("<?php %s AE0 extends B\n{}", $classy),
  706. sprintf('<?php %s AE0 extends B {}', $classy),
  707. ],
  708. [
  709. sprintf("<?php %s /**/ AE1 /**/ extends /**/ B /**/\n{}", $classy),
  710. sprintf('<?php %s/**/AE1/**/extends/**/B/**/{}', $classy),
  711. ],
  712. [
  713. sprintf("<?php %s /*%s*/ AE2 extends\nB\n{}", $classy, $classy),
  714. sprintf("<?php %s /*%s*/ AE2 extends\nB{}", $classy, $classy),
  715. ],
  716. [
  717. sprintf('<?php
  718. %s Test124 extends
  719. \Exception
  720. {}', $classy),
  721. sprintf('<?php
  722. %s
  723. Test124
  724. extends
  725. \Exception {}', $classy),
  726. ],
  727. ];
  728. }
  729. private function provideClassyImplementsCases()
  730. {
  731. return [
  732. [
  733. "<?php class E implements B\n{}",
  734. "<?php class E \nimplements B \t{}",
  735. ],
  736. [
  737. "<?php abstract class F extends B implements C\n{}",
  738. '<?php abstract class F extends B implements C {}',
  739. ],
  740. [
  741. "<?php abstract class G extends //
  742. B /* */ implements C\n{}",
  743. '<?php abstract class G extends //
  744. B/* */implements C{}',
  745. ],
  746. [
  747. '<?php
  748. class Aaa IMPLEMENTS
  749. \RFb,
  750. \Fcc,
  751. \GFddZz
  752. {
  753. }',
  754. '<?php
  755. class Aaa IMPLEMENTS
  756. \RFb,
  757. \Fcc, \GFddZz
  758. {
  759. }',
  760. ],
  761. [
  762. '<?php
  763. class //
  764. X //
  765. extends //
  766. Y //
  767. implements //
  768. Z, //
  769. U //
  770. {} //',
  771. '<?php
  772. class //
  773. X //
  774. extends //
  775. Y //
  776. implements //
  777. Z , //
  778. U //
  779. {} //',
  780. ],
  781. [
  782. '<?php
  783. class Aaa implements
  784. PhpCsFixer\Tests\Fixer,
  785. \RFb,
  786. \Fcc1,
  787. \GFdd
  788. {
  789. }',
  790. '<?php
  791. class Aaa implements
  792. PhpCsFixer\Tests\Fixer,\RFb,
  793. \Fcc1, \GFdd
  794. {
  795. }',
  796. ],
  797. [
  798. '<?php
  799. class /**/ Test123 EXtends /**/ \RuntimeException implements
  800. TestZ
  801. {
  802. }',
  803. '<?php
  804. class/**/Test123
  805. EXtends /**/ \RuntimeException implements
  806. TestZ
  807. {
  808. }',
  809. ],
  810. [
  811. '<?php
  812. class Aaa implements Ebb, \Ccc
  813. {
  814. }',
  815. '<?php
  816. class Aaa implements Ebb, \Ccc
  817. {
  818. }',
  819. ],
  820. [
  821. '<?php
  822. class X2 IMPLEMENTS
  823. Z, //
  824. U,
  825. D
  826. {
  827. }',
  828. '<?php
  829. class X2 IMPLEMENTS
  830. Z , //
  831. U, D
  832. {
  833. }',
  834. ],
  835. [
  836. '<?php
  837. class VeryLongClassNameWithLotsOfLetters extends AnotherVeryLongClassName implements
  838. VeryLongInterfaceNameThatIDontWantOnTheSameLine
  839. {
  840. }',
  841. '<?php
  842. class VeryLongClassNameWithLotsOfLetters extends AnotherVeryLongClassName implements
  843. VeryLongInterfaceNameThatIDontWantOnTheSameLine
  844. {
  845. }',
  846. ],
  847. [
  848. '<?php
  849. class /**/ Test125 //aaa
  850. extends /*
  851. */
  852. //
  853. \Exception //
  854. {}',
  855. '<?php
  856. class/**/Test125 //aaa
  857. extends /*
  858. */
  859. //
  860. \Exception //
  861. {}',
  862. ],
  863. [
  864. '<?php
  865. class Test extends TestInterface8 implements /*a*/ /*b*/
  866. TestInterface1, /* test */
  867. TestInterface2, // test
  868. '.'
  869. // test
  870. TestInterface3, /**/
  871. TestInterface4,
  872. TestInterface5, '.'
  873. /**/TestInterface6c
  874. {
  875. }',
  876. '<?php
  877. class Test
  878. extends
  879. TestInterface8
  880. implements /*a*/ /*b*/TestInterface1 , /* test */
  881. TestInterface2 , // test
  882. '.'
  883. // test
  884. TestInterface3, /**/ TestInterface4 ,
  885. TestInterface5 , '.'
  886. /**/TestInterface6c
  887. {
  888. }',
  889. ],
  890. ];
  891. }
  892. }