Skip to content

Commit fc270ae

Browse files
committed
Merge remote-tracking branch 'origin/main' into feature/static-closure-improved
2 parents 64e1b4a + d1ff945 commit fc270ae

78 files changed

Lines changed: 1434 additions & 331 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/code_analysis.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050

5151
-
5252
name: 'Finalize classes'
53-
run: vendor/bin/swiss-knife finalize-classes src tests rules --dry-run
53+
run: vendor/bin/swiss-knife finalize-classes src tests rules --dry-run --skip-file="src/PhpParser/Node/FileNode.php"
5454

5555
-
5656
name: 'Check before/after test fixture on no-changes'

.github/workflows/rector_laravel_rector_dev.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ jobs:
2828
- run: git clone https://github.com/driftingly/rector-laravel.git
2929
- run: composer require rector/rector:dev-main --working-dir rector-laravel
3030
- run: cd rector-laravel && vendor/bin/phpunit
31+

UPGRADING.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,110 @@
1+
# Upgrading from Rector 2.2.14 to 2.3
2+
3+
* `FileWithoutNamespace` is deprecated, and replaced by `FileNode` that represents both namespaced and non-namespaced files and allow changes inside
4+
* `beforeTraverse()` is now marked as `@final`, use `getNodeTypes()` with `FileNode::class` instead
5+
6+
**Before**
7+
8+
```php
9+
use Rector\PhpParser\Node\FileWithoutNamespace;
10+
use Rector\Rector\AbstractRector;
11+
12+
final class SomeRector extends AbstractRector
13+
{
14+
public function getNodeTypes(): array
15+
{
16+
return [FileWithoutNamespace::class];
17+
}
18+
19+
public function beforeTraverse(array $nodes): array
20+
{
21+
// some node hacking
22+
}
23+
24+
/**
25+
* @param FileWithoutNamespace $node
26+
*/
27+
public function refactor(Node $node): ?Node
28+
{
29+
// ...
30+
}
31+
32+
}
33+
```
34+
35+
**After**
36+
37+
```php
38+
use Rector\PhpParser\Node\FileNode;
39+
use Rector\Rector\AbstractRector;
40+
41+
final class SomeRector extends AbstractRector
42+
{
43+
public function getNodeTypes(): array
44+
{
45+
return [FileNode::class];
46+
}
47+
48+
/**
49+
* @param FileNode $node
50+
*/
51+
public function refactor(Node $node): ?Node
52+
{
53+
foreach ($node->stmts as $stmt) {
54+
// check if has declare_strict already?
55+
// ...
56+
57+
// create it
58+
$declareStrictTypes = $this->createDeclareStrictTypesNode();
59+
60+
// add it
61+
$node->stmts = array_merge([$declareStrictTypes], $node->stmts);
62+
}
63+
64+
return $node;
65+
}
66+
67+
}
68+
```
69+
70+
<br>
71+
72+
The `FileNode` handles both namespaced and non-namespaced files. To handle the first stmts inside the file, you hook into 2 nodes:
73+
74+
```php
75+
use Rector\PhpParser\Node\FileNode;
76+
use Rector\Rector\AbstractRector;
77+
use PhpParser\Node\Stmt\Namespace_;
78+
79+
final class SomeRector extends AbstractRector
80+
{
81+
public function getNodeTypes(): array
82+
{
83+
return [FileNode::class, Namespace_::class];
84+
}
85+
86+
/**
87+
* @param FileNode|Namespace_ $node
88+
*/
89+
public function refactor(Node $node): ?Node
90+
{
91+
if ($node instanceof FileNode && $node->isNamespaced()) {
92+
// handled in the Namespace_ node
93+
return null;
94+
}
95+
96+
foreach ($node->stmts as $stmt) {
97+
// modify stmts in desired way here
98+
}
99+
100+
return $node;
101+
}
102+
103+
}
104+
```
105+
106+
<br>
107+
1108
# Upgrading from Rector 1.x to 2.0
2109

3110
## PHP version requirements

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"require": {
1515
"php": "^8.2",
1616
"clue/ndjson-react": "^1.3",
17-
"composer/pcre": "^3.3.0",
17+
"composer/pcre": "^3.3.2",
1818
"composer/semver": "^3.4",
1919
"composer/xdebug-handler": "^3.0.5",
2020
"doctrine/inflector": "^2.1",
@@ -50,7 +50,7 @@
5050
"phpstan/phpstan-phpunit": "^2.0",
5151
"phpstan/phpstan-webmozart-assert": "^2.0",
5252
"phpunit/phpunit": "^11.5",
53-
"rector/jack": "^0.4.0",
53+
"rector/jack": "^0.4",
5454
"rector/release-notes-generator": "^0.5",
5555
"rector/swiss-knife": "^2.3",
5656
"rector/type-perfect": "^2.1",

phpstan.neon

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ parameters:
1010

1111
# see https://phpstan.org/writing-php-code/phpdoc-types#global-type-aliases
1212
typeAliases:
13-
StmtsAware: \PhpParser\Node\Stmt\Block | \PhpParser\Node\Expr\Closure | \PhpParser\Node\Stmt\Case_ | \PhpParser\Node\Stmt\Catch_ | \PhpParser\Node\Stmt\ClassMethod | \PhpParser\Node\Stmt\Do_ | \PhpParser\Node\Stmt\Else_ | \PhpParser\Node\Stmt\ElseIf_ | \PhpParser\Node\Stmt\Finally_ | \PhpParser\Node\Stmt\For_ | \PhpParser\Node\Stmt\Foreach_ | \PhpParser\Node\Stmt\Function_ | \PhpParser\Node\Stmt\If_ | \PhpParser\Node\Stmt\Namespace_ | \PhpParser\Node\Stmt\TryCatch | \PhpParser\Node\Stmt\While_ | \Rector\PhpParser\Node\CustomNode\FileWithoutNamespace
13+
StmtsAware: \PhpParser\Node\Stmt\Block | \PhpParser\Node\Expr\Closure | \PhpParser\Node\Stmt\Case_ | \PhpParser\Node\Stmt\Catch_ | \PhpParser\Node\Stmt\ClassMethod | \PhpParser\Node\Stmt\Do_ | \PhpParser\Node\Stmt\Else_ | \PhpParser\Node\Stmt\ElseIf_ | \PhpParser\Node\Stmt\Finally_ | \PhpParser\Node\Stmt\For_ | \PhpParser\Node\Stmt\Foreach_ | \PhpParser\Node\Stmt\Function_ | \PhpParser\Node\Stmt\If_ | \PhpParser\Node\Stmt\Namespace_ | \PhpParser\Node\Stmt\TryCatch | \PhpParser\Node\Stmt\While_ | \Rector\PhpParser\Node\FileNode
1414

1515
# requires exact closure types
1616
checkMissingCallableSignature: true
@@ -160,6 +160,8 @@ parameters:
160160
- src/Validation/RectorConfigValidator.php
161161
# for phpunit version check
162162
- src/Testing/PHPUnit/AbstractLazyTestCase.php
163+
# future node class exists check
164+
- src/Reporting/DeprecatedRulesReporter.php
163165

164166
# use of internal phpstan classes
165167
-
@@ -187,8 +189,10 @@ parameters:
187189
message: '#Method Rector\\Util\\ArrayParametersMerger\:\:mergeLeftToRightWithCallable\(\) has parameter \$mergeCallback with no signature specified for callable#'
188190
path: src/Util/ArrayParametersMerger.php
189191

190-
# fixture class
191-
- '#Class "Rector\\Tests\\Issues\\ScopeNotAvailable\\Variable\\ArrayItemForeachValueRector" is missing @see annotation with test case class reference#'
192+
# fixture Rector rules
193+
-
194+
identifier: symplify.seeAnnotationToTest
195+
path: tests/Issues/
192196

193197
# classes are part of *.php.inc fixture
194198
-
@@ -284,7 +288,6 @@ parameters:
284288
- src/Configuration/RectorConfigBuilder.php
285289
- src/Reporting/DeprecatedRulesReporter.php
286290
identifier: classConstant.deprecatedInterface
287-
- '#Class Rector\\PhpParser\\Node\\CustomNode\\FileWithoutNamespace implements deprecated interface Rector\\Contract\\PhpParser\\Node\\StmtsAwareInterface#'
288291

289292
# allowed internally only
290293
-
@@ -324,6 +327,11 @@ parameters:
324327
- '#expects array<PhpParser\\Node\\Stmt>, array<PhpParser\\Node> given#'
325328
- '#should return non\-empty\-string but returns string#'
326329

330+
# known non-empty class method
331+
-
332+
message: '#Offset 0 might not exist on array<PhpParser\\Node\\Stmt>\|null#'
333+
path: rules/DeadCode/Rector/ClassMethod/RemoveParentDelegatingConstructorRector.php
334+
327335
# false positive, can accept non-class string
328336
- '#Parameter \#1 \$name of method PHPStan\\BetterReflection\\Reflection\\Adapter\\ReflectionClass\:\:getAttributes\(\) expects class\-string\|null, string given#'
329337

@@ -391,12 +399,6 @@ parameters:
391399
paths:
392400
- rules/Php70/Rector/If_/IfToSpaceshipRector.php
393401

394-
# handles full file
395-
-
396-
paths:
397-
- rules/TypeDeclaration/Rector/StmtsAwareInterface/IncreaseDeclareStrictTypesRector.php
398-
identifier: rector.noOnlyNullReturnInRefactor
399-
400402
-
401403
identifier: rector.noIntegerRefactorReturn
402404
paths:
@@ -409,22 +411,22 @@ parameters:
409411
# condition check, just to be sure
410412
- '#Method Rector\\Rector\\AbstractRector\:\:enterNode\(\) never returns 3 so it can be removed from the return type#'
411413

412-
# special case, working on a file-level
413-
-
414-
identifier: rector.noOnlyNullReturnInRefactor
415-
path: rules/TypeDeclaration/Rector/StmtsAwareInterface/DeclareStrictTypesRector.php
416-
417-
# handle next with FileNode
418-
-
419-
identifier: method.parentMethodFinalByPhpDoc
420-
path: rules/TypeDeclaration/Rector/StmtsAwareInterface/DeclareStrictTypesRector.php
421-
422414
# deprecated
423415
-
424416
identifier: public.method.unused
425417
paths:
426418
- rules/Transform/ValueObject/ClassMethodReference.php
427419
- rules/CodeQuality/ValueObject/KeyAndExpr.php
420+
-
421+
identifier: symplify.forbiddenExtendOfNonAbstractClass
422+
path: src/PhpParser/Node/FileNode.php
423+
-
424+
identifier: method.deprecatedClass
425+
path: src/PhpParser/Node/FileNode.php
426+
427+
-
428+
identifier: class.extendsDeprecatedClass
429+
path: src/PhpParser/Node/FileNode.php
428430

429431
-
430432
identifier: public.classConstant.unused
@@ -433,13 +435,32 @@ parameters:
433435
- rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php
434436
- rules/Php81/Enum/AttributeName.php
435437

438+
-
439+
identifier: symplify.seeAnnotationToTest
440+
paths:
441+
- tests/PhpParser/NodeTraverser/StopTraverseOnTypeChange/Class_
442+
436443
# deprecated rule
437444
- '#Rule Rector\\Php81\\Rector\\Array_\\FirstClassCallableRector must implements Rector\\VersionBonding\\Contract\\MinPhpVersionInterface#'
438445
- '#Register "Rector\\Php81\\Rector\\Array_\\FirstClassCallableRector" service to "php81\.php" config set#'
439446
- '#Class "Rector\\CodingStyle\\Rector\\String_\\SymplifyQuoteEscapeRector" is missing @see annotation with test case class reference#'
440447
- '#Access to constant on deprecated class Rector\\Php81\\Rector\\Array_\\FirstClassCallableRector#'
448+
449+
# BC layer for FileWithoutNamespace node
450+
- message: '#Use @see \\Rector\\PhpParser\\Node\\FileNode instead#'
451+
- '#BC layer for FileNode and FileWithoutNamespace compat, use FileNode instead#'
452+
-
453+
path: src/PhpParser/Node/CustomNode/FileWithoutNamespace.php
454+
identifier: symplify.forbiddenExtendOfNonAbstractClass
441455
-
442456
message: '#Only abstract classes can be extended#'
443457
path: rules/Php81/Rector/Array_/FirstClassCallableRector.php
444458

459+
- '#Method Rector\\Tests\\Issues\\FileWithoutNamespaceCompat\\Rector\\SubscribedToFileWithoutNamespaceRector\:\:refactor\(\) should return Rector\\PhpParser\\Node\\FileNode but returns Rector\\PhpParser\\Node\\CustomNode\\FileWithoutNamespace#'
445460

461+
# BC layer for FileWithoutNamespace node
462+
- message: '#Use @see \\Rector\\PhpParser\\Node\\FileNode instead#'
463+
- '#Class Rector\\PhpParser\\Node\\CustomNode\\FileWithoutNamespace extends final class Rector\\PhpParser\\Node\\FileNode#'
464+
-
465+
path: src/PhpParser/Node/CustomNode/FileWithoutNamespace.php
466+
identifier: symplify.forbiddenExtendOfNonAbstractClass
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector\Fixture;
4+
5+
use PhpParser\Node\Scalar\String_;
6+
7+
final class SomeDifferentArgs extends String_
8+
{
9+
public function __construct($value, $attributes)
10+
{
11+
parent::__construct($value, []);
12+
}
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector\Fixture;
4+
5+
use PhpParser\Node\Scalar\String_;
6+
7+
final class SkipDifferentCount extends String_
8+
{
9+
public function __construct($value)
10+
{
11+
parent::__construct($value, []);
12+
}
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector\Fixture;
6+
7+
use PhpParser\NodeTraverser;
8+
use Rector\Comments\NodeVisitor\CommentRemovingNodeVisitor;
9+
10+
final class SkipDifferentType extends NodeTraverser
11+
{
12+
public function __construct(CommentRemovingNodeVisitor $commentRemovingNodeVisitor)
13+
{
14+
parent::__construct($commentRemovingNodeVisitor);
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector\Fixture;
4+
5+
use PhpParser\Node\Scalar\String_;
6+
7+
final class SkipFirstClassCallable extends String_
8+
{
9+
public function __construct($value, $attributes)
10+
{
11+
parent::__construct(...);
12+
}
13+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector\Fixture;
4+
5+
use PhpParser\Node\Scalar\String_;
6+
7+
final class SomeClass extends String_
8+
{
9+
public function __construct($value, $attributes)
10+
{
11+
parent::__construct($value, $attributes);
12+
}
13+
}
14+
15+
?>
16+
-----
17+
<?php
18+
19+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector\Fixture;
20+
21+
use PhpParser\Node\Scalar\String_;
22+
23+
final class SomeClass extends String_
24+
{
25+
}
26+
27+
?>

0 commit comments

Comments
 (0)