TomasVotruba / bladestan

PHPStan analysis for Blade templates

Home Page:https://tomasvotruba.com/blog/introducing-bladestan-phpstan-analysis-of-blade-templates/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Should not happen...happens

calebdw opened this issue Β· comments

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:

Uncaught TomasVotruba\Bladestan\Exception\ShouldNotHappenException:  in /var/www/vendor/tomasvotruba/bladestan/src/PhpParser/NodeVisitor/ViewFunctionArgumentsNodeVisitor.php:77
#0 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(113): TomasVotruba\Bladestan\PhpParser\NodeVisitor\ViewFunctionArgumentsNodeVisitor->enterNode(Object(PhpParser\Node\Expr\MethodCall))
#1 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(133): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Expr\MethodCall))
#2 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(133): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Expr\Assign))
#3 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Expression))
#4 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105): PhpParser\NodeTraverser->traverseArray(Array)
#5 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Foreach_))
#6 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105): PhpParser\NodeTraverser->traverseArray(Array)
#7 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\ClassMethod))
#8 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105): PhpParser\NodeTraverser->traverseArray(Array)
#9 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Trait_))
#10 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(105): PhpParser\NodeTraverser->traverseArray(Array)
#11 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(196): PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Namespace_))
#12 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(85): PhpParser\NodeTraverser->traverseArray(Array)
#13 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Parser/RichParser.php(81): PhpParser\NodeTraverser->traverse(Array)
#14 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Parser/RichParser.php(54): PHPStan\Parser\RichParser->parseString('<?php\n\nnamespac...')
#15 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Parser/PathRoutingParser.php(56): PHPStan\Parser\RichParser->parseFile('/var/www/eagle/...')
#16 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Parser/CachedParser.php(44): PHPStan\Parser\PathRoutingParser->parseFile('/var/www/eagle/...')
#17 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Reflection/BetterReflection/SourceLocator/FileNodesFetcher.php(31): PHPStan\Parser\CachedParser->parseFile('/var/www/eagle/...')
#18 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Reflection/BetterReflection/SourceLocator/NewOptimizedDirectorySourceLocator.php(57): PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher->fetchNodes('/var/www/eagle/...')
#19 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AggregateSourceLocator.php(26): PHPStan\Reflection\BetterReflection\SourceLocator\NewOptimizedDirectorySourceLocator->locateIdentifier(Object(PHPStan\BetterReflection\Reflector\DefaultReflector), Object(PHPStan\BetterReflection\Identifier\Identifier))
#20 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Reflection/BetterReflection/SourceLocator/RewriteClassAliasSourceLocator.php(32): PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator->locateIdentifier(Object(PHPStan\BetterReflection\Reflector\DefaultReflector), Object(PHPStan\BetterReflection\Identifier\Identifier))
#21 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/AggregateSourceLocator.php(26): PHPStan\Reflection\BetterReflection\SourceLocator\RewriteClassAliasSourceLocator->locateIdentifier(Object(PHPStan\BetterReflection\Reflector\DefaultReflector), Object(PHPStan\BetterReflection\Identifier\Identifier))
#22 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/SourceLocator/Type/MemoizingSourceLocator.php(33): PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator->locateIdentifier(Object(PHPStan\BetterReflection\Reflector\DefaultReflector), Object(PHPStan\BetterReflection\Identifier\Identifier))
#23 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/Reflector/DefaultReflector.php(32): PHPStan\BetterReflection\SourceLocator\Type\MemoizingSourceLocator->locateIdentifier(Object(PHPStan\BetterReflection\Reflector\DefaultReflector), Object(PHPStan\BetterReflection\Identifier\Identifier))
#24 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/Reflection/ReflectionClass.php(1025): PHPStan\BetterReflection\Reflector\DefaultReflector->reflectClass('Eagle\\File\\Rela...')
#25 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/Reflection/Adapter/ReflectionClass.php(360): PHPStan\BetterReflection\Reflection\ReflectionClass->getTraits()
#26 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Reflection/ClassReflection.php(851): PHPStan\BetterReflection\Reflection\Adapter\ReflectionClass->getTraits()
#27 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Dependency/DependencyResolver.php(448): PHPStan\Reflection\ClassReflection->getTraits()
#28 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Dependency/DependencyResolver.php(313): PHPStan\Dependency\DependencyResolver->addClassToDependencies('App\\Settings\\Mo...', Array)
#29 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(149): PHPStan\Dependency\DependencyResolver->resolveDependencies(Object(PhpParser\Node\Expr\ClassConstFetch), Object(PHPStan\Analyser\MutatingScope))
#30 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Node/ClassStatementsGatherer.php(108): PHPStan\Analyser\FileAnalyser->PHPStan\Analyser\{closure}(Object(PhpParser\Node\Expr\ClassConstFetch), Object(PHPStan\Analyser\MutatingScope))
#31 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(2674): PHPStan\Node\ClassStatementsGatherer->__invoke(Object(PhpParser\Node\Expr\ClassConstFetch), Object(PHPStan\Analyser\MutatingScope))
#32 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(1606): PHPStan\Analyser\NodeScopeResolver->callNodeCallbackWithExpression(Object(PHPStan\Node\ClassStatementsGatherer), Object(PhpParser\Node\Expr\ClassConstFetch), Object(PHPStan\Analyser\MutatingScope), Object(PHPStan\Analyser\ExpressionContext))
#33 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(701): PHPStan\Analyser\NodeScopeResolver->processExprNode(Object(PhpParser\Node\Expr\ClassConstFetch), Object(PHPStan\Analyser\MutatingScope), Object(PHPStan\Node\ClassStatementsGatherer), Object(PHPStan\Analyser\ExpressionContext))
#34 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(680): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\PropertyProperty), Object(PHPStan\Analyser\MutatingScope), Object(PHPStan\Node\ClassStatementsGatherer), Object(PHPStan\Analyser\StatementContext))
#35 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(402): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\Property), Object(PHPStan\Analyser\MutatingScope), Object(PHPStan\Node\ClassStatementsGatherer), Object(PHPStan\Analyser\StatementContext))
#36 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(669): PHPStan\Analyser\NodeScopeResolver->processStmtNodes(Object(PhpParser\Node\Stmt\Class_), Array, Object(PHPStan\Analyser\MutatingScope), Object(PHPStan\Node\ClassStatementsGatherer), Object(PHPStan\Analyser\StatementContext))
#37 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(402): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\Class_), Object(PHPStan\Analyser\MutatingScope), Object(Closure), Object(PHPStan\Analyser\StatementContext))
#38 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(641): PHPStan\Analyser\NodeScopeResolver->processStmtNodes(Object(PhpParser\Node\Stmt\Namespace_), Array, Object(PHPStan\Analyser\MutatingScope), Object(Closure), Object(PHPStan\Analyser\StatementContext))
#39 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(371): PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\Namespace_), Object(PHPStan\Analyser\MutatingScope), Object(Closure), Object(PHPStan\Analyser\StatementContext))
#40 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(166): PHPStan\Analyser\NodeScopeResolver->processNodes(Array, Object(PHPStan\Analyser\MutatingScope), Object(Closure))
#41 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/Analyser.php(72): PHPStan\Analyser\FileAnalyser->analyseFile('/var/www/app/Se...', Array, Object(PHPStan\Rules\LazyRegistry), Object(PHPStan\Collectors\Registry), NULL)
#42 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Command/AnalyserRunner.php(62): PHPStan\Analyser\Analyser->analyse(Array, Object(Closure), NULL, true, Array)
#43 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Command/AnalyseApplication.php(209): PHPStan\Command\AnalyserRunner->runAnalyser(Array, Array, Object(Closure), NULL, true, true, '/var/www/phpsta...', Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput))
#44 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Command/AnalyseApplication.php(101): PHPStan\Command\AnalyseApplication->runAnalyser(Array, Array, true, '/var/www/phpsta...', Object(PHPStan\Command\Symfony\SymfonyOutput), Object(PHPStan\Command\Symfony\SymfonyOutput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput))
#45 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/src/Command/AnalyseCommand.php(198): PHPStan\Command\AnalyseApplication->analyse(Array, false, Object(PHPStan\Command\Symfony\SymfonyOutput), Object(PHPStan\Command\Symfony\SymfonyOutput), false, true, '/var/www/phpsta...', Array, Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput))
#46 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Command/Command.php(259): PHPStan\Command\AnalyseCommand->execute(Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Output\ConsoleOutput))
#47 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(870): _PHPStan_39fe102d2\Symfony\Component\Console\Command\Command->run(Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Output\ConsoleOutput))
#48 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(261): _PHPStan_39fe102d2\Symfony\Component\Console\Application->doRunCommand(Object(PHPStan\Command\AnalyseCommand), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Output\ConsoleOutput))
#49 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(157): _PHPStan_39fe102d2\Symfony\Component\Console\Application->doRun(Object(_PHPStan_39fe102d2\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_39fe102d2\Symfony\Component\Console\Output\ConsoleOutput))
#50 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(124): _PHPStan_39fe102d2\Symfony\Component\Console\Application->run()
#51 phar:///var/www/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(125): _PHPStan_39fe102d2\{closure}()
#52 /var/www/vendor/phpstan/phpstan/phpstan(8): require('phar:///var/www...')
#53 /var/www/vendor/bin/phpstan(119): include('/var/www/vendor...')
#54 {main}

Thanks!

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:


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 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:

  1. @property-read annotation above the MaintenanceSystem model
  2. HasFiles::restoreAllFiles() trait method

The 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.