-
Notifications
You must be signed in to change notification settings - Fork 58
feat: Discourage assert(Not)Empty if "empty" usage is disallowed #325
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 2.0.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,8 @@ rules: | |
| conditionalTags: | ||
| PHPStan\Rules\PHPUnit\AssertEqualsIsDiscouragedRule: | ||
| phpstan.rules.rule: [%strictRulesInstalled%, %featureToggles.bleedingEdge%] | ||
| PHPStan\Rules\PHPUnit\AssertEmptyIsDiscouragedRule: | ||
| phpstan.rules.rule: [%strictRulesInstalled%, %strictRules.disallowedEmpty%] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it be also behind
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch, I think you are right. |
||
|
|
||
| PHPStan\Rules\PHPUnit\DataProviderDataRule: | ||
| phpstan.rules.rule: %featureToggles.bleedingEdge% | ||
|
|
@@ -39,5 +41,8 @@ services: | |
| - | ||
| class: PHPStan\Rules\PHPUnit\AssertEqualsIsDiscouragedRule | ||
|
|
||
| - | ||
| class: PHPStan\Rules\PHPUnit\AssertEmptyIsDiscouragedRule | ||
|
|
||
| - | ||
| class: PHPStan\Rules\PHPUnit\DataProviderDataRule | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| <?php declare(strict_types = 1); | ||
|
|
||
| namespace PHPStan\Rules\PHPUnit; | ||
|
|
||
| use PhpParser\Node; | ||
| use PhpParser\Node\Expr\CallLike; | ||
| use PhpParser\Node\Expr\FuncCall; | ||
| use PhpParser\Node\Expr\MethodCall; | ||
| use PhpParser\Node\Expr\StaticCall; | ||
| use PhpParser\Node\Identifier; | ||
| use PhpParser\Node\Name; | ||
| use PHPStan\Analyser\Scope; | ||
| use PHPStan\Rules\Rule; | ||
| use PHPStan\Rules\RuleErrorBuilder; | ||
| use function count; | ||
| use function in_array; | ||
| use function sprintf; | ||
| use function strtolower; | ||
|
|
||
| /** | ||
| * @implements Rule<CallLike> | ||
| */ | ||
| class AssertEmptyIsDiscouragedRule implements Rule | ||
| { | ||
|
|
||
| public function getNodeType(): string | ||
| { | ||
| return CallLike::class; | ||
| } | ||
|
|
||
| public function processNode(Node $node, Scope $scope): array | ||
| { | ||
| if ($node->isFirstClassCallable() || count($node->getArgs()) < 1) { | ||
| return []; | ||
| } | ||
|
|
||
| if ($node instanceof MethodCall || $node instanceof StaticCall) { | ||
| if (!$node->name instanceof Identifier || !in_array($node->name->toLowerString(), ['assertempty', 'assertnotempty'], true)) { | ||
| return []; | ||
| } | ||
| if (!AssertRuleHelper::isMethodOrStaticCallOnAssert($node, $scope)) { | ||
| return []; | ||
| } | ||
| } elseif ($node instanceof FuncCall) { | ||
| if (!$node->name instanceof Name || !in_array(strtolower($scope->resolveName($node->name)), ['phpunit\\framework\\assertempty', 'phpunit\\framework\\assertnotempty'], true)) { | ||
| return []; | ||
| } | ||
| } else { | ||
| return []; | ||
| } | ||
|
Comment on lines
+44
to
+50
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. function based assertions seem to be not supported by other Assert* rules, so I think we shouldn't start here. it would need a separate PR doing it in all rules (not sure its worth adding,... noone asked for these yet AFAIR) |
||
|
|
||
| return [ | ||
| RuleErrorBuilder::message(sprintf( | ||
| '%s() is not allowed. Use more strict assertion.', | ||
| $node instanceof FuncCall ? $node->name->getLast() : $node->name->toString(), | ||
| )) | ||
| ->identifier('empty.notAllowed') | ||
| ->build(), | ||
| ]; | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <?php declare(strict_types = 1); | ||
|
|
||
| namespace PHPStan\Rules\PHPUnit; | ||
|
|
||
| use PHPStan\Rules\Rule; | ||
| use PHPStan\Testing\RuleTestCase; | ||
|
|
||
| /** | ||
| * @extends RuleTestCase<AssertEmptyIsDiscouragedRule> | ||
| */ | ||
| final class AssertEmptyIsDiscouragedRuleTest extends RuleTestCase | ||
| { | ||
|
|
||
| public function testRule(): void | ||
| { | ||
| $this->analyse([__DIR__ . '/data/assert-empty-is-discouraged.php'], [ | ||
| ['assertEmpty() is not allowed. Use more strict assertion.', 15], | ||
| ['assertNotEmpty() is not allowed. Use more strict assertion.', 16], | ||
| ['assertEmpty() is not allowed. Use more strict assertion.', 17], | ||
| ['assertNotEmpty() is not allowed. Use more strict assertion.', 18], | ||
| ['assertEmpty() is not allowed. Use more strict assertion.', 19], | ||
| ['assertNotEmpty() is not allowed. Use more strict assertion.', 20], | ||
| ]); | ||
| } | ||
|
|
||
| protected function getRule(): Rule | ||
| { | ||
| return new AssertEmptyIsDiscouragedRule(); | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| <?php declare(strict_types = 1); | ||
|
|
||
| namespace AssertEmptyIsDiscouragedTest; | ||
|
|
||
| use PHPUnit\Framework\Assert; | ||
| use PHPUnit\Framework\TestCase; | ||
| use function PHPUnit\Framework\assertEmpty; | ||
| use function PHPUnit\Framework\assertNotEmpty; | ||
|
|
||
| final class AssertEmptyTest extends TestCase | ||
| { | ||
|
|
||
| public function test(): void | ||
| { | ||
| $this->assertEmpty([]); | ||
| $this->assertNotEmpty([1]); | ||
| Assert::assertEmpty([]); | ||
| static::assertNotEmpty([1]); | ||
| assertEmpty([]); | ||
| assertNotEmpty([1]); | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@staabm You implemented AssertEqualIsDiscouraged with 10880da
Looking at how AssertEmptyIsDiscouragedRule is configured ; I wonder if it wouldn't be good to be behind
disallowedLooseComparisonhere ?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure what you are referring to?
AssertEqualIsDiscouragedis configured with[%strictRulesInstalled%, %featureToggles.bleedingEdge%]?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean it should be with
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we cannot use
%strictRules.disallowedLooseComparison%because it would result into a fatal error when strict rules are not installed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%strictRulesInstalled%is a flag which is available because it is known in phpstan-src.https://github.com/phpstan/phpstan-src/blob/b3547b6e094d604560bd0f97420f2ac8fcfa0961/conf/config.neon#L92
we cannot depend on other 1st party config flags which are only available when a extension is installed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then https://github.com/phpstan/phpstan-phpunit/pull/325/changes#diff-0874caf5d665ad61748aa19c613530c9c0db6782cb4a80440c4a8ec1024f79e5R16
[%strictRulesInstalled%, %strictRules.disallowedEmpty%]is not valid