Skip to content

[BetterPhpDocParser] Handle parseString() got ShouldNotHappenException #5299

Merged
TomasVotruba merged 29 commits intomasterfrom
fix-5267
Jan 24, 2021
Merged

[BetterPhpDocParser] Handle parseString() got ShouldNotHappenException #5299
TomasVotruba merged 29 commits intomasterfrom
fix-5267

Conversation

@samsonasik
Copy link
Copy Markdown
Member

@samsonasik samsonasik commented Jan 24, 2021

Fixes #5267

@samsonasik samsonasik force-pushed the fix-5267 branch 3 times, most recently from 9064d13 to 496b80f Compare January 24, 2021 05:38
@samsonasik
Copy link
Copy Markdown
Member Author

samsonasik commented Jan 24, 2021

@vhenzl @ERuban please verify if this can fix #5267 , You can try with the following steps:

composer config minimum-stability dev  
composer config prefer-stable true
composer remove rector/rector
composer require --dev rector/rector:dev-fix-5267

# run rector process to the file affected
composer rector -- process --no-progress-bar --dry-run --debug src/RectorBug.php

@samsonasik
Copy link
Copy Markdown
Member Author

All checks have passed 🎉 @TomasVotruba it is ready for review.

@samsonasik samsonasik changed the title Fixes #5267 [BetterPhpDocParser] Handle parseString() got ShouldNotHappenException Jan 24, 2021
@vhenzl
Copy link
Copy Markdown
Contributor

vhenzl commented Jan 24, 2021

Thanks @samsonasik for looking into that, but I don't think this is correct. I had just a quick glance, but the first impression is that you are here treating symptoms instead of the disease cause.

By ignoring the parsing error of a comment with @var and providing empty comment instead, you lose the property type ($abc would be mixed instead of Xyz).

Also, having a logic based on an exception named ShouldNotHappenException isn't IMO correct. As for its name, the exception is for cases that really shouldn't happen (and afaik used mostly to silence PHPStan when it complains about something being null but you know it never should be null - like it this case where CurrentNodeProvider instance should contain the current node).

See these two my comments: #5267 (comment) and #5267 (comment). I believe the problem was introduced in #5250 which removed PhpDocInfoNodeVisitor.php and as a result, PhpDocInfoFactory isn't called and the current node isn't set anymore.

@samsonasik
Copy link
Copy Markdown
Member Author

@vhenzl thank you for verify, feel free to create other PR if you have better solution ;)

@samsonasik
Copy link
Copy Markdown
Member Author

samsonasik commented Jan 24, 2021

@vhenzl I created new commit to verify PropertyFetch by checking for its type from scope as the PropertyFetch is came from the method parameter.

Please verify if that is better solution ;)

@samsonasik
Copy link
Copy Markdown
Member Author

rebased.

@samsonasik
Copy link
Copy Markdown
Member Author

All checks have passed 🎉 @TomasVotruba it is ready for review.

@samsonasik
Copy link
Copy Markdown
Member Author

updated with better approach with check PropertyFetch has PhpDocInfo 57db2fe

@samsonasik
Copy link
Copy Markdown
Member Author

samsonasik commented Jan 24, 2021

I refactored to ensure $phpDocInfo->getVarTagValueNode() instanceof VarTagValueNode and use the VarTagValueNode's TypeNode to check with StaticTypeMapper.

@samsonasik
Copy link
Copy Markdown
Member Author

All checks have passed 🎉 @TomasVotruba it is ready for review.

@ERuban
Copy link
Copy Markdown

ERuban commented Jan 24, 2021

Good job, @samsonasik. The problem is disappeared in my project.
So, waiting the release with this fix.
Thank you.

@TomasVotruba TomasVotruba merged commit 31f357d into master Jan 24, 2021
@TomasVotruba TomasVotruba deleted the fix-5267 branch January 24, 2021 16:46
@vhenzl
Copy link
Copy Markdown
Contributor

vhenzl commented Jan 24, 2021

@TomasVotruba @samsonasik This isn't correct. Yes, it fixes the issue, but the resolved type of a property fetch is wrong.

There isn't any test for PropertyFetchTypeResolver so I modified NodeTypeResolver::resolver() to output the resolved types like this:

// vendor/rector/rector/packages/node-type-resolver/src/NodeTypeResolver.php
    public function resolve(Node $node): Type
    {
        $type = $this->resolveFirstType($node);
        if (! $type instanceof TypeWithClassName) {
            echo "<1 " . __METHOD__ . ": {$node->getType()} ({$node->name}): ".$type->describe(VerbosityLevel::cache())."\n";
            return $type;
        }

        $type = $this->parentClassLikeTypeCorrector->correct($type);
        echo "<2 " . __METHOD__ . ": {$node->getType()} ({$node->name}): ".$type->describe(VerbosityLevel::cache())."\n";
        return $type;
    }

The original repro example isn't exactly good, so I modified it like this:

// src/Abc.php
class Abc
{
    public function get(string $s): string
    {
        return $s;
    }
}

// src/Xyz.php
class Xyz
{
    /**
     * @var Abc
     */
    public $abc;

    /**
     * @var string
     */
    public $str;
}

// src/RectorBug.php
class RectorBug
{
    public function fails(Xyz $xyz): void
    {
        $xyz->abc->get('xxx');
        $xyz->str->xxx();
    }
}

Rector 0.9.10 correctly prints:

...
[parsing] src/RectorBug.php
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_Variable (xyz): RectorBugTest\Xyz
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_PropertyFetch (abc): Abc
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_Variable (xyz): RectorBugTest\Xyz
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_Variable (xyz): RectorBugTest\Xyz
<1 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_PropertyFetch (str): string
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_Variable (xyz): RectorBugTest\Xyz
[refactoring] src/RectorBug.php
...

Rector with this PR resolves types incorrectly and prints:


[parsing] src/RectorBug.php
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_Variable (xyz): RectorBugTest\Xyz
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_PropertyFetch (abc): RectorBugTest\Xyz
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_Variable (xyz): RectorBugTest\Xyz
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_Variable (xyz): RectorBugTest\Xyz
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_PropertyFetch (str): RectorBugTest\Xyz
<2 Rector\NodeTypeResolver\NodeTypeResolver::resolve: Expr_Variable (xyz): RectorBugTest\Xyz
[refactoring] src/RectorBug.php

@samsonasik
Copy link
Copy Markdown
Member Author

samsonasik commented Jan 25, 2021

@vhenzl please create PR with the failing test and fixture for that, thank you.

@vhenzl
Copy link
Copy Markdown
Contributor

vhenzl commented Jan 25, 2021

@samsonasik See #5307

TomasVotruba added a commit that referenced this pull request Dec 2, 2023
rectorphp/rector-src@7badba6 [PostRector] Allow remove unused use sub namespace on UnusedImportRemovingPostRector (#5299)
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 15, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parsing error on @var in v0.9.12

4 participants