diff --git a/extension.neon b/extension.neon index 09e83bc3..8b1305cf 100644 --- a/extension.neon +++ b/extension.neon @@ -16,7 +16,17 @@ services: show_rule_names: %phpat.show_rule_names%, ) - # # # # # DECLARATION RULES # # # # # + # # # # # DECLARATION RULES # # # # # + + # ShouldBeImmutable rules + - + class: PHPat\Rule\Assertion\Declaration\ShouldBeImmutable\PropertyAssignationRule + tags: + - phpstan.rules.rule + - + class: PHPat\Rule\Assertion\Declaration\ShouldBeImmutable\MutablePropertyRule + tags: + - phpstan.rules.rule # ShouldBeAbstract rules - @@ -42,7 +52,7 @@ services: tags: - phpstan.rules.rule - # # # # # RELATION RULES # # # # # + # # # # # RELATION RULES # # # # # # ShouldImplement rules - diff --git a/src/Rule/Assertion/Declaration/ShouldBeImmutable/MutablePropertyRule.php b/src/Rule/Assertion/Declaration/ShouldBeImmutable/MutablePropertyRule.php new file mode 100644 index 00000000..e134002a --- /dev/null +++ b/src/Rule/Assertion/Declaration/ShouldBeImmutable/MutablePropertyRule.php @@ -0,0 +1,17 @@ + + */ +class MutablePropertyRule extends ShouldBeImmutable implements Rule +{ + use MutablePropertyExtractor; +} diff --git a/src/Rule/Assertion/Declaration/ShouldBeImmutable/PropertyAssignationRule.php b/src/Rule/Assertion/Declaration/ShouldBeImmutable/PropertyAssignationRule.php new file mode 100644 index 00000000..12d383e0 --- /dev/null +++ b/src/Rule/Assertion/Declaration/ShouldBeImmutable/PropertyAssignationRule.php @@ -0,0 +1,17 @@ + + */ +class PropertyAssignationRule extends ShouldBeImmutable implements Rule +{ + use PropertyAssignedOutOfConstructorExtractor; +} diff --git a/src/Rule/Assertion/Declaration/ShouldBeImmutable/ShouldBeImmutable.php b/src/Rule/Assertion/Declaration/ShouldBeImmutable/ShouldBeImmutable.php new file mode 100644 index 00000000..bd0e0d28 --- /dev/null +++ b/src/Rule/Assertion/Declaration/ShouldBeImmutable/ShouldBeImmutable.php @@ -0,0 +1,46 @@ +applyShould($ruleName, $subject, $meetsDeclaration, $tips); + } + + protected function getMessage(string $ruleName, string $subject): string + { + return $this->prepareMessage( + $ruleName, + sprintf('%s should be immutable', $subject) + ); + } +} diff --git a/src/Rule/Extractor/Declaration/MutablePropertyExtractor.php b/src/Rule/Extractor/Declaration/MutablePropertyExtractor.php new file mode 100644 index 00000000..dcce1509 --- /dev/null +++ b/src/Rule/Extractor/Declaration/MutablePropertyExtractor.php @@ -0,0 +1,34 @@ +getClassReflection(); + if ($class && $class->isReadOnly()) { + return true; + } + + if (!$node->isPublic() || $node->isReadonly()) { + return true; + } + + return false; + } +} diff --git a/src/Rule/Extractor/Declaration/PropertyAssignedOutOfConstructorExtractor.php b/src/Rule/Extractor/Declaration/PropertyAssignedOutOfConstructorExtractor.php new file mode 100644 index 00000000..275326d1 --- /dev/null +++ b/src/Rule/Extractor/Declaration/PropertyAssignedOutOfConstructorExtractor.php @@ -0,0 +1,30 @@ +getFunction(); + if ($functionReflection === null || $functionReflection->getName() === '__construct') { + return true; + } + + return false; + } +} diff --git a/src/Test/Builder/AssertionStep.php b/src/Test/Builder/AssertionStep.php index c2b38e83..2bd4731b 100644 --- a/src/Test/Builder/AssertionStep.php +++ b/src/Test/Builder/AssertionStep.php @@ -6,6 +6,7 @@ use PHPat\Rule\Assertion\Declaration\ShouldBeAbstract\ShouldBeAbstract; use PHPat\Rule\Assertion\Declaration\ShouldBeFinal\ShouldBeFinal; +use PHPat\Rule\Assertion\Declaration\ShouldBeImmutable\ShouldBeImmutable; use PHPat\Rule\Assertion\Declaration\ShouldNotBeAbstract\ShouldNotBeAbstract; use PHPat\Rule\Assertion\Declaration\ShouldNotBeFinal\ShouldNotBeFinal; use PHPat\Rule\Assertion\Relation\CanOnlyDepend\CanOnlyDepend; @@ -18,6 +19,13 @@ class AssertionStep extends AbstractStep { + public function shouldBeImmutable(): Rule + { + $this->rule->assertion = ShouldBeImmutable::class; + + return new BuildStep($this->rule); + } + public function shouldBeAbstract(): Rule { $this->rule->assertion = ShouldBeAbstract::class; diff --git a/tests/architecture/ConfigurationTest.php b/tests/architecture/ConfigurationTest.php index d0f2b1d8..3202bfa0 100644 --- a/tests/architecture/ConfigurationTest.php +++ b/tests/architecture/ConfigurationTest.php @@ -25,4 +25,11 @@ public function test_configuration_is_final(): Rule ->classes(Selector::classname(Configuration::class)) ->shouldBeFinal(); } + + public function test_configuration_is_immutable(): Rule + { + return PHPat::rule() + ->classes(Selector::classname(Configuration::class)) + ->shouldBeImmutable(); + } }