laravel-ide-helper icon indicating copy to clipboard operation
laravel-ide-helper copied to clipboard

I believe I've been able to improve some of the intellisense for model queries, please implement this (but maybe expand it first)

Open Evertt opened this issue 5 months ago • 4 comments

So I'm using VSCode with every extension I could install that gives my IDE the best possible understanding of how most of Laravel's magic methods work and what types they return. However, it's still not enough and luckily this package makes the autocompletion in my IDE better still.

However, I still found a scenario where my IDE doesn't understand what a certain method-call is referring to. Let me show you an example.

I have this model:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

/**
 * @mixin IdeHelperTrainingDate
 */
class TrainingDate extends Model
{
    public function scopeSearch($query, $search) {}
}

And then this in my _ide_helper_models.php file:

namespace App\Models{
/**
 * App\Models\TrainingDate
 * 
 * @method static \Illuminate\Database\Eloquent\Builder|TrainingDate query()
 * @method static \Illuminate\Database\Eloquent\Builder|TrainingDate search($search)
 * @mixin \Eloquent
 */
    class IdeHelperTrainingDate {}
}

Strictly speaking, I don't even need the line for search there, because one of my extensions is already smart enough to be able to link search() to scopeSearch(), but it's fine. So when I do this, things work completely fine:

$training_dates = TrainingDate::query()
    ->search("foo")
    ->get();

I can hover the search() call, and it will give me the desired type information and I can cmd + click on it and it will refer me directly to scopeSearch(). However, that breaks as soon as I do this:

$training_dates = TrainingDate::query()
    ->with("training")
    ->search("foo")
    ->get();

Because with() simply returns Builder and now neither my extensions nor your _ide_helper_models.php file is able to make my IDE understand that search() is still available. I thought maybe running php artisan ide-helper:eloquent and / or php artisan ide-helper:generate would fix that issue, but it didn't. However, I've been able to fix it myself! 😃 By adding the following lines at the top of _ide_helper_models.php:

namespace Illuminate\Database\Eloquent {
	/**
	 * @template TModel of \Eloquent
	 * @mixin TModel
	 */
	class Builder {}
}

And then changing docblock of IdeHelperTrainingDate to the following:

namespace App\Models{
/**
 * App\Models\TrainingDate
 * 
 * @method static \Illuminate\Database\Eloquent\Builder<TrainingDate> query()
 * @method static \Illuminate\Database\Eloquent\Builder<TrainingDate> search($search)
 * @mixin \Eloquent
 */
    class IdeHelperTrainingDate {}
}

Now I can easily mix and match methods coming from Builder and scope methods coming from TrainingDate and my IDE will never forget that it can keep using both.

Now of course, this was the quickest fix I was able to do, because I'm on a deadline and I'm sure there are lots of caveats here that I haven't thought of yet. And maybe the intellisense of IDEs could be expanded even more through methods similar to these.

So basically my request is, would you be willing to check out whether this approach is viable. As in, whether this doesn't create more problems than it solves. And if it does seem like a viable approach to extend IDE's intellisense then would you be willing to experiment what else could be improved with methods like these?

Edit

Okay after experimenting some more I'm now a bit confused. Because one of the things I was using to improve VSCode's understanding of my Laravel code was phpstan with an extension for it called larastan. And well, maybe some of all those many libraries and extensions have been feeding VSCode contradictory information or something? Because at some point, I was just disabling some extensions here and there to see whether I would lose important intellisense, but well, not always. Sometimes intellisense stayed the same and sometimes it even got a little better. And well now I'm not sure if my solution actually solved a problem that needed solving, if you know what I mean.

Still I'd appreciate if anyone here would be willing to take a little time to experiment with this and see what's what. 😬 🙏

Evertt avatar Mar 24 '24 11:03 Evertt