diff --git a/src/Rules/DeadCode/UnusedPrivateConstantRule.php b/src/Rules/DeadCode/UnusedPrivateConstantRule.php index 6b3006f87f..ad3b249beb 100644 --- a/src/Rules/DeadCode/UnusedPrivateConstantRule.php +++ b/src/Rules/DeadCode/UnusedPrivateConstantRule.php @@ -85,6 +85,7 @@ public function processNode(Node $node, Scope $scope): array 'classStartLine' => $node->getClass()->getStartLine(), 'constantName' => $constantName, ]) + ->tip(sprintf('See: %s', 'https://phpstan.org/developing-extensions/always-used-class-constants')) ->build(); } diff --git a/src/Rules/DeadCode/UnusedPrivatePropertyRule.php b/src/Rules/DeadCode/UnusedPrivatePropertyRule.php index 6ba7338b28..54f4f3085c 100644 --- a/src/Rules/DeadCode/UnusedPrivatePropertyRule.php +++ b/src/Rules/DeadCode/UnusedPrivatePropertyRule.php @@ -185,6 +185,7 @@ public function processNode(Node $node, Scope $scope): array } else { $propertyName = sprintf('Property %s::$%s', $scope->getClassReflection()->getDisplayName(), $name); } + $tip = sprintf('See: %s', 'https://phpstan.org/developing-extensions/always-read-written-properties'); if (!$data['read']) { if (!$data['written']) { $errors[] = RuleErrorBuilder::message(sprintf('%s is unused.', $propertyName)) @@ -196,12 +197,13 @@ public function processNode(Node $node, Scope $scope): array 'classStartLine' => $node->getClass()->getStartLine(), 'propertyName' => $name, ]) + ->tip($tip) ->build(); } else { - $errors[] = RuleErrorBuilder::message(sprintf('%s is never read, only written.', $propertyName))->line($propertyNode->getStartLine())->build(); + $errors[] = RuleErrorBuilder::message(sprintf('%s is never read, only written.', $propertyName))->line($propertyNode->getStartLine())->tip($tip)->build(); } } elseif (!$data['written'] && (!array_key_exists($name, $uninitializedProperties) || !$this->checkUninitializedProperties)) { - $errors[] = RuleErrorBuilder::message(sprintf('%s is never written, only read.', $propertyName))->line($propertyNode->getStartLine())->build(); + $errors[] = RuleErrorBuilder::message(sprintf('%s is never written, only read.', $propertyName))->line($propertyNode->getStartLine())->tip($tip)->build(); } } diff --git a/tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php b/tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php index 305c37cf13..16b90f4be2 100644 --- a/tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php +++ b/tests/PHPStan/Rules/DeadCode/UnusedPrivateConstantRuleTest.php @@ -38,10 +38,12 @@ public function testRule(): void [ 'Constant UnusedPrivateConstant\Foo::BAR_CONST is unused.', 10, + 'See: https://phpstan.org/developing-extensions/always-used-class-constants', ], [ 'Constant UnusedPrivateConstant\TestExtension::UNUSED is unused.', 23, + 'See: https://phpstan.org/developing-extensions/always-used-class-constants', ], ]); } diff --git a/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php b/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php index 5b8b717227..d7a3eb437e 100644 --- a/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php +++ b/tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php @@ -67,60 +67,75 @@ public function testRule(): void $this->alwaysWrittenTags = []; $this->alwaysReadTags = []; + $tip = 'See: https://phpstan.org/developing-extensions/always-read-written-properties'; + $this->analyse([__DIR__ . '/data/unused-private-property.php'], [ [ 'Property UnusedPrivateProperty\Foo::$bar is never read, only written.', 10, + $tip, ], [ 'Property UnusedPrivateProperty\Foo::$baz is unused.', 12, + $tip, ], [ 'Property UnusedPrivateProperty\Foo::$lorem is never written, only read.', 14, + $tip, ], [ 'Property UnusedPrivateProperty\Bar::$baz is never written, only read.', 57, + $tip, ], [ 'Static property UnusedPrivateProperty\Baz::$bar is never read, only written.', 86, + $tip, ], [ 'Static property UnusedPrivateProperty\Baz::$baz is unused.', 88, + $tip, ], [ 'Static property UnusedPrivateProperty\Baz::$lorem is never written, only read.', 90, + $tip, ], [ 'Property UnusedPrivateProperty\Lorem::$baz is never read, only written.', 117, + $tip, ], [ 'Property class@anonymous/tests/PHPStan/Rules/DeadCode/data/unused-private-property.php:152::$bar is unused.', 153, + $tip, ], [ 'Property UnusedPrivateProperty\DolorWithAnonymous::$foo is unused.', 148, + $tip, ], ]); $this->analyse([__DIR__ . '/data/TestExtension.php'], [ [ 'Property UnusedPrivateProperty\TestExtension::$unused is unused.', 8, + $tip, ], [ 'Property UnusedPrivateProperty\TestExtension::$read is never written, only read.', 10, + $tip, ], [ 'Property UnusedPrivateProperty\TestExtension::$written is never read, only written.', 12, + $tip, ], ]); } @@ -129,14 +144,17 @@ public function testAlwaysUsedTags(): void { $this->alwaysWrittenTags = ['@ORM\Column']; $this->alwaysReadTags = ['@get']; + $tip = 'See: https://phpstan.org/developing-extensions/always-read-written-properties'; $this->analyse([__DIR__ . '/data/private-property-with-tags.php'], [ [ 'Property PrivatePropertyWithTags\Foo::$title is never read, only written.', 13, + $tip, ], [ 'Property PrivatePropertyWithTags\Foo::$text is never written, only read.', 18, + $tip, ], ]); } @@ -155,10 +173,12 @@ public function testBug3636(): void } $this->alwaysWrittenTags = []; $this->alwaysReadTags = []; + $tip = 'See: https://phpstan.org/developing-extensions/always-read-written-properties'; $this->analyse([__DIR__ . '/data/bug-3636.php'], [ [ 'Property Bug3636\Bar::$date is never written, only read.', 22, + $tip, ], ]); } @@ -171,10 +191,12 @@ public function testPromotedProperties(): void $this->alwaysWrittenTags = []; $this->alwaysReadTags = ['@get']; + $tip = 'See: https://phpstan.org/developing-extensions/always-read-written-properties'; $this->analyse([__DIR__ . '/data/unused-private-promoted-property.php'], [ [ 'Property UnusedPrivatePromotedProperty\Foo::$lorem is never read, only written.', 12, + $tip, ], ]); }