From 184dc38e62a2b53e723ce1001cf270882fd762bb Mon Sep 17 00:00:00 2001 From: Caleb White Date: Tue, 25 Aug 2026 21:30:43 -0500 Subject: [PATCH] Register conditionally enabled rules with attributes Adds the optional enabledBy parameter to RegisteredRule and RegisteredCollector. It accepts a boolean parameter reference and only adds the rule or collector tag when that parameter is enabled. This moves PHPStan's 18 conditionally registered rules out of conditionalTags and service definitions and onto the rule classes. The five conditional restricted-usage extension tags remain in NEON because they are not rules or collectors. --- conf/config.level0.neon | 5 -- conf/config.level1.neon | 8 --- conf/config.level2.neon | 10 ---- conf/config.level4.neon | 42 ------------- conf/config.level5.neon | 18 ------ conf/config.neon | 29 --------- .../AutowiredAttributeServicesExtension.php | 59 +++++++++++++++++-- .../RegisteredCollector.php | 6 +- src/DependencyInjection/RegisteredRule.php | 6 +- ...wStaticInAbstractClassStaticMethodRule.php | 2 + ...possibleInArrayHaystackFiniteTypesRule.php | 4 ++ src/Rules/Comparison/SwitchConditionRule.php | 4 ++ .../Constants/ValueAssignedToDefineRule.php | 2 + .../ValueAssignedToGlobalConstantRule.php | 2 + src/Rules/DateIntervalInstantiationRule.php | 2 + .../MethodThrowTypeCovarianceRule.php | 4 ++ ...ngCheckedExceptionInFunctionThrowsRule.php | 2 + ...singCheckedExceptionInMethodThrowsRule.php | 2 + ...eckedExceptionInPropertyHookThrowsRule.php | 2 + .../TooWideFunctionThrowTypeRule.php | 2 + .../Exceptions/TooWideMethodThrowTypeRule.php | 5 ++ .../TooWidePropertyHookThrowTypeRule.php | 4 ++ .../ParameterCastableToNumberRule.php | 2 + .../Functions/PrintfParameterTypeRule.php | 4 ++ src/Rules/Keywords/UnusedLabelRule.php | 2 + .../Properties/UninitializedPropertyRule.php | 2 + .../AssignToByRefExprFromForeachRule.php | 2 + 27 files changed, 114 insertions(+), 118 deletions(-) diff --git a/conf/config.level0.neon b/conf/config.level0.neon index 805ea348a91..c6020232152 100644 --- a/conf/config.level0.neon +++ b/conf/config.level0.neon @@ -12,13 +12,8 @@ conditionalTags: phpstan.restrictedClassNameUsageExtension: %featureToggles.internalTag% PHPStan\Rules\InternalTag\RestrictedInternalFunctionUsageExtension: phpstan.restrictedFunctionUsageExtension: %featureToggles.internalTag% - PHPStan\Rules\Classes\NewStaticInAbstractClassStaticMethodRule: - phpstan.rules.rule: %featureToggles.newStaticInAbstractClassStaticMethod% services: - - - class: PHPStan\Rules\Classes\NewStaticInAbstractClassStaticMethodRule - - class: PHPStan\Rules\InternalTag\RestrictedInternalClassConstantUsageExtension diff --git a/conf/config.level1.neon b/conf/config.level1.neon index 70f5a903f8d..9dc4f8bc670 100644 --- a/conf/config.level1.neon +++ b/conf/config.level1.neon @@ -10,11 +10,3 @@ parameters: autowiredAttributeServices: # registers rules with #[RegisteredRule] attribute level: 1 - -conditionalTags: - PHPStan\Rules\Variables\AssignToByRefExprFromForeachRule: - phpstan.rules.rule: %featureToggles.assignToByRefForeachExpr% - -services: - - - class: PHPStan\Rules\Variables\AssignToByRefExprFromForeachRule diff --git a/conf/config.level2.neon b/conf/config.level2.neon index bb615c07c34..dd50138b541 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -15,10 +15,6 @@ conditionalTags: phpstan.restrictedPropertyUsageExtension: %featureToggles.internalTag% PHPStan\Rules\InternalTag\RestrictedInternalMethodUsageExtension: phpstan.restrictedMethodUsageExtension: %featureToggles.internalTag% - PHPStan\Rules\Constants\ValueAssignedToDefineRule: - phpstan.rules.rule: %featureToggles.checkDynamicConstantNameValues% - PHPStan\Rules\Constants\ValueAssignedToGlobalConstantRule: - phpstan.rules.rule: %featureToggles.checkDynamicConstantNameValues% services: - @@ -26,9 +22,3 @@ services: - class: PHPStan\Rules\InternalTag\RestrictedInternalMethodUsageExtension - - - - class: PHPStan\Rules\Constants\ValueAssignedToDefineRule - - - - class: PHPStan\Rules\Constants\ValueAssignedToGlobalConstantRule diff --git a/conf/config.level4.neon b/conf/config.level4.neon index 4206d36d3c1..06cd652606b 100644 --- a/conf/config.level4.neon +++ b/conf/config.level4.neon @@ -5,47 +5,5 @@ autowiredAttributeServices: # registers rules with #[RegisteredRule] and #[RegisteredCollector] attributes level: 4 -conditionalTags: - PHPStan\Rules\Exceptions\TooWideFunctionThrowTypeRule: - phpstan.rules.rule: %exceptions.check.tooWideThrowType% - PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule: - phpstan.rules.rule: %exceptions.check.tooWideThrowType% - PHPStan\Rules\Exceptions\TooWidePropertyHookThrowTypeRule: - phpstan.rules.rule: %exceptions.check.tooWideThrowType% - PHPStan\Rules\Keywords\UnusedLabelRule: - phpstan.rules.rule: %featureToggles.unusedLabel% - PHPStan\Rules\Comparison\ImpossibleInArrayHaystackFiniteTypesRule: - phpstan.rules.rule: %featureToggles.finiteTypesInHaystack% - PHPStan\Rules\Comparison\SwitchConditionRule: - phpstan.rules.rule: %featureToggles.switchConditionAlwaysFalse% - parameters: checkAdvancedIsset: true - -services: - - - class: PHPStan\Rules\Exceptions\TooWideFunctionThrowTypeRule - - - - class: PHPStan\Rules\Exceptions\TooWideMethodThrowTypeRule - arguments: - checkProtectedAndPublicMethods: %checkTooWideThrowTypesInProtectedAndPublicMethods% - tooWideImplicitThrows: %exceptions.check.tooWideImplicitThrowType% - - - - class: PHPStan\Rules\Exceptions\TooWidePropertyHookThrowTypeRule - arguments: - checkProtectedAndPublicMethods: %checkTooWideThrowTypesInProtectedAndPublicMethods% - - - - class: PHPStan\Rules\Keywords\UnusedLabelRule - - - - class: PHPStan\Rules\Comparison\ImpossibleInArrayHaystackFiniteTypesRule - arguments: - treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% - - - - class: PHPStan\Rules\Comparison\SwitchConditionRule - arguments: - treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% diff --git a/conf/config.level5.neon b/conf/config.level5.neon index 534d58dde0b..a5719c183ec 100644 --- a/conf/config.level5.neon +++ b/conf/config.level5.neon @@ -5,24 +5,6 @@ parameters: checkFunctionArgumentTypes: true checkArgumentsPassedByReference: true -conditionalTags: - PHPStan\Rules\Functions\ParameterCastableToNumberRule: - phpstan.rules.rule: %featureToggles.checkParameterCastableToNumberFunctions% - PHPStan\Rules\Functions\PrintfParameterTypeRule: - phpstan.rules.rule: %featureToggles.checkPrintfParameterTypes% - PHPStan\Rules\DateIntervalInstantiationRule: - phpstan.rules.rule: %featureToggles.checkDateIntervalConstructor% - autowiredAttributeServices: # registers rules with #[RegisteredRule] attribute level: 5 - -services: - - - class: PHPStan\Rules\Functions\ParameterCastableToNumberRule - - - class: PHPStan\Rules\Functions\PrintfParameterTypeRule - arguments: - checkStrictPrintfPlaceholderTypes: %checkStrictPrintfPlaceholderTypes% - - - class: PHPStan\Rules\DateIntervalInstantiationRule diff --git a/conf/config.neon b/conf/config.neon index 74db379e5b7..864255c3169 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -260,36 +260,7 @@ parameters: autowiredAttributeServices: level: null -conditionalTags: - PHPStan\Rules\Exceptions\MissingCheckedExceptionInFunctionThrowsRule: - phpstan.rules.rule: %exceptions.check.missingCheckedExceptionInThrows% - PHPStan\Rules\Exceptions\MissingCheckedExceptionInMethodThrowsRule: - phpstan.rules.rule: %exceptions.check.missingCheckedExceptionInThrows% - PHPStan\Rules\Exceptions\MissingCheckedExceptionInPropertyHookThrowsRule: - phpstan.rules.rule: %exceptions.check.missingCheckedExceptionInThrows% - PHPStan\Rules\Properties\UninitializedPropertyRule: - phpstan.rules.rule: %checkUninitializedProperties% - PHPStan\Rules\Exceptions\MethodThrowTypeCovarianceRule: - phpstan.rules.rule: %exceptions.check.throwTypeCovariance% - services: - - - class: PHPStan\Rules\Exceptions\MissingCheckedExceptionInFunctionThrowsRule - - - - class: PHPStan\Rules\Exceptions\MissingCheckedExceptionInMethodThrowsRule - - - - class: PHPStan\Rules\Exceptions\MissingCheckedExceptionInPropertyHookThrowsRule - - - - class: PHPStan\Rules\Properties\UninitializedPropertyRule - - - - class: PHPStan\Rules\Exceptions\MethodThrowTypeCovarianceRule - arguments: - implicitThrows: %exceptions.implicitThrows% - # autowired services are now registered with the help of attributes # like #[PHPStan\DependencyInjection\AutowiredService] or #[PHPStan\DependencyInjection\GenerateFactory] diff --git a/src/DependencyInjection/AutowiredAttributeServicesExtension.php b/src/DependencyInjection/AutowiredAttributeServicesExtension.php index 6f71bd6b86a..40240d85cf7 100644 --- a/src/DependencyInjection/AutowiredAttributeServicesExtension.php +++ b/src/DependencyInjection/AutowiredAttributeServicesExtension.php @@ -27,6 +27,8 @@ use function explode; use function implode; use function is_array; +use function is_bool; +use function preg_match; use function preg_split; use function sprintf; use function strcasecmp; @@ -38,6 +40,9 @@ final class AutowiredAttributeServicesExtension extends CompilerExtension { + /** @var list */ + private array $conditionalTags = []; + #[Override] public function getConfigSchema(): Schema { @@ -133,9 +138,9 @@ public function loadConfiguration(): void $definition = $builder->addDefinition(null) ->setFactory($class->name) - ->setAutowired($class->name) - ->addTag(LazyRegistry::RULE_TAG); + ->setAutowired($class->name); + $this->tag($definition, LazyRegistry::RULE_TAG, $attribute->enabledBy); self::processConstructorParameters($builder, $class->name, $definition, $constructorParameters); } @@ -147,13 +152,59 @@ public function loadConfiguration(): void $definition = $builder->addDefinition(null) ->setFactory($class->name) - ->setAutowired($class->name) - ->addTag(RegistryFactory::COLLECTOR_TAG); + ->setAutowired($class->name); + $this->tag($definition, RegistryFactory::COLLECTOR_TAG, $attribute->enabledBy); self::processConstructorParameters($builder, $class->name, $definition, $constructorParameters); } } + private function tag(ServiceDefinition $definition, string $tag, ?string $enabledBy): void + { + if ($enabledBy === null) { + $definition->addTag($tag); + + return; + } + + $this->conditionalTags[] = [$definition, $tag, $enabledBy]; + } + + #[Override] + public function beforeCompile(): void + { + $builder = $this->getContainerBuilder(); + foreach ($this->conditionalTags as [$definition, $tag, $enabledBy]) { + if (!self::resolveCondition($builder, $enabledBy)) { + continue; + } + + $definition->addTag($tag); + } + } + + private static function resolveCondition(ContainerBuilder $builder, string $enabledBy): bool + { + if (preg_match('#^%([\w.-]+)%$#D', $enabledBy, $matches) !== 1) { + throw new ShouldNotHappenException(sprintf('enabledBy must be a parameter reference, %s given.', $enabledBy)); + } + + $parameter = $builder->parameters; + foreach (explode('.', $matches[1]) as $key) { + if (!is_array($parameter) || !array_key_exists($key, $parameter)) { + throw new ShouldNotHappenException(sprintf("Missing parameter '%s'.", $matches[1])); + } + + $parameter = $parameter[$key]; + } + + if (!is_bool($parameter)) { + throw new ShouldNotHappenException(sprintf('Parameter %s referenced by enabledBy must be bool.', $enabledBy)); + } + + return $parameter; + } + /** * @param class-string $className * @param array>> $constructorParameters diff --git a/src/DependencyInjection/RegisteredCollector.php b/src/DependencyInjection/RegisteredCollector.php index 42af140bfcf..7916575b1a3 100644 --- a/src/DependencyInjection/RegisteredCollector.php +++ b/src/DependencyInjection/RegisteredCollector.php @@ -7,6 +7,10 @@ /** * Registers a collector in the DI container on the set rule level. * + * Pass enabledBy a `%parameter%` reference to make the registration depend on + * configuration, the way a `conditionalTags` entry would. The collector is only + * tagged when the parameter is truthy. + * * Works thanks to https://github.com/ondrejmirtes/composer-attribute-collector * and AutowiredAttributeServicesExtension. */ @@ -14,7 +18,7 @@ final class RegisteredCollector { - public function __construct(public int $level) + public function __construct(public int $level, public ?string $enabledBy = null) { } diff --git a/src/DependencyInjection/RegisteredRule.php b/src/DependencyInjection/RegisteredRule.php index 3bb80348d50..8590cb93b94 100644 --- a/src/DependencyInjection/RegisteredRule.php +++ b/src/DependencyInjection/RegisteredRule.php @@ -7,6 +7,10 @@ /** * Registers a rule in the DI container on the set rule level. * + * Pass enabledBy a `%parameter%` reference to make the registration depend on + * configuration, the way a `conditionalTags` entry would. The rule is only + * tagged when the parameter is truthy. + * * Works thanks to https://github.com/ondrejmirtes/composer-attribute-collector * and AutowiredAttributeServicesExtension. */ @@ -14,7 +18,7 @@ final class RegisteredRule { - public function __construct(public int $level) + public function __construct(public int $level, public ?string $enabledBy = null) { } diff --git a/src/Rules/Classes/NewStaticInAbstractClassStaticMethodRule.php b/src/Rules/Classes/NewStaticInAbstractClassStaticMethodRule.php index 0b2842648b2..38cc6fb9bc4 100644 --- a/src/Rules/Classes/NewStaticInAbstractClassStaticMethodRule.php +++ b/src/Rules/Classes/NewStaticInAbstractClassStaticMethodRule.php @@ -4,6 +4,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -13,6 +14,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 0, enabledBy: '%featureToggles.newStaticInAbstractClassStaticMethod%')] final class NewStaticInAbstractClassStaticMethodRule implements Rule { diff --git a/src/Rules/Comparison/ImpossibleInArrayHaystackFiniteTypesRule.php b/src/Rules/Comparison/ImpossibleInArrayHaystackFiniteTypesRule.php index 621b94a7c50..c286bd6c665 100644 --- a/src/Rules/Comparison/ImpossibleInArrayHaystackFiniteTypesRule.php +++ b/src/Rules/Comparison/ImpossibleInArrayHaystackFiniteTypesRule.php @@ -5,6 +5,8 @@ use PhpParser\Node; use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\AutowiredParameter; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\Rule; @@ -30,6 +32,7 @@ * * @implements Rule */ +#[RegisteredRule(level: 4, enabledBy: '%featureToggles.finiteTypesInHaystack%')] final class ImpossibleInArrayHaystackFiniteTypesRule implements Rule { @@ -42,6 +45,7 @@ final class ImpossibleInArrayHaystackFiniteTypesRule implements Rule public function __construct( private InitializerExprTypeResolver $initializerExprTypeResolver, + #[AutowiredParameter(ref: '%treatPhpDocTypesAsCertain%')] private bool $treatPhpDocTypesAsCertain, ) { diff --git a/src/Rules/Comparison/SwitchConditionRule.php b/src/Rules/Comparison/SwitchConditionRule.php index cc030c0b9ad..37bb26753c8 100644 --- a/src/Rules/Comparison/SwitchConditionRule.php +++ b/src/Rules/Comparison/SwitchConditionRule.php @@ -7,6 +7,8 @@ use PHPStan\Analyser\CollectedDataEmitter; use PHPStan\Analyser\NodeCallbackInvoker; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\AutowiredParameter; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Node\SwitchConditionNode; use PHPStan\Php\PhpVersion; @@ -20,6 +22,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 4, enabledBy: '%featureToggles.switchConditionAlwaysFalse%')] final class SwitchConditionRule implements Rule { @@ -29,6 +32,7 @@ public function __construct( private ConstantConditionInTraitHelper $constantConditionInTraitHelper, private ExprPrinter $exprPrinter, private PhpVersion $phpVersion, + #[AutowiredParameter(ref: '%treatPhpDocTypesAsCertain%')] private bool $treatPhpDocTypesAsCertain, ) { diff --git a/src/Rules/Constants/ValueAssignedToDefineRule.php b/src/Rules/Constants/ValueAssignedToDefineRule.php index 75af39cca47..2e3711b98d5 100644 --- a/src/Rules/Constants/ValueAssignedToDefineRule.php +++ b/src/Rules/Constants/ValueAssignedToDefineRule.php @@ -6,6 +6,7 @@ use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\ConstantResolver; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\VerbosityLevel; @@ -16,6 +17,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 2, enabledBy: '%featureToggles.checkDynamicConstantNameValues%')] final class ValueAssignedToDefineRule implements Rule { diff --git a/src/Rules/Constants/ValueAssignedToGlobalConstantRule.php b/src/Rules/Constants/ValueAssignedToGlobalConstantRule.php index dd75bddd0c0..a079008fe17 100644 --- a/src/Rules/Constants/ValueAssignedToGlobalConstantRule.php +++ b/src/Rules/Constants/ValueAssignedToGlobalConstantRule.php @@ -5,6 +5,7 @@ use PhpParser\Node; use PHPStan\Analyser\ConstantResolver; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\VerbosityLevel; @@ -13,6 +14,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 2, enabledBy: '%featureToggles.checkDynamicConstantNameValues%')] final class ValueAssignedToGlobalConstantRule implements Rule { diff --git a/src/Rules/DateIntervalInstantiationRule.php b/src/Rules/DateIntervalInstantiationRule.php index 97e5753aa1d..2601f16f370 100644 --- a/src/Rules/DateIntervalInstantiationRule.php +++ b/src/Rules/DateIntervalInstantiationRule.php @@ -6,6 +6,7 @@ use PhpParser\Node; use PhpParser\Node\Expr\New_; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use Throwable; use function count; use function sprintf; @@ -14,6 +15,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 5, enabledBy: '%featureToggles.checkDateIntervalConstructor%')] final class DateIntervalInstantiationRule implements Rule { diff --git a/src/Rules/Exceptions/MethodThrowTypeCovarianceRule.php b/src/Rules/Exceptions/MethodThrowTypeCovarianceRule.php index e723ef21fe6..1624c3d7db6 100644 --- a/src/Rules/Exceptions/MethodThrowTypeCovarianceRule.php +++ b/src/Rules/Exceptions/MethodThrowTypeCovarianceRule.php @@ -4,6 +4,8 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\AutowiredParameter; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\InClassMethodNode; use PHPStan\Rules\Methods\ParentMethodHelper; use PHPStan\Rules\Rule; @@ -17,11 +19,13 @@ /** * @implements Rule */ +#[RegisteredRule(level: 0, enabledBy: '%exceptions.check.throwTypeCovariance%')] final class MethodThrowTypeCovarianceRule implements Rule { public function __construct( private ParentMethodHelper $parentMethodHelper, + #[AutowiredParameter(ref: '%exceptions.implicitThrows%')] private bool $implicitThrows, ) { diff --git a/src/Rules/Exceptions/MissingCheckedExceptionInFunctionThrowsRule.php b/src/Rules/Exceptions/MissingCheckedExceptionInFunctionThrowsRule.php index f3ed6e08f89..8e320f2ed1d 100644 --- a/src/Rules/Exceptions/MissingCheckedExceptionInFunctionThrowsRule.php +++ b/src/Rules/Exceptions/MissingCheckedExceptionInFunctionThrowsRule.php @@ -4,6 +4,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\FunctionReturnStatementsNode; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -12,6 +13,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 0, enabledBy: '%exceptions.check.missingCheckedExceptionInThrows%')] final class MissingCheckedExceptionInFunctionThrowsRule implements Rule { diff --git a/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php b/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php index c564711b2f7..4d356679770 100644 --- a/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php +++ b/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php @@ -4,6 +4,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\MethodReturnStatementsNode; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -12,6 +13,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 0, enabledBy: '%exceptions.check.missingCheckedExceptionInThrows%')] final class MissingCheckedExceptionInMethodThrowsRule implements Rule { diff --git a/src/Rules/Exceptions/MissingCheckedExceptionInPropertyHookThrowsRule.php b/src/Rules/Exceptions/MissingCheckedExceptionInPropertyHookThrowsRule.php index d9b7a6b864e..328ce6c70cd 100644 --- a/src/Rules/Exceptions/MissingCheckedExceptionInPropertyHookThrowsRule.php +++ b/src/Rules/Exceptions/MissingCheckedExceptionInPropertyHookThrowsRule.php @@ -4,6 +4,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\PropertyHookReturnStatementsNode; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -14,6 +15,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 0, enabledBy: '%exceptions.check.missingCheckedExceptionInThrows%')] final class MissingCheckedExceptionInPropertyHookThrowsRule implements Rule { diff --git a/src/Rules/Exceptions/TooWideFunctionThrowTypeRule.php b/src/Rules/Exceptions/TooWideFunctionThrowTypeRule.php index 6688dec466f..bf50be44ce7 100644 --- a/src/Rules/Exceptions/TooWideFunctionThrowTypeRule.php +++ b/src/Rules/Exceptions/TooWideFunctionThrowTypeRule.php @@ -4,6 +4,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\FunctionReturnStatementsNode; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -12,6 +13,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 4, enabledBy: '%exceptions.check.tooWideThrowType%')] final class TooWideFunctionThrowTypeRule implements Rule { diff --git a/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php b/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php index 92eb7c025f7..169359d3d84 100644 --- a/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php +++ b/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php @@ -5,6 +5,8 @@ use PhpParser\Comment\Doc; use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\AutowiredParameter; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\MethodReturnStatementsNode; use PHPStan\Reflection\ClassReflection; use PHPStan\Rules\Rule; @@ -21,13 +23,16 @@ /** * @implements Rule */ +#[RegisteredRule(level: 4, enabledBy: '%exceptions.check.tooWideThrowType%')] final class TooWideMethodThrowTypeRule implements Rule { public function __construct( private FileTypeMapper $fileTypeMapper, private TooWideThrowTypeCheck $check, + #[AutowiredParameter(ref: '%checkTooWideThrowTypesInProtectedAndPublicMethods%')] private bool $checkProtectedAndPublicMethods, + #[AutowiredParameter(ref: '%exceptions.check.tooWideImplicitThrowType%')] private bool $tooWideImplicitThrows, ) { diff --git a/src/Rules/Exceptions/TooWidePropertyHookThrowTypeRule.php b/src/Rules/Exceptions/TooWidePropertyHookThrowTypeRule.php index ce9be38a969..75e03e478a9 100644 --- a/src/Rules/Exceptions/TooWidePropertyHookThrowTypeRule.php +++ b/src/Rules/Exceptions/TooWidePropertyHookThrowTypeRule.php @@ -4,6 +4,8 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\AutowiredParameter; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\PropertyHookReturnStatementsNode; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -14,11 +16,13 @@ /** * @implements Rule */ +#[RegisteredRule(level: 4, enabledBy: '%exceptions.check.tooWideThrowType%')] final class TooWidePropertyHookThrowTypeRule implements Rule { public function __construct( private TooWideThrowTypeCheck $check, + #[AutowiredParameter(ref: '%checkTooWideThrowTypesInProtectedAndPublicMethods%')] private bool $checkProtectedAndPublicMethods, ) { diff --git a/src/Rules/Functions/ParameterCastableToNumberRule.php b/src/Rules/Functions/ParameterCastableToNumberRule.php index 92d33b98e4d..66797125f9d 100644 --- a/src/Rules/Functions/ParameterCastableToNumberRule.php +++ b/src/Rules/Functions/ParameterCastableToNumberRule.php @@ -5,6 +5,7 @@ use PhpParser\Node; use PhpParser\Node\Expr\FuncCall; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Php\PhpVersion; use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Reflection\ReflectionProvider; @@ -19,6 +20,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 5, enabledBy: '%featureToggles.checkParameterCastableToNumberFunctions%')] final class ParameterCastableToNumberRule implements Rule { diff --git a/src/Rules/Functions/PrintfParameterTypeRule.php b/src/Rules/Functions/PrintfParameterTypeRule.php index 520c9f3b356..fa93d2f28f1 100644 --- a/src/Rules/Functions/PrintfParameterTypeRule.php +++ b/src/Rules/Functions/PrintfParameterTypeRule.php @@ -4,6 +4,8 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\AutowiredParameter; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -25,6 +27,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 5, enabledBy: '%featureToggles.checkPrintfParameterTypes%')] final class PrintfParameterTypeRule implements Rule { @@ -43,6 +46,7 @@ public function __construct( private PrintfHelper $printfHelper, private ReflectionProvider $reflectionProvider, private RuleLevelHelper $ruleLevelHelper, + #[AutowiredParameter(ref: '%checkStrictPrintfPlaceholderTypes%')] private bool $checkStrictPrintfPlaceholderTypes, ) { diff --git a/src/Rules/Keywords/UnusedLabelRule.php b/src/Rules/Keywords/UnusedLabelRule.php index 5a8d9551fa6..5fb26e8ee19 100644 --- a/src/Rules/Keywords/UnusedLabelRule.php +++ b/src/Rules/Keywords/UnusedLabelRule.php @@ -4,6 +4,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Parser\GotoLabelVisitor; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; @@ -12,6 +13,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 4, enabledBy: '%featureToggles.unusedLabel%')] final class UnusedLabelRule implements Rule { diff --git a/src/Rules/Properties/UninitializedPropertyRule.php b/src/Rules/Properties/UninitializedPropertyRule.php index 525a9ecbb69..70dbc7edcd4 100644 --- a/src/Rules/Properties/UninitializedPropertyRule.php +++ b/src/Rules/Properties/UninitializedPropertyRule.php @@ -4,6 +4,7 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\ClassPropertiesNode; use PHPStan\Reflection\ConstructorsHelper; use PHPStan\Rules\Rule; @@ -13,6 +14,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 0, enabledBy: '%checkUninitializedProperties%')] final class UninitializedPropertyRule implements Rule { diff --git a/src/Rules/Variables/AssignToByRefExprFromForeachRule.php b/src/Rules/Variables/AssignToByRefExprFromForeachRule.php index 7b6d23e8bd5..4662b798233 100644 --- a/src/Rules/Variables/AssignToByRefExprFromForeachRule.php +++ b/src/Rules/Variables/AssignToByRefExprFromForeachRule.php @@ -5,6 +5,7 @@ use PhpParser\Node; use PhpParser\NodeAbstract; use PHPStan\Analyser\Scope; +use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Node\Expr\ForeachValueByRefExpr; use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Node\PropertyAssignNode; @@ -16,6 +17,7 @@ /** * @implements Rule */ +#[RegisteredRule(level: 1, enabledBy: '%featureToggles.assignToByRefForeachExpr%')] final class AssignToByRefExprFromForeachRule implements Rule {