Skip to content

Commit

Permalink
Merge branch '2.15'
Browse files Browse the repository at this point in the history
  • Loading branch information
keradus committed Nov 3, 2019
2 parents d328d21 + b0aec5b commit c8ba40f
Show file tree
Hide file tree
Showing 42 changed files with 1,105 additions and 119 deletions.
2 changes: 1 addition & 1 deletion .composer-require-checker.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"null", "true", "false",
"static", "self", "parent",
"array", "string", "int", "float", "bool", "iterable", "callable", "void",
"T_COALESCE_EQUAL"
"T_COALESCE_EQUAL", "T_FN"
],
"php-core-extensions" : [
"dom", "mbstring", "Phar",
Expand Down
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: keradus
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
include:
-
stage: Static Code Analysis
php: 7.2
php: 7.3
env: COMPOSER_FLAGS="--prefer-stable"
install:
- travis_retry ./dev-tools/install.sh
Expand Down
2 changes: 2 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ parameters:
ignoreErrors:
- '/^.+::__construct\(\) does not call parent constructor from SplFileInfo\.$/'
- '/^Return typehint of method PhpCsFixer\\Tests\\Test\\.+::createIsIdenticalStringConstraint\(\) has invalid type PHPUnit_Framework_Constraint_IsIdentical\.$/'
## cannot analyse out of PHP 7.4
- '/^Constant T_FN not found\.$/'
25 changes: 22 additions & 3 deletions src/Fixer/CastNotation/LowercaseCastFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
namespace PhpCsFixer\Fixer\CastNotation;

use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\VersionSpecification;
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;

Expand All @@ -31,7 +32,7 @@ public function getDefinition()
return new FixerDefinition(
'Cast should be written in lower case.',
[
new CodeSample(
new VersionSpecificCodeSample(
'<?php
$a = (BOOLEAN) $b;
$a = (BOOL) $b;
Expand All @@ -46,7 +47,25 @@ public function getDefinition()
$a = (OBJect) $b;
$a = (UNset) $b;
$a = (Binary) $b;
'
',
new VersionSpecification(null, 70399)
),
new VersionSpecificCodeSample(
'<?php
$a = (BOOLEAN) $b;
$a = (BOOL) $b;
$a = (INTEGER) $b;
$a = (INT) $b;
$a = (DOUBLE) $b;
$a = (FLoaT) $b;
$a = (flOAT) $b;
$a = (sTRING) $b;
$a = (ARRAy) $b;
$a = (OBJect) $b;
$a = (UNset) $b;
$a = (Binary) $b;
',
new VersionSpecification(70400)
),
]
);
Expand Down
14 changes: 12 additions & 2 deletions src/Fixer/CastNotation/ShortScalarCastFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
namespace PhpCsFixer\Fixer\CastNotation;

use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\VersionSpecification;
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;

Expand All @@ -30,7 +31,16 @@ public function getDefinition()
{
return new FixerDefinition(
'Cast `(boolean)` and `(integer)` should be written as `(bool)` and `(int)`, `(double)` and `(real)` as `(float)`, `(binary)` as `(string)`.',
[new CodeSample("<?php\n\$a = (boolean) \$b;\n\$a = (integer) \$b;\n\$a = (double) \$b;\n\$a = (real) \$b;\n\n\$a = (binary) \$b;\n")]
[
new VersionSpecificCodeSample(
"<?php\n\$a = (boolean) \$b;\n\$a = (integer) \$b;\n\$a = (double) \$b;\n\$a = (real) \$b;\n\n\$a = (binary) \$b;\n",
new VersionSpecification(null, 70399)
),
new VersionSpecificCodeSample(
"<?php\n\$a = (boolean) \$b;\n\$a = (integer) \$b;\n\$a = (double) \$b;\n\n\$a = (binary) \$b;\n",
new VersionSpecification(70400)
),
]
);
}

Expand Down
25 changes: 21 additions & 4 deletions src/Fixer/FunctionNotation/FunctionDeclarationFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\VersionSpecification;
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixer\Tokenizer\TokensAnalyzer;
Expand Down Expand Up @@ -48,6 +50,10 @@ final class FunctionDeclarationFixer extends AbstractFixer implements Configurat
*/
public function isCandidate(Tokens $tokens)
{
if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) {
return true;
}

return $tokens->isTokenKindFound(T_FUNCTION);
}

Expand Down Expand Up @@ -82,6 +88,13 @@ function foo ($bar, $baz)
',
['closure_function_spacing' => self::SPACING_NONE]
),
new VersionSpecificCodeSample(
'<?php
$f = fn () => null;
',
new VersionSpecification(70400),
['closure_function_spacing' => self::SPACING_NONE]
),
]
);
}
Expand All @@ -96,7 +109,10 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
for ($index = $tokens->count() - 1; $index >= 0; --$index) {
$token = $tokens[$index];

if (!$token->isGivenKind(T_FUNCTION)) {
if (
!$token->isGivenKind(T_FUNCTION)
&& (\PHP_VERSION_ID < 70400 || !$token->isGivenKind(T_FN))
) {
continue;
}

Expand All @@ -106,13 +122,14 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
}

$endParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $startParenthesisIndex);
$startBraceIndex = $tokens->getNextTokenOfKind($endParenthesisIndex, [';', '{']);
$startBraceIndex = $tokens->getNextTokenOfKind($endParenthesisIndex, [';', '{', [T_DOUBLE_ARROW]]);

// fix single-line whitespace before {
// fix single-line whitespace before { or =>
// eg: `function foo(){}` => `function foo() {}`
// eg: `function foo() {}` => `function foo() {}`
// eg: `fn() =>` => `fn() =>`
if (
$tokens[$startBraceIndex]->equals('{') &&
$tokens[$startBraceIndex]->equalsAny(['{', [T_DOUBLE_ARROW]]) &&
(
!$tokens[$startBraceIndex - 1]->isWhitespace() ||
$tokens[$startBraceIndex - 1]->isWhitespace($this->singleLineWhitespaceOptions)
Expand Down
9 changes: 8 additions & 1 deletion src/Fixer/FunctionNotation/FunctionTypehintSpaceFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ public function getDefinition()
*/
public function isCandidate(Tokens $tokens)
{
if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) {
return true;
}

return $tokens->isTokenKindFound(T_FUNCTION);
}

Expand All @@ -57,7 +61,10 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
for ($index = $tokens->count() - 1; $index >= 0; --$index) {
$token = $tokens[$index];

if (!$token->isGivenKind(T_FUNCTION)) {
if (
!$token->isGivenKind(T_FUNCTION)
&& (\PHP_VERSION_ID < 70400 || !$token->isGivenKind(T_FN))
) {
continue;
}

Expand Down
7 changes: 6 additions & 1 deletion src/Fixer/FunctionNotation/MethodArgumentSpaceFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ public function getPriority()
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens)
{
$expectedTokens = [T_LIST, T_FUNCTION];
if (\PHP_VERSION_ID >= 70400) {
$expectedTokens[] = T_FN;
}

for ($index = $tokens->count() - 1; $index > 0; --$index) {
$token = $tokens[$index];

Expand All @@ -149,7 +154,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
$meaningfulTokenBeforeParenthesis = $tokens[$tokens->getPrevMeaningfulToken($index)];
if (
$meaningfulTokenBeforeParenthesis->isKeyword()
&& !$meaningfulTokenBeforeParenthesis->isGivenKind([T_LIST, T_FUNCTION])
&& !$meaningfulTokenBeforeParenthesis->isGivenKind($expectedTokens)
) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ function example($foo = "two words", $bar) {}
*/
public function isCandidate(Tokens $tokens)
{
if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) {
return true;
}

return $tokens->isTokenKindFound(T_FUNCTION);
}

Expand All @@ -66,7 +70,10 @@ public function isRisky()
protected function applyFix(\SplFileInfo $file, Tokens $tokens)
{
for ($i = 0, $l = $tokens->count(); $i < $l; ++$i) {
if (!$tokens[$i]->isGivenKind(T_FUNCTION)) {
if (
!$tokens[$i]->isGivenKind(T_FUNCTION)
&& (\PHP_VERSION_ID < 70400 || !$tokens[$i]->isGivenKind(T_FN))
) {
continue;
}

Expand Down
9 changes: 8 additions & 1 deletion src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ function my_foo()
*/
public function isCandidate(Tokens $tokens)
{
if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) {
return true;
}

return \PHP_VERSION_ID >= 70000 && $tokens->isTokenKindFound(T_FUNCTION);
}

Expand Down Expand Up @@ -161,7 +165,10 @@ protected function createConfigurationDefinition()
protected function applyFix(\SplFileInfo $file, Tokens $tokens)
{
for ($index = $tokens->count() - 1; 0 < $index; --$index) {
if (!$tokens[$index]->isGivenKind(T_FUNCTION)) {
if (
!$tokens[$index]->isGivenKind(T_FUNCTION)
&& (\PHP_VERSION_ID < 70400 || !$tokens[$index]->isGivenKind(T_FN))
) {
continue;
}

Expand Down
22 changes: 19 additions & 3 deletions src/Fixer/FunctionNotation/StaticLambdaFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public function getDefinition()
*/
public function isCandidate(Tokens $tokens)
{
if (\PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_FN)) {
return true;
}

return $tokens->isTokenKindFound(T_FUNCTION);
}

Expand All @@ -61,8 +65,13 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
{
$analyzer = new TokensAnalyzer($tokens);

$expectedFunctionKinds = [T_FUNCTION];
if (\PHP_VERSION_ID >= 70400) {
$expectedFunctionKinds[] = T_FN;
}

for ($index = $tokens->count() - 4; $index > 0; --$index) {
if (!$tokens[$index]->isGivenKind(T_FUNCTION) || !$analyzer->isLambda($index)) {
if (!$tokens[$index]->isGivenKind($expectedFunctionKinds) || !$analyzer->isLambda($index)) {
continue;
}

Expand All @@ -71,11 +80,18 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
continue; // lambda is already 'static'
}

$argumentsStartIndex = $tokens->getNextTokenOfKind($index, ['(']);
$argumentsEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $argumentsStartIndex);

// figure out where the lambda starts ...
$lambdaOpenIndex = $tokens->getNextTokenOfKind($index, ['{']);
$lambdaOpenIndex = $tokens->getNextTokenOfKind($argumentsEndIndex, ['{', [T_DOUBLE_ARROW]]);

// ... and where it ends
$lambdaEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $lambdaOpenIndex);
if ($tokens[$lambdaOpenIndex]->isGivenKind(T_DOUBLE_ARROW)) {
$lambdaEndIndex = $tokens->getNextTokenOfKind($lambdaOpenIndex, [';']);
} else {
$lambdaEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $lambdaOpenIndex);
}

if ($this->hasPossibleReferenceToThis($tokens, $lambdaOpenIndex, $lambdaEndIndex)) {
continue;
Expand Down
2 changes: 1 addition & 1 deletion src/Tokenizer/Analyzer/FunctionsAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function getFunctionReturnType(Tokens $tokens, $methodIndex)
$type = '';
$typeStartIndex = $tokens->getNextMeaningfulToken($typeColonIndex);
$typeEndIndex = $typeStartIndex;
$functionBodyStart = $tokens->getNextTokenOfKind($typeColonIndex, ['{', ';']);
$functionBodyStart = $tokens->getNextTokenOfKind($typeColonIndex, ['{', ';', [T_DOUBLE_ARROW]]);
for ($i = $typeStartIndex; $i < $functionBodyStart; ++$i) {
if ($tokens[$i]->isWhitespace() || $tokens[$i]->isComment()) {
continue;
Expand Down
2 changes: 1 addition & 1 deletion src/Tokenizer/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ public static function getKeywords()
'T_CATCH', 'T_CLASS', 'T_CLONE', 'T_CONST', 'T_CONTINUE', 'T_DECLARE', 'T_DEFAULT', 'T_DO',
'T_ECHO', 'T_ELSE', 'T_ELSEIF', 'T_EMPTY', 'T_ENDDECLARE', 'T_ENDFOR', 'T_ENDFOREACH',
'T_ENDIF', 'T_ENDSWITCH', 'T_ENDWHILE', 'T_EVAL', 'T_EXIT', 'T_EXTENDS', 'T_FINAL',
'T_FINALLY', 'T_FOR', 'T_FOREACH', 'T_FUNCTION', 'T_GLOBAL', 'T_GOTO', 'T_HALT_COMPILER',
'T_FINALLY', 'T_FN', 'T_FOR', 'T_FOREACH', 'T_FUNCTION', 'T_GLOBAL', 'T_GOTO', 'T_HALT_COMPILER',
'T_IF', 'T_IMPLEMENTS', 'T_INCLUDE', 'T_INCLUDE_ONCE', 'T_INSTANCEOF', 'T_INSTEADOF',
'T_INTERFACE', 'T_ISSET', 'T_LIST', 'T_LOGICAL_AND', 'T_LOGICAL_OR', 'T_LOGICAL_XOR',
'T_NAMESPACE', 'T_NEW', 'T_PRINT', 'T_PRIVATE', 'T_PROTECTED', 'T_PUBLIC', 'T_REQUIRE',
Expand Down
7 changes: 5 additions & 2 deletions src/Tokenizer/TokensAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,11 @@ public function isAnonymousClass($index)
*/
public function isLambda($index)
{
if (!$this->tokens[$index]->isGivenKind(T_FUNCTION)) {
throw new \LogicException(sprintf('No T_FUNCTION at given index %d, got %s.', $index, $this->tokens[$index]->getName()));
if (
!$this->tokens[$index]->isGivenKind(T_FUNCTION)
&& (\PHP_VERSION_ID < 70400 || !$this->tokens[$index]->isGivenKind(T_FN))
) {
throw new \LogicException(sprintf('No T_FUNCTION or T_FN at given index %d, got %s.', $index, $this->tokens[$index]->getName()));
}

$startParenthesisIndex = $this->tokens->getNextMeaningfulToken($index);
Expand Down
7 changes: 6 additions & 1 deletion src/Tokenizer/Transformer/ReturnRefTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,14 @@ public function getRequiredPhpVersionId()
*/
public function process(Tokens $tokens, Token $token, $index)
{
$prevKinds = [T_FUNCTION];
if (\PHP_VERSION_ID >= 70400) {
$prevKinds[] = T_FN;
}

if (
$token->equals('&')
&& $tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind(T_FUNCTION)
&& $tokens[$tokens->getPrevMeaningfulToken($index)]->isGivenKind($prevKinds)
) {
$tokens[$index] = new Token([CT::T_RETURN_REF, '&']);
}
Expand Down
7 changes: 6 additions & 1 deletion src/Tokenizer/Transformer/TypeColonTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ public function process(Tokens $tokens, Token $token, $index)
$prevToken = $tokens[$prevIndex];
}

if ($prevToken->isGivenKind([T_FUNCTION, CT::T_RETURN_REF, CT::T_USE_LAMBDA])) {
$prevKinds = [T_FUNCTION, CT::T_RETURN_REF, CT::T_USE_LAMBDA];
if (\PHP_VERSION_ID >= 70400) {
$prevKinds[] = T_FN;
}

if ($prevToken->isGivenKind($prevKinds)) {
$tokens[$index] = new Token([CT::T_TYPE_COLON, ':']);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,30 @@ public function provideFixCases()
],
];
}

/**
* @param string $expected
* @param null|string $input
*
* @dataProvider provideFixPhp74Cases
* @requires PHP 7.4
*/
public function testFixPhp74($expected, $input = null)
{
$this->doTest($expected, $input);
}

public function provideFixPhp74Cases()
{
return [
[
'<?php
$fn = fn() => null;',
'<?php
$fn = fn()
=>
null;',
],
];
}
}
Loading

0 comments on commit c8ba40f

Please sign in to comment.