Open calebdw opened 11 months ago
Hi, it's hard to debug with out knowing the code that triggers this. Can you please provide an example of how your code calls the view()
method? Extra points for giving a minimal testcase that can replicate the issue.
For reference this is where the analyzer dies: https://github.com/TomasVotruba/bladestan/blob/c8f99c508772e2d872d86558a0c426388c4dc7dd/src/PhpParser/NodeVisitor/ViewFunctionArgumentsNodeVisitor.php#L77
If you can modify that to output the class of $rootViewNode->name
that could also be helpful.
My best guess from looking at the stack trace is that the code looks something like this:
<?php
namespace Eagle\File\Relation;
use App\Settings\Model\SomeSetting, but that's just a guess;
trait Something
{
public somthing()
{
new SomeSetting();
foreach () {
$thing = view();
}
}
}
I took a look at https://github.com/eagle-metal, but it does not appear that the offending code is part of the publicly available repos.
You can run phpstan
with --debug
to have it print out what file it is currently working on, that should let you know what it's choking on.
@AJenbo, thanks for the response.
Hi, it's hard to debug with out knowing the code that triggers this
I completely understand, however, this was produced with --debug
and -vvv
and the message yielded is not very helpful---the error output could certainly be improved.
I'm not even sure what file caused the error as the last filename on the list does not contain a view
command and passes when I analyze it individually. I suspect it's choking on some View composers (which comes right after the Settings model you mentioned)
It's hard to say, it could be interactions between other PHPStan plugins so it's not really easy to say without a test case. Hopefully you can work on narrowing down the code that triggers it.
@AJenbo, here's a minimum example (although there could be other issues not represented here):
<?php
namespace App\View\Components;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class Messages extends Component
{
public function __construct(
public string $resourceRoute,
public array $messages = [],
public ?string $fileMorphAlias = null,
public bool $canCreateMessage = false,
) {
}
public function render(): View
{
return view('ems._components.messages');
}
}
@php
use App\Mail\Models\Message;
@endphp
<div class="mr-6">
<span>
<x-button.success
class="text-sm"
x-show="selected_message?.type === {{ Js::from(Message::TYPE_OUTGOING) }}"
>
Resend message
</x-button.success>
</span>
<div class="mr-6">
@isset($additional_actions)
{{ $additional_actions }}
@endisset
</div>
</div>
Note that if I remove the x-show
line or the isset
block then the issue goes away---although they seen completely unrelated to each other
Could you try this:
<?php
namespace App\View\Components;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class Messages extends Component
{
public function __construct(
public string $resourceRoute,
public array $messages = [],
public ?string $fileMorphAlias = null,
public bool $canCreateMessage = false,
) {
}
public function render(): View
{
return $this->view('ems._components.messages', [
'resourceRoute' => $this->resourceRoute,
'messages' => $this->messages,
'fileMorphAlias' => $this->fileMorphAlias,
'canCreateMessage' => $this->canCreateMessage,
]);
}
}
Bladestan isn't able to infer that the component and it's properties will be grabbed from the scope of the caller when calls happen inside a component. Also calling the member method gives it a slightly better context.
Is the blade file you posted ems/_components/messages.blade.php
?
Also we are missing button.blade.php
since it's being required by the template you posted.
@AJenbo, no go...
Here's the output of dd($rootViewNode)
/var/www/app/View/Components/Messages.php
PhpParser\Node\Expr\MethodCall^ {#56669
#attributes: array:6 [
"startLine" => 123
"startTokenPos" => 789
"startFilePos" => 3609
"endLine" => 123
"endTokenPos" => 795
"endFilePos" => 3632
]
+var: PhpParser\Node\Expr\Variable^ {#56667
#attributes: array:6 [
"startLine" => 123
"startTokenPos" => 789
"startFilePos" => 3609
"endLine" => 123
"endTokenPos" => 789
"endFilePos" => 3613
]
+name: "this"
}
+name: PhpParser\Node\Expr\Variable^ {#56668
#attributes: array:6 [
"startLine" => 123
"startTokenPos" => 792
"startFilePos" => 3617
"endLine" => 123
"endTokenPos" => 792
"endFilePos" => 3629
]
+name: "relationship"
}
+args: []
} // vendor/tomasvotruba/bladestan/src/PhpParser/NodeVisitor/ViewFunctionArgumentsNodeVisitor.php:77
@AJenbo
Also we are missing button.blade.php since it's being required by the template you posted.
this is not relevant to the error, the template I posted has been trimmed down while still obtaining the error---you can just substitute a button element
@AJenbo,
Here's another MRE:
<?php
namespace App\View\Components\Maintenance\System;
use Eagle\Maintenance\Models\MaintenanceSystem;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection;
use Illuminate\View\Component;
class DropdownTree extends Component
{
public function __construct(
/** @var Collection<int, MaintenanceSystem> */
public Collection $systems,
public bool $onlyActive = true,
public ?MaintenanceSystem $selectedSystem = null,
) {
}
public function render(): View
{
return view('ems.maintenance.system._components.dropdown-tree');
}
}
<div>
</div>
Note that I've removed the entire blade contents and the failure still occurs---it's not until I remove all the properties from the class that phpstan passes:
<?php
namespace App\View\Components\Maintenance\System;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class DropdownTree extends Component
{
public function __construct(
) {
}
public function render(): View
{
return view('ems.maintenance.system._components.dropdown-tree');
}
}
You don't need to @ me I'm active in the topic π
I noticed that you are using promoted constructors, could you test if that is what is causing the issue?
Scratch that I have some components like that as well and they do not cause any issues.
Here's another MRE:
<?php namespace App\View\Components\Maintenance\System; use Eagle\Maintenance\Models\MaintenanceSystem; use Illuminate\Contracts\View\View; use Illuminate\Support\Collection; use Illuminate\View\Component; class DropdownTree extends Component { public function __construct( /** @var Collection<int, MaintenanceSystem> */ public Collection $systems, public bool $onlyActive = true, public ?MaintenanceSystem $selectedSystem = null, ) { } public function render(): View { return view('ems.maintenance.system._components.dropdown-tree'); } }
<div> </div>
Sorry but this is not enough to replicate the issue (I tried adding them to another repo and analyzing them). Like I mentioned it could be interactions between other PHPStan plugins you are using, or some other aspect of your repo. Please provide a project or steps to replicate the error.
$ vendor/bin/phpstan analyze app/View/Components/Maintenance/System/DropdownTree.php --level 1
Note: Using configuration file phpstan.neon.
1/1 [ββββββββββββββββββββββββββββ] 100%
------ ---------------------------------------------------------------------------------------------------------------------------------------------------------
Line DropdownTree.php
------ ---------------------------------------------------------------------------------------------------------------------------------------------------------
16 Parameter $selectedSystem of method App\View\Components\Maintenance\System\DropdownTree::__construct() has invalid type
Eagle\Maintenance\Models\MaintenanceSystem.
16 Property App\View\Components\Maintenance\System\DropdownTree::$selectedSystem has unknown class Eagle\Maintenance\Models\MaintenanceSystem as its type.
π‘ Learn more at https://phpstan.org/user-guide/discovering-symbols
------ ---------------------------------------------------------------------------------------------------------------------------------------------------------
Maybe the issue is with MaintenanceSystem
?
Swapping it for a ransom model gives me a [OK] No errors
all the way to level 9.
Have you tried removing $systems
and $selectedSystem
, but not $onlyActive
?
I've created an example repo here: https://github.com/calebdw/bladestan-errors
I've narrowed the issue down to two completely unrelated things that don't cause the failure when either of them are missing---not sure why their combined presence causes the failure. You're right about the issue being on the model---specifically with the $selectedSystem
property in the DropdownTree
component:
The two interactions are:
@property-read
annotation above the MaintenanceSystem modelHasFiles::restoreAllFiles()
trait methodThe MaintenanceSystem is a recursive model and therefore uses the laravel-adjacency-list package for the recursive relationships. The @property-read
annotation is required as Larastan is not able to deduce type for the $ancestorsAndSelf
property relation.
We also have a custom Files relation that can be added to a model through the HasFiles
trait. Bladestan is failing in the HasFiles::restoreAllFiles()
method, specifically with the $this->{$relationship}()
dynamic access:
public function restoreAllFiles(): void
{
foreach ($this->fileRelationships as $relationship) {
$loaded = $this->{$relationship}()->withTrashed()->get();
foreach ($loaded as $relation) {
$relation->restore();
}
}
}
however, there are other methods in the same trait with similar access that don't give Bladestan any issues---Bladestan should not be trying to analyze these methods in the first place though. For some reason, Bladestan is trying to analyze the HasFiles::restoreAllFiles()
method only when the @property-read Collection<int, self> $ancestorsAndSelf
annotation is on the model.
Maybe this issue is solved now ?
@williamdes Someone confirmed it last week. Did you test with the example repo for triggering the issue?
Hello!
I'm trying to install and use this extension but I'm getting several of the below errors when trying to run PHPStan (level 1) on my codebase:
Thanks!