Phpstan: phpDoc type hints don't work in traits

Created on 26 Jul 2018  路  24Comments  路  Source: phpstan/phpstan

PHPStan 0.10.2

Summary of a problem or a feature request

This causes several issues in the new Method signature rule.

Basically, PHPStan only sees the native type hints in methods coming from traits.

Code snippet that reproduces the problem

phpDoc type hint:
https://phpstan.org/r/6deeacd8c9098df919d86a67a2731118

Native type hint:
https://phpstan.org/r/698b43ecb1901190111f1726b6762111

Expected output

I'd expect the same error in both:

Parameter #1 $test of function takesString expects string, int given.

bug

Most helpful comment

Here's some other reproducable cases together with phpstan-strict-rules

https://github.com/chregu/phpstan-bug

It doesn't fail, when I have a very specific formatting in the trait method

works (https://github.com/chregu/phpstan-bug/blob/works/src/SomeTrait.php)

    /**
     * @param mixed $data
     * @return int
     */
    private function traitCall($data): int {

The following three don't work

https://github.com/chregu/phpstan-bug/blob/fail-no-return/src/SomeTrait.php
(no @return at all)

    /**
     * @param mixed $data
     */
    private function traitCall($data): int {

https://github.com/chregu/phpstan-bug/blob/fail-return-between-param-and-return/src/SomeTrait.php
(empty line between @return and @param)

    /**
     * @param mixed $data
     * 
     * @return int
     */
    private function traitCall($data): int {

https://github.com/chregu/phpstan-bug/blob/fail-comment-after-param/src/SomeTrait.php
(comment after @param)

    /**
     * @param mixed $data Some Comment.
     * @return int
     */
    private function traitCall($data): int {

The one with no @return at all works also in 0.10.3, but not 0.10.4 and later. The other two also don't work in 0.10.3

Hope that helps to pin down the problem.

All 24 comments

Hi, this is weird, it usually works. See NodeScopeResolverTest::dataTraitsPhpDocs - $this->traitMethod().

@ondrejmirtes Ok, I think the reason this doesn't work is because the trait and the class are in the same file. PhpClassReflectionExtension assumes that the trait is in a different file.

I think the issue in https://github.com/phpstan/phpstan/pull/1292 was unrelated. I put a phpcs:ignore comment after the phpDoc comment. I've had to use phpcs:disable and phpcs:enable. Now it's working.

@ondrejmirtes Should I close this? It works as long as the trait is in a separate file. I guess that will be the case in 99% of cases.

Same problem here. To refine it, the parameter/return type is then mixed(explicit=false).
It is hard to reproduce it on phpstan.org because https://github.com/phpstan/playground/issues/3

and linking with #1142

@iluuu1994 Nope, don't close this, it's a bug and should be fixed.

@iluuu1994 Can you retest with master/0.10.3?

@iluuu1994 This is correct example ;-)
https://phpstan.org/r/6deeacd8c9098df919d86a67a2731118

Example you posted is correct.

Oops, sorry 馃槀

I'm still having issues with 0.10.3. Unfortunately, now it's very inconsistent. From most of the methods in the traits, it's working fine. But some methods it's not. It's hard to reproduce. :disappointed:

Weirder still is that's I'm getting the issue in the context of one class, while the others are fine. If I make an actual mistake, I get an error for all classes.

Here's some other reproducable cases together with phpstan-strict-rules

https://github.com/chregu/phpstan-bug

It doesn't fail, when I have a very specific formatting in the trait method

works (https://github.com/chregu/phpstan-bug/blob/works/src/SomeTrait.php)

    /**
     * @param mixed $data
     * @return int
     */
    private function traitCall($data): int {

The following three don't work

https://github.com/chregu/phpstan-bug/blob/fail-no-return/src/SomeTrait.php
(no @return at all)

    /**
     * @param mixed $data
     */
    private function traitCall($data): int {

https://github.com/chregu/phpstan-bug/blob/fail-return-between-param-and-return/src/SomeTrait.php
(empty line between @return and @param)

    /**
     * @param mixed $data
     * 
     * @return int
     */
    private function traitCall($data): int {

https://github.com/chregu/phpstan-bug/blob/fail-comment-after-param/src/SomeTrait.php
(comment after @param)

    /**
     * @param mixed $data Some Comment.
     * @return int
     */
    private function traitCall($data): int {

The one with no @return at all works also in 0.10.3, but not 0.10.4 and later. The other two also don't work in 0.10.3

Hope that helps to pin down the problem.

I may have found the root cause. Caching...
If I delete the /tmp/phpstan [1] folder before running, all tests run fine. So the problem seems to be somewhere in that cache

[1] more complicated to find on OS X, but you can define the cache folder in phpstan.neon:

parameters:
    tmpDir: /tmp/phpstan

EDIT: Submitted into a separate issue: https://github.com/phpstan/phpstan/issues/1586 .

I still can reproduce that type hints do not work properly using traits.

I have the following test case: https://github.com/phpstan/phpstan/compare/master...sustmi:issue-1294-failing-test?expand=1

However, it is only reproducible if the trait is in a different file (as was already stated above). So in order to run the test, you cannot simply run phpunit because LevelsIntegrationTest does not support autoloading.

(EDIT: It works even with phpunit. I just forgot to composer dump-autoload.)

Just run:

bin/phpstan analyse --memory-limit=-1 --level 7 --ansi --autoload-file tests/PHPStan/Levels/data/SingletonTrait.php tests/PHPStan/Levels/data/annotations.php

The actual output is:

 ------ ----------------------------------------------------------------------------- 
  Line   annotations.php                                                              
 ------ ----------------------------------------------------------------------------- 
  37     Access to an undefined property Levels\Annotations\Bar::$undefinedProperty.  
  40     Access to an undefined property Exception::$someReadOnlyProperty.            
  41     Access to an undefined property Exception::$undefinedProperty.               
 ------ ----------------------------------------------------------------------------- 


 [ERROR] Found 3 errors

but expected output is:

 ------ ----------------------------------------------------------------------------- 
  Line   annotations.php                                                              
 ------ ----------------------------------------------------------------------------- 
  37     Access to an undefined property Levels\Annotations\Bar::$undefinedProperty.  
  41     Access to an undefined property Levels\Annotations\Baz::$undefinedProperty.               
 ------ ----------------------------------------------------------------------------- 


 [ERROR] Found 2 errors

FYI: If I change the trait to a class and make Bar and Baz extend the class instead of using, it works as expected (the type from the @method annotation has precedence before the type from the parent class).

you cannot simply run phpunit because LevelsIntegrationTest does not support autoloading.

You probably just need to run composer dump-autoload.

I just realized that your issue, @iluuu1994 , is not an issue any more and this issue was left open ( https://github.com/phpstan/phpstan/issues/1294#issuecomment-410541105 ) for a different reason ( https://github.com/phpstan/phpstan/issues/1294#issuecomment-408144901 ).

Can we change the topic of this issue (something like "phpstan does not work properly when trait is in the same file as class using it") or open another issue for this so it is more clear?

Also I realized that the test case I posted above ( https://github.com/phpstan/phpstan/issues/1294#issuecomment-436612240 ) would be probably better as a separate issue.

I think this is caused by multiple issues, I have some other cases where it is not related to the trait being in the same file. It's fine here. I'm looking at your test-case right now.

@sustmi Nevermind. Your test-case does seem unrelated. This issue is about PHPStan ignoring phpDocs of methods in traits.

Can everybody check if #1587 solves the problem for you?

@iluuu1994 Yes, it solves it for me. :+1:

I still have that "cache" issue:
I get errors on code which is ok, but when I delete the phpstan cache folder, they indeed return ok.

vagrant@api:/vagrant$ git clone [email protected]:chregu/phpstan-bug.git
vagrant@api:/vagrant$ cd phpstan-bug/
vagrant@api:/vagrant/phpstan-bug$ composer install
vagrant@api:/vagrant/phpstan-bug$ ./vendor/bin/phpstan analyze -l7 src/
Note: Using configuration file /vagrant/phpstan-bug/phpstan.neon.
 2/2 [鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔] 100%


 [OK] No errors


vagrant@api:/vagrant/phpstan-bug$ git checkout fail-no-return
Branch fail-no-return set up to track remote branch fail-no-return from origin.
Switched to a new branch 'fail-no-return'
vagrant@api:/vagrant/phpstan-bug$ ./vendor/bin/phpstan analyze -l7 src/
Note: Using configuration file /vagrant/phpstan-bug/phpstan.neon.
 2/2 [鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔] 100%

 ------ -------------------------------------------------------------------------------
  Line   SomeTrait.php (in context of class SomeClass)
 ------ -------------------------------------------------------------------------------
  9      Method SomeClass::traitCall() has parameter $data with no typehint specified.
 ------ -------------------------------------------------------------------------------


 [ERROR] Found 1 error


vagrant@api:/vagrant/phpstan-bug$ rm -rf /tmp/phpstan/
vagrant@api:/vagrant/phpstan-bug$ ./vendor/bin/phpstan analyze -l7 src/
Note: Using configuration file /vagrant/phpstan-bug/phpstan.neon.
 2/2 [鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔鈻撯枔] 100%


 [OK] No errors

Ok, to summarize, it looks like there's three problems:

  • [x] Trait is just randomly not recognized (this one is fixed but I'm not sure in what situation that occurred)
  • [ ] Caching issues
  • [x] Issues when trait and class are in the same file

I'll close this issue and create two separate ones.

Never actually closed this issue.

Was this page helpful?
0 / 5 - 0 ratings