Skip to content

Commit

Permalink
PHP8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
SpacePossum committed Oct 19, 2020
1 parent 2d444c4 commit 3057fac
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 42 deletions.
28 changes: 14 additions & 14 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ Choose from the list of available rules:

Calling ``unset`` on multiple items should be done in one call.

* **combine_nested_dirname** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP8Migration:risky]
* **combine_nested_dirname** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP80Migration:risky]

Replace multiple nested calls of ``dirname`` by only one call with second
``$level`` parameter. Requires PHP >= 7.0.
Expand Down Expand Up @@ -456,7 +456,7 @@ Choose from the list of available rules:
- ``space`` (``'none'``, ``'single'``): spacing to apply around the equal sign;
defaults to ``'none'``

* **declare_strict_types** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP8Migration:risky]
* **declare_strict_types** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP80Migration:risky]

Force strict types declaration in all files. Requires PHP >= 7.0.

Expand Down Expand Up @@ -768,15 +768,15 @@ Choose from the list of available rules:
- ``separate`` (``'both'``, ``'bottom'``, ``'none'``, ``'top'``): whether the header should be
separated from the file content with a new line; defaults to ``'both'``

* **heredoc_indentation** [@PHP73Migration, @PHP8Migration]
* **heredoc_indentation** [@PHP73Migration, @PHP80Migration]

Heredoc/nowdoc content must be properly indented. Requires PHP >= 7.3.

* **heredoc_to_nowdoc** [@PhpCsFixer]

Convert ``heredoc`` to ``nowdoc`` where possible.

* **implode_call** [@Symfony:risky, @PhpCsFixer:risky, @PHP8Migration:risky]
* **implode_call** [@Symfony:risky, @PhpCsFixer:risky, @PHP80Migration:risky]

Function ``implode`` must be called with 2 arguments in the documented
order.
Expand Down Expand Up @@ -972,7 +972,7 @@ Choose from the list of available rules:

All instances created with new keyword must be followed by braces.

* **no_alias_functions** [@Symfony:risky, @PhpCsFixer:risky, @PHP8Migration:risky]
* **no_alias_functions** [@Symfony:risky, @PhpCsFixer:risky, @PHP80Migration:risky]

Master functions shall be used instead of aliases.

Expand Down Expand Up @@ -1180,7 +1180,7 @@ Choose from the list of available rules:
- ``namespaces`` (``bool``): remove unneeded curly braces from bracketed
namespaces; defaults to ``false``

* **no_unneeded_final_method** [@Symfony:risky, @PhpCsFixer:risky, @PHP8Migration:risky]
* **no_unneeded_final_method** [@Symfony:risky, @PhpCsFixer:risky, @PHP80Migration:risky]

A ``final`` class must not have ``final`` methods and ``private`` methods must
not be ``final``.
Expand All @@ -1194,7 +1194,7 @@ Choose from the list of available rules:

*Risky rule: modifies the signature of functions; therefore risky when using systems (such as some Symfony components) that rely on those (for example through reflection).*

* **no_unset_cast** [@PhpCsFixer, @PHP8Migration]
* **no_unset_cast** [@PhpCsFixer, @PHP80Migration]

Variables must be set ``null`` instead of using ``(unset)`` casting.

Expand Down Expand Up @@ -1230,7 +1230,7 @@ Choose from the list of available rules:

Remove trailing whitespace at the end of blank lines.

* **non_printable_character** [@Symfony:risky, @PhpCsFixer:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP8Migration:risky]
* **non_printable_character** [@Symfony:risky, @PhpCsFixer:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP80Migration:risky]

Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and other
invisible unicode symbols.
Expand All @@ -1242,7 +1242,7 @@ Choose from the list of available rules:
- ``use_escape_sequences_in_strings`` (``bool``): whether characters should be
replaced with escape sequences in strings; defaults to ``false``

* **normalize_index_brace** [@Symfony, @PhpCsFixer, @PHP8Migration]
* **normalize_index_brace** [@Symfony, @PhpCsFixer, @PHP80Migration]

Array index should always be written by using square braces.

Expand Down Expand Up @@ -1658,7 +1658,7 @@ Choose from the list of available rules:
``@var`` and ``@type`` annotations of classy properties should not contain
the name.

* **pow_to_exponentiation** [@PHP56Migration:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP8Migration:risky]
* **pow_to_exponentiation** [@PHP56Migration:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP80Migration:risky]

Converts ``pow`` to the ``**`` operator.

Expand Down Expand Up @@ -1691,7 +1691,7 @@ Choose from the list of available rules:

*Risky rule: this fixer may change your class name, which will break the code that depends on the old name.*

* **random_api_migration** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP8Migration:risky]
* **random_api_migration** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP80Migration:risky]

Replaces ``rand``, ``srand``, ``getrandmax`` functions calls with their ``mt_*``
analogs.
Expand Down Expand Up @@ -1862,7 +1862,7 @@ Choose from the list of available rules:

Standardize spaces around ternary operator.

* **ternary_to_null_coalescing** [@PHP70Migration, @PHP71Migration, @PHP73Migration, @PHP8Migration]
* **ternary_to_null_coalescing** [@PHP70Migration, @PHP71Migration, @PHP73Migration, @PHP80Migration]

Use ``null`` coalescing operator ``??`` where possible. Requires PHP >= 7.0.

Expand All @@ -1884,7 +1884,7 @@ Choose from the list of available rules:

Unary operators should be placed adjacent to their operands.

* **visibility_required** [@PSR2, @Symfony, @PhpCsFixer, @PHP71Migration, @PHP73Migration, @PHP8Migration]
* **visibility_required** [@PSR2, @Symfony, @PhpCsFixer, @PHP71Migration, @PHP73Migration, @PHP80Migration]

Visibility MUST be declared on all properties and methods; ``abstract``
and ``final`` MUST be declared before the visibility; ``static`` MUST be
Expand All @@ -1896,7 +1896,7 @@ Choose from the list of available rules:
elements to fix (PHP >= 7.1 required for ``const``); defaults to
``['property', 'method']``

* **void_return** [@PHP71Migration:risky, @PHP8Migration:risky]
* **void_return** [@PHP71Migration:risky, @PHP80Migration:risky]

Add ``void`` return type to functions with missing or empty return
statements, but priority is given to ``@return`` annotations. Requires
Expand Down
19 changes: 15 additions & 4 deletions src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer
* iterable PHP 7.1.0
* void PHP 7.1.0
* object PHP 7.2.0
* static PHP 8.0.0 (return type only)
*
* @var array<string, true>
*/
Expand Down Expand Up @@ -86,6 +87,10 @@ public function __construct()
$this->hints = array_merge($this->hints, ['object' => true]);
}

if (\PHP_VERSION_ID >= 80000) {
$this->hints = array_merge($this->hints, ['static' => true]);
}

$this->functionsAnalyzer = new FunctionsAnalyzer();
}

Expand Down Expand Up @@ -162,16 +167,22 @@ private function fixArgumentType(Tokens $tokens, TypeAnalysis $type = null)
return;
}

$argumentIndex = $type->getStartIndex();
if ($argumentIndex !== $type->getEndIndex()) {
return; // the type to fix are always unqualified and so are always composed as one token
$argumentStartIndex = $type->getStartIndex();
$argumentExpectedEndIndex = $type->isNullable()
? $tokens->getNextMeaningfulToken($argumentStartIndex)
: $argumentStartIndex
;

if ($argumentExpectedEndIndex !== $type->getEndIndex()) {
return; // the type to fix is always unqualified and so is always composed of one token and possible a nullable '?' one
}

$lowerCasedName = strtolower($type->getName());

if (!isset($this->hints[$lowerCasedName])) {
return; // check of type is of interest based on name (slower check than previous index based)
}

$tokens[$argumentIndex] = new Token([$tokens[$argumentIndex]->getId(), $lowerCasedName]);
$tokens[$argumentExpectedEndIndex] = new Token([$tokens[$argumentExpectedEndIndex]->getId(), $lowerCasedName]);
}
}
42 changes: 34 additions & 8 deletions src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,19 @@ function bar() {}
new VersionSpecification(70100),
['scalar_types' => false]
),
new VersionSpecificCodeSample(
'<?php
final class Foo {
/**
* @return static
*/
public function create($prototype) {
return new static($prototype);
}
}
',
new VersionSpecification(80000)
),
],
null,
'This rule is EXPERIMENTAL and [1] is not covered with backward compatibility promise. [2] `@return` annotation is mandatory for the fixer to make changes, signatures of methods without it (no docblock, inheritdocs) will not be fixed. [3] Manual actions are required if inherited signatures are not properly documented. [4] `@inheritdocs` support is under construction.'
Expand Down Expand Up @@ -189,11 +202,13 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
}

$funcName = $tokens->getNextMeaningfulToken($index);

if ($tokens[$funcName]->equalsAny($this->excludeFuncNames, false)) {
continue;
}

$returnTypeAnnotation = $this->findReturnAnnotations($tokens, $index);

if (1 !== \count($returnTypeAnnotation)) {
continue;
}
Expand Down Expand Up @@ -233,7 +248,7 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
}

if ('static' === $returnType) {
$returnType = 'self';
$returnType = \PHP_VERSION_ID < 80000 ? 'self' : 'static';
}

if (isset($this->skippedTypes[$returnType])) {
Expand Down Expand Up @@ -299,27 +314,38 @@ private function fixFunctionDefinition(Tokens $tokens, $index, $isNullable, $ret
static $specialTypes = [
'array' => [CT::T_ARRAY_TYPEHINT, 'array'],
'callable' => [T_CALLABLE, 'callable'],
'static' => [T_STATIC, 'static'],
];

$newTokens = [
new Token([CT::T_TYPE_COLON, ':']),
new Token([T_WHITESPACE, ' ']),
];

if (true === $isNullable) {
$newTokens[] = new Token([CT::T_NULLABLE_TYPE, '?']);
}

if (isset($specialTypes[$returnType])) {
$newTokens[] = new Token($specialTypes[$returnType]);
} else {
foreach (explode('\\', $returnType) as $nsIndex => $value) {
if (0 === $nsIndex && '' === $value) {
continue;
}
$returnTypeUnqualified = ltrim($returnType, '\\');

if (isset($this->scalarTypes[$returnTypeUnqualified]) || isset($this->versionSpecificTypes[$returnTypeUnqualified])) {
// 'scalar's, 'void', 'iterable' and 'object' must be unqualified
$newTokens[] = new Token([T_STRING, $returnTypeUnqualified]);
} else {
foreach (explode('\\', $returnType) as $nsIndex => $value) {
if (0 === $nsIndex && '' === $value) {
continue;
}

if (0 < $nsIndex) {
$newTokens[] = new Token([T_NS_SEPARATOR, '\\']);
}

if (0 < $nsIndex) {
$newTokens[] = new Token([T_NS_SEPARATOR, '\\']);
$newTokens[] = new Token([T_STRING, $value]);
}
$newTokens[] = new Token([T_STRING, $value]);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/RuleSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,12 @@ final class RuleSet implements RuleSetInterface
'@PHP71Migration' => true,
'heredoc_indentation' => true,
],
'@PHP8Migration' => [
'@PHP80Migration' => [
'@PHP73Migration' => true,
'no_unset_cast' => true,
'normalize_index_brace' => true,
],
'@PHP8Migration:risky' => [
'@PHP80Migration:risky' => [
'@PHP71Migration:risky' => true,
'implode_call' => true,
'no_alias_functions' => ['sets' => ['@all']],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ public function provideFix71Cases()
'<?php function Foo(iterable $A): void {}',
'<?php function Foo(ITERABLE $A): VOID {}',
],
[
'<?php function Foo(?int $A): void {}',
'<?php function Foo(?INT $A): VOID {}',
],
[
'<?php function Foo(string $A): ?/* */int {}',
'<?php function Foo(STRING $A): ?/* */INT {}',
],
];
}

Expand All @@ -193,4 +201,30 @@ public function provideFix72Cases()
],
];
}

/**
* @param string $expected
* @param string $input
*
* @dataProvider provideFix80Cases
* @requires PHP 8.0
*/
public function testFix80($expected, $input)
{
$this->doTest($expected, $input);
}

public function provideFix80Cases()
{
return [
[
'<?php class T { public function Foo(object $A): static {}}',
'<?php class T { public function Foo(object $A): StatiC {}}',
],
[
'<?php class T { public function Foo(object $A): ?static {}}',
'<?php class T { public function Foo(object $A): ?StatiC {}}',
],
];
}
}
Loading

0 comments on commit 3057fac

Please sign in to comment.