Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange behavior dealing with PHP attributes and interfaces in dependencies #6688

Closed
liarco opened this issue Sep 13, 2021 · 6 comments · Fixed by rectorphp/rector-src#889
Closed
Labels

Comments

@liarco
Copy link

liarco commented Sep 13, 2021

Bug Report

Subject Details
Rector version v0.11.53

Issue description

Rector fails with a Class ... was not found while trying to analyse it... when a dependency is using attributes and JsonSerializable in an abstract class.

Additional info: it's not a matter of which rules are enabled, the command fails even with no rule enabled.

Minimal PHP Code Causing Issue

This issue appears while using composer dependencies so I had to create a reproducer (I tried to keep it minimal).

Run:

> git clone git@github.com:liarco/rector-issue.git
> cd rector-issue/project
> composer install
> vendor/bin/rector --dry-run --clear-cache
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
                                                                                                                        
 [ERROR] Could not process "src/MyProjectClass.php" file, due to:                                                       
         "Analyze error: "Class MyCode\AbstractClass was not found while trying to analyse it - discovering symbols is  
         probably not configured properly.". Include your files in "$parameters->set(Option::AUTOLOAD_PATHS, [...]);" in
         "rector.php" config.                                                                                           
         See https://github.com/rectorphp/rector#configuration".

Removing the #[Test] attribute or implements JsonSerializable from AbstractClass.php removes the error.

Update 2021-09-15

I'm removing the repository since #6688 (comment), here is a brief description of the example.

I had two projects:

  • my main project
  • a composer package as a dependency of the main project

The dependency had an abstract class implementing JsonSerializable:

// vendor/acme/my-dependency/src/AbstractClass.php

<?php

namespace MyCode;

use JsonSerializable;

#[Test]
abstract class AbstractClass implements JsonSerializable
{
    /**
     * @return array<string, mixed>
     */
    public function jsonSerialize(): array
    {
        return [
            'test' => 'my-test',
            'data' => $this->getData(),
        ];
    }

    /**
     * @return array<string, mixed>
     */
    abstract protected function getData(): array;
}

The project was using a direct child of AbstractClass (the actual implementation doesn't matter). Rector fails with the error above, but removing the PHP attribute or the interface implementation from AbstractClass removes the error.

Expected Behaviour

The MyCode\AbstractClass class should be loaded successfully as is.

Thank you for your time.

@liarco liarco added the bug label Sep 13, 2021
@liarco
Copy link
Author

liarco commented Sep 15, 2021

I'm trying to investigate further, here is some additional debugging info:

  • I'm having the same problem with dev-main

  • the file containing my AbstractClass seems to be autoloaded properly since a dd('debug'); inside it stops the execution as soon as the file is required

  • The exception is thrown by:

    } catch (\PHPStan\AnalysedCodeException $analysedCodeException) {
    // inform about missing classes in tests
    if (\Rector\Testing\PHPUnit\StaticPHPUnitEnvironment::isPHPUnitRun()) {
    throw $analysedCodeException;
    }
    $this->notParsedFiles[] = $file;
    $error = $this->errorFactory->createAutoloadError($analysedCodeException, $file->getSmartFileInfo());
    $file->addRectorError($error);

    The AnalysedCodeException is a PHPStan\Broker\ClassNotFoundException (from phpstan.phar/src/Reflection/ReflectionProvider/ChainReflectionProvider.php", line 40).

    I can't understand why this is happening since PHPStan works perfectly (standalone) on the same project.

@liarco
Copy link
Author

liarco commented Sep 15, 2021

I think I found a solution, can you please help me understanding what's happening?

I published the fix to my reproducer repo: https://github.com/liarco/rector-issue/blob/2afdceb5ca71a1be5e644c63e2eeb9b1124b44e2/project/rector.php#L38-L41

When I first read the docs I tried fixing my problem with:

// rector.php

// ...
    $parameters->set(Option::AUTOLOAD_PATHS, [
        __DIR__.'/vendor/autoload.php',
    ]);
// ...

But it didn't work, so I thought that my problem was not related to Option::AUTOLOAD_PATHS.

Now i tried:

// rector.php

// ...
    // HERE IS THE FIX!
    $parameters->set(Option::AUTOLOAD_PATHS, [
        __DIR__.'/vendor/acme/my-custom-package/src',
    ]);
// ...

And everything works fine... is this a correct configuration?

Thank you

@samsonasik
Copy link
Member

that's possibly due to symlink usage, if that's the only way, that possibly worth to be mentioned to documentation, could you create PR for it?

@liarco
Copy link
Author

liarco commented Sep 15, 2021

Hi, thank you for your feedback! Unfortunately I don't think that symlinks can be the culprit here since my main project is not using them at all (they are used in the reproducer to simplify the setup).

I couldn't find a better way to solve it, so it may be worth to mention it (at least until we figure out a better solution).
I would be happy to create the PR, just a question: should I add it here?

@samsonasik
Copy link
Member

Yes please, you may need to make it under TroubleShooting, thank you.

@samsonasik
Copy link
Member

Please create PR to rector-src https://github.com/rectorphp/rector-src/blob/main/build/target-repository/docs/static_reflection_and_autoload.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants