-
-
Notifications
You must be signed in to change notification settings - Fork 12
Open
Description
Letting PHPStan (2.x) analyze the following code/file leads to an internal error.
This is because PHPStan Laminas Framework assumes that properties in classes extending AbstractOptions are named a certain way, which is invalid because AbstractOptions only imposes naming conventions on property getters and setters but not underlying properties (which AbstractOptions does not know/access directly).
IMPORTANT NOTE
PHPStan Laminas Framework may check obvious candidates (queried property name, queried property name without underscores) first but since properties may be named "randomly", it must be prepared for those checks to fail and then provide some fallback handling.
Workaround: Rename properties
Code/file:
declare(strict_types=1);
use Laminas\Stdlib\AbstractOptions;
require __DIR__ . '/../vendor/autoload.php';
/**
* @extends AbstractOptions<mixed>
*/
class FooOptions extends AbstractOptions
{
private string $fooBar = '';
/** @param iterable<string, mixed> $options */
public function __construct($options)
{
parent::__construct($options);
if ($this->foo_bar === '') {
throw new InvalidArgumentException('Missing option foo_bar');
}
echo $this->foo_bar;
}
public function getFooBar(): string
{
return $this->fooBar;
}
public function setFooBar(string $fooBar): void
{
$this->fooBar = $fooBar;
}
}
$ok = new FooOptions(['foo_bar' => 'baz']);
$broken = new FooOptions([]);Error:
Internal error: Property $foo_bar was not found in reflection of class FooOptions. while analysing file
/path/to/src/FooOptions.php
Stack trace:
## phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Reflection/ClassReflection.php(587)
#0
/path/to/vendor/slam/phpstan-laminas-framework/src/Type/Laminas/StdlibAbstractOptionsPropertiesClassReflectionExtension.php(72):
PHPStan\Reflection\ClassReflection->getNativeProperty('foo_bar')
#1 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Reflection/WrappedExtendedPropertyReflection.php(38):
PHPStan\Reflection\PropertyReflection@anonymous->getReadableType()
#2 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.php(56):
PHPStan\Reflection\WrappedExtendedPropertyReflection->getReadableType()
#3 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Reflection/Type/CallbackUnresolvedPropertyPrototypeReflection.php(48):
PHPStan\Reflection\Type\CallbackUnresolvedPropertyPrototypeReflection->transformPropertyWithStaticType(Object(PHPStan\Reflection\ClassReflection),
Object(PHPStan\Reflection\WrappedExtendedPropertyReflection))
#4 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Type/StaticType.php(170):
PHPStan\Reflection\Type\CallbackUnresolvedPropertyPrototypeReflection->getTransformedProperty()
#5 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(3860):
PHPStan\Type\StaticType->getProperty('foo_bar', Object(PHPStan\Analyser\MutatingScope))
#6 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(3867):
PHPStan\Analyser\MutatingScope->getPropertyReflection(Object(PHPStan\Type\ThisType), 'foo_bar')
#7 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1560):
PHPStan\Analyser\MutatingScope->propertyFetchType(Object(PHPStan\Type\ThisType), 'foo_bar', Object(PhpParser\Node\Expr\PropertyFetch))
#8 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1566):
PHPStan\Analyser\MutatingScope->PHPStan\Analyser\{closure}()
#9 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(546):
PHPStan\Analyser\MutatingScope->resolveType('$this->foo_bar', Object(PhpParser\Node\Expr\PropertyFetch))
#10 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/RicherScopeGetTypeHelper.php(29):
PHPStan\Analyser\MutatingScope->getType(Object(PhpParser\Node\Expr\PropertyFetch))
#11 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(703):
PHPStan\Analyser\RicherScopeGetTypeHelper->getIdenticalResult(Object(PHPStan\Analyser\MutatingScope), Object(PhpParser\Node\Expr\BinaryOp\Identical))
#12 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(546):
PHPStan\Analyser\MutatingScope->resolveType('$this->foo_bar ...', Object(PhpParser\Node\Expr\BinaryOp\Identical))
#13 /path/to/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanRuleHelper.php(24):
PHPStan\Analyser\MutatingScope->getType(Object(PhpParser\Node\Expr\BinaryOp\Identical))
#14 /path/to/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInIfConditionRule.php(33):
PHPStan\Rules\BooleansInConditions\BooleanRuleHelper->passesAsBoolean(Object(PHPStan\Analyser\MutatingScope), Object(PhpParser\Node\Expr\BinaryOp\Identical))
#15 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(103):
PHPStan\Rules\BooleansInConditions\BooleanInIfConditionRule->processNode(Object(PhpParser\Node\Stmt\If_), Object(PHPStan\Analyser\MutatingScope))
#16 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Node/ClassStatementsGatherer.php(116):
PHPStan\Analyser\FileAnalyser->PHPStan\Analyser\{closure}(Object(PhpParser\Node\Stmt\If_), Object(PHPStan\Analyser\MutatingScope))
#17 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(647):
PHPStan\Node\ClassStatementsGatherer->__invoke(Object(PhpParser\Node\Stmt\If_), Object(PHPStan\Analyser\MutatingScope))
#18 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(520):
PHPStan\Analyser\NodeScopeResolver::PHPStan\Analyser\{closure}(Object(PhpParser\Node\Stmt\If_), Object(PHPStan\Analyser\MutatingScope))
#19 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(450):
PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\If_), Object(PHPStan\Analyser\MutatingScope), Object(Closure),
Object(PHPStan\Analyser\StatementContext))
#20 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(646):
PHPStan\Analyser\NodeScopeResolver->processStmtNodes(Object(PhpParser\Node\Stmt\ClassMethod), Array, Object(PHPStan\Analyser\MutatingScope), Object(Closure),
Object(PHPStan\Analyser\StatementContext))
#21 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(450):
PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\ClassMethod), Object(PHPStan\Analyser\MutatingScope),
Object(PHPStan\Node\ClassStatementsGatherer), Object(PHPStan\Analyser\StatementContext))
#22 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(786):
PHPStan\Analyser\NodeScopeResolver->processStmtNodes(Object(PhpParser\Node\Stmt\Class_), Array, Object(PHPStan\Analyser\MutatingScope),
Object(PHPStan\Node\ClassStatementsGatherer), Object(PHPStan\Analyser\StatementContext))
#23 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(398):
PHPStan\Analyser\NodeScopeResolver->processStmtNode(Object(PhpParser\Node\Stmt\Class_), Object(PHPStan\Analyser\MutatingScope), Object(Closure),
Object(PHPStan\Analyser\StatementContext))
#24 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(162):
PHPStan\Analyser\NodeScopeResolver->processNodes(Array, Object(PHPStan\Analyser\MutatingScope), Object(Closure))
#25 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(136):
PHPStan\Analyser\FileAnalyser->analyseFile('/path/to/...', Array, Object(PHPStan\Rules\LazyRegistry), Object(PHPStan\Collectors\Registry), NULL)
#26 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/EventEmitterTrait.php(111):
PHPStan\Command\WorkerCommand::PHPStan\Command\{closure}(Array)
#27 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/clue/ndjson-react/src/Decoder.php(117):
_PHPStan_2f712479f\Evenement\EventEmitter->emit('data', Array)
#28 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/EventEmitterTrait.php(111):
_PHPStan_2f712479f\Clue\React\NDJson\Decoder->handleData(Array)
#29 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/Util.php(62):
_PHPStan_2f712479f\Evenement\EventEmitter->emit('data', Array)
#30 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/EventEmitterTrait.php(111):
_PHPStan_2f712479f\React\Stream\Util::_PHPStan_2f712479f\React\Stream\{closure}('{"action":"anal...')
#31 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/DuplexResourceStream.php(168):
_PHPStan_2f712479f\Evenement\EventEmitter->emit('data', Array)
#32 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(201):
_PHPStan_2f712479f\React\Stream\DuplexResourceStream->handleData(Resource id #5772)
#33 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(173):
_PHPStan_2f712479f\React\EventLoop\StreamSelectLoop->waitForStreamActivity(NULL)
#34 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(96):
_PHPStan_2f712479f\React\EventLoop\StreamSelectLoop->run()
#35 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Command/Command.php(259):
PHPStan\Command\WorkerCommand->execute(Object(_PHPStan_2f712479f\Symfony\Component\Console\Input\ArgvInput),
Object(_PHPStan_2f712479f\Symfony\Component\Console\Output\ConsoleOutput))
#36 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(870):
_PHPStan_2f712479f\Symfony\Component\Console\Command\Command->run(Object(_PHPStan_2f712479f\Symfony\Component\Console\Input\ArgvInput),
Object(_PHPStan_2f712479f\Symfony\Component\Console\Output\ConsoleOutput))
#37 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(261):
_PHPStan_2f712479f\Symfony\Component\Console\Application->doRunCommand(Object(PHPStan\Command\WorkerCommand),
Object(_PHPStan_2f712479f\Symfony\Component\Console\Input\ArgvInput), Object(_PHPStan_2f712479f\Symfony\Component\Console\Output\ConsoleOutput))
#38 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(157):
_PHPStan_2f712479f\Symfony\Component\Console\Application->doRun(Object(_PHPStan_2f712479f\Symfony\Component\Console\Input\ArgvInput),
Object(_PHPStan_2f712479f\Symfony\Component\Console\Output\ConsoleOutput))
#39 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(114):
_PHPStan_2f712479f\Symfony\Component\Console\Application->run()
#40 phar:///path/to/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(115): _PHPStan_2f712479f\{closure}()
#41 /path/to/vendor/phpstan/phpstan/phpstan(8): require('phar:///path/to/...')
#42 /path/to/vendor/bin/phpstan(119): include('/path/to/...')
#43 {main}
Metadata
Metadata
Assignees
Labels
No labels