rector: Syntax error in unknown file

Bug Report

Subject Details
Rector version e.g. v0.11.40

I am struggling with finding root cause of the problem with “syntax error” when I analyse files with Rector. I get:

vendor/bin/rector process -vvv --dry-run packages/Ecommerce/tests/Unit/Common/EcommerceCommandTest.php
[parsing] packages/Ecommerce/tests/Unit/Common/EcommerceCommandTest.php
[refactoring] packages/Ecommerce/tests/Unit/Common/EcommerceCommandTest.php
    [applying] Rector\CodeQuality\Rector\Name\FixClassCaseSensitivityNameRector
    [applying] Rector\CodeQuality\Rector\Class_\CompleteDynamicPropertiesRector
    [applying] Rector\Php52\Rector\Property\VarToPublicPropertyRector
    [applying] Rector\Php74\Rector\Property\TypedPropertyRector
    [applying] Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector

In ParserAbstract.php line 269:

  [PhpParser\Error]
  Syntax error, unexpected '}', expecting T_VARIABLE on line 792


Exception trace:
  at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php:269
 PhpParser\ParserAbstract->doParse() at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php:143
 PhpParser\ParserAbstract->parse() at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/Parser/Multiple.php:48
 PhpParser\Parser\Multiple->tryParse() at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/Parser/Multiple.php:31
 PhpParser\Parser\Multiple->parse() at ./vendor/rector/rector/packages/FamilyTree/Reflection/FamilyRelationsAnalyzer.php:114
 Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer->getPossibleUnionPropertyType() at ./vendor/rector/rector/rules/Php74/Rector/Property/TypedPropertyRector.php:139
 Rector\Php74\Rector\Property\TypedPropertyRector->refactor() at ./vendor/rector/rector/src/Rector/AbstractRector.php:248
 Rector\Core\Rector\AbstractRector->enterNode() at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:176
 PhpParser\NodeTraverser->traverseArray() at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:105
 PhpParser\NodeTraverser->traverseNode() at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:196
 PhpParser\NodeTraverser->traverseArray() at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:105
 PhpParser\NodeTraverser->traverseNode() at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:196
 PhpParser\NodeTraverser->traverseArray() at ./vendor/rector/rector/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:85
 PhpParser\NodeTraverser->traverse() at ./vendor/rector/rector/src/PhpParser/NodeTraverser/RectorNodeTraverser.php:52
 Rector\Core\PhpParser\NodeTraverser\RectorNodeTraverser->traverse() at ./vendor/rector/rector/src/Application/FileProcessor.php:54
 Rector\Core\Application\FileProcessor->refactor() at ./vendor/rector/rector/src/Application/FileProcessor/PhpFileProcessor.php:135
 Rector\Core\Application\FileProcessor\PhpFileProcessor->Rector\Core\Application\FileProcessor\{closure}() at ./vendor/rector/rector/src/Application/FileProcessor/PhpFileProcessor.php:147
 Rector\Core\Application\FileProcessor\PhpFileProcessor->tryCatchWrapper() at ./vendor/rector/rector/src/Application/FileProcessor/PhpFileProcessor.php:136
 Rector\Core\Application\FileProcessor\PhpFileProcessor->refactorNodesWithRectors() at ./vendor/rector/rector/src/Application/FileProcessor/PhpFileProcessor.php:91
 Rector\Core\Application\FileProcessor\PhpFileProcessor->process() at ./vendor/rector/rector/src/Application/ApplicationFileProcessor.php:76
 Rector\Core\Application\ApplicationFileProcessor->processFiles() at ./vendor/rector/rector/src/Application/ApplicationFileProcessor.php:57
 Rector\Core\Application\ApplicationFileProcessor->run() at ./vendor/rector/rector/src/Console/Command/ProcessCommand.php:145
 Rector\Core\Console\Command\ProcessCommand->execute() at ./vendor/rector/rector/vendor/symfony/console/Command/Command.php:274
 RectorPrefix20210725\Symfony\Component\Console\Command\Command->run() at ./vendor/rector/rector/vendor/symfony/console/Application.php:870
 RectorPrefix20210725\Symfony\Component\Console\Application->doRunCommand() at ./vendor/rector/rector/vendor/symfony/console/Application.php:266
 RectorPrefix20210725\Symfony\Component\Console\Application->doRun() at ./vendor/rector/rector/src/Console/ConsoleApplication.php:71
 Rector\Core\Console\ConsoleApplication->doRun() at ./vendor/rector/rector/vendor/symfony/console/Application.php:162
 RectorPrefix20210725\Symfony\Component\Console\Application->run() at ./vendor/rector/rector/bin/rector.php:61
 require_once() at ./vendor/rector/rector/bin/rector:5

process [-n|--dry-run] [-a|--autoload-file AUTOLOAD-FILE] [-o|--output-format [OUTPUT-FORMAT]] [--no-progress-bar] [--no-diffs] [--clear-cache] [--] [<source>...]

The point is that analyzed file doesn’t have line 792. Looking at inheritance tree there are 2 files with this line, but each looks fine. I don’t know how to find out what’s the problem.

Minimal PHP Code Causing Issue

Not known.

Expected Behaviour

Rector should be more helpful with finding the real problem (logs, exception’s message).

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 27 (25 by maintainers)

Most upvoted comments

Here’s an example I was able to strip down to minimum to still produce the error:

rector.php

<?php

declare(strict_types=1);

use Rector\Core\Configuration\Option;
use Rector\Core\ValueObject\PhpVersion;
use Rector\Set\ValueObject\SetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
    $parameters = $containerConfigurator->parameters();
    $parameters->set(Option::PATHS, [__DIR__ . '/src', __DIR__ . '/tests']);
    $parameters->set(Option::PHP_VERSION_FEATURES, PhpVersion::PHP_74);
    $containerConfigurator->import(SetList::PHP_74);
};

ValidateTraitTest.php

<?php

declare(strict_types=1);

namespace Phlib\Beanstalk;

use PHPUnit\Framework\TestCase;

class ValidateTraitTest extends TestCase
{
    /**
     * @var ValidateTrait
     */
    protected $validate;
}

output

$ ./vendor/bin/rector process tests/ValidateTraitTest.php                                                                                                                -1-
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 [ERROR] Could not process "tests/ValidateTraitTest.php" file, due to:
         "Syntax error, unexpected '}', expecting T_VARIABLE:792". On line: 269

env

rector/rector                      0.11.40

PHP 7.4.21 (cli) (built: Jul  5 2021 03:32:42) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.21, Copyright (c), by Zend Technologies
    with Xdebug v3.0.4, Copyright (c) 2002-2021, by Derick Rethans

macOS v11.4

You run test suite on PHP 8.0 and then you somehow allow usage of rector/rector for ^7.1

Yes, looks like an oversight. PHPStan (which inspired Rector for the rector-src workflow) runs unit tests in phpstan-src on all supported PHP versions - from PHP 7.1 to 8.0.

Yeah, I’ve just checked and subsequent executions does not result in error, so I’ve added --clear-cache to composer rector script. Can’t work on Github Actions now but maybe it’s not required for now 🙂

I’ve just tried dev-main version in reproducer and it works properly 👍

@Wirone Clear cache helped 😃

@ondrejmirtes I’m looking into it, thanks 👍 I’m surprise Rector does not do the same by default.

@TomasVotruba I am out now, when I’ll be at home I’ll check, but I run this multiple times yesterday and had that error 😉 and it’s what Docker encapsulation does - it’s not my/your/local/ci problem since it’s executed in the same environment. Try with --clear-cache since I was using docker-compose down between runs just to be sure if provided command will work.

I will try to add Github Actions later.

@TomasVotruba Use different PhpParser instances in different places. Can’t be more specific than that - I’m not familiar with Rector’s codebase.

@TomasVotruba based on @puniserv’s comment I’ve created reproducer repo. Steps:

  • clone the repo
  • docker-compose run php composer install && composer rector

Docker image should be built, container created and composer install && composer rector should be executed within isolated environment. Of course it should result with Syntax error, unexpected '}', expecting T_VARIABLE.

PHP 7.4.20 “rector/rector”: “0.11.40”

FamilyRelationsAnalyzer::getPossibleUnionPropertyType

$fileName: rector/vendor/rector/rector/vendor/phpstan/phpstan/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/SourceLocator/SourceStubber/…/…/…/…/…/jetbrains/phpstorm-stubs/Core/Core_c.stub

$ancestorName: ‘Countable’ $varType: FullyQualifiedObjectType $propertyTypeNode: FullyQualified

Example to replicate issue:


declare(strict_types=1);

use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
    $containerConfigurator->services()->set(\Rector\Php74\Rector\Property\TypedPropertyRector::class);
};

<?php

declare(strict_types=1);

namespace Hmm\OhNo;

use Hmm\OhNo\Some\BlaBla;
use PHPUnit\Framework\MockObject\MockObject;

use PHPUnit\Framework\TestCase;

class SomeTest extends TestCase
{
    /**
     * @var BlaBla
     */
    private $bla;
    /**
     * @var MockObject&BlaBla
     */
    private $mock;

    protected function setUp(): void
    {
        parent::setUp();
        $this->bla = new BlaBla();
        $this->mock = $this->createMock(BlaBla::class);
    }
}
<?php

declare(strict_types=1);

namespace Hmm\OhNo\Some;

class BlaBla implements \Countable
{
    public function count(): int
    {
        return 0;
    }
}
{
    "require-dev": {
        "rector/rector": "^0.11.40",
        "phpunit/phpunit": "8.5.18"
    },
    "autoload": {
        "psr-4": {
            "Hmm\\OhNo\\": "src"
        }
    }
}

I don’t know how Rector is configured but with PHPStan on PHP 7.x I always parse phpstorm-stubs with Emulative lexer set to PHP 8 so it understands PHP 8-specific syntax in the stubs.

@TomasVotruba I use PHP 7.4.21. Provided output was with --debug (actually I’ve used -vvv). Most probably tokens are not correct after applying Rector refactoring, when file is about to be saved. But IMO it should not work this way 🙂 Will be great if Rector could handle this in a way that user would know that some rector rule is not able to produce valid syntax (if that’s the case).