Skip to content
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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generics annotations support #1298

Merged
merged 10 commits into from
Jan 28, 2023
Merged

Conversation

tanerkay
Copy link
Contributor

@tanerkay tanerkay commented Jan 17, 2022

Summary

Add option use_generics_annotations for collection type hints

Before:

 * @property-read \Illuminate\Database\Eloquent\Collection|Simple[] $regularHasMany

After:

 * @property-read \Illuminate\Database\Eloquent\Collection<int, Simple> $regularHasMany

I feel this is is a useful transition given what has evolved since #942 (comment). Namely:

Note: for some reason, specific support for @property and @property-read didn't land until PhpStorm version 2022.3. Testing now to make sure things work

Type of change

  • New feature (non-breaking change which adds functionality)

Checklist

  • Existing tests have been adapted and/or new tests have been added
  • Add a CHANGELOG.md entry
  • Update the README.md
  • Code style has been fixed via composer fix-style

| e.g. `Collection<User>` instead of `Collection|User[]`.
|
*/
'use_generics_annotations' => false,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not yet looked into detail of this PR and will do it later, but if it works really good I'm also tempted to suggesting to make it even default to true. But that was just a quick showerthought :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be my preference too, but I thought this was a decision best left to you. I originally had the fallback value as version_compare($this->laravel['version'], '9', '>=') (i.e. true if Laravel version is at least version 9), but was in two minds about it. In the end, I removed it. Open to suggestions here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option is to set the default to true, then do the inverse check for Laravel version, thereby falling back to false if the config option is not set and the Laravel version is less than 9.

@mfn mfn self-requested a review January 17, 2022 09:53
@LastDragon-ru
Copy link
Contributor

phpstan with checkGenericClassInNonGenericObjectType: true wants

  • @property-read \Illuminate\Database\Eloquent\Collection<int, Simple> $regularHasMany

@Legion112
Copy link

How the progress is going on this one?
Will it support previous versions of laravel?

@Legion112
Copy link

In pull request, I don't see generation for \Illuminate\Database\Eloquent\Collection method such get, add, etc

@Legion112
Copy link

Each method here should have and template annotation to define return time base on template type
image

@tanerkay
Copy link
Contributor Author

@Legion112

Will it support previous versions of laravel?

Yes

In pull request, I don't see generation for \Illuminate\Database\Eloquent\Collection method such get, add, etc

The idea is that the collection class is type hinted, so the IDE can infer those class methods. Right?

Each method here should have and template annotation to define return time base on template type

That didn't make sense to me. Rephrase?

@Legion112
Copy link

Legion112 commented Mar 30, 2022

@tanerkay

The idea is that the collection class is type hinted, so the IDE can infer those class methods. Right?

This is wrong. You need to have a defined template that ide would be able to know what will be return then you call a method on the collection.

Look here https://psalm.dev/docs/annotating_code/templated_annotations/

Without such a template, IDE cannot determine the type of any method of the collection It would alwasy think mixed.

/**
 * @template T
 */
class MyContainer {
  /** @var T */
  private $value;

  /** @param T $value */
  public function __construct($value) {
    $this->value = $value;
  }

  /** @return T */
  public function getValue() {
    return $this->value;
  }
}

@tanerkay
Copy link
Contributor Author

@Legion112

This is wrong. You need to have a defined template that ide would be able to know what will be return then you call a method on the collection.

Sorry, still don't understand. The templates are defined in the Laravel collection classes: \Illuminate\Database\Eloquent\Collection and \Illuminate\Support\Collection. Are you looking at Laravel 8 code?

@tanerkay
Copy link
Contributor Author

Haven't really been following this closely or thinking too much about it as PhpStorm still has incomplete support for this, see https://youtrack.jetbrains.com/issue/WI-64963/@property-does-not-support-@template-declaration

@Legion112
Copy link

I didn't have much sleep lately 😪 . I will try my best to read the last link to understand the problem.
@tanerkay

@barryvdh
Copy link
Owner

So what is the status of this, is this 100% done or not?

@mfn
Copy link
Collaborator

mfn commented Jun 20, 2022

It definitely slipped my radar to go through the PR, whoopsie. Hope to do it in the next days!

@bbprojectnet
Copy link

Any news on this? ;)

@tanerkay
Copy link
Contributor Author

tanerkay commented Aug 8, 2022

Any news on this? ;)

Still not supported by PhpStorm at time of writing (version 2022.2)

Feel free to +1 the linked issue on Jetbrains' issue tracker or comment, as it would be awesome if this were implemented sooner rather than later: https://youtrack.jetbrains.com/issue/WI-64963/@property-does-not-support-@template-declaration

@shahruslan
Copy link

Is this PR waiting for a bug in PhpStorm to be fixed?

@tanerkay
Copy link
Contributor Author

tanerkay commented Sep 7, 2022

Is this PR waiting for a bug in PhpStorm to be fixed?

yes, I've lost track of the actual issue in their bug tracker, as they've marked them as duplicates of unrelated issues

@tanerkay
Copy link
Contributor Author

tanerkay commented Sep 7, 2022

Apparently fixed in upcoming PhpStorm version, 2022.3 🎉

@jnoordsij
Copy link
Contributor

Any update on this? Would be great to have!

I opened larastan/larastan#1470 in an effort to create a workaround on their side, but enabling this package to allow for adding generics would be much better.

@grEvenX
Copy link

grEvenX commented Jan 25, 2023

@barryvdh Support for this has been out for a while in PhpStorm now and this PR should be ready for review.
I've tested it on our codebase and it works perfectly 👍

I guess a decision should be made if this should now in 2023 be set as the default, or if it's needed to set use_generics_annotations to true in the ide-helper config file.

@tanerkay
Copy link
Contributor Author

I guess a decision should be made if this should now in 2023 be set as the default, or if it's needed to set use_generics_annotations to true in the ide-helper config file.

I think it makes sense to, I just have the following concerns:

  • it ties this package more with PhpStorm. might be undesired for developers who don't use it. Nevertheless, they have the option to change the config value.
  • users using Laravel 8 and running vendor:publish for the first time will have the option set to true*

I guess the benefits from having the collection type hinted using generics outweighs the limited benefit from the alternative syntax.

In any case, I've changed the default in this PR to true. Can leave the decision to @barryvdh . The change is in 28775bd in case it is decided to revert it.

*An alternative middle of the road option is to block the use of generics annotations if the Laravel version is not version 9 or greater, e.g.

diff --git a/src/Console/ModelsCommand.php b/src/Console/ModelsCommand.php
--- a/src/Console/ModelsCommand.php	(revision 28775bd73779318b764f91ca28b2e7f3ae312478)
+++ b/src/Console/ModelsCommand.php	(date 1674662581752)
@@ -1091,7 +1091,7 @@
     protected function getCollectionTypeHint(string $collectionClassNameInModel, string $relatedModel): string
     {
         $useGenericsSyntax = $this->laravel['config']->get('ide-helper.use_generics_annotations', false);
-        if ($useGenericsSyntax) {
+        if ($useGenericsSyntax && version_compare($this->laravel['version'], '9', '>=')) {
             return $collectionClassNameInModel . '<int, ' . $relatedModel . '>';
         } else {
             return $collectionClassNameInModel . '|' . $relatedModel . '[]';

Copy link
Collaborator

@mfn mfn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it ties this package more with PhpStorm. might be undesired for developers who don't use it. Nevertheless, they have the option to change the config value.

I would not kid ourselves myself over this: PhpStorm is on the forefront and their endeavors are part of why the community thrives, too.

Some tests are failing, but I'd willing to approve this, makes sense (now that's 2023).

@tanerkay
Copy link
Contributor Author

I would not kid ourselves myself over this: PhpStorm is on the forefront and their endeavors are part of why the community thrives, too.

Fair call, I wanted to bring up the topic but acknowledge the significance of PhpStorm at the same time.

Some tests are failing, but I'd willing to approve this, makes sense (now that's 2023).

Awesome. I'll sort out tests today :)

@tanerkay
Copy link
Contributor Author

tests updated

Copy link
Collaborator

@mfn mfn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test now where it does not use the generics annotation? I see the test setting it to false, but I failed to spot a diff in the PR where this is the case (or I'm blind).

@tanerkay
Copy link
Contributor Author

Is there a test now where it does not use the generics annotation?

Yes, in the namespace Barryvdh\LaravelIdeHelper\Tests\Console\ModelsCommand\GenericsSyntaxDisabled

https://github.com/barryvdh/laravel-ide-helper/pull/1298/files#diff-7f2f9319ecfc1e0b601eeb87d07266d79901707f53c161979a89918ce2e4d6b4

@tanerkay
Copy link
Contributor Author

I know that creates a regression for users who just updated the package and not the config, but this is easily fixed if they care/it poses a problem for them and, in the end, this is a change for the better so we want to promote this.

That would be my preference too, but was wary that it's a regression as you mentioned. If the idea is to promote it (which I'm completely in agreeance), then let's change it :)

Copy link
Collaborator

@mfn mfn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼

@barryvdh after merging and releasing this, existing annotations will be changed to use the new generics annotation but it an be disabled in the config

@Sergiobop
Copy link

Sergiobop commented Feb 7, 2023

I don't know if it is just me, but after this is released, every time the model command is ran, some generic annotations are being duplicated even if they are already in the phpdoc.

@grEvenX
Copy link

grEvenX commented Feb 7, 2023

@Sergiobop I see I get the same experience when running:

php artisan ide-helper:models "App\MyModel" --write --reset
php artisan ide-helper:models "App\MyModel" --write

Should probably open a new issue about it.

d3v2a pushed a commit to d3v2a/laravel-ide-helper that referenced this pull request Feb 16, 2024
* option to use generics syntax, default to yes in laravel 9

* rename `use_generics_syntax` to `use_generics_annotations`

* update readme and changelog

* remove laravel 9 default override

* include key type in generics annotations

* readme rewording

* set `use_generics_annotations` to `true` by default

* update tests to reflect `use_generics_annotations` being set to `true` by default

* default `use_generics_annotations` setting to true when not set in config

Co-authored-by: Markus Podar <[email protected]>

---------

Co-authored-by: Markus Podar <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants