-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NamedArgumentTransformer - Introduction
- Loading branch information
1 parent
1ff5457
commit cde0236
Showing
4 changed files
with
258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of PHP CS Fixer. | ||
* | ||
* (c) Fabien Potencier <[email protected]> | ||
* Dariusz Rumiński <[email protected]> | ||
* | ||
* This source file is subject to the MIT license that is bundled | ||
* with this source code in the file LICENSE. | ||
*/ | ||
|
||
namespace PhpCsFixer\Tokenizer\Transformer; | ||
|
||
use PhpCsFixer\Tokenizer\AbstractTransformer; | ||
use PhpCsFixer\Tokenizer\CT; | ||
use PhpCsFixer\Tokenizer\Token; | ||
use PhpCsFixer\Tokenizer\Tokens; | ||
|
||
/** | ||
* Transform named argument tokens. | ||
* | ||
* @author SpacePossum | ||
* | ||
* @internal | ||
*/ | ||
final class NamedArgumentTransformer extends AbstractTransformer | ||
{ | ||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getPriority() | ||
{ | ||
// needs to run after TypeColonTransformer | ||
return -15; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getRequiredPhpVersionId() | ||
{ | ||
return 80000; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function process(Tokens $tokens, Token $token, $index) | ||
{ | ||
if (!$tokens[$index]->equals(':')) { | ||
return; | ||
} | ||
|
||
$stringIndex = $tokens->getPrevMeaningfulToken($index); | ||
|
||
if (!$tokens[$stringIndex]->isGivenKind(T_STRING)) { | ||
return; | ||
} | ||
|
||
$preStringIndex = $tokens->getPrevMeaningfulToken($stringIndex); | ||
|
||
// if equals any [';', '{', '}', [T_OPEN_TAG]] than it is a goto label | ||
// if equals ')' than likely it is a type colon, but sure not a name argument | ||
// if equals '?' than it is part of ternary statement | ||
|
||
if (!$tokens[$preStringIndex]->equalsAny([',', '('])) { | ||
return; | ||
} | ||
|
||
$tokens[$stringIndex] = new Token([CT::T_NAMED_ARGUMENT_NAME, $tokens[$stringIndex]->getContent()]); | ||
$tokens[$index] = new Token([CT::T_NAMED_ARGUMENT_COLON, ':']); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
protected function getDeprecatedCustomTokens() | ||
{ | ||
return [ | ||
CT::T_NAMED_ARGUMENT_COLON, | ||
CT::T_NAMED_ARGUMENT_NAME, | ||
]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 170 additions & 0 deletions
170
tests/Tokenizer/Transformer/NamedArgumentTransformerTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of PHP CS Fixer. | ||
* | ||
* (c) Fabien Potencier <[email protected]> | ||
* Dariusz Rumiński <[email protected]> | ||
* | ||
* This source file is subject to the MIT license that is bundled | ||
* with this source code in the file LICENSE. | ||
*/ | ||
|
||
namespace PhpCsFixer\Tests\Tokenizer\Transformer; | ||
|
||
use PhpCsFixer\Tests\Test\AbstractTransformerTestCase; | ||
use PhpCsFixer\Tokenizer\CT; | ||
use PhpCsFixer\Tokenizer\Tokens; | ||
|
||
/** | ||
* @internal | ||
* | ||
* @covers \PhpCsFixer\Tokenizer\Transformer\NamedArgumentTransformer | ||
*/ | ||
final class NamedArgumentTransformerTest extends AbstractTransformerTestCase | ||
{ | ||
/** | ||
* @param string $source | ||
* | ||
* @dataProvider provideProcessCases | ||
* @requires PHP 8.0 | ||
*/ | ||
public function testProcess($source, array $expectedTokens) | ||
{ | ||
$this->doTest($source, $expectedTokens); | ||
} | ||
|
||
public function provideProcessCases() | ||
{ | ||
yield 'function call' => [ | ||
'<?php foo(test: 1);', | ||
[ | ||
3 => CT::T_NAMED_ARGUMENT_NAME, | ||
4 => CT::T_NAMED_ARGUMENT_COLON, | ||
], | ||
]; | ||
|
||
yield 'dynamic function 2x' => [ | ||
'<?php $foo(foo: 1, bar: 2, 3,);', | ||
[ | ||
3 => CT::T_NAMED_ARGUMENT_NAME, | ||
4 => CT::T_NAMED_ARGUMENT_COLON, | ||
9 => CT::T_NAMED_ARGUMENT_NAME, | ||
10 => CT::T_NAMED_ARGUMENT_COLON, | ||
], | ||
]; | ||
|
||
yield 'method' => [ | ||
'<?php | ||
class Bar { | ||
public function a($foo){} | ||
} | ||
$foo = new Bar(); | ||
$foo->a(foo: 1); | ||
', | ||
[ | ||
36 => CT::T_NAMED_ARGUMENT_NAME, | ||
37 => CT::T_NAMED_ARGUMENT_COLON, | ||
], | ||
]; | ||
|
||
yield 'nested' => [ | ||
'<?php | ||
foo(test: static function() { | ||
bar(test: 1); | ||
},); | ||
', | ||
[ | ||
4 => CT::T_NAMED_ARGUMENT_NAME, | ||
5 => CT::T_NAMED_ARGUMENT_COLON, | ||
17 => CT::T_NAMED_ARGUMENT_NAME, | ||
18 => CT::T_NAMED_ARGUMENT_COLON, | ||
], | ||
]; | ||
} | ||
|
||
/** | ||
* @param string $source | ||
* | ||
* @dataProvider provideDoNotChangeCases | ||
*/ | ||
public function testDoNotChange($source) | ||
{ | ||
static::assertNotChange($source); | ||
} | ||
|
||
public function provideDoNotChangeCases() | ||
{ | ||
yield 'switch/case/constants' => [ | ||
'<?php | ||
define(\'FOO\', 123); | ||
define(\'BAR\', 123); | ||
$a = $guard = 123; | ||
switch($a) { | ||
case FOO: | ||
echo 456; | ||
break; | ||
case 3 + FOO: | ||
echo 789; | ||
break; | ||
case ($guard ? BAR : 2): | ||
echo 456; | ||
break; | ||
} | ||
foo(1 , $a3 ? BAR : 2); | ||
$a1 = [1, BAR ? 1 : 2]; | ||
$a2 = [1, (BAR) ? 1 : 2]; | ||
', | ||
]; | ||
|
||
yield 'goto' => [ | ||
'<?php | ||
define(\'FOO\', 123); | ||
$guard = 1; | ||
{ | ||
beginning: | ||
echo $guard ? 1 + FOO : 2; | ||
echo $guard ? 1 : 2; | ||
} | ||
', | ||
]; | ||
} | ||
|
||
/** | ||
* @param string $source | ||
* | ||
* @dataProvider provideDoNotChange70Cases | ||
* @requires PHP 7.0 | ||
*/ | ||
public function testDoNotChange70($source) | ||
{ | ||
static::assertNotChange($source); | ||
} | ||
|
||
public function provideDoNotChange70Cases() | ||
{ | ||
yield 'return type' => ['<?php function foo(): array { return []; }']; | ||
} | ||
|
||
/** | ||
* @param string $source | ||
*/ | ||
private static function assertNotChange($source) | ||
{ | ||
Tokens::clearCache(); | ||
|
||
foreach (Tokens::fromCode($source) as $token) { | ||
static::assertFalse($token->isGivenKind([ | ||
CT::T_NAMED_ARGUMENT_NAME, | ||
CT::T_NAMED_ARGUMENT_COLON, | ||
])); | ||
} | ||
} | ||
} |