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

Uncaught Exception: Could not locate trait statement #2951

Closed
kelunik opened this issue Mar 9, 2020 · 9 comments
Closed

Uncaught Exception: Could not locate trait statement #2951

kelunik opened this issue Mar 9, 2020 · 9 comments
Labels

Comments

@kelunik
Copy link
Contributor

kelunik commented Mar 9, 2020

git clone https://github.com/amphp/amp
cd amp
./vendor/bin/psalm.phar --init
Psalm 3.9.4@352bd3f5c5789db04e4010856c2f4e01ed354f4e

Running --init on Amp currently isn't possible. This is due to the conditional definition of our CallableMaker trait. Can I work around this or could Psalm be extended to evaluate PHP_VERSION_ID and pick the right version?

@psalm-github-bot
Copy link

Hey @kelunik, can you reproduce the issue on https://psalm.dev ?

@kelunik
Copy link
Contributor Author

kelunik commented Mar 9, 2020

Not really, it says ERROR: DuplicateClass - 56:11 - Class Amp\CallableMaker has already been defined there. https://psalm.dev/r/a6601ab157

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/a6601ab157
<?php

namespace Amp;

// @codeCoverageIgnoreStart
if (\PHP_VERSION_ID < 70100) {
    trait CallableMaker
    {
        /** @var \ReflectionClass */
        private static $__reflectionClass;

        /** @var \ReflectionMethod[] */
        private static $__reflectionMethods = [];

        /**
         * Creates a callable from a protected or private instance method that may be invoked by callers requiring a
         * publicly invokable callback.
         *
         * @param string $method Instance method name.
         *
         * @return callable
         */
        private function callableFromInstanceMethod(string $method): callable
        {
            if (!isset(self::$__reflectionMethods[$method])) {
                if (self::$__reflectionClass === null) {
                    self::$__reflectionClass = new \ReflectionClass(self::class);
                }
                self::$__reflectionMethods[$method] = self::$__reflectionClass->getMethod($method);
            }

            return self::$__reflectionMethods[$method]->getClosure($this);
        }

        /**
         * Creates a callable from a protected or private static method that may be invoked by methods requiring a
         * publicly invokable callback.
         *
         * @param string $method Static method name.
         *
         * @return callable
         */
        private static function callableFromStaticMethod(string $method): callable
        {
            if (!isset(self::$__reflectionMethods[$method])) {
                if (self::$__reflectionClass === null) {
                    self::$__reflectionClass = new \ReflectionClass(self::class);
                }
                self::$__reflectionMethods[$method] = self::$__reflectionClass->getMethod($method);
            }

            return self::$__reflectionMethods[$method]->getClosure();
        }
    }
} else {
    trait CallableMaker
    {
        /**
         * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1.
         */
        private function callableFromInstanceMethod(string $method): callable
        {
            return \Closure::fromCallable([$this, $method]);
        }

        /**
         * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1.
         */
        private static function callableFromStaticMethod(string $method): callable
        {
            return \Closure::fromCallable([self::class, $method]);
        }
    }
} // @codeCoverageIgnoreEnd
Psalm output (using commit 60fb392):

ERROR: DuplicateClass - 56:11 - Class Amp\CallableMaker has already been defined in /var/www/vhosts/psalm.dev/httpdocs/src/../src/somefile.php

@weirdan
Copy link
Collaborator

weirdan commented Mar 9, 2020

@muglug muglug added the bug label Mar 9, 2020
@muglug
Copy link
Collaborator

muglug commented Mar 9, 2020

I'll release a fix today for this that uses reflection to determine the winner when there's more than one trait defined in a given file.

@muglug muglug closed this as completed in 1399b13 Mar 9, 2020
@kelunik
Copy link
Contributor Author

kelunik commented Mar 21, 2020

@muglug Thanks for the quick fix. Now I get the DuplicateClass as on psalm.dev. I guess this error needs to be suppressed by me now?

ERROR: DuplicateClass - lib/CallableMaker.php:56:11 - Class Amp\CallableMaker has already been defined in /home/kelunik/GitHub/amphp/amp/lib/CallableMaker.php
    trait CallableMaker

@kelunik
Copy link
Contributor Author

kelunik commented Mar 21, 2020

Adding @psalm-suppress DuplicateClass to both definitions doesn't seem to help.

@muglug
Copy link
Collaborator

muglug commented Mar 21, 2020

You can suppress that in your psalm.xml:

    <issueHandlers>
        <DuplicateClass>
            <errorLevel type="suppress">
                <file name="lib/CallableMaker.php" />
            </errorLevel>
        </DuplicateClass>
    </issueHandlers>

@kelunik
Copy link
Contributor Author

kelunik commented Mar 22, 2020

Thanks!

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

No branches or pull requests

3 participants