mirror of
https://github.com/rectorphp/rector.git
synced 2024-07-05 17:13:32 +00:00
[BetterPhpDocParser] Handle parseString() got ShouldNotHappenException (#5299)
* Fixes #5267 * cs fix * use true for 3rd parameter is_a * try use method_exists * patch in BetterPhpDocParser * clean * clean * [ci-review] Rector Rectify * [ci-review] Rector Rectify * phpstan * phpstan * phpstan * add test case * better solution * phpstan * phpstan * clean up * clean up * phpstan * clean up * final touch: use ObjectType check instead * better approach * ensure $phpDocInfo->getVarTagValueNode() instanceof VarTagValueNode as well * clean up * use of the VarTagValueNode * use of the VarTagValueNode * use of the VarTagValueNode * [ci-review] Rector Rectify * phpstan Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
parent
13380b5b16
commit
31f357d6c0
|
@ -76,11 +76,6 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
*/
|
||||
private $classAnnotationMatcher;
|
||||
|
||||
/**
|
||||
* @var Lexer
|
||||
*/
|
||||
private $lexer;
|
||||
|
||||
/**
|
||||
* @var AnnotationContentResolver
|
||||
*/
|
||||
|
@ -101,7 +96,6 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
MultilineSpaceFormatPreserver $multilineSpaceFormatPreserver,
|
||||
CurrentNodeProvider $currentNodeProvider,
|
||||
ClassAnnotationMatcher $classAnnotationMatcher,
|
||||
Lexer $lexer,
|
||||
AnnotationContentResolver $annotationContentResolver,
|
||||
PHPUnitDataProviderDocNodeFactory $phpUnitDataProviderDocNodeFactory,
|
||||
array $phpDocNodeFactories = []
|
||||
|
@ -114,21 +108,12 @@ final class BetterPhpDocParser extends PhpDocParser
|
|||
$this->multilineSpaceFormatPreserver = $multilineSpaceFormatPreserver;
|
||||
$this->currentNodeProvider = $currentNodeProvider;
|
||||
$this->classAnnotationMatcher = $classAnnotationMatcher;
|
||||
$this->lexer = $lexer;
|
||||
$this->annotationContentResolver = $annotationContentResolver;
|
||||
$this->phpUnitDataProviderDocNodeFactory = $phpUnitDataProviderDocNodeFactory;
|
||||
|
||||
$this->setPhpDocNodeFactories($phpDocNodeFactories);
|
||||
}
|
||||
|
||||
public function parseString(string $docBlock): PhpDocNode
|
||||
{
|
||||
$tokens = $this->lexer->tokenize($docBlock);
|
||||
$tokenIterator = new TokenIterator($tokens);
|
||||
|
||||
return parent::parse($tokenIterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AttributeAwarePhpDocNode|PhpDocNode
|
||||
*/
|
||||
|
|
|
@ -10,11 +10,12 @@ use PhpParser\Node\Stmt\ClassLike;
|
|||
use PhpParser\Node\Stmt\Nop;
|
||||
use PhpParser\Node\Stmt\Trait_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\TypeWithClassName;
|
||||
use Rector\BetterPhpDocParser\PhpDocParser\BetterPhpDocParser;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\NodeCollector\NodeCollector\ParsedNodeCollector;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
|
||||
|
@ -22,7 +23,6 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
|
|||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
use Rector\NodeTypeResolver\PHPStan\Collector\TraitNodeScopeCollector;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
* @see \Rector\NodeTypeResolver\Tests\PerNodeTypeResolver\NameTypeResolver\NameTypeResolverTest
|
||||
|
@ -44,11 +44,6 @@ final class PropertyFetchTypeResolver implements NodeTypeResolverInterface
|
|||
*/
|
||||
private $nodeNameResolver;
|
||||
|
||||
/**
|
||||
* @var BetterPhpDocParser
|
||||
*/
|
||||
private $betterPhpDocParser;
|
||||
|
||||
/**
|
||||
* @var StaticTypeMapper
|
||||
*/
|
||||
|
@ -60,7 +55,6 @@ final class PropertyFetchTypeResolver implements NodeTypeResolverInterface
|
|||
private $traitNodeScopeCollector;
|
||||
|
||||
public function __construct(
|
||||
BetterPhpDocParser $betterPhpDocParser,
|
||||
NodeNameResolver $nodeNameResolver,
|
||||
ParsedNodeCollector $parsedNodeCollector,
|
||||
StaticTypeMapper $staticTypeMapper,
|
||||
|
@ -68,7 +62,6 @@ final class PropertyFetchTypeResolver implements NodeTypeResolverInterface
|
|||
) {
|
||||
$this->parsedNodeCollector = $parsedNodeCollector;
|
||||
$this->nodeNameResolver = $nodeNameResolver;
|
||||
$this->betterPhpDocParser = $betterPhpDocParser;
|
||||
$this->staticTypeMapper = $staticTypeMapper;
|
||||
$this->traitNodeScopeCollector = $traitNodeScopeCollector;
|
||||
}
|
||||
|
@ -150,20 +143,17 @@ final class PropertyFetchTypeResolver implements NodeTypeResolverInterface
|
|||
return new MixedType();
|
||||
}
|
||||
|
||||
// property is used
|
||||
$reflectionProperty = new ReflectionProperty($varObjectType->getClassName(), $propertyName);
|
||||
if (! $reflectionProperty->getDocComment()) {
|
||||
$phpDocInfo = $propertyFetch->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if (! $phpDocInfo instanceof PhpDocInfo) {
|
||||
return $varObjectType;
|
||||
}
|
||||
|
||||
$tagValueNode = $phpDocInfo->getVarTagValueNode();
|
||||
if (! $tagValueNode instanceof VarTagValueNode) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
$phpDocNode = $this->betterPhpDocParser->parseString((string) $reflectionProperty->getDocComment());
|
||||
$varTagValues = $phpDocNode->getVarTagValues();
|
||||
|
||||
if (! isset($varTagValues[0])) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
$typeNode = $varTagValues[0]->type;
|
||||
$typeNode = $tagValueNode->type;
|
||||
if (! $typeNode instanceof TypeNode) {
|
||||
return new MixedType();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use Nette\Utils\Json;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\CodingStyle\NodeAnalyzer\ImplodeAnalyzer;
|
||||
|
@ -70,7 +71,7 @@ final class JsonArrayFactory
|
|||
): ?Expr {
|
||||
if ($node instanceof Array_ && count($node->items) === 1) {
|
||||
$onlyItem = $node->items[0];
|
||||
if ($onlyItem === null) {
|
||||
if (! $onlyItem instanceof ArrayItem) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Core\Tests\Issues\Issue5267\DoNotThrowShouldNotHappenException;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class DoNotThrowShouldNotHappenExceptionTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
// bin/rector process ... --config config/some_config.php
|
||||
|
||||
protected function provideConfigFileInfo(): SmartFileInfo
|
||||
{
|
||||
return new SmartFileInfo(__DIR__ . '/config/some_config.php');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Core\Tests\Issues\Issue5267\DoNotThrowShouldNotHappenException\Fixture;
|
||||
|
||||
use Rector\Core\Tests\Issues\Issue5267\DoNotThrowShouldNotHappenException\Source\Xyz;
|
||||
|
||||
class SkipThrowShouldNotHappenException
|
||||
{
|
||||
public function fails(Xyz $xyz): void
|
||||
{
|
||||
$xyz->abc->get('xxx');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Core\Tests\Issues\Issue5267\DoNotThrowShouldNotHappenException\Source;
|
||||
|
||||
class Xyz
|
||||
{
|
||||
/**
|
||||
* @var Xyz
|
||||
*/
|
||||
public $abc;
|
||||
|
||||
public function get(string $s): string
|
||||
{
|
||||
return $s;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Core\Configuration\Option;
|
||||
use Rector\Set\ValueObject\SetList;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$parameters = $containerConfigurator->parameters();
|
||||
|
||||
$parameters->set(Option::SETS, [SetList::DEAD_CODE]);
|
||||
$parameters->set(Option::AUTO_IMPORT_NAMES, true);
|
||||
};
|
Loading…
Reference in New Issue
Block a user