* Dariusz Rumiński * * This source file is subject to the MIT license that is bundled * with this source code in the file LICENSE. */ namespace PhpCsFixer\Tests\Fixer\Basic; use PhpCsFixer\Fixer\Basic\BracesFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; use PhpCsFixer\WhitespacesFixerConfig; /** * @author Dariusz Rumiński * * @internal * * @covers \PhpCsFixer\Fixer\Basic\BracesFixer */ final class BracesFixerTest extends AbstractFixerTestCase { private static $configurationOopPositionSameLine = ['position_after_functions_and_oop_constructs' => BracesFixer::LINE_SAME]; private static $configurationCtrlStructPositionNextLine = ['position_after_control_structures' => BracesFixer::LINE_NEXT]; private static $configurationAnonymousPositionNextLine = ['position_after_anonymous_constructs' => BracesFixer::LINE_NEXT]; public function testInvalidConfigurationClassyConstructs() { $this->expectException(\PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('#^\[braces\] Invalid configuration: The option "position_after_functions_and_oop_constructs" with value "neither" is invalid\. Accepted values are: "next", "same"\.$#'); $this->fixer->configure(['position_after_functions_and_oop_constructs' => 'neither']); } /** * @param string $expected * @param null|string $input * * @dataProvider provideFixControlContinuationBracesCases */ public function testFixControlContinuationBraces($expected, $input = null, array $configuration = []) { $this->fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixControlContinuationBracesCases() { return [ [ ' TestTest foo; echo $collection->items{1}->property; } ', ], [ ' TestTest TestTest foo; echo $collection->items{1}->property; } ', null, self::$configurationOopPositionSameLine, ], [ ' echo 1; echo 2; ', ], ]; } /** * @param string $expected * @param null|string $input * * @dataProvider provideFixMissingBracesAndIndentCases */ public function testFixMissingBracesAndIndent($expected, $input = null, array $configuration = []) { $this->fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixMissingBracesAndIndentCases() { return [ [ 'next());', ], [ 'getTest());', 'getTest());', ], [ 'getTest());', 'getTest());', ], [ 'c()}d"; }', ], [ '{$c->d}($e); $f->{$g} = $h; $i->{$j}[$k] = $l; $m = $n->{$o}; $p = array($q->{$r}, $s->{$t}); $u->{$v}->w = 1; }', ], [ '{"a{$c}d"}(); }', ], [ '{"a{$c->{\'foo-bar\'}()}d"}(); }', ], [ '{"a{$c->{\'foo-bar\'}()}d"}(); }', ], [ 'x', 'x', ], [ 'phoneNumbers->filter(function ($phone) { $a = 1; $b = 1; $c = 1; return ($phone->getType() === 1) ? true : false; }); } } }', 'phoneNumbers->filter(function ($phone) { $a = 1; $b = 1; $c = 1; return ($phone->getType() === 1) ? true : false; }); } }', ], [ 'next());', null, self::$configurationOopPositionSameLine, ], [ 'getTest());', 'getTest());', self::$configurationOopPositionSameLine, ], [ 'getTest());', 'getTest());', self::$configurationOopPositionSameLine, ], [ 'c()}d"; }', 'c()}d"; }', self::$configurationOopPositionSameLine, ], [ 'c()}d"; }', 'c()}d"; }', self::$configurationOopPositionSameLine + self::$configurationCtrlStructPositionNextLine, ], [ '{$c->d}($e); $f->{$g} = $h; $i->{$j}[$k] = $l; $m = $n->{$o}; $p = array($q->{$r}, $s->{$t}); $u->{$v}->w = 1; }', '{$c->d}($e); $f->{$g} = $h; $i->{$j}[$k] = $l; $m = $n->{$o}; $p = array($q->{$r}, $s->{$t}); $u->{$v}->w = 1; }', self::$configurationOopPositionSameLine, ], [ '{$c->d}($e); $f->{$g} = $h; $i->{$j}[$k] = $l; $m = $n->{$o}; $p = array($q->{$r}, $s->{$t}); $u->{$v}->w = 1; }', '{$c->d}($e); $f->{$g} = $h; $i->{$j}[$k] = $l; $m = $n->{$o}; $p = array($q->{$r}, $s->{$t}); $u->{$v}->w = 1; }', self::$configurationOopPositionSameLine + self::$configurationCtrlStructPositionNextLine, ], [ '{"a{$c}d"}(); }', '{"a{$c}d"}(); }', self::$configurationOopPositionSameLine, ], [ '{"a{$c->{\'foo-bar\'}()}d"}(); }', '{"a{$c->{\'foo-bar\'}()}d"}(); }', self::$configurationOopPositionSameLine, ], [ '{"a{$c->{\'foo-bar\'}()}d"}(); }', '{"a{$c->{\'foo-bar\'}()}d"}(); }', self::$configurationOopPositionSameLine, ], [ 'x', 'x', self::$configurationOopPositionSameLine, ], [ 'phoneNumbers->filter(function ($phone) { $a = 1; $b = 1; $c = 1; return ($phone->getType() === 1) ? true : false; }); } } }', 'phoneNumbers->filter(function ($phone) { $a = 1; $b = 1; $c = 1; return ($phone->getType() === 1) ? true : false; }); } }', self::$configurationOopPositionSameLine, ], [ 'phoneNumbers->filter(function ($phone) { $a = 1; $b = 1; $c = 1; return ($phone->getType() === 1) ? true : false; }); } } }', 'phoneNumbers->filter(function ($phone) { $a = 1; $b = 1; $c = 1; return ($phone->getType() === 1) ? true : false; }); } }', self::$configurationOopPositionSameLine + self::$configurationCtrlStructPositionNextLine, ], [ 'phoneNumbers->filter(function ($phone) { $a = 1; $b = 1; $c = 1; return ($phone->getType() === 1) ? true : false; }); } } }', 'phoneNumbers->filter(function ($phone) { $a = 1; $b = 1; $c = 1; return ($phone->getType() === 1) ? true : false; }); } }', self::$configurationOopPositionSameLine + self::$configurationCtrlStructPositionNextLine + self::$configurationAnonymousPositionNextLine, ], [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixClassyBracesCases() { return [ [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixAnonFunctionInShortArraySyntaxCases() { return [ [ ' function ($data) { return true; } ], [ "callback" => function ($data) { return true; }, ], ]; }', ' function ($data) { return true; } ], [ "callback" => function ($data) { return true; }, ], ]; }', ], [ ' function ($data) { return true; } ], [ "callback" => function ($data) { return true; }, ], ]; }', ' function ($data) { return true; } ], [ "callback" => function ($data) { return true; }, ], ]; }', self::$configurationOopPositionSameLine, ], [ ' function ($data) { return true; } ], [ "callback" => function ($data) { return true; }, ], ]; }', ' function ($data) { return true; } ], [ "callback" => function ($data) { return true; }, ], ]; }', self::$configurationOopPositionSameLine + self::$configurationAnonymousPositionNextLine, ], ]; } /** * @param string $expected * @param null|string $input * * @dataProvider provideFixCommentBeforeBraceCases */ public function testFixCommentBeforeBrace($expected, $input = null, array $configuration = []) { $this->fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixCommentBeforeBraceCases() { return [ [ 'guess($class, $property, function (Constraint $constraint) use ($guesser) { return $guesser->guessRequiredForConstraint($constraint); // Fallback to false... // ... due to sth... }, false); ', ], [ '', ], [ '', ], ]; } /** * @param string $expected * @param null|string $input * * @dataProvider provideFixCommentBeforeBrace70Cases * @requires PHP 7.0 */ public function testFixCommentBeforeBrace70($expected, $input = null, array $configuration = []) { $this->fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixCommentBeforeBrace70Cases() { return [ [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixWhitespaceBeforeBraceCases() { return [ [ 'getFile()) { }', 'getFile()) { }', ], [ 'getFile()) { }', 'getFile()) { }', self::$configurationOopPositionSameLine, ], [ 'getFile()) { }', 'getFile()) { }', self::$configurationAnonymousPositionNextLine, ], [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixFunctionsCases() { return [ [ 'bar(), function ($o) { return $o->isBaz(); }); }, $collection));', 'bar(), function ($o) { return $o->isBaz(); }); }, $collection));', ], [ 'fixers, function &($a, $b) use ($selfName) { return 1; });', ], [ 'fixers, function &($a, $b) use ($selfName) { return 1; } );', ], [ 'bar(), function ($o) { return $o->isBaz(); }); }, $collection));', 'bar(), function ($o) { return $o->isBaz(); }); }, $collection));', self::$configurationOopPositionSameLine, ], [ 'bar(), function ($o) { return $o->isBaz(); }); }, $collection));', 'bar(), function ($o) { return $o->isBaz(); }); }, $collection));', self::$configurationOopPositionSameLine + self::$configurationAnonymousPositionNextLine, ], [ 'fixers, function &($a, $b) use ($selfName) { return 1; });', null, self::$configurationOopPositionSameLine, ], [ 'fixers, function &($a, $b) use ($selfName) { return 1; } );', null, self::$configurationOopPositionSameLine, ], [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixMultiLineStructuresCases() { return [ [ ' $fooBarBazBuzz ) { }', ' $fooBarBazBuzz ) { }', self::$configurationCtrlStructPositionNextLine, ], [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFixSpaceAroundTokenCases() { return [ [ 'tesT ($test)) { }', 'tesT ($test)) { }', ], [ 'tesT ($test)) { }', 'tesT ($test)) { }', self::$configurationOopPositionSameLine, ], [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFinallyCases() { return [ [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFunctionImportCases() { return [ [ 'fixer->configure($configuration); $this->doTest($expected, $input); } public function provideFix70Cases() { return [ [ ' true], ], [ ' true], ], [ ' true], ], [ ' true], ], ]; } /** * @param string $expected * @param null|string $input * * @dataProvider providePreserveLineAfterControlBraceCases */ public function testPreserveLineAfterControlBrace($expected, $input = null, array $configuration = []) { $this->fixer->configure($configuration); $this->doTest($expected, $input); } public function providePreserveLineAfterControlBraceCases() { return [ [ 'fixer->configure([ 'allow_single_line_closure' => true, ]); $this->doTest($expected, $input); } public function provideFixWithAllowOnelineLambdaCases() { return [ [ 'doTest($expected, $input); } public function provideDoWhileLoopInsideAnIfWithoutBracketsCases() { return [ [ 'fixer->configure($configuration); $this->fixer->setWhitespacesConfig(new WhitespacesFixerConfig("\t", "\r\n")); $this->doTest($expected, $input); } public function provideMessyWhitespacesCases() { return [ [ 'doTest($expected, $input); } public function provideNowdocInTemplatesCases() { return [ [ <<<'EOT' doTest($expected, $input); $this->doTest(str_replace('//', '#', $expected), null === $input ? null : str_replace('//', '#', $input)); } public function provideFixCommentsCases() { return [ [ 'doTest( 'fixer->setWhitespacesConfig($config); } $this->doTest($expected, $input); } public function provideIndentCommentCases() { yield [ "doTest($expected, $input); } public function provideFixAlternativeSyntaxCases() { yield [ ' X ', ]; yield [ ' X ', ]; yield [ ' X ', ]; yield [ ' X ', ]; yield [ ' X ', ]; yield [ ' X ,', ]; yield [ ' ', ]; } /** * @requires PHP 8.0 * * @param string $input * @param string $expected * * @dataProvider provideFix80Cases */ public function testFix80($expected, $input) { $this->doTest($expected, $input); } public function provideFix80Cases() { yield 'match' => [ ' "Same for 1 and 2", };', ' "Same for 1 and 2", };', ]; } }