Skip to content

Scope not available on "PhpParser\Node\Expr\FuncCall #9235

@VincentLanglet

Description

@VincentLanglet

Bug Report

Subject Details
Rector version 2.1.0

Minimal PHP Code Causing Issue

I reproduce the error with

<?php

namespace App\Behavior\Entity;

use App\Entity\Url;

class UrlBehavior
{
    /**
     * @param array<Url> $urls
     */
    public function create(array $urls, string $hash): ?Url
    {
        if (0 === \count($urls)) {
            $url = new Url();
        } else {
            $url = null;
            foreach ($urls as $urlToCheck) {
                if ($urlToCheck->getPathHash() === $hash) {
                    $url = $urlToCheck;
                    break;
                }
            }
        }

        return $url;
    }
}

StackTrace

[ERROR] Could not process "/Users/vincentl/Weglot/core/src/Behavior/Entity/UrlBehavior.php" file, due to:              
         "System error: "Scope not available on "PhpParser\Node\Expr\FuncCall" node. Fix scope refresh on changed nodes 
         first"                                                                                                         
                                                                                                                        
         Stack trace:                                                                                                   
         #0 vendor/rector/rector/rules/Php55/Rector/FuncCall/GetCalledClassToStaticClassRector.php(54):                 
         Rector\PHPStan\ScopeFetcher::fetch(Object(PhpParser\Node\Expr\FuncCall))                                       
         #1 vendor/rector/rector/src/Rector/AbstractRector.php(119):                                                    
         Rector\Php55\Rector\FuncCall\GetCalledClassToStaticClassRector->refactor(Object(PhpParser\Node\Expr\FuncCall)) 
         #2 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(103):                          
         Rector\Rector\AbstractRector->enterNode(Object(PhpParser\Node\Expr\FuncCall))                                  
         #3 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(125):                          
         PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Expr\Assign))                                      
         #4 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(200):                          
         PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Expression))                                  
         #5 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(90):                           
         PhpParser\NodeTraverser->traverseArray(Array)                                                                  
         #6 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(125):                          
         PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Else_))                                       
         #7 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(200):                          
         PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\If_))                                         
         #8 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(90):                           
         PhpParser\NodeTraverser->traverseArray(Array)                                                                  
         #9 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(200):                          
         PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\ClassMethod))                                 
         #10 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(90):                          
         PhpParser\NodeTraverser->traverseArray(Array)                                                                  
         #11 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(200):                         
         PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Class_))                                      
         #12 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(90):                          
         PhpParser\NodeTraverser->traverseArray(Array)                                                                  
         #13 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(200):                         
         PhpParser\NodeTraverser->traverseNode(Object(PhpParser\Node\Stmt\Namespace_))                                  
         #14 vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php(71):                          
         PhpParser\NodeTraverser->traverseArray(Array)                                                                  
         #15 vendor/rector/rector/src/PhpParser/NodeTraverser/RectorNodeTraverser.php(49):                              
         PhpParser\NodeTraverser->traverse(Array)                                                                       
         #16 vendor/rector/rector/src/Application/FileProcessor.php(95):                                                
         Rector\PhpParser\NodeTraverser\RectorNodeTraverser->traverse(Array)                                            
         #17 vendor/rector/rector/src/Application/ApplicationFileProcessor.php(183):                                    
         Rector\Application\FileProcessor->processFile(Object(Rector\ValueObject\Application\File),                     
         Object(Rector\ValueObject\Configuration))                                                                      
         #18 vendor/rector/rector/src/Application/ApplicationFileProcessor.php(160):                                    
         Rector\Application\ApplicationFileProcessor->processFile(Object(Rector\ValueObject\Application\File),          
         Object(Rector\ValueObject\Configuration))                                                                      
         #19 vendor/rector/rector/src/Application/ApplicationFileProcessor.php(134):                                    
         Rector\Application\ApplicationFileProcessor->processFiles(Array, Object(Rector\ValueObject\Configuration),     
         Object(Closure), Object(Closure))                                                                              
         #20 vendor/rector/rector/src/Console/Command/ProcessCommand.php(176):                                          
         Rector\Application\ApplicationFileProcessor->run(Object(Rector\ValueObject\Configuration),                     
         Object(RectorPrefix202506\Symfony\Component\Console\Input\ArgvInput))                                          
         #21 vendor/rector/rector/vendor/symfony/console/Command/Command.php(285):                                      
         Rector\Console\Command\ProcessCommand->execute(Object(RectorPrefix202506\Symfony\Component\Console\Input\ArgvI 
         nput), Object(RectorPrefix202506\Symfony\Component\Console\Output\ConsoleOutput))                              
         #22 vendor/rector/rector/vendor/symfony/console/Application.php(900):                                          
         RectorPrefix202506\Symfony\Component\Console\Command\Command->run(Object(RectorPrefix202506\Symfony\Component\ 
         Console\Input\ArgvInput), Object(RectorPrefix202506\Symfony\Component\Console\Output\ConsoleOutput))           
         #23 vendor/rector/rector/vendor/symfony/console/Application.php(279):                                          
         RectorPrefix202506\Symfony\Component\Console\Application->doRunCommand(Object(Rector\Console\Command\ProcessCo 
         mmand), Object(RectorPrefix202506\Symfony\Component\Console\Input\ArgvInput),                                  
         Object(RectorPrefix202506\Symfony\Component\Console\Output\ConsoleOutput))                                     
         #24 vendor/rector/rector/src/Console/ConsoleApplication.php(63):                                               
         RectorPrefix202506\Symfony\Component\Console\Application->doRun(Object(RectorPrefix202506\Symfony\Component\Co 
         nsole\Input\ArgvInput), Object(RectorPrefix202506\Symfony\Component\Console\Output\ConsoleOutput))             
         #25 vendor/rector/rector/vendor/symfony/console/Application.php(162):                                          
         Rector\Console\ConsoleApplication->doRun(Object(RectorPrefix202506\Symfony\Component\Console\Input\ArgvInput), 
         Object(RectorPrefix202506\Symfony\Component\Console\Output\ConsoleOutput))                                     
         #26 vendor/rector/rector/bin/rector.php(130): RectorPrefix202506\Symfony\Component\Console\Application->run()  
         #27 vendor/rector/rector/bin/rector(5): require_once('/Users/vincentl...')                                     
         #28 vendor/bin/rector(119): include('/Users/vincentl...')                                                      
         #29 {main}". On line: 19

My whole config is

<?php

declare(strict_types=1);

use Rector\CodingStyle\Rector\ArrowFunction\StaticArrowFunctionRector;
use Rector\CodingStyle\Rector\Closure\StaticClosureRector;
use Rector\Config\RectorConfig;
use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector;
use Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector;
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
use Rector\Php83\Rector\ClassMethod\AddOverrideAttributeToOverriddenMethodsRector;
use Rector\Php84\Rector\MethodCall\NewMethodCallWithoutParenthesesRector;
use Rector\PHPUnit\CodeQuality\Rector\Class_\NarrowUnusedSetUpDefinedPropertyRector;
use Rector\PHPUnit\CodeQuality\Rector\Class_\PreferPHPUnitThisCallRector;
use Rector\PHPUnit\CodeQuality\Rector\Class_\RemoveDataProviderParamKeysRector;
use Rector\PHPUnit\CodeQuality\Rector\Class_\YieldDataProviderRector;
use Rector\PHPUnit\Set\PHPUnitSetList;

return RectorConfig::configure()
    ->withPaths([
        __DIR__.'/fixtures',
        __DIR__.'/migrations',
        __DIR__.'/phpstan',
        __DIR__.'/src',
        __DIR__.'/tests',
    ])
    ->withCache('.cache/rector')
    ->withAttributesSets(symfony: true, doctrine: true, phpunit: true)
    ->withPhpSets()
    ->withSets([
        PHPUnitSetList::PHPUNIT_CODE_QUALITY,
    ])
    ->withRules([
        JsonThrowOnErrorRector::class,
        StaticArrowFunctionRector::class,
        StaticClosureRector::class,
    ])
    ->withImportNames(importShortClasses: false)
    ->withTreatClassesAsFinal()
    ->withSkip([
        // PHP
        AddOverrideAttributeToOverriddenMethodsRector::class, // Unwanted
        ChangeSwitchToMatchRector::class, // PHP 8.0 TODO
        NullToStrictStringFuncCallArgRector::class, // PHP 8.1 TODO
        NewMethodCallWithoutParenthesesRector::class, // Unwanted ?
        // PHPUnit
        NarrowUnusedSetUpDefinedPropertyRector::class, // Unwanted
        PreferPHPUnitThisCallRector::class, // Conflict with PHPStan and PHP-CS-Fixer
        RemoveDataProviderParamKeysRector::class, // Unwanted
        YieldDataProviderRector::class, // Unwanted
    ]);

if it helps.

Expected Behaviour

I dunno if it's related to ForeachToArray* rules, since they are new and the simplified version

public function create(array $urls, string $hash): ?Url
    {
        if (0 === \count($urls)) {
            return new Url();
        }

        $url = null;
        foreach ($urls as $urlToCheck) {
            if ($urlToCheck->getPathHash() === $hash) {
                $url = $urlToCheck;
                break;
            }
        }

        return $url;
    }

is correctly fixed by StaticArrowFunctionRector + ForeachToArrayFindRector rule.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions