Skip to content

Commit fbb95aa

Browse files
authored
[dx] add withTypeCoverageDocblockLevel() (#7363)
* [dx] split of TypeDeclarationDocblockLevel * [dx] add withTypeCoverageDocblockLevel()fs * avoid duplicate registration
1 parent 03efcf0 commit fbb95aa

File tree

3 files changed

+104
-37
lines changed

3 files changed

+104
-37
lines changed

config/set/type-declaration-docblocks.php

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,12 @@
22

33
declare(strict_types=1);
44

5+
use Rector\Config\Level\TypeDeclarationDocblocksLevel;
56
use Rector\Config\RectorConfig;
6-
use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnArrayDocblockBasedOnArrayMapRector;
7-
use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnDocblockForScalarArrayFromAssignsRector;
8-
use Rector\TypeDeclarationDocblocks\Rector\Class_\AddReturnDocblockDataProviderRector;
9-
use Rector\TypeDeclarationDocblocks\Rector\Class_\ClassMethodArrayDocblockParamFromLocalCallsRector;
10-
use Rector\TypeDeclarationDocblocks\Rector\Class_\DocblockVarArrayFromGetterReturnRector;
11-
use Rector\TypeDeclarationDocblocks\Rector\Class_\DocblockVarArrayFromPropertyDefaultsRector;
12-
use Rector\TypeDeclarationDocblocks\Rector\Class_\DocblockVarFromParamDocblockInConstructorRector;
13-
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddParamArrayDocblockFromDataProviderRector;
14-
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddParamArrayDocblockFromDimFetchAccessRector;
15-
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForArrayDimAssignedObjectRector;
16-
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForCommonObjectDenominatorRector;
17-
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForJsonArrayRector;
18-
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\DocblockGetterReturnArrayFromPropertyDocblockVarRector;
19-
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\DocblockReturnArrayFromDirectArrayInstanceRector;
207

218
/**
229
* @experimental * 2025-09, experimental hidden set for type declaration in docblocks
2310
*/
2411
return static function (RectorConfig $rectorConfig): void {
25-
$rectorConfig->rules([
26-
// property var
27-
DocblockVarFromParamDocblockInConstructorRector::class,
28-
DocblockVarArrayFromPropertyDefaultsRector::class,
29-
DocblockVarArrayFromGetterReturnRector::class,
30-
31-
// param
32-
AddParamArrayDocblockFromDimFetchAccessRector::class,
33-
ClassMethodArrayDocblockParamFromLocalCallsRector::class,
34-
35-
// return
36-
DocblockGetterReturnArrayFromPropertyDocblockVarRector::class,
37-
AddReturnDocblockForCommonObjectDenominatorRector::class,
38-
AddReturnArrayDocblockBasedOnArrayMapRector::class,
39-
AddReturnDocblockForScalarArrayFromAssignsRector::class,
40-
DocblockReturnArrayFromDirectArrayInstanceRector::class,
41-
AddReturnDocblockForArrayDimAssignedObjectRector::class,
42-
AddReturnDocblockForJsonArrayRector::class,
43-
44-
// tests
45-
AddParamArrayDocblockFromDataProviderRector::class,
46-
AddReturnDocblockDataProviderRector::class,
47-
]);
12+
$rectorConfig->rules(TypeDeclarationDocblocksLevel::RULES);
4813
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Config\Level;
6+
7+
use Rector\Contract\Rector\RectorInterface;
8+
use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnArrayDocblockBasedOnArrayMapRector;
9+
use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnDocblockForScalarArrayFromAssignsRector;
10+
use Rector\TypeDeclarationDocblocks\Rector\Class_\AddReturnDocblockDataProviderRector;
11+
use Rector\TypeDeclarationDocblocks\Rector\Class_\ClassMethodArrayDocblockParamFromLocalCallsRector;
12+
use Rector\TypeDeclarationDocblocks\Rector\Class_\DocblockVarArrayFromGetterReturnRector;
13+
use Rector\TypeDeclarationDocblocks\Rector\Class_\DocblockVarArrayFromPropertyDefaultsRector;
14+
use Rector\TypeDeclarationDocblocks\Rector\Class_\DocblockVarFromParamDocblockInConstructorRector;
15+
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddParamArrayDocblockFromDataProviderRector;
16+
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddParamArrayDocblockFromDimFetchAccessRector;
17+
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForArrayDimAssignedObjectRector;
18+
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForCommonObjectDenominatorRector;
19+
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\AddReturnDocblockForJsonArrayRector;
20+
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\DocblockGetterReturnArrayFromPropertyDocblockVarRector;
21+
use Rector\TypeDeclarationDocblocks\Rector\ClassMethod\DocblockReturnArrayFromDirectArrayInstanceRector;
22+
23+
final class TypeDeclarationDocblocksLevel
24+
{
25+
/**
26+
* @var array<class-string<RectorInterface>>
27+
*/
28+
public const RULES = [
29+
// start with rules based on native code
30+
// property var
31+
DocblockVarArrayFromPropertyDefaultsRector::class,
32+
33+
// tests
34+
AddParamArrayDocblockFromDataProviderRector::class,
35+
AddReturnDocblockDataProviderRector::class,
36+
37+
// param
38+
AddParamArrayDocblockFromDimFetchAccessRector::class,
39+
ClassMethodArrayDocblockParamFromLocalCallsRector::class,
40+
41+
// return
42+
AddReturnDocblockForCommonObjectDenominatorRector::class,
43+
AddReturnArrayDocblockBasedOnArrayMapRector::class,
44+
AddReturnDocblockForScalarArrayFromAssignsRector::class,
45+
DocblockReturnArrayFromDirectArrayInstanceRector::class,
46+
AddReturnDocblockForArrayDimAssignedObjectRector::class,
47+
AddReturnDocblockForJsonArrayRector::class,
48+
49+
// move to rules based on existing docblocks, as more risky
50+
// property var
51+
DocblockVarFromParamDocblockInConstructorRector::class,
52+
DocblockVarArrayFromGetterReturnRector::class,
53+
54+
// return
55+
DocblockGetterReturnArrayFromPropertyDocblockVarRector::class,
56+
];
57+
}

src/Configuration/RectorConfigBuilder.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Rector\Config\Level\CodeQualityLevel;
1212
use Rector\Config\Level\CodingStyleLevel;
1313
use Rector\Config\Level\DeadCodeLevel;
14+
use Rector\Config\Level\TypeDeclarationDocblocksLevel;
1415
use Rector\Config\Level\TypeDeclarationLevel;
1516
use Rector\Config\RectorConfig;
1617
use Rector\Config\RegisteredService;
@@ -141,6 +142,8 @@ final class RectorConfigBuilder
141142
*/
142143
private ?bool $isTypeCoverageLevelUsed = null;
143144

145+
private ?bool $isTypeCoverageDocblockLevelUsed = null;
146+
144147
private ?bool $isDeadCodeLevelUsed = null;
145148

146149
private ?bool $isCodeQualityLevelUsed = null;
@@ -224,6 +227,17 @@ public function __invoke(RectorConfig $rectorConfig): void
224227
));
225228
}
226229

230+
if (in_array(
231+
SetList::TYPE_DECLARATION_DOCBLOCKS,
232+
$uniqueSets,
233+
true
234+
) && $this->isTypeCoverageDocblockLevelUsed === true) {
235+
throw new InvalidConfigurationException(sprintf(
236+
'Your config already enables type declarations set.%sRemove "->withTypeCoverageDocblockLevel()" as it only duplicates it, or remove type declaration set.',
237+
PHP_EOL
238+
));
239+
}
240+
227241
if (in_array(SetList::DEAD_CODE, $uniqueSets, true) && $this->isDeadCodeLevelUsed === true) {
228242
throw new InvalidConfigurationException(sprintf(
229243
'Your config already enables dead code set.%sRemove "->withDeadCodeLevel()" as it only duplicates it, or remove dead code set.',
@@ -742,6 +756,7 @@ public function withPreparedSets(
742756
bool $codeQuality = false,
743757
bool $codingStyle = false,
744758
bool $typeDeclarations = false,
759+
bool $typeDeclarationDocblocks = false,
745760
bool $privatization = false,
746761
bool $naming = false,
747762
bool $instanceOf = false,
@@ -761,6 +776,7 @@ public function withPreparedSets(
761776
SetList::CODE_QUALITY => $codeQuality,
762777
SetList::CODING_STYLE => $codingStyle,
763778
SetList::TYPE_DECLARATION => $typeDeclarations,
779+
SetList::TYPE_DECLARATION_DOCBLOCKS => $typeDeclarationDocblocks,
764780
SetList::PRIVATIZATION => $privatization,
765781
SetList::NAMING => $naming,
766782
SetList::INSTANCEOF => $instanceOf,
@@ -1019,6 +1035,35 @@ public function withTypeCoverageLevel(int $level): self
10191035
return $this;
10201036
}
10211037

1038+
/**
1039+
* Raise your type coverage docblock from the safest type rules
1040+
* to more affecting ones, one level at a time
1041+
*/
1042+
public function withTypeCoverageDocblockLevel(int $level): self
1043+
{
1044+
Assert::natural($level);
1045+
1046+
$this->isTypeCoverageDocblockLevelUsed = true;
1047+
1048+
$levelRules = LevelRulesResolver::resolve($level, TypeDeclarationDocblocksLevel::RULES, __METHOD__);
1049+
1050+
// too high
1051+
$levelRulesCount = count($levelRules);
1052+
if ($levelRulesCount + self::MAX_LEVEL_GAP < $level) {
1053+
$this->levelOverflows[] = new LevelOverflow(
1054+
__METHOD__,
1055+
$level,
1056+
$levelRulesCount,
1057+
'TypeDeclarationDocblocksLevel',
1058+
'TYPE_DECLARATION_DOCBLOCKS'
1059+
);
1060+
}
1061+
1062+
$this->rules = array_merge($this->rules, $levelRules);
1063+
1064+
return $this;
1065+
}
1066+
10221067
/**
10231068
* Raise your dead-code coverage from the safest rules
10241069
* to more affecting ones, one level at a time

0 commit comments

Comments
 (0)