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

Should not happen...happens #92

Open
calebdw opened this issue Dec 14, 2023 · 14 comments
Open

Should not happen...happens #92

calebdw opened this issue Dec 14, 2023 · 14 comments

Comments

@calebdw
Copy link

calebdw commented Dec 14, 2023

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!

@AJenbo
Copy link
Contributor

AJenbo commented Dec 14, 2023

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.

@calebdw
Copy link
Author

calebdw commented Dec 18, 2023

@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)

@AJenbo
Copy link
Contributor

AJenbo commented Dec 18, 2023

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.

@calebdw
Copy link
Author

calebdw commented Dec 18, 2023

@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

@AJenbo
Copy link
Contributor

AJenbo commented Dec 18, 2023

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.

@AJenbo
Copy link
Contributor

AJenbo commented Dec 18, 2023

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.

@calebdw
Copy link
Author

calebdw commented Dec 18, 2023

@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

@calebdw
Copy link
Author

calebdw commented Dec 18, 2023

@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

@calebdw
Copy link
Author

calebdw commented Dec 18, 2023

@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');
    }
}

@AJenbo
Copy link
Contributor

AJenbo commented Dec 19, 2023

You don't need to @ me I'm active in the topic 🙂

@AJenbo
Copy link
Contributor

AJenbo commented Dec 19, 2023

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.

@AJenbo
Copy link
Contributor

AJenbo commented Dec 19, 2023

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.

@AJenbo
Copy link
Contributor

AJenbo commented Dec 19, 2023

Have you tried removing $systems and $selectedSystem, but not $onlyActive?

@calebdw
Copy link
Author

calebdw commented Dec 19, 2023

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.

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

No branches or pull requests

2 participants