uuf6429/phpstan-phpdoc-type-resolver
最新稳定版本:3.0.0
Composer 安装命令:
composer require uuf6429/phpstan-phpdoc-type-resolver
包简介
Resolve (fully-qualify) types from PHPStan's PHPDoc parser
README 文档
README
Resolve (fully-qualify) types from PHPStan's PHPDoc parser.
💾 Installation
This package can be installed with Composer, simply run the following:
composer require uuf6429/phpstan-phpdoc-type-resolver
Consider using --dev if you intend to use this library during development only.
🤔 Why?
Because phpstan/phpdoc-parser doesn't resolve types (it's not its responsibility) and phpdocument/type-resolver
currently has some major limitations.
🚀 Usage
In principle the resolver needs two things:
- The PHPStan-PHPDoc type (an instance of
TypeNode). - 'Scope' information of where that type occurred.
There are two ways to retrieve that information, as shown below.
Important: The resolver will always convert some specific PHPStan types into something else as follows:
- *
ThisTypeNodeis converted intoIdentifierTypeNodefor the currently-passed class. - *
GenericTypeNodeto eitherConcreteGenericTypeNodeorTemplateGenericTypeNodebased on if the received instance contains unresolved generic/template types. - PHPStan locally-defined or imported-types, a
TypeDefTypeNodewill be provided (instead of anIdentifierTypeNodewith just the type name).
(*) conversion is mandatory, failures will trigger some sort of exception (meaning: the original type should never be returned).
😎 Via Reflection
Let's assume we have a \My\Project\Greeter class with a greet method, here's how we can resolve that method's
return type:
<?php // Reflect our class method $reflector = new \ReflectionMethod(\My\Project\Greeter::class, 'greet'); // Use the provided factory to easily parse the PHPDoc, which additionally automatically resolves the types $docBlock = \uuf6429\PHPStanPHPDocTypeResolver\PhpDoc\Factory::createInstance() ->createFromReflector($reflector); // And finally, retrieve the resolved type of the return tag /** @var \PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode $returnTag */ $returnTag = $docBlock->getTag('@return'); $finalReturnType = $returnTag->type;
🙈 Without Factory/DocBlock Wrapper
Assuming as before that we have a \My\Project\Greeter class with a greet method, here's the longer way to resolve
the method's return type:
<?php // Reflect our class method $reflector = new \ReflectionMethod(\My\Project\Greeter::class, 'greet'); // Use the scope resolver to get information about that method $scopeResolver = new \uuf6429\PHPStanPHPDocTypeResolver\PhpDoc\ReflectorScopeResolver(); $scope = $scopeResolver->resolve($reflector); // Parse the PHPDoc block with PHPStan PHPDoc parser $lexer = new \PHPStan\PhpDocParser\Lexer\Lexer(); $constExprParser = new \PHPStan\PhpDocParser\Parser\ConstExprParser(); $typeParser = new \PHPStan\PhpDocParser\Parser\TypeParser($constExprParser); $parser = new \PHPStan\PhpDocParser\Parser\PhpDocParser($typeParser, $constExprParser); $docBlock = $parser->parse( new \PHPStan\PhpDocParser\Parser\TokenIterator( $lexer->tokenize($scope->comment) // 👈 note that the scope resolver also retrieves the PHPDoc block for us ) ); // Finally, we initialize the type resolver and resolve the first return type of the doc block $typeResolver = new \uuf6429\PHPStanPHPDocTypeResolver\TypeResolver(); $finalReturnType = $typeResolver->resolve($scope, $docBlock->getReturnTagValues()[0]->type);
🤪 Via Source Strings
It's also possible to resolve the type without actually loading the PHP source code (which is a requirement for reflection). However, this will take more work - the main difference is that you will need to set up the scope yourself.
Let's assume we want to resolve a type in a PHP source code string:
<?php $source = <<<'PHP' <?php namespace My\Project\Services; use My\Project\PersonEntity as Person; class Greeter { /** * @param Person|object{name: string} $person */ public function greet($person): void { echo "Hello, {$person->name}!"; } } PHP; // Construct the scope manually - automating this will take some work $scope = new \uuf6429\PHPStanPHPDocTypeResolver\PhpDoc\Scope( // In-memory file; you could also use php memory streams etc file: 'data:base64,' . base64_encode($source), // approximate line where the type has occurred - everything else below has to be specified manually line: 73, class: 'My\Project\Services\Greeter', comment: <<<'PHP' /** * @param Person|object{name: string} $person */ PHP ); // The factory can also be used with a custom scope $docBlock = \uuf6429\PHPStanPHPDocTypeResolver\PhpDoc\Factory::createInstance() ->createFromScope($scope); // And as before, retrieve the resolved type of the return tag /** @var \PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode $returnTag */ $returnTag = $docBlock->getTag('@return'); $finalReturnType = $returnTag->type;
统计信息
- 总下载量: 101
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 0
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2024-06-16