phpstan / phpstan-webmozart-assert

PHPStan extension for webmozart/assert
MIT License
165 stars 28 forks source link

Add FQCN support to `implementsInterface` #144

Closed herndlm closed 2 years ago

herndlm commented 2 years ago

Closes https://github.com/phpstan/phpstan-webmozart-assert/issues/17 Closes https://github.com/phpstan/phpstan-webmozart-assert/issues/18

The idea behind this is amazingly simple. If the $class arg is a known interface we can simply use is_subclass_of to check if the given object or FQCN implements that interface.

herndlm commented 2 years ago

If you want a simple fix for a long outstanding bug, this is it 😊

ondrejmirtes commented 2 years ago

Can you please remove the changes in src/ and see what the tests do since we already depend on PHPStan 1.9.0 here and the method has these annotations? https://github.com/webmozarts/assert/blob/11cb2199493b2f8a3b53e7f19068fc6aac760991/src/Assert.php#L1566-L1577

Thanks!

herndlm commented 2 years ago

interesting, indeed it understands more now, I get those failures

1) PHPStan\Type\WebMozartAssert\AssertTypeSpecifyingExtensionTest::testFileAsserts with data set "/Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php:41" ('type', '/Users/herndlm/Development/so...ct.php', PHPStan\Type\Constant\ConstantStringType Object (...), PHPStan\Type\Generic\GenericClassStringType Object (...), 41)
Expected type class-string<PHPStan\Type\WebMozartAssert\ObjectFoo>|PHPStan\Type\WebMozartAssert\ObjectFoo, got type class-string<PHPStan\Type\WebMozartAssert\ObjectFoo> in /Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php on line 41.
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'class-string<PHPStan\Type\WebMozartAssert\ObjectFoo>|PHPStan\Type\WebMozartAssert\ObjectFoo'
+'class-string<PHPStan\Type\WebMozartAssert\ObjectFoo>'

phar:///Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/vendor/phpstan/phpstan/phpstan.phar/src/Testing/TypeInferenceTestCase.php:58
/Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/AssertTypeSpecifyingExtensionTest.php:35
phpvfscomposer:///Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/vendor/phpunit/phpunit/phpunit:97

2) PHPStan\Type\WebMozartAssert\AssertTypeSpecifyingExtensionTest::testFileAsserts with data set "/Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php:44" ('type', '/Users/herndlm/Development/so...ct.php', PHPStan\Type\Constant\ConstantStringType Object (...), PHPStan\Type\UnionType Object (...), 44)
Expected type class-string<PHPStan\Type\WebMozartAssert\ObjectFoo>|PHPStan\Type\WebMozartAssert\ObjectFoo|null, got type class-string<PHPStan\Type\WebMozartAssert\ObjectFoo>|null in /Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php on line 44.
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'class-string<PHPStan\Type\WebMozartAssert\ObjectFoo>|PHPStan\Type\WebMozartAssert\ObjectFoo|null'
+'class-string<PHPStan\Type\WebMozartAssert\ObjectFoo>|null'

phar:///Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/vendor/phpstan/phpstan/phpstan.phar/src/Testing/TypeInferenceTestCase.php:58
/Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/AssertTypeSpecifyingExtensionTest.php:35
phpvfscomposer:///Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/vendor/phpunit/phpunit/phpunit:97

3) PHPStan\Type\WebMozartAssert\AssertTypeSpecifyingExtensionTest::testFileAsserts with data set "/Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php:50" ('type', '/Users/herndlm/Development/so...ct.php', PHPStan\Type\Constant\ConstantStringType Object (...), PHPStan\Type\NeverType Object (...), 50)
Expected type PHPStan\Type\WebMozartAssert\ObjectFoo, got type *NEVER* in /Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php on line 50.
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'PHPStan\Type\WebMozartAssert\ObjectFoo'
+'*NEVER*'

phar:///Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/vendor/phpstan/phpstan/phpstan.phar/src/Testing/TypeInferenceTestCase.php:58
/Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/AssertTypeSpecifyingExtensionTest.php:35
phpvfscomposer:///Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/vendor/phpunit/phpunit/phpunit:97

4) PHPStan\Type\WebMozartAssert\AssertTypeSpecifyingExtensionTest::testFileAsserts with data set "/Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php:53" ('type', '/Users/herndlm/Development/so...ct.php', PHPStan\Type\Constant\ConstantStringType Object (...), PHPStan\Type\Generic\GenericClassStringType Object (...), 53)
Expected type mixed, got type class-string<PHPStan\Type\WebMozartAssert\ObjectTest> in /Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php on line 53.
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'mixed'
+'class-string<PHPStan\Type\WebMozartAssert\ObjectTest>'

phar:///Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/vendor/phpstan/phpstan/phpstan.phar/src/Testing/TypeInferenceTestCase.php:58
/Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/AssertTypeSpecifyingExtensionTest.php:35
phpvfscomposer:///Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/vendor/phpunit/phpunit/phpunit:97

5) PHPStan\Type\WebMozartAssert\AssertTypeSpecifyingExtensionTest::testFileAsserts with data set "/Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php:56" ('type', '/Users/herndlm/Development/so...ct.php', PHPStan\Type\Constant\ConstantStringType Object (...), PHPStan\Type\Generic\GenericClassStringType Object (...), 56)
Expected type mixed, got type class-string<PHPStan\Type\WebMozartAssert\Unknown> in /Users/herndlm/Development/source/git-forks/phpstan-webmozart-assert/tests/Type/WebMozartAssert/data/object.php on line 56.
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-'mixed'
+'class-string<PHPStan\Type\WebMozartAssert\Unknown>'

looks like objects are not working because of the class-string assert or is that ok? and the last 2 failures are kind of expected I guess, the first is using a class instead of an interface (which I explicitly forbid via reflection) and the second is an unknown class. the only real thing bothering me is the *NEVER* for the object hmm

ondrejmirtes commented 2 years ago

The annotation and the implementation suggests to me that only strings can ever work there...

herndlm commented 2 years ago

annotation yeah, class_implements() does support objects though :/

herndlm commented 2 years ago

anyways, I think it would still close the linked issues by using only phpstan 1.9.0 assert annotations, I'll adapt this

ondrejmirtes commented 2 years ago

Oh I get it now, yeah, objects are indeed supported. Please try to send a PR to the library :)

ondrejmirtes commented 2 years ago

Until then, our extension is superior :)