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

class_alias business causing fatal error #30

Open
jaydiablo opened this issue Apr 22, 2019 · 3 comments
Open

class_alias business causing fatal error #30

jaydiablo opened this issue Apr 22, 2019 · 3 comments

Comments

@jaydiablo
Copy link

This is sort of similar to the issue I ran into with the Mockery plugin (vimeo/psalm#1537) in that a class_alias is being used to conditionally alias one class to another. In this case, it's Zend Framework's zend-test that's doing it:

https://github.com/zendframework/zend-test/blob/master/autoload/phpunit-class-aliases.php#L15

use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\TestCase;
if (! class_exists(ExpectationFailedException::class)) {
    class_alias(\PHPUnit_Framework_ExpectationFailedException::class, ExpectationFailedException::class);
}
if (! class_exists(TestCase::class)) {
    class_alias(\PHPUnit_Framework_TestCase::class, TestCase::class);
}

That second if condition is causing Psalm, with this phpunit plugin enabled, to spit out this Fatal error:

Fatal error: Uncaught InvalidArgumentException: Could not get class storage for PHPUnit_Framework_TestCase in ./vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php:44

In my case \PHPUnit_Framework\TestCase does not exist, as we're using PHPUnit 7.x which does not have that class defined. However, PHPUnit\Framework\TestCase should exist, but perhaps it's not seen by Psalm when analyzing this autoloaded file?

Without the plugin enabled, the error is not thrown, but Psalm does complain about Zend's classes (which we extend) depending on that class (PHPUnit_Framework_TestCase) and the class not existing.

If I comment out that second if condition in the file I link to above, all processes as expected.

Is this something that this plugin should deal with? Perhaps as an addition to the stubs?

@jaydiablo
Copy link
Author

By adding this stub to this plugin's TestCase.php stub file:

namespace 
{
    use PHPUnit\Framework\TestCase;
    
    abstract class PHPUnit_Framework_TestCase extends TestCase
    {
        
    }
}

(and wrapping the other stubs in that file in a namespace wrapper rather than global to the file) I can make the fatal error go away, but Psalm still reports this error on any classes that extend Zend's test classes (which ultimately extend PHPUnit\Framework\TestCase):

MissingDependency - tests/Controller/LoginControllerTest.php:14:35 - tests\Framework\HttpControllerTestCase depends on class or interface PHPUnit_Framework_TestCase that does not exist

I'll continue to poke around a bit.

@asgrim
Copy link

asgrim commented Feb 3, 2021

Maybe more information, hopefully: I also noticed this on a project that uses symfony/phpunit-bridge (which has a class_alias as described above), but only in certain circumstances:

Uncaught InvalidArgumentException: Could not get class storage for phpunit\framework\testcase in /path/to/project/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php:42
  • running Psalm on CLI with <directory name="tests" /> included, I get the error
  • running Psalm on CLI with <directory name="tests" /> removed, the error goes away
  • PhpStorm runs Psalm in the background, I get the error regardless of <directory name="tests" /> being in the <projectFiles> or not
  • Removing symfony/phpunit-bridge fixed the issue

@IvoPereira
Copy link

IvoPereira commented Apr 10, 2021

I have also faced a similar issue (and stacktrace), in my case while running psalm with Yii2 framework, executing the psalm init command:

./vendor/bin/psalm --init

By creating a manual psalm.xml like instructed in the website, and specifying psalm to ignore the tests folder (like @asgrim points out) I was able to move on with this issue.

psalm.xml

<?xml version="1.0"?>
<psalm>
    <projectFiles>
        <directory name="." />
        <ignoreFiles>
            <directory name="./tests" />
        </ignoreFiles>
    </projectFiles>
</psalm>

However, later, I've found out an error of the same nature:

Uncaught InvalidArgumentException: Could not get class storage for zend\xmlrpc\zend\xmlrpc\value in /app/vendor/vimeo/psalm/src/Psalm/Internal/Provider/ClassLikeStorageProvider.php:42
Stack trace:
#0 /app/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/ClassLikes.php(1476): Psalm\Internal\Provider\ClassLikeStorageProvider->get('zend\\xmlrpc\\zen...')
#1 /app/vendor/vimeo/psalm/src/Psalm/Internal/TypeVisitor/TypeChecker.php(339): Psalm\Internal\Codebase\ClassLikes->getClassConstantType('zend\\xmlrpc\\zen...', 'constant', 1024, NULL)
#2 /app/vendor/vimeo/psalm/src/Psalm/Internal/TypeVisitor/TypeChecker.php(107): Psalm\Internal\TypeVisitor\TypeChecker->checkScalarClassConstant(Object(Psalm\Type\Atomic\TScalarClassConstant))
#3 /app/vendor/vimeo/psalm/src/Psalm/Type/NodeVisitor.php(19): Psalm\Internal\TypeVisitor\TypeChecker->enterNode(Object(Psalm\Type\Atomic\TScalarClassConstant))
#4 /app/vendor/vimeo/psalm/src/Psalm/Type/NodeVisitor.php(44): Psalm\Type\NodeVisitor->traverse(Object(Psalm\Type\Atomic\TScalarClassConstant))
#5 /app/vendor/vimeo/psalm/src/Psalm/Type/Union.php(1286): Psalm\Type\NodeVisitor->traverseArray(Array)
#6 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php(987): Psalm\Type\Union->check(Object(Psalm\Internal\Analyzer\MethodAnalyzer), Object(Psalm\CodeLocation\DocblockTypeLocation), Array, Array, false, false, true, 'zend\\xmlrpc\\val...')
#7 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php(317): Psalm\Internal\Analyzer\FunctionLikeAnalyzer->processParams(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(Psalm\Storage\MethodStorage), 'Zend\\XmlRpc\\Abs...', Array, Object(Psalm\Context), false)
#8 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php(126): Psalm\Internal\Analyzer\FunctionLikeAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Internal\Provider\NodeDataProvider), NULL, true)
#9 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php(420): Psalm\Internal\Analyzer\ClassLikeAnalyzer->getMethodMutations('getxmlrpcvalue', Object(Psalm\Context))
#10 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(1384): Psalm\Internal\Analyzer\FileAnalyzer->getMethodMutations(Object(Psalm\Internal\MethodIdentifier), Object(Psalm\Context), true)
#11 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php(387): Psalm\Internal\Analyzer\ProjectAnalyzer->getMethodMutations(Object(Psalm\Internal\MethodIdentifier), Object(Psalm\Context), '/app/vendor/zen...', 'vendor/zendfram...')
#12 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/ExistingAtomicStaticCallAnalyzer.php(111): Psalm\Internal\Analyzer\FileAnalyzer->getMethodMutations(Object(Psalm\Internal\MethodIdentifier), Object(Psalm\Context))
#13 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php(727): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod\ExistingAtomicStaticCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(PhpParser\Node\Identifier), Array, Object(Psalm\Context), Object(Psalm\Type\Atomic\TNamedObject), Object(Psalm\Internal\MethodIdentifier), 'Zend\\XmlRpc\\Val...', Object(Psalm\Storage\ClassLikeStorage), false)
#14 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php(177): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod\AtomicStaticCallAnalyzer::handleNamedCall(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(PhpParser\Node\Identifier), Object(Psalm\Context), Object(Psalm\Type\Atomic\TNamedObject), Array, 'Zend\\XmlRpc\\Val...', false, true)
#15 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticCallAnalyzer.php(206): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod\AtomicStaticCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context), Object(Psalm\Type\Atomic\TNamedObject), false, false, false, true)
#16 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(152): Psalm\Internal\Analyzer\Statements\Expression\Call\StaticCallAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context))
#17 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(40): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context), false, NULL, false)
#18 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Expression/AssignmentAnalyzer.php(199): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\StaticCall), Object(Psalm\Context))
#19 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(129): Psalm\Internal\Analyzer\Statements\Expression\AssignmentAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Variable), Object(PhpParser\Node\Expr\StaticCall), NULL, Object(Psalm\Context), NULL)
#20 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/ExpressionAnalyzer.php(40): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::handleExpression(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Assign), Object(Psalm\Context), false, NULL, true)
#21 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(530): Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Expr\Assign), Object(Psalm\Context), false, NULL, true)
#22 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(172): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Expression), Object(Psalm\Context), NULL)
#23 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElse/IfAnalyzer.php(61): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context))
#24 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/IfElseAnalyzer.php(358): Psalm\Internal\Analyzer\Statements\Block\IfElse\IfAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Internal\Scope\IfScope), Object(Psalm\Internal\Scope\IfConditionalScope), Object(Psalm\Context), Object(Psalm\Context), Object(Psalm\Context), Array)
#25 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(478): Psalm\Internal\Analyzer\Statements\Block\IfElseAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context))
#26 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(172): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\If_), Object(Psalm\Context), NULL)
#27 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/LoopAnalyzer.php(203): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context))
#28 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/Statements/Block/ForeachAnalyzer.php(307): Psalm\Internal\Analyzer\Statements\Block\LoopAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Array, Array, Array, Object(Psalm\Internal\Scope\LoopScope), Object(Psalm\Context), false, false)
#29 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(490): Psalm\Internal\Analyzer\Statements\Block\ForeachAnalyzer::analyze(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Foreach_), Object(Psalm\Context))
#30 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/StatementsAnalyzer.php(172): Psalm\Internal\Analyzer\StatementsAnalyzer::analyzeStatement(Object(Psalm\Internal\Analyzer\StatementsAnalyzer), Object(PhpParser\Node\Stmt\Foreach_), Object(Psalm\Context), Object(Psalm\Context))
#31 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FunctionLikeAnalyzer.php(416): Psalm\Internal\Analyzer\StatementsAnalyzer->analyze(Array, Object(Psalm\Context), Object(Psalm\Context), true)
#32 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(1212): Psalm\Internal\Analyzer\FunctionLikeAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Internal\Provider\NodeDataProvider), Object(Psalm\Context), true)
#33 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ClassAnalyzer.php(505): Psalm\Internal\Analyzer\ClassAnalyzer->checkPropertyInitialization(Object(Psalm\Codebase), Object(Psalm\Config), Object(Psalm\Storage\ClassLikeStorage), Object(Psalm\Context), Object(Psalm\Context), Object(Psalm\Internal\Analyzer\MethodAnalyzer))
#34 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/FileAnalyzer.php(213): Psalm\Internal\Analyzer\ClassAnalyzer->analyze(Object(Psalm\Context), Object(Psalm\Context))
#35 /app/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(341): Psalm\Internal\Analyzer\FileAnalyzer->analyze(NULL)
#36 /app/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(580): Psalm\Internal\Codebase\Analyzer->Psalm\Internal\Codebase\{closure}(11216, '/app/vendor/zen...')
#37 /app/vendor/vimeo/psalm/src/Psalm/Internal/Codebase/Analyzer.php(270): Psalm\Internal\Codebase\Analyzer->doAnalysis(Object(Psalm\Internal\Analyzer\ProjectAnalyzer), 1)
#38 /app/vendor/vimeo/psalm/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php(636): Psalm\Internal\Codebase\Analyzer->analyzeFiles(Object(Psalm\Internal\Analyzer\ProjectAnalyzer), 1, false, true)
#39 /app/vendor/vimeo/psalm/src/psalm.php(700): Psalm\Internal\Analyzer\ProjectAnalyzer->check('/app/', true)
#40 /app/vendor/vimeo/psalm/src/psalm.php(884): Psalm\{closure}(Array)
#41 /app/vendor/vimeo/psalm/psalm(2): require_once('/app/vendor/vim...')
#42 {main}
(Psalm 4.7.0@d4377c0baf3ffbf0b1ec6998e8d1be2a40971005 crashed due to an uncaught Throwable)

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

No branches or pull requests

3 participants