* 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\Operator; use PhpCsFixer\ConfigurationException\InvalidFixerConfigurationException; use PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer; use PhpCsFixer\Tests\Test\AbstractFixerTestCase; /** * @author Dariusz Rumiński * @author Gregor Harlan * @author Carlos Cirello * * @internal * * @covers \PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer * * @extends AbstractFixerTestCase<\PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer> * * @phpstan-import-type _AutogeneratedInputConfiguration from \PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer */ final class BinaryOperatorSpacesFixerTest extends AbstractFixerTestCase { /** * @param _AutogeneratedInputConfiguration $configuration * * @dataProvider provideWithTabsCases */ public function testWithTabs(string $expected, ?string $input = null, array $configuration = []): void { $this->fixer->configure($configuration); $this->doTest($expected, $input); } public static function provideWithTabsCases(): iterable { yield [ " ['=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ " ['=' => BinaryOperatorSpacesFixer::ALIGN]], ]; } /** * @param _AutogeneratedInputConfiguration $configuration * * @dataProvider provideConfiguredCases */ public function testConfigured(string $expected, ?string $input = null, array $configuration = []): void { $this->fixer->configure($configuration); $this->doTest($expected, $input); } public static function provideConfiguredCases(): iterable { yield [ 'a = $this->b = 1 ;', 'a = $this->b = 1 ;', ['operators' => ['=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ 'newName = $this->path = $this->randomName = $this->remoteFile = $this->tmpContent = null;', 'newName = $this->path = $this->randomName = $this->remoteFile = $this->tmpContent = null;', ['operators' => ['=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' ['=' => BinaryOperatorSpacesFixer::SINGLE_SPACE]], ]; yield [ ' ['=' => BinaryOperatorSpacesFixer::AT_LEAST_SINGLE_SPACE]], ]; yield [ ' 2]; foreach ([ 1 => 2, 2 => 3, ] as $k => $v) { $var[] = [$i => $bar]; }', '2]; foreach ([ 1=> 2, 2 =>3, ] as $k => $v) { $var[] = [$i => $bar]; }', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' 2, 4 => 5, 5 => 2, 6 => 5, 7 => 8, 9 => 10, 11 => 1222, );', '2, 4=>5, 5=>2, 6 => 5, 7=>8, 9=>10, 11=>1222, );', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' 2, 4 => 5);', '2, 4 => 5);', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' 2, 4 => 5 && $b, 5 => 5 && $b, 6 => 5 && $b, 7 => 5 && $b);', ' 2, 4 => 5&&$b, 5 => 5 && $b, 6 => 5&& $b, 7 => 5 &&$b);', ['operators' => ['&&' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' "foo"]; [2 => "foo"]; [3 => "foo"]; ', ' "foo"]; [2 =>"foo"]; [3=>"foo"]; ', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE]], ]; yield [ ' "foo"]; [2 => "foo"]; [3 => "foo"]; ', ' "foo"]; [2 =>"foo"]; [3=>"foo"]; ', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' ['+=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE]], ]; yield [ ' ['+=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' ['+=' => BinaryOperatorSpacesFixer::ALIGN]], ]; yield [ ' ['!==' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE]], ]; yield [ ' ['!==' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' [ 'and' => BinaryOperatorSpacesFixer::SINGLE_SPACE, '*=' => BinaryOperatorSpacesFixer::ALIGN, 'or' => null, ], ], ]; yield [ ' ['!==' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' 2, 2 => 3, ];', '2, 2 => 3, ];', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' "foo", 2 => "foo"]; ', ' "foo", 2 => "foo"]; ', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' "foo"]; $i += 1; ', ' "foo"]; $i+= 1; ', ['operators' => ['+=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ '3, 4 => 3, 5=>2, );', null, ['default' => null], ]; yield [ ' $ø0ø0ø, $ø4 => $ø1ø1ø, $ø5 => $ø2ø2ø, ); $a = 12 + 1; $a = 13 + 41; ', '$ø0ø0ø, $ø4 => $ø1ø1ø, $ø5=>$ø2ø2ø, ); $a = 12 + 1; $a = 13+41; ', ['default' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL], ]; yield 'do not align with nor touch strings' => [ ' ['=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE]], ]; yield 'do not align with declare' => [ ' ['=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield 'do not align with multibyte character in array key' => [ ' "oe", ]; ', null, ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE]], ]; yield 'align correctly with multibyte characters in array key' => [ ' "øasø", "ytė\b" => "øisø", "iūtė\b" => "øiusø", "utė\b" => array( "aitė\b" => "øas", "ytė\b" => "øis", "iūtė\b" => $øøius, "utė\b" => "us", ), );', ' "øasø", "ytė\b" => "øisø", "iūtė\b" => "øiusø", "utė\b" => array( "aitė\b" => "øas", "ytė\b" => "øis", "iūtė\b" => $øøius, "utė\b" => "us", ), );', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE]], ]; yield [ ' BinaryOperatorSpacesFixer::NO_SPACE, 'operators' => ['=' => BinaryOperatorSpacesFixer::SINGLE_SPACE], ], ]; yield [ ' null, 'operators' => [ '=' => BinaryOperatorSpacesFixer::SINGLE_SPACE, '|' => BinaryOperatorSpacesFixer::NO_SPACE, ], ], ]; yield [ ' ['|' => BinaryOperatorSpacesFixer::NO_SPACE], ], ]; yield [ ' 1; echo 1 <=> 2; echo 2 <=> 1; echo 2 <=> 1; $a = $a ?? $b; $a = $ab ?? $b; $a = $ac ?? $b; $a = $ad ?? $b; $a = $ae ?? $b; ', '1; echo 1 <=>2; echo 2<=> 1; echo 2 <=> 1; $a = $a ?? $b; $a = $ab ?? $b; $a = $ac ?? $b; $a = $ad ?? $b; $a = $ae?? $b; ', ['operators' => ['=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE, '??' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield 'align array destructuring' => [ ' ['=' => BinaryOperatorSpacesFixer::ALIGN]], ]; yield 'align array destructuring with assignments' => [ ' $a, "b" => $b, "c" => $c ] = $array; ', '$a, "b" => $b, "c" => $c ] = $array; ', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield 'multiple exceptions catch, default config' => [ ' [ ' ['|' => BinaryOperatorSpacesFixer::NO_SPACE]], ]; yield [ ' null; $b = fn() => null; ', ' null; $b = fn() => null; ', ['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE_MINIMAL]], ]; yield [ ' ['??=' => BinaryOperatorSpacesFixer::ALIGN_SINGLE_SPACE]], ]; } /** * @dataProvider provideFixDefaultsCases */ public function testFixDefaults(string $expected, ?string $input = null): void { $this->doTest($expected, $input); } /** * @return iterable */ public static function provideFixDefaultsCases(): iterable { yield [ ' "c", );', '"c", );', ]; yield [ ' "c", );', '"c", );', ]; yield [ ' "c", );', ' "c", );', ]; yield [ '-.html">Test']; yield 'reference in functions declarations' => [ ' $x + 1; ', ]; } /** * @dataProvider provideUnalignEqualsCases */ public function testUnalignEquals(string $expected, ?string $input = null): void { $this->doTest($expected, $input); } /** * @return iterable */ public static function provideUnalignEqualsCases(): iterable { yield [ '', '', ]; yield [ 'expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches( '/^\[binary_operator_spaces\] Invalid configuration: The option "foo" does not exist\. Defined options are: "default", "operators"\.$/' ); $this->fixer->configure(['foo' => true]); } public function testWrongConfigTypeForOperators(): void { $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches( '/^\[binary_operator_spaces\] Invalid configuration: The option "operators" with value true is expected to be of type "array", but is of type "(bool|boolean)"\.$/' ); $this->fixer->configure(['operators' => true]); // @phpstan-ignore-line } public function testWrongConfigTypeForOperatorsKey(): void { $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[binary_operator_spaces\] Invalid configuration: Unexpected "operators" key, expected any of ".*", got "integer#123"\.$/'); $this->fixer->configure(['operators' => [123 => 1]]); // @phpstan-ignore-line } public function testWrongConfigTypeForOperatorsKeyValue(): void { $this->expectException(InvalidFixerConfigurationException::class); $this->expectExceptionMessageMatches('/^\[binary_operator_spaces\] Invalid configuration: Unexpected value for operator "\+", expected any of ".*", got "string#abc"\.$/'); $this->fixer->configure(['operators' => ['+' => 'abc']]); } /** * @dataProvider provideUnalignDoubleArrowCases */ public function testUnalignDoubleArrow(string $expected, ?string $input = null): void { $this->doTest($expected, $input); } /** * @return iterable */ public static function provideUnalignDoubleArrowCases(): iterable { yield [ ' "Bar", "main" => array( [ "baz" => "Test", "bazaa" => $a->{"Test"}, "bazaa" => $a["Test"], "bazaaaa" => b("Test"), ] ), "bar" => array(), ];', ' "Bar", "main" => array( [ "baz" => "Test", "bazaa" => $a->{"Test"}, "bazaa" => $a["Test"], "bazaaaa" => b("Test"), ] ), "bar" => array(), ];', ]; yield [ ' "Bar", "main" => [array("baz" => "Test")], "bar" => array(), ]; $data = array( "foo" => "Bar", "main" => array("baz" => "Test"), "bar" => array(), ); $var = []; foreach ($foo as $i => $bar) { $var[] = /* Comment */ [$i => $bar]; }', ' "Bar", "main" => [array("baz" => "Test")], "bar" => array(), ]; $data = array( "foo" => "Bar", "main" => array("baz" => "Test"), "bar" => array(), ); $var = []; foreach ($foo as $i => $bar) { $var[] = /* Comment */ [$i => $bar]; }', ]; yield [ ' "Bar", "main" => [array("baz" => "Test")], "bar" => array(), ];', ' "Bar", "main" => [array("baz" => "Test")], "bar" => array(), ];', ]; yield [ ' "Bar", "main" => array("baz" => "Test"), "bar" => array(), );', ' "Bar", "main" => array("baz" => "Test"), "bar" => array(), );', ]; yield [ ' "Bar", "main" => array(array("baz" => "Test")), "bar" => array(), );', ' "Bar", "main" => array(array("baz" => "Test")), "bar" => array(), );', ]; yield [ ' $bar) { $var[] = /* Comment */ [$i => $bar]; }', ' $bar) { $var[] = /* Comment */ [$i => $bar]; }', ]; yield [ ' $bar) { $var[] = [$i => $bar]; }', ]; yield [ ' 2] as $k => $v) { $var[] = [$i => $bar]; }', ]; yield [ ' $v){ $var[] = [$i => $bar]; }', ]; yield [ ' $bar, $iaaa => $bar, ]; }', ' $bar, $iaaa => $bar, ]; }', ]; yield [ ' "Bar", "main" => [["baz" => "Test", "bar" => "Test2"]], "bar" => [], ];', ' "Bar", "main" => [["baz" => "Test", "bar" => "Test2"]], "bar" => [], ];', ]; yield [ ' 1, 10 /*Comment*/ => [ 1 => 2, 22 => 3, ], 100 => [ 1 => 2, 22 => 3, ] ];', ' 1, 10 /*Comment*/ => [ 1 => 2, 22 => 3, ], 100 => [ 1 => 2, 22 => 3, ] ];', ]; yield [ ' 1, 10 => array( 1 => 2, 22 => 3, ), 100 => array( 1 => 2, 22 => 3, ) );', ' 1, 10 => array( 1 => 2, 22 => 3, ), 100 => array( 1 => 2, 22 => 3, ) );', ]; yield [ ' 1, $bbbb => \' $cccccccc = 3; \', );', ' 1, $bbbb => \' $cccccccc = 3; \', );', ]; yield [ ' 1, $bbbb => \' $cccccccc = 3; \', ];', ' 1, $bbbb => \' $cccccccc = 3; \', ];', ]; yield [ ' $v){ $arr = array($k => 1, $a => 1, $bbbb => \' $cccccccc = 3; \', ); }', ' $v){ $arr = array($k => 1, $a => 1, $bbbb => \' $cccccccc = 3; \', ); }', ]; yield [ ' 11, 20 => 22, 30 => 33, 40 => 44, );', ' 11, 20 => 22, 30=>33, 40 => 44, );', ]; yield [ ' "", "\t" => "", "\n" => "", "\r" => "", "\0" => "", "\x0B" => "", );', ' "", "\t" => "", "\n" => "", "\r" => "", "\0" => "", "\x0B" => "", );', ]; yield [ 'grabAttribsBeforeToken( $tokens, $index, $tokenAttribsMap, array( "abstract" => null, "final" => null, "visibility" => new Token(array(T_PUBLIC, "public")), "static" => null, ) );', 'grabAttribsBeforeToken( $tokens, $index, $tokenAttribsMap, array( "abstract" => null, "final" => null, "visibility" => new Token(array(T_PUBLIC, "public")), "static" => null, ) );', ]; yield [ ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_0 => array("symbol" => "III", "description" => "invalid file syntax, file ignored"), );', ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_0 => array("symbol" => "III", "description" => "invalid file syntax, file ignored"), );', ]; yield [ ' b(array( 1 => 2, 5 => [ 6 => 7, 8 => 9, ], 3 => 4, 10 => 11, )), );', ' b(array( 1 => 2, 5 => [ 6 => 7, 8 => 9, ], 3 => 4, 10 => 11, )), );', ]; yield [ 'aaa(array(1 => 2))->bbb("a", "b"); ', ]; yield [ ' 2; }', ]; } /** * @dataProvider provideFixAlignEqualsCases */ public function testFixAlignEquals(string $expected, ?string $input = null): void { $this->fixer->configure(['operators' => ['=' => BinaryOperatorSpacesFixer::ALIGN]]); $this->doTest($expected, $input); } /** * @return iterable */ public static function provideFixAlignEqualsCases(): iterable { yield [ 'setDefaults( [ "choices" => function (Options $options) { $choices = TaskService::getFormMapperObjectList(); $element = null; $elementId = null; if (isset($options["task"]) && $options["task"]->getElement() === 42) { $element = $options["task"]->getElement(); $elementId = $options["task"]->getElementId(); } elseif (isset($options["elementId"], $options["element"]) && $options["element"] === 42) { $element = $options["element"]; $elementId = $options["elementId"]; }; }, ] ); } } ', 'setDefaults( [ "choices" => function (Options $options) { $choices = TaskService::getFormMapperObjectList(); $element = null; $elementId = null; if (isset($options["task"]) && $options["task"]->getElement() === 42) { $element = $options["task"]->getElement(); $elementId = $options["task"]->getElementId(); } elseif (isset($options["elementId"], $options["element"]) && $options["element"] === 42) { $element = $options["element"]; $elementId = $options["elementId"]; }; }, ] ); } } ', ]; yield [ ' $x + 3; $f = 123; ', ]; yield [ ' 100) { $_data = \'100+\'; } elseif (($c = count($array)) > 0) { $_data = \'0+\'; } ', ]; yield [ ' 100) { $closure = fn ($x = 1) => $x + 3; } elseif (($c = count($array)) > 0) { $closure = fn ($x = 1) => $x ** 3; } ', ]; yield [ 'getContainerSuppliers()->map(fn (ContainerSupplier $containerSupplier) => $containerSupplier->getSupplier()->getTitle()); $suppliersClassifications = $container->getContainerSuppliers()->map(fn (ContainerSupplier $containerSupplier) => $containerSupplier->getSupplier()->getClassification()); ', 'getContainerSuppliers()->map(fn (ContainerSupplier $containerSupplier) => $containerSupplier->getSupplier()->getTitle()); $suppliersClassifications = $container->getContainerSuppliers()->map(fn (ContainerSupplier $containerSupplier) => $containerSupplier->getSupplier()->getClassification()); ', ]; yield [ ' 5, $c => 9,]; $ab = [$bc = 1]; $someOtherArray = [$bcd = 1]; $a = [$b]; $ab = [$bc]; $abc = [$bcd]; ', ' 5, $c => 9,]; $ab = [$bc = 1]; $someOtherArray = [$bcd = 1]; $a = [$b]; $ab = [$bc]; $abc = [$bcd]; ', ]; yield [ 'query = $this->db->prepare(static function ($db) { $sql = "INSERT INTO {$db->protectIdentifiers($db->DBPrefix)} (" . $db->protectIdentifiers("name") . ", " . $db->protectIdentifiers("email") . ", " . $db->protectIdentifiers("country"); }); $classSet = Closure::bind(function ($key, $value) { $this->{$key} = $value; }, $classObj, $className); ', ]; yield [ 'setOverrides(["first" => "Bobby"], $persist = false); $bobbyUser = $fabricator->make(); $bobbyUser = $fabricator->make(); ', ]; yield [ 'setOverrides( ["first" => "Bobby"], $persist = false); $fabricator->setOverrides(["first" => "Bobby"], $persist = false ); ', ]; yield [ 'setTimezone("UTC") : $date->setTimezone("Europe/London") ); ', ]; } /** * @dataProvider provideFixAlignDoubleArrowCases */ public function testFixAlignDoubleArrow(string $expected, ?string $input = null): void { $this->fixer->configure(['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN]]); $this->doTest($expected, $input); } /** * @return iterable */ public static function provideFixAlignDoubleArrowCases(): iterable { yield [ ' function ($param1, $param2) { return; } );', ]; yield [ ' "OK", "html" => 1, /**/array( "foo" => "bar", "foofoo" => array( "a" => 1, "b" => 2 ) ),) );', ' "OK", "html" => 1, /**/array( "foo" => "bar", "foofoo" => array( "a" => 1, "b" => 2 ) ),) );', ]; yield [ ' "OK", "html" => renderView("views/my_view.html.twig", array( "foo" => "bar", "foofoo" => 43, )), ]);', ' "OK", "html" => renderView("views/my_view.html.twig", array( "foo" => "bar", "foofoo" => 43, )), ]);', ]; yield [ ' "OK", "html" => renderView("views/my_view.html.twig", [ "foo" => "bar", "foofoo" => 42, ]), "baz" => "OK", ]);', ' "OK", "html" => renderView("views/my_view.html.twig", [ "foo" => "bar", "foofoo" => 42, ]), "baz" => "OK", ]);', ]; yield [ ' "Bar", "main" => array( [ "baz" => "Test", "bazaa" => $a->{"Test"}, "bazaa" => $a["Test"], "bazaaaa" => b("Test"), ] ), "bar" => array(), ];', ' "Bar", "main" => array( [ "baz" => "Test", "bazaa" => $a->{"Test"}, "bazaa" => $a["Test"], "bazaaaa" => b("Test"), ] ), "bar" => array(), ];', ]; yield [ ' "Bar", "main" => [array("baz" => "Test")], "bar" => array(), ]; $data = array( "foo" => "Bar", "main" => array("baz" => "Test"), "bar" => array(), ); $var = []; foreach ($foo as $i => $bar) { $var[] = /* Comment */ [$i => $bar]; }', ]; yield [ ' "Bar", "main" => [array("baz" => "Test")], "bar" => array(), ];', ]; yield [ ' "Bar", "main" => array("baz" => "Test"), "bar" => array(), );', ]; yield [ ' "Bar", "main" => array(array("baz" => "Test")), "bar" => array(), );', ]; yield [ ' $bar) { $var[] = /* Comment */ [$i => $bar]; }', ]; yield [ ' $bar) { $var[] = [$i => $bar]; }', ]; yield [ ' 2] as $k => $v) { $var[] = [$i => $bar]; }', ]; yield [ ' $v){ $var[] = [$i => $bar]; }', ]; yield [ ' $bar, $iaaa => $bar, ]; }', ]; yield [ ' "Bar", "main" => [["baz" => "Test", "bar" => "Test2"]], "bar" => [], ];', ]; yield [ ' "Bar", "main" => ["baz" => "Test"], "bar" => [], ];', ]; yield [ ' 1, 10 /*Comment*/ => [ 1 => 2, 22 => 3, ], 100 => [ 1 => 2, 22 => 3, ] ];', ' 1, 10 /*Comment*/ => [ 1 => 2, 22 => 3, ], 100 => [ 1 => 2, 22 => 3, ] ];', ]; yield [ ' 1, 10 => array( 1 => 2, 22 => 3, ), 100 => array( 1 => 2, 22 => 3, ) );', ]; yield [ ' 1, $bbbb => \' $cccccccc2 = 3; \', );', ' 1, $bbbb => \' $cccccccc2 = 3; \', );', ]; yield [ ' 1, $bbbb => \' $cccccccc3 = 3; \', ];', ' 1, $bbbb => \' $cccccccc3 = 3; \', ];', ]; yield [ ' $v){ $arr = array($k => 1, $a => 1, $bbbb => \' $cccccccc4 = 3; \', ); }', ]; yield [ ' 11, 20 => 22, 30 => 33, 40 => 44, );', ' 11, 20 => 22, 30=>33, 40 => 44, );', ]; yield [ ' "", "\t" => "", "\n" => "", "\r" => "", "\0" => "", "\x0B" => "", );', ' "", "\t" => "", "\n" => "", "\r" => "", "\0" => "", "\x0B" => "", );', ]; yield [ 'grabAttribsBeforeToken( $tokens, $index, $tokenAttribsMap, array( "abstract" => null, "final" => null, "visibility" => new Token(array(T_PUBLIC, "public")), "static" => null, ) );', 'grabAttribsBeforeToken( $tokens, $index, $tokenAttribsMap, array( "abstract" => null, "final" => null, "visibility" => new Token(array(T_PUBLIC, "public")), "static" => null, ) );', ]; yield [ ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_1 => array("symbol" => "III", "description" => "invalid file syntax, file ignored"), );', ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_1 => array("symbol" => "III", "description" => "invalid file syntax, file ignored"), );', ]; yield [ ' b(array( 1 => 2, 5 => [ 6 => 7, 8 => 9, ], 3 => 4, 10 => 11, )), );', ' b(array( 1 => 2, 5 => [ 6 => 7, 8 => 9, ], 3 => 4, 10 => 11, )), );', ]; yield [ 'aaa(array(1 => 2))->bbb("a", "b"); ', ]; yield [ ' "as", "ytė\b" => "is", "iūtė\b" => "ius", "utė\b" => "us", );', ' "as", "ytė\b" => "is", "iūtė\b" => "ius", "utė\b" => "us", );', ]; yield [ 'add(\'foo\', null, [\'required\' => false]) ->add(\'dummy_field\', null, [\'required\' => false]) ; ', ]; yield [ 'add(\'foo\', null, array(\'required\' => false)) ->add(\'dummy_field\', null, array(\'required\' => false)) ; ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy(["server1" => $object], ["addedAt" => "DESC"], 5); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy(["server2" => $object], ["checkedAt" => "desc"], 50); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy(array("server1" => $object), array("addedAt" => "DESC"), 5); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy(array("server2" => $object), array("checkedAt" => "desc"), 50); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy($foo[123]); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy($foo[123]); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy([1, 2, 3]); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy([1, 2, 3]); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy((1 + 2)); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy((1 + 2)); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy(array(1, 2)); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy(array(1, 2)); ', ]; yield [ ' "foo", "foo" => $bar[123], "a" => foo(), "b" => 1, ]; ', ' "foo", "foo" => $bar[123], "a" => foo(), "b" => 1, ]; ', ]; yield [ ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_2 => array("symbol123" => "III", "description" => "invalid file syntax, file ignored"), );', ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_2 => array("symbol123" => "III", "description" => "invalid file syntax, file ignored"), );', ]; yield [ ' array((1 + 11)=> "?", "description" => "unknown"), self::STATUS_INVALID_3 => array((2 + 3)=> "III", "description" => "invalid file syntax, file ignored"), );', ' array((1+11)=> "?", "description" => "unknown"), self::STATUS_INVALID_3 => array((2+3)=> "III", "description" => "invalid file syntax, file ignored"), );', ]; yield [ ' ["symbol" => "?", "description" => "unknown"], self::STATUS_INVALID_4 => ["symbol123" => "III", "description" => "invalid file syntax, file ignored"], ];', ' ["symbol" => "?", "description" => "unknown"], self::STATUS_INVALID_4 => ["symbol123" => "III", "description" => "invalid file syntax, file ignored"], ];', ]; yield [ ' [(1 + 11)=> "?", "description" => "unknown"], self::STATUS_INVALID_7 => [(2 + 3)=> "III", "description" => "invalid file syntax, file ignored"], ];', ' [(1+11)=> "?", "description" => "unknown"], self::STATUS_INVALID_7 => [(2+3)=> "III", "description" => "invalid file syntax, file ignored"], ];', ]; yield [ ' function() { foreach([$a => 2] as $b) { $bv = [ $b => 2, $cc => 3, ]; }}, 2 => 3]; ', ' function() { foreach([$a => 2] as $b) { $bv = [ $b => 2, $cc => 3, ]; }}, 2 => 3]; ', ]; yield [ ' fn () => false, "is" => fn () => false, "an" => fn () => false, "example" => fn () => false, "array" => fn () => false, ]; } ', ' fn () => false, "is" => fn () => false, "an" => fn () => false, "example" => fn () => false, "array" => fn () => false, ]; } ', ]; yield [ 'map(fn ($arg) => []) ->keyBy(fn ($arg) => []); ', ]; yield [ 'save([ "bar" => "baz", "barbarbar" => "baz", ])) { // Do the work } ', 'save([ "bar" => "baz", "barbarbar" => "baz", ])) { // Do the work } ', ]; yield [ 'test1(fn () => $this->test2($a)); foreach ($result as $k => $v) { } $result = $this->test1(fn () => $this->test2($a, $b)); foreach ($result as $k => $v) { } } } ', ]; yield [ ' 123, "longkey" => "test", "baz" => fn () => "value", ]; ', ' 123, "longkey" => "test", "baz" => fn () => "value", ]; ', ]; yield [ 'query = $this->db->prepare(static fn ($db) => $db->table("user")->insert([ "name" => "a", "email" => "b@example.com", "country" => "JP", ])); foreach ($data as $name => $array) { foreach ($array as $field => $value) { yield $type => $case; } } } ', 'query = $this->db->prepare(static fn ($db) => $db->table("user")->insert([ "name" => "a", "email" => "b@example.com", "country" => "JP", ])); foreach ($data as $name => $array) { foreach ($array as $field => $value) { yield $type => $case; } } } ', ]; yield [ ' [ "expected" => null, "ourCustomer" => null, ]; yield "no underlying user" => [ "expected" => null, "ourCustomer" => Customer::seed(), ]; } ', ]; } /** * @dataProvider provideFixAlignScopedDoubleArrowCases */ public function testFixAlignScopedDoubleArrow(string $expected, ?string $input = null): void { $this->fixer->configure(['operators' => ['=>' => BinaryOperatorSpacesFixer::ALIGN_BY_SCOPE]]); $this->doTest($expected, $input); } /** * @return iterable */ public static function provideFixAlignScopedDoubleArrowCases(): iterable { yield [ ' function ($param1, $param2) { return; } );', ]; yield [ ' "OK", "html" => 1, /**/array( "foo" => "bar", "foofoo" => array( "a" => 1, "b" => 2 ) ),) );', ' "OK", "html" => 1, /**/array( "foo" => "bar", "foofoo" => array( "a" => 1, "b" => 2 ) ),) );', ]; yield [ ' "OK", "html" => renderView("views/my_view.html.twig", array( "foo" => "bar", "foofoo" => 43, )), ]);', ' "OK", "html" => renderView("views/my_view.html.twig", array( "foo" => "bar", "foofoo" => 43, )), ]);', ]; yield [ ' "OK", "html" => renderView("views/my_view.html.twig", [ "foo" => "bar", "foofoo" => 42, ]), "baz" => "OK", ]);', ' "OK", "html" => renderView("views/my_view.html.twig", [ "foo" => "bar", "foofoo" => 42, ]), "baz" => "OK", ]);', ]; yield [ ' "Bar", "main" => array( [ "baz" => "Test", "bazaa" => $a->{"Test"}, "bazaa" => $a["Test"], "bazaaaa" => b("Test"), ] ), "bar" => array(), ];', ' "Bar", "main" => array( [ "baz" => "Test", "bazaa" => $a->{"Test"}, "bazaa" => $a["Test"], "bazaaaa" => b("Test"), ] ), "bar" => array(), ];', ]; yield [ ' "Bar", "main" => [array("baz" => "Test")], "bar" => array(), ]; $data = array( "foo" => "Bar", "main" => array("baz" => "Test"), "bar" => array(), ); $var = []; foreach ($foo as $i => $bar) { $var[] = /* Comment */ [$i => $bar]; }', ]; yield [ ' "Bar", "main" => [array("baz" => "Test")], "bar" => array(), ];', ]; yield [ ' "Bar", "main" => array("baz" => "Test"), "bar" => array(), );', ]; yield [ ' "Bar", "main" => array(array("baz" => "Test")), "bar" => array(), );', ]; yield [ ' $bar) { $var[] = /* Comment */ [$i => $bar]; }', ]; yield [ ' $bar) { $var[] = [$i => $bar]; }', ]; yield [ ' 2] as $k => $v) { $var[] = [$i => $bar]; }', ]; yield [ ' $v){ $var[] = [$i => $bar]; }', ]; yield [ ' $bar, $iaaa => $bar, ]; }', ]; yield [ ' "Bar", "main" => [["baz" => "Test", "bar" => "Test2"]], "bar" => [], ];', ]; yield [ ' "Bar", "main" => ["baz" => "Test"], "bar" => [], ];', ]; yield [ ' 1, 10 /*Comment*/ => [ 1 => 2, 22 => 3, ], 100 => [ 1 => 2, 22 => 3, ] ];', ' 1, 10 /*Comment*/ => [ 1 => 2, 22 => 3, ], 100 => [ 1 => 2, 22 => 3, ] ];', ]; yield [ ' 1, 10 => array( 1 => 2, 22 => 3, ), 100 => array( 1 => 2, 22 => 3, ) );', ]; yield [ ' 1, $bbbb => \' $cccccccc2 = 3; \', );', ' 1, $bbbb => \' $cccccccc2 = 3; \', );', ]; yield [ ' 1, $bbbb => \' $cccccccc3 = 3; \', ];', ' 1, $bbbb => \' $cccccccc3 = 3; \', ];', ]; yield [ ' $v){ $arr = array($k => 1, $a => 1, $bbbb => \' $cccccccc4 = 3; \', ); }', ]; yield [ ' 11, 20 => 22, 30 => 33, 40 => 44, );', ' 11, 20 => 22, 30=>33, 40 => 44, );', ]; yield [ ' "", "\t" => "", "\n" => "", "\r" => "", "\0" => "", "\x0B" => "", );', ' "", "\t" => "", "\n" => "", "\r" => "", "\0" => "", "\x0B" => "", );', ]; yield [ 'grabAttribsBeforeToken( $tokens, $index, $tokenAttribsMap, array( "abstract" => null, "final" => null, "visibility" => new Token(array(T_PUBLIC, "public")), "static" => null, ) );', 'grabAttribsBeforeToken( $tokens, $index, $tokenAttribsMap, array( "abstract" => null, "final" => null, "visibility" => new Token(array(T_PUBLIC, "public")), "static" => null, ) );', ]; yield [ ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_1 => array("symbol" => "III", "description" => "invalid file syntax, file ignored"), );', ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_1 => array("symbol" => "III", "description" => "invalid file syntax, file ignored"), );', ]; yield [ ' b(array( 1 => 2, 5 => [ 6 => 7, 8 => 9, ], 3 => 4, 10 => 11, )), );', ' b(array( 1 => 2, 5 => [ 6 => 7, 8 => 9, ], 3 => 4, 10 => 11, )), );', ]; yield [ 'aaa(array(1 => 2))->bbb("a", "b"); ', ]; yield [ ' "as", "ytė\b" => "is", "iūtė\b" => "ius", "utė\b" => "us", );', ' "as", "ytė\b" => "is", "iūtė\b" => "ius", "utė\b" => "us", );', ]; yield [ 'add(\'foo\', null, [\'required\' => false]) ->add(\'dummy_field\', null, [\'required\' => false]) ; ', ]; yield [ 'add(\'foo\', null, array(\'required\' => false)) ->add(\'dummy_field\', null, array(\'required\' => false)) ; ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy(["server1" => $object], ["addedAt" => "DESC"], 5); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy(["server2" => $object], ["checkedAt" => "desc"], 50); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy(array("server1" => $object), array("addedAt" => "DESC"), 5); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy(array("server2" => $object), array("checkedAt" => "desc"), 50); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy($foo[123]); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy($foo[123]); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy([1, 2, 3]); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy([1, 2, 3]); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy((1 + 2)); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy((1 + 2)); ', ]; yield [ 'get("doctrine")->getRepository("AppBundle:Entity")->findBy(array(1, 2)); $foobar = $this->getDoctrine()->getRepository("AppBundle:Entity")->findBy(array(1, 2)); ', ]; yield [ ' "foo", "foo" => $bar[123], "a" => foo(), "b" => 1, ]; ', ' "foo", "foo" => $bar[123], "a" => foo(), "b" => 1, ]; ', ]; yield [ ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_2 => array("symbol123" => "III", "description" => "invalid file syntax, file ignored"), );', ' array("symbol" => "?", "description" => "unknown"), self::STATUS_INVALID_2 => array("symbol123" => "III", "description" => "invalid file syntax, file ignored"), );', ]; yield [ ' array((1 + 11)=> "?", "description" => "unknown"), self::STATUS_INVALID_3 => array((2 + 3)=> "III", "description" => "invalid file syntax, file ignored"), );', ' array((1+11)=> "?", "description" => "unknown"), self::STATUS_INVALID_3 => array((2+3)=> "III", "description" => "invalid file syntax, file ignored"), );', ]; yield [ ' ["symbol" => "?", "description" => "unknown"], self::STATUS_INVALID_4 => ["symbol123" => "III", "description" => "invalid file syntax, file ignored"], ];', ' ["symbol" => "?", "description" => "unknown"], self::STATUS_INVALID_4 => ["symbol123" => "III", "description" => "invalid file syntax, file ignored"], ];', ]; yield [ ' [(1 + 11)=> "?", "description" => "unknown"], self::STATUS_INVALID_7 => [(2 + 3)=> "III", "description" => "invalid file syntax, file ignored"], ];', ' [(1+11)=> "?", "description" => "unknown"], self::STATUS_INVALID_7 => [(2+3)=> "III", "description" => "invalid file syntax, file ignored"], ];', ]; yield [ ' function() { foreach([$a => 2] as $b) { $bv = [ $b => 2, $cc => 3, ]; }}, 2 => 3]; ', ' function() { foreach([$a => 2] as $b) { $bv = [ $b => 2, $cc => 3, ]; }}, 2 => 3]; ', ]; yield [ ' fn () => false, "is" => fn () => false, "an" => fn () => false, "example" => fn () => false, "array" => fn () => false, ]; } ', ' fn () => false, "is" => fn () => false, "an" => fn () => false, "example" => fn () => false, "array" => fn () => false, ]; } ', ]; yield [ 'map(fn ($arg) => []) ->keyBy(fn ($arg) => []); ', ]; yield [ 'save([ "bar" => "baz", "barbarbar" => "baz", ])) { // Do the work } ', 'save([ "bar" => "baz", "barbarbar" => "baz", ])) { // Do the work } ', ]; yield [ 'test1(fn () => $this->test2($a)); foreach ($result as $k => $v) { } $result = $this->test1(fn () => $this->test2($a, $b)); foreach ($result as $k => $v) { } } } ', ]; yield [ ' 123, "longkey" => "test", "baz" => fn () => "value", ]; ', ' 123, "longkey" => "test", "baz" => fn () => "value", ]; ', ]; yield [ 'query = $this->db->prepare(static fn ($db) => $db->table("user")->insert([ "name" => "a", "email" => "b@example.com", "country" => "JP", ])); foreach ($data as $name => $array) { foreach ($array as $field => $value) { yield $type => $case; } } } ', 'query = $this->db->prepare(static fn ($db) => $db->table("user")->insert([ "name" => "a", "email" => "b@example.com", "country" => "JP", ])); foreach ($data as $name => $array) { foreach ($array as $field => $value) { yield $type => $case; } } } ', ]; yield [ ' [ "expected" => null, "ourCustomer" => null, ]; yield "no underlying user" => [ "expected" => null, "ourCustomer" => Customer::seed(), ]; } ', ]; } public function testDoNotTouchEqualsAndArrowByConfig(): void { $this->fixer->configure( [ 'operators' => [ '=' => null, '=>' => null, ], ] ); $this->doTest( ' 5, 2 => 4, 3 => 3, 4 => 2, 5 => 1, 6 => 7, ); ' ); } /** * @requires PHP 8.0 */ public function testUnionTypesAreNotChanged(): void { $this->doTest( 'doTest( '