GithubHelp home page GithubHelp logo

tomasvotruba / bladestan Goto Github PK

View Code? Open in Web Editor NEW
283.0 283.0 13.0 270 KB

PHPStan analysis for Blade templates

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

License: MIT License

PHP 93.20% Blade 6.80%

bladestan's Introduction

Hi, I'm Tomas, and I love Legacy

Nothing excites me more than good old legacy code. A code that can be improved light-years in a matter of few-days work. Not tedious and repetitive work. But with intelligent modern automated almost-futuristic tools.


"If you really want to do something, you'll find a way.

If you don't, you'll find an excuse."


My biggest passion is to innovate in the area of "impossible" and help developers to be happier ❤️ at their daily work.

If you're happy, you enjoy your work and life more, don't you? 😉


I Love to Share and Work

  • 🚀 I work on Rector to help you forget about technical debt and upgrade from PHP 5.6 to PHP 8.1 in a day 💪
  • 🖌️ I blog weekly about PHP and cool coding shortcuts at tomasvotruba.com
  • 📖 I wrote a book about Rector - The Power of Automated Refactoring together with my childhood hero
  • ❤️ Do you enjoy tasty fruits of my work? Support me at Github Sponsors
  • 🐦 I tweet about ideas worth learning at @votrubaT
  • 🔨 Currently, I help successful PHP projects to turn their legacy around to modern, productive code, and fun project to work with.

Do you want your code to be like that? Let me know

bladestan's People

Contributors

ajenbo avatar canvural avatar ghbob avatar joeri-abbo avatar ngmy avatar owenvoke avatar robchett avatar seb33300 avatar spawnia avatar staabm avatar szepeviktor avatar thibauddauce avatar tomasvotruba avatar ziming avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

bladestan's Issues

Component support

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Thumb extends Component
{
    public function render()
    {
        return view('components.img.view', []);
    }
}

When the class is extending Component it can be assumed that the view will be included in a context where the following variables exists as as such we should inject them when evaluating it out of context to pass the template correctly.

$slot = new Illuminate\Support\HtmlString();
$attributes = new Illuminate\View\ComponentAttributeBag();

If detecting the context of view() is problematic we could require that Component::view() be used instead.

Should not happen...happens

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!

Invalid configuration

Based on the fact that I already use Larastan in my projects, I wanted to try bladestan in addition. Unfortunately, however, I make the experience, no matter how I configure phpstan.neon, I am always told invalid configuration.

Invalid configuration:
Unexpected item 'parameters › bladestan'.

I tried it together with larastan configuration, but also just took out that configuration and wanted to run the bladestan configuration alone.

Inline anonymous components

As things are components are analyzed from the context of there associated class. This however leaves out anonymous Components since they do not have a corresponding class which render them by calling view().

https://laravel.com/docs/10.x/blade#anonymous-components

The solution here (I have not yet investigated it) is probably to inline them in a similar fashion to how @include directives are being handled.

I might be able to work on this, but do not have a time line for when that would happen as there are a few other things we need to work on at the moment.


As a side note we have rolled out Bladestan on our code and it's now passing 24 blade files at level 9, 556 at level 1, and 391 at level 3... minus how ever many anonymous components we have :)

setup documentation: add phpstan.neon includes

Couldn't find it in the blogpost (1) nor the readme (2) but one actually has to require the extension to run bladestan with phpstan, correct?

Otherwise I immediately run into:

Invalid configuration:
Unexpected item 'parameters › bladestan'.

therefore e.g.

includes:
    - ./vendor/tomasvotruba/bladestan/config/extension.neon
    - ./vendor/phpstan/phpstan-strict-rules/rules.neon
    - ./vendor/nunomaduro/larastan/extension.neon

Thanks!

Fail to reflect on model when Larastan and config() is used

This appears to be a bad interaction between bladestan, larastan and the given project. When ever an instance of Spatie\Permission\Models\Role is used i get the below stack trace.

This may well be related to #29

Drilling down to it we can see that getTable() on the model calls config() for which Laravel's container will try to resolve the Illuminate\Config\Repository class via the alias config, probably because of Illuminate\Support\Facades\Config.

    public function getTable()
    {
        return config('permission.table_names.roles', parent::getTable());
    }

Disabeling Larastan will resolve this, but that is obviously not a viable option.

Internal error: Internal error: Target class [config] does not exist. in file
 /project/app/Http/Controllers/Admin/RolesController.php 

 Post the following stack trace to https://github.com/phpstan/phpstan/issues/new?template=Bug_report.md:
 #0 /project/vendor/laravel/framework/src/Illuminate/Container/Container.php(770): Illuminate\Container\Container->build() 
 #1 /project/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(856): Illuminate\Container\Container->resolve()
 #2 /project/vendor/laravel/framework/src/Illuminate/Container/Container.php(706): Illuminate\Foundation\Application->resolve()
 #3 /project/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(841): Illuminate\Container\Container->make() 
 #4 /project/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php(120): Illuminate\Foundation\Application->make()
 #5 /project/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php(276): app()
 #6 /project/vendor/spatie/laravel-permission/src/Models/Role.php(41): config()
 #7 /project/vendor/nunomaduro/larastan/src/Properties/ModelPropertyExtension.php(70): Spatie\Permission\Models\Role->getTable() 
 #8 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Reflection/ClassReflection.php(420): 
 NunoMaduro\Larastan\Properties\ModelPropertyExtension->hasProperty() 
 #9 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Type/ObjectType.php(134):
 PHPStan\Reflection\ClassReflection->hasProperty()
 #10 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(3384): 
 PHPStan\Type\ObjectType->hasProperty() 
 #11 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(3394): 
 PHPStan\Analyser\MutatingScope->getPropertyReflection()
 #12 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1399): 
 PHPStan\Analyser\MutatingScope->propertyFetchType()
 #13 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1405): 
 PHPStan\Analyser\MutatingScope->PHPStan\Analyser\{closure}() 
 #14 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(556):
 PHPStan\Analyser\MutatingScope->resolveType()
 #15 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1333): 
 PHPStan\Analyser\MutatingScope->getType()
 #16 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1339): 
 PHPStan\Analyser\MutatingScope->PHPStan\Analyser\{closure}() 
 #17 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(556):
 PHPStan\Analyser\MutatingScope->resolveType()
 #18 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1333): 
 PHPStan\Analyser\MutatingScope->getType()
 #19 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1339): 
 PHPStan\Analyser\MutatingScope->PHPStan\Analyser\{closure}() 
 #20 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(556):
 PHPStan\Analyser\MutatingScope->resolveType()
 #21 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(742):
 PHPStan\Analyser\MutatingScope->getType()
 #22 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(556):
 PHPStan\Analyser\MutatingScope->resolveType()
 #23 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(1452): 
 PHPStan\Analyser\MutatingScope->getType()
 #24 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(562):
 PHPStan\Analyser\NodeScopeResolver->findEarlyTerminatingExpr() 
 #25 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(332):
 PHPStan\Analyser\NodeScopeResolver->processStmtNode()
 #26 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(175): 
 PHPStan\Analyser\NodeScopeResolver->processNodes() 
 #27 /project/vendor/tomasvotruba/bladestan/src/Rules/ViewRuleHelper.php(100): PHPStan\Analyser\FileAnalyser->analyseFile()
 #28 /project/vendor/tomasvotruba/bladestan/src/Rules/ViewRuleHelper.php(55):
 TomasVotruba\Bladestan\Rules\ViewRuleHelper->processTemplateFilePath() 
 #29 /project/vendor/tomasvotruba/bladestan/src/Rules/BladeRule.php(59): TomasVotruba\Bladestan\Rules\ViewRuleHelper->processNode()
 #30 /project/vendor/tomasvotruba/bladestan/src/Rules/BladeRule.php(42): 
 TomasVotruba\Bladestan\Rules\BladeRule->processLaravelViewFunction() 
 #31 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(106): 
 TomasVotruba\Bladestan\Rules\BladeRule->processNode()
 #32 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Node/ClassStatementsGatherer.php(98): 
 PHPStan\Analyser\FileAnalyser->PHPStan\Analyser\{closure}()
 #33 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(511):
 PHPStan\Node\ClassStatementsGatherer->__invoke() 
 #34 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(2484): 
 PHPStan\Analyser\NodeScopeResolver::PHPStan\Analyser\{closure}() 
 #35 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(1477): 
 PHPStan\Analyser\NodeScopeResolver->callNodeCallbackWithExpression() 
 #36 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(541):
 PHPStan\Analyser\NodeScopeResolver->processExprNode()
 #37 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(365):
 PHPStan\Analyser\NodeScopeResolver->processStmtNode()
 #38 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(526):
 PHPStan\Analyser\NodeScopeResolver->processStmtNodes() 
 #39 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(365):
 PHPStan\Analyser\NodeScopeResolver->processStmtNode()
 #40 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(604):
 PHPStan\Analyser\NodeScopeResolver->processStmtNodes() 
 #41 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(365):
 PHPStan\Analyser\NodeScopeResolver->processStmtNode()
 #42 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(576):
 PHPStan\Analyser\NodeScopeResolver->processStmtNodes() 
 #43 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(332):
 PHPStan\Analyser\NodeScopeResolver->processStmtNode()
 #44 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(175): 
 PHPStan\Analyser\NodeScopeResolver->processNodes() 
 #45 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(134): 
 PHPStan\Analyser\FileAnalyser->analyseFile() 
 #46 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97): 
 PHPStan\Command\WorkerCommand->PHPStan\Command\{closure}() 
 #47 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/clue/ndjson-react/src/Decoder.php(110):
 _PHPStan_eb00fd21c\Evenement\EventEmitter->emit()
 #48 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97): 
 _PHPStan_eb00fd21c\Clue\React\NDJson\Decoder->handleData() 
 #49 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/Util.php(62): 
 _PHPStan_eb00fd21c\Evenement\EventEmitter->emit()
 #50 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97): 
 _PHPStan_eb00fd21c\React\Stream\Util::_PHPStan_eb00fd21c\React\Stream\{closure}()
 #51 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/DuplexResourceStream.php(154):
 _PHPStan_eb00fd21c\Evenement\EventEmitter->emit()
 #52 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(201):
 _PHPStan_eb00fd21c\React\Stream\DuplexResourceStream->handleData() 
 #53 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(173):
 _PHPStan_eb00fd21c\React\EventLoop\StreamSelectLoop->waitForStreamActivity() 
 #54 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(97):
 _PHPStan_eb00fd21c\React\EventLoop\StreamSelectLoop->run() 
 #55 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Command/Command.php(259):
 PHPStan\Command\WorkerCommand->execute() 
 #56 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(870):
 _PHPStan_eb00fd21c\Symfony\Component\Console\Command\Command->run()
 #57 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(261):
 _PHPStan_eb00fd21c\Symfony\Component\Console\Application->doRunCommand() 
 #58 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(157):
 _PHPStan_eb00fd21c\Symfony\Component\Console\Application->doRun()
 #59 phar:///project/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(124): 
 _PHPStan_eb00fd21c\Symfony\Component\Console\Application->run()
 #60 phar:///project/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(125): _PHPStan_eb00fd21c\{closure}()
 #61 /project/vendor/phpstan/phpstan/phpstan(8): require('...')
 #62 /project/vendor/bin/phpstan(120): include('...')
 #63 {main} 

README typo formatter option

shouldn't

vendor/bin/phpstan --error-format blade

be

vendor/bin/phpstan --error-format=blade

as I get

Command "blade" is not defined.

Add support for response()->view()

I scanned a few of my current projects, and over 99% of the time I'm returning a view from a controller, I use the global view() helper, but that < 1% would be nice to cover too.

Sometimes if you need to set a response header or alter the status code, I'll use Response::view() or response()->view().

I'm contemplating standardizing on response()->view() since it returns a concrete Response type, whereas the global view helper returns a much larger union type.

BladeRule not found

Now that I have Bladestan up and running, I run into the next problem.

In Resolver.php line 111:
                                                                                  
  Service 'rules.150': Class 'TomasVotruba\Bladestan\Rules\BladeRule' not found.

MailMessage::view() not analyzed

use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class Whatever extends Notification
{
  // ...
  public function toMail($notifiable): MailMessage
  {
    return (new MailMessage())->view('my-view-name', [
      'var1' => 'value1',
      // ...
    ])->subject('not relevant');
  }
}

Syntax error, unexpected T_VARIABLE, expecting ';'

Not sure exactly what's causing this error, but I can update the title if we come to a more specific description of the issue.

When I install bladestan and run phpstan for the first time, I see the following error:

 ------ ---------------------------------------------------------------
  Line   app/View/Components/EntityList.php
 ------ ---------------------------------------------------------------
  17     Syntax error, unexpected T_VARIABLE, expecting ';' on line 17
 ------ ---------------------------------------------------------------

There are no other reported errors.

From some of the other issue descriptions in this repo, I gather that the line number corresponds to the template, not the controller? I saw that removing a blank line in the template caused an equal change in line numbering in the error report (was L18, now is L17).

Here is the relevant context, including both the template and its corresponding Component class:

rg --context=5 EntityListLayout::GRID
resources/views/components/entity-list/index.blade.php
12-
13-  <div @class([
14-      'entity-list__items',
15-      "is-layout-$layout->value",
16-      'flex',
17:      'gap-4' => $layout === EntityListLayout::GRID,
18-      'flex-col gap-y-8' => $layout === EntityListLayout::STREAM,
19-  ])>
20-    @foreach ($entities as $entity)
21-      <div class="gap-4">
22-        <x-dynamic-component

app/View/Components/EntityList.php
14-{
15-    public function __construct(
16-        /** @var CoreObject[] */
17-        public array $entities,
18-        public ?string $title = null,
19:        public EntityListLayout $layout = EntityListLayout::GRID,
20-    ) {}
21-
22-    public function render()
23-    {
24-        return view('components.entity-list.index');

Other notes:

  • EntityListLayout is an enum
  • No effect: Commenting out L17-L18 in the template
  • No effect: Commenting out L17-L19 in EntityList.php
  • No effect: Replacing all variable interpolation in the template with sprintfs
  • No effect: clearing view cache
  • This project is using the Illuminate packages via roots/acorn

Add Livewire support

the blade can access the public property of the livewire component without having to specify it as a parameter for "view" helper in the "render" method? like so

public $foo = 'bar';
public function render()
{
    return view('custom-livewire');
}

in blade
{{ $foo }}

Too many like this for each livewire component

Line app/Http/Requests/Requests/Livewire/View/ActionsLivewire.php


29 Variable $foo might not be defined.
29 Variable $foo might not be defined.
29 Variable $foo might not be defined.
29 Variable $foo might not be defined.
29 Variable $foo might not be defined.
29 Variable $foo might not be defined.


Type of $this gets mangled when passed as a variable to blade

If in a component you use the following to pass the component model to the blade template:

view('my-template', ['model' => $this]);

The analyzed PHP code will looks like this:

/** @var $this(App\View\Components\MyForm) $model */

Thisisn't valid an will generate errors and warnings in PHPStan, instead the correctly generated phpDoc should look like this:

/** @var App\View\Components\MyForm $model */

Wildcards in template_paths?

Great package! Is it possible to use wildcards in template paths? Eg:

parameters:
    bladestan:
        template_paths:
            # default
            - resources/views
            - modules/*/views

Problems with enums

while using a enum in a blade I get this

Parameter #1 (App\Enums\PlaceholderTypeEnum::Checkbox) of echo cannot be converted to string.

it is uses like this:

<x-native-select
        label="{{ __('Select type') }}"
        wire:model="placeholders.{{ $key }}.type"
        placeholder="{{ __('Select type') }}">
    <option value="">{{ __('Select type') }}</option>
    <option value="{{PlaceholderTypeEnum::Checkbox }}">{{ __('Checkbox') }}</option>
    <option value="{{PlaceholderTypeEnum::Number }}">{{ __('Number') }}</option>
    <option value="{{PlaceholderTypeEnum::Date }}">{{ __('Date') }}</option>
    <option value="{{PlaceholderTypeEnum::Today}}">{{ __('Today') }}</option>
    <option value="{{PlaceholderTypeEnum::Text }}">{{ __('Text') }}</option>
    <option value="{{PlaceholderTypeEnum::Email }}">{{ __('Email') }}</option>
    <option value="{{PlaceholderTypeEnum::Signature }}">{{ __('Signature') }}</option>
    <option value="{{PlaceholderTypeEnum::Decimal }}">{{ __('Decimal') }}</option>
    <option value="{{PlaceholderTypeEnum::YesNo }}">{{ __('YesNo') }}</option>
    <option value="{{PlaceholderTypeEnum::UploadPDF }}">{{ __('Upload pdf') }}</option>
    <option value="{{PlaceholderTypeEnum::UploadImage }}">{{ __('Upload image') }}</option>
  </x-native-select>

component support?

canvural/phpstan-blade-rule has a not in the readme:

Blade components are not analyzed. Support for it will come soon.

Has this been reolved since it does not appear?

I noticed that the following will produce an error:

<?php

namespace App\View\Components;

use Illuminate\Contracts\View\View;
use Illuminate\View\Component;

class MyComponent extends Component
{
    public string $test;

    public function render(): View
    {
        return view('components.my-component');
    }
}

Variable $test might not be defined.

Find missing translation strings in blade files

Hello,

I recently developed a package (coding-socks/lost-in-translation) which is able to scan Blade files to identify translation strings and report if the translation for that string is missing from a locale.

u/boreasaurus on Reddit said the following:

It would be amazing if somehow this functionality existed in larastan, as that is already reporting errors for e.g. view('some.unknown.view')

In larastan/larastan#1822 I was informed that they probably meant this package and not Larastan.

My package provides a lost-in-translation:find {locale} artisan command which reads all blade files, compiles them to PHP, converts them to tokens, and then finds the relevant nodes in the AST (Abstract syntax tree). As far as I know, this is similar to how static analysis tools work.

I'm not sure if I will have enough time in the upcoming days but I would happily work on adding this feature if you think it's a good addition. However, I might require some guidance on where to start because I'm not familiar enough with PHPStan.

Internal error: Internal error: config in file

Internal error: Internal error: config in file /project/app/View/Components/Products/ProductSearch.php                   
																																													   
Post the following stack trace to https://github.com/phpstan/phpstan/issues/new?template=Bug_report.md:                                                                                   
#0 /project/vendor/nunomaduro/larastan/src/ReturnTypes/AuthExtension.php(50):                                            
Illuminate\Container\Container->get()                                                                                                                                                     
#1 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(3355):                             
NunoMaduro\Larastan\ReturnTypes\AuthExtension->getTypeFromStaticMethodCall()                                                                                                              
#2 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1374):                             
PHPStan\Analyser\MutatingScope->methodCallReturnType()                                                                                                                                    
#3 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1380):                             
PHPStan\Analyser\MutatingScope->PHPStan\Analyser\{closure}()                                                                                                                              
#4 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(556):                              
PHPStan\Analyser\MutatingScope->resolveType()                                                                                                                                             
#5 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1399):                             
PHPStan\Analyser\MutatingScope->getType()                                                                                                                                                 
#6 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1405):                             
PHPStan\Analyser\MutatingScope->PHPStan\Analyser\{closure}()                                                                                                                              
#7 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(556):                              
PHPStan\Analyser\MutatingScope->resolveType()                                                                                                                                             
#8 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(742):                              
PHPStan\Analyser\MutatingScope->getType()                                                                                                                                                 
#9 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(556):                              
PHPStan\Analyser\MutatingScope->resolveType()                                                                                                                                             
#10 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(1452):                        
PHPStan\Analyser\MutatingScope->getType()                                                                                                                                                 
#11 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(562):                         
PHPStan\Analyser\NodeScopeResolver->findEarlyTerminatingExpr()                                                                                                                            
#12 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(365):                         
PHPStan\Analyser\NodeScopeResolver->processStmtNode()                                                                                                                                     
#13 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(526):                         
PHPStan\Analyser\NodeScopeResolver->processStmtNodes()                                                                                                                                    
#14 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(365):                         
PHPStan\Analyser\NodeScopeResolver->processStmtNode()                                                                                                                                     
#15 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(604):                         
PHPStan\Analyser\NodeScopeResolver->processStmtNodes()                                                                                                                                    
#16 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(365):                         
PHPStan\Analyser\NodeScopeResolver->processStmtNode()                                                                                                                                     
#17 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(576):                         
PHPStan\Analyser\NodeScopeResolver->processStmtNodes()                                                                                                                                    
#18 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(332):                         
PHPStan\Analyser\NodeScopeResolver->processStmtNode()                                                                                                                                     
#19 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(175):                              
PHPStan\Analyser\NodeScopeResolver->processNodes()                                                                                                                                        
#20 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(134):                              
PHPStan\Analyser\FileAnalyser->analyseFile()                                                                                                                                              
#21                                                                                                                                                                                       
phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97):  
PHPStan\Command\WorkerCommand->PHPStan\Command\{closure}()                                                                                                                                
#22 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/clue/ndjson-react/src/Decoder.php(110):                   
_PHPStan_eb00fd21c\Evenement\EventEmitter->emit()                                                                                                                                         
#23                                                                                                                                                                                       
phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97):  
_PHPStan_eb00fd21c\Clue\React\NDJson\Decoder->handleData()                                                                                                                                
#24 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/Util.php(62):                            
_PHPStan_eb00fd21c\Evenement\EventEmitter->emit()                                                                                                                                         
#25                                                                                                                                                                                       
phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97):  
_PHPStan_eb00fd21c\React\Stream\Util::_PHPStan_eb00fd21c\React\Stream\{closure}()                                                                                                         
#26 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/DuplexResourceStream.php(154):           
_PHPStan_eb00fd21c\Evenement\EventEmitter->emit()                                                                                                                                         
#27 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(201):           
_PHPStan_eb00fd21c\React\Stream\DuplexResourceStream->handleData()                                                                                                                        
#28 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(173):           
_PHPStan_eb00fd21c\React\EventLoop\StreamSelectLoop->waitForStreamActivity()                                                                                                              
#29 phar:///project/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(97):                               
_PHPStan_eb00fd21c\React\EventLoop\StreamSelectLoop->run()                                                                                                                                
#30 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Command/Command.php(259):                 
PHPStan\Command\WorkerCommand->execute()                                                                                                                                                  
#31 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(870):                     
_PHPStan_eb00fd21c\Symfony\Component\Console\Command\Command->run()                                                                                                                       
#32 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(261):                     
_PHPStan_eb00fd21c\Symfony\Component\Console\Application->doRunCommand()                                                                                                                  
#33 phar:///project/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(157):                     
_PHPStan_eb00fd21c\Symfony\Component\Console\Application->doRun()                                                                                                                         
#34 phar:///project/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(124):                                                
_PHPStan_eb00fd21c\Symfony\Component\Console\Application->run()                                                                                                                           
#35 phar:///project/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(125): _PHPStan_eb00fd21c\{closure}()                 
#36 /project/vendor/phpstan/phpstan/phpstan(8): require('...')                                                           
#37 /project/vendor/bin/phpstan(120): include('...')                                                                     
#38 {main}                                                                                                                                                                                
Child process error (exit code 1):
<?php

namespace App\View\Components\Products;

use Illuminate\Support\Facades\Auth;
use Livewire\Component;

class ProductSearch extends Component
{
    public function render(): void
    {
    }

    private function setDefaultValues(): void
    {
        $this->userEmail = Auth::user()->email;
    }
}

Caching of results

PHPStan has a pretty good caching scheme but from what I can tell Bladestan is working in a way that doesn't really benefit from it.

Since adding Bladestan to our CI process the total time it takes to run has almost doubled. I'm thinking that it might be worth looking into implementing result caching to speed things up with little has changed between two runs.

Are there any thought about how caching could be implemented in an effective way for Bladestan?

How to use Bladestan? resources/views vs. app

What is the intended usage? May I use both? What is the real difference in findings?

phpstan analyze -c vendor/tomasvotruba/bladestan/config/extension.neon -l max resources/views/
phpstan analyze -c vendor/tomasvotruba/bladestan/config/extension.neon -l max app/

Syntax error, unexpected ',' on line 1

If a blade template has at least 2 @include() and this first has spaces between brackets, a syntax error is returned by the phpstan analyse command:

@include('template.path', ['param' => 'value'] )  <= syntax error because of the space just before )
@include('template.path', ['param' => 'value'])

Infinite loop on template recursion

Bladestan 0.5.0
PHP 8.3.2
PHPStan 1.10.59 with extension installer
Laravel 10.45.1
Livewire 3.4.6

It seems this plugin doesn't account for template recursion as I get a

     Child process error: PHPStan process crashed because it reached configured PHP memory limit: 2G  
     Increase your memory limit in php.ini or run PHPStan with --memory-limit CLI option.    

Whenever I do something like this inside my resources/views/livewire/category/partials/options.blade.php:

@foreach($children as $category)
    <option value="{{ $category->id }}" {{ $category->id === $editingCategoryParentId ? 'selected' : '' }} >
        @for ($i = $category->lvl; $i >= 1; $i--)-@endfor
        {{ $category->name }}
    </option>
    @if($category->children)
        @include('livewire.category.partials.options', ['children' => $category->children])
    @endif
@endforeach

as you can probably see this is a blade partial to render options for a tree structure which can have multiple levels like you can see here
image

When I disable the recursive template renderings I don't get the error and instead get correct balde template stan issues.

View variables are not recognized if stored in a variable

The following will fail

$items = ['item'];
$compat = compact('items');
return view('newsletters.edit-new-segmented', $compat);

But this will pass

$items = ['item'];
return view('newsletters.edit-new-segmented', compact('items'));

@TomasVotruba I expect to start adding test cases next week, so no need to mention it again :)

`@vite` directive path checking

Vite is quiet popular as Laravel has it built in.

@vite('resources/js/app.css')

I'm met with this non-existent path.
Could we check the path in vite directive?

Bladestan + Larastan - Custom Artisan command error

I have created a reproducer repository for you to try + to exemplify the error. Everything is stock Laravel 10.18 except for:

I've commented on the files to be explanatory. When running ./vendor/bin/phpstan analyze ./app/Console/Commands/DusterCodeFix.php -v with both extensions enabled, the following error is produced:

 -- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
     Error
 -- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------   
     Internal error: Internal error: Target [Illuminate\Database\Migrations\MigrationRepositoryInterface] is not instantiable while building [Illuminate\Database\Console\Migrations\MigrateCommand,
     Illuminate\Database\Migrations\Migrator]. in file /e/server/bladestan-error/app/Console/Commands/DusterCodeFix.php

     Post the following stack trace to https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml:
     #0 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(921): Illuminate\Container\Container->notInstantiable()
     #1 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(795): Illuminate\Container\Container->build()
     #2 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(933): Illuminate\Container\Container->resolve()
     #3 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(731): Illuminate\Foundation\Application->resolve()
     #4 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(918): Illuminate\Container\Container->make()
     #5 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(1066): Illuminate\Foundation\Application->make()
     #6 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(982): Illuminate\Container\Container->resolveClass()
     #7 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(943): Illuminate\Container\Container->resolveDependencies()
     #8 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(795): Illuminate\Container\Container->build()
     #9 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(933): Illuminate\Container\Container->resolve()
     #10 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(731): Illuminate\Foundation\Application->resolve()
     #11 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(918): Illuminate\Container\Container->make()
     #12 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(1066): Illuminate\Foundation\Application->make()
     #13 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(982): Illuminate\Container\Container->resolveClass()
     #14 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(943): Illuminate\Container\Container->resolveDependencies()
     #15 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(795): Illuminate\Container\Container->build()
     #16 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(933): Illuminate\Container\Container->resolve()
     #17 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Container/Container.php(731): Illuminate\Foundation\Application->resolve()
     #18 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(918): Illuminate\Container\Container->make()
     #19 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Console/Application.php(249): Illuminate\Foundation\Application->make()
     #20 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Console/Application.php(263): Illuminate\Console\Application->resolve()
     #21 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Support/ServiceProvider.php(404): Illuminate\Console\Application->resolveCommands()
     #22 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Console/Application.php(130): Illuminate\Support\ServiceProvider->Illuminate\Support\{closure}()
     #23 /e/server/bladestan-error/vendor/laravel/framework/src/Illuminate/Console/Application.php(77): Illuminate\Console\Application->bootstrap()
     #24 /e/server/bladestan-error/vendor/nunomaduro/larastan/src/Internal/ConsoleApplicationResolver.php(50): Illuminate\Console\Application->__construct()
     #25 /e/server/bladestan-error/vendor/nunomaduro/larastan/src/Internal/ConsoleApplicationResolver.php(26): NunoMaduro\Larastan\Internal\ConsoleApplicationResolver->getApplication()
     #26 /e/server/bladestan-error/vendor/nunomaduro/larastan/src/ReturnTypes/ConsoleCommand/ArgumentDynamicReturnTypeExtension.php(69):
     NunoMaduro\Larastan\Internal\ConsoleApplicationResolver->findCommands()
     #27 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(3481):
     NunoMaduro\Larastan\ReturnTypes\ConsoleCommand\ArgumentDynamicReturnTypeExtension->getTypeFromMethodCall()
     #28 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1376): PHPStan\Analyser\MutatingScope->methodCallReturnType()
     #29 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1382): PHPStan\Analyser\MutatingScope->PHPStan\Analyser\{closure}()
     #30 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(564): PHPStan\Analyser\MutatingScope->resolveType()
     #31 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(761): PHPStan\Analyser\MutatingScope->getType()
     #32 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(564): PHPStan\Analyser\MutatingScope->resolveType()
     #33 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(1545): PHPStan\Analyser\MutatingScope->getType()
     #34 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(598): PHPStan\Analyser\NodeScopeResolver->findEarlyTerminatingExpr()
     #35 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(384): PHPStan\Analyser\NodeScopeResolver->processStmtNode()
     #36 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(557): PHPStan\Analyser\NodeScopeResolver->processStmtNodes()
     #37 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(384): PHPStan\Analyser\NodeScopeResolver->processStmtNode()
     #38 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(640): PHPStan\Analyser\NodeScopeResolver->processStmtNodes()
     #39 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(384): PHPStan\Analyser\NodeScopeResolver->processStmtNode()
     #40 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(612): PHPStan\Analyser\NodeScopeResolver->processStmtNodes()
     #41 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(353): PHPStan\Analyser\NodeScopeResolver->processStmtNode()
     #42 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(166): PHPStan\Analyser\NodeScopeResolver->processNodes()
     #43 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(130): PHPStan\Analyser\FileAnalyser->analyseFile()
     #44 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97): PHPStan\Command\WorkerCommand->PHPStan\Command\{closure}()    
     #45 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/clue/ndjson-react/src/Decoder.php(117): _PHPStan_7c49c944c\Evenement\EventEmitter->emit()
     #46 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97): _PHPStan_7c49c944c\Clue\React\NDJson\Decoder->handleData()    
     #47 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/Util.php(62): _PHPStan_7c49c944c\Evenement\EventEmitter->emit()
     #48 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97):
     _PHPStan_7c49c944c\React\Stream\Util::_PHPStan_7c49c944c\React\Stream\{closure}()
     #49 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/DuplexResourceStream.php(154): _PHPStan_7c49c944c\Evenement\EventEmitter->emit()
     #50 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(201): _PHPStan_7c49c944c\React\Stream\DuplexResourceStream->handleData()
     #51 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(173):
     _PHPStan_7c49c944c\React\EventLoop\StreamSelectLoop->waitForStreamActivity()
     #52 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(96): _PHPStan_7c49c944c\React\EventLoop\StreamSelectLoop->run()
     #53 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Command/Command.php(259): PHPStan\Command\WorkerCommand->execute()
     #54 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(870): _PHPStan_7c49c944c\Symfony\Component\Console\Command\Command->run()
     #55 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(261): _PHPStan_7c49c944c\Symfony\Component\Console\Application->doRunCommand()
     #56 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(157): _PHPStan_7c49c944c\Symfony\Component\Console\Application->doRun()
     #57 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(124): _PHPStan_7c49c944c\Symfony\Component\Console\Application->run()
     #58 phar:///e/server/bladestan-error/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(125): _PHPStan_7c49c944c\{closure}()
     #59 /e/server/bladestan-error/vendor/phpstan/phpstan/phpstan(8): require('...')
     #60 /e/server/bladestan-error/vendor/bin/phpstan(120): include('...')
     #61 {main}
     Child process error (exit code 1):
 -- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  

In our production repo, the error is different since we have different packages installed:

Internal error: Internal error: Target class [command.debugbar.clear] does not exist. in file /e/server/private-repo/app/Console/Commands/DusterCodeFix.php

I'd love to have a way to specify Bladestan (and not PHPStan as a whole) ignore specific files and directories. Or to see this fixed generally!

Please let me know if this is ultimately a Larastan issue or if I can help in any way.

Use statments in partials results in parsing errors

Example:

@include('partial')

Partial:

@php
use \Exception();
@endphp

Result:

Syntax error, unexpected T_USE

This happens as it's translated to:

<?php
function () {
    use \Exception();
}

Insted all use statements should be hoisted to the top of the generated code:

<?php
use \Exception();
function () {
}

Workaround: use FQN in partials.

Cannot access property error via `auth()->user()` when property is always available

We're seeing the following errors in a Blade template:

  23     Cannot access property $ID on App\Models\Account|null.                                                                                
         rendered in: test.blade.php:99                                                                                                        
  23     Cannot access property $ID on App\Models\EventPlanner|null.                                                                           
         rendered in: test.blade.php:105                                                                                                       
  23     Cannot access property $ID on App\Models\Promokit|null.                                                                               
         rendered in: test.blade.php:103         

Here is how they are being output in the template:

@auth('account')
	(<code>{{ auth('account')->user()->id }}</code>)
@endauth
@auth('promokit')
	<p>Active PromoKit: <code>{{ auth('promokit')->user()->id }}</code></p>
@elseauth('event-planner')
	<p>Active event planner: <code>{{ auth('event-planner')->user()->id }}</code></p>
@endauth

In both cases, the ->id column is non-nullable in the database schema, which we're utilizing via PHPStan with the following config option:

	squashedMigrationsPath:
		- database/schema

In the examples above, there is an outer @auth directive conditional, but note that it occurs even without those. It also occurs with fields other than ->id. And although we have multiple guards, it also occurs with auth()->user()->id (which utilizes the default guard, which is account).

Why is this the case? Is it an issue with Bladestan or are we doing something incorrectly?

Thank you!! We'd love to use your great extension.

Wrong mapping when the same partial is included multiple times

The following blade code

@include('partial', ['use' => $a])
@include('partial', ['use' => $b])

Results in this PHP code:

<?php

if ($a) {
    (function () use ($a, $b): void {
        $use = $a;
    });
}
if ($b) {
    (function () use ($a, $b): void {
        $use = $a; // <--- wrong mapping
    });
}

Prevent PHPStan from caching any file that calls view()

Since PHPStan will skip analyzing a file if it has not changed, we can end up in situations where changed templates are not being analyzed as they are only scanned when something that utilizes them gets scanned.

So to ensure that all changes to templates are scanned we need to always analyze the php files that render blade files.

Product of @foreach not vissible to @include

                @foreach($products as $product)
                    @include('product-list._row', ['product => $product])
                @endforeach

Undefined variable: $product (template: product-list.blade.php, line: 15)

P.s. is there some way where I can inspect the generated PHP? I'm having a few strange cases that I'm having a hard time groging.

Report when a template cannot be found

Currently the package simply ignores when a template cannot be found and just assumes it's an empty file.

} catch (Throwable) {

If we instead throw a PHPStan\AnalysedCodeException we could report issues like these back to the user.

I gave it a quick go and it looked to work well, the only issue was that I couldn't figure out how to make this test happy since it tries to include a non existing file and I can't figure out what path it is looking in so couldn't add a file for it either.

https://github.com/TomasVotruba/bladestan/blob/main/tests/Compiler/BladeToPHPCompiler/Fixture/basic_include.blade.php#L1

But maybe it would also be better to not stop processing but simply report the issue and continue as we du currently. But I don't know how to do so 😅

Public properties are reported to be maybe undefined

class Option extends Component
{
    /**
     * The option name.
     */
    public string $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function render(): View
    {
        return $this->view('components.cookie.option', [
            'acceptText' => __(':name engedélyezése', ['name' => $this->label]),
            'declineText' => __(':name elutasítása', ['name' => $this->label]),
        ]);
    }
}

AFAIK public Model properties are available in blade templates.
Bladestan reports {{ $name }} as

Variable $name might not be defined.

Please advise.

Non terminated statements causes parsing error

Sample

@php
echo ''
@endphp

Results:
Syntax error, unexpected T_ECHO

Workaround:

@php
echo '';
@endphp

Probably the tags are being stripped so instead of:

<?php
echo ''
?>

We end up with

echo ''

File ends with a trailing whitespace.

What can I do to fix this error?

noname-crop

-- ----------------------------------------------------------------------------------------------------------------------
Error
-- ----------------------------------------------------------------------------------------------------------------------
Internal error: Internal error: config in file G:\laragon\www\urlhub\app\Http\Middleware\RedirectIfAuthenticated.php
Run PHPStan with -v option and post the stack trace to:
https://github.com/phpstan/phpstan/issues/new?template=Bug_report.md
Child process error (exit code 1):
Internal error: Internal error: config in file G:\laragon\www\urlhub\app\Providers\RouteServiceProvider.php
Run PHPStan with -v option and post the stack trace to:
https://github.com/phpstan/phpstan/issues/new?template=Bug_report.md
Child process error (exit code 1):

But, When I disabled Bladestan, there is no error

noname-craop

TODOs

  • FileNameAndLineNumberAddingPreCompiler::setFileName #14
    remove fluent, make service method with fileName as argument to avoid miss-use
  • LaravelViewFunctionMatcher::match
    $funcName !== 'view' maybe make sure this function is coming from Laravel (Reflection)
  • ViewFunctionArgumentsNodeVisitor::enterNode
    ! $rootViewNode->name instanceof Identifier add test

View composer data not recognized ("might not be defined" warning)

When using a view composer to bind data to a view each time it is rendered, the data being passed to the view is not recognized by Bladestan. A "might not be defined" warning occurs as a result.

Here's a basic example of the issue:

app/View/Composers/ProfileComposer.php:

<?php

namespace App\View\Composers;

use Illuminate\View\View;

class ProfileComposer
{
    public function compose(View $view): void
    {
       $data['example'] = 'Example data';

       $view->with('data', $data);
    }

app/Providers/ViewServiceProvider.php:

<?php

namespace App\Providers;

use App\View\Composers\ProfileComposer;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class ViewServiceProvider extends ServiceProvider
{
	public function register(): void
	{
	}

	public function boot(): void
	{
		View::composer('profile.show', ProfileComposer::class);
	}
}

app/Http/Controllers/ProfileController.php:

<?php

namespace App\Http\Controllers;

use App\Models\Profile;
use Illuminate\Routing\Controller;
use Illuminate\View\View;

class ProfileController extends Controller
{
	public function show(Profile $profile): View
	{
		return view('profile.show', ['profile' => $profile]); // "Variable $data might not be defined." error here without `--error-format=blade`
	}

resources/views/profile/show.blade.php:

<x-app-layout>
	@dump($profile)
	@dump('data: ', $data) {{-- "Variable $data might not be defined." error here with `--error-format=blade` --}}
</x-app-layout>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.