From 31f357d6c0af03634c9c98c289891f528db9c77c Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 24 Jan 2021 23:46:06 +0700 Subject: [PATCH] [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 --- .../src/PhpDocParser/BetterPhpDocParser.php | 15 --------- .../PropertyFetchTypeResolver.php | 30 ++++++------------ .../src/NodeFactory/JsonArrayFactory.php | 3 +- ...DoNotThrowShouldNotHappenExceptionTest.php | 31 +++++++++++++++++++ ..._throw_should_not_happen_exception.php.inc | 18 +++++++++++ .../Source/Xyz.php | 18 +++++++++++ .../config/some_config.php | 14 +++++++++ 7 files changed, 93 insertions(+), 36 deletions(-) create mode 100644 tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/DoNotThrowShouldNotHappenExceptionTest.php create mode 100644 tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/Fixture/skip_throw_should_not_happen_exception.php.inc create mode 100644 tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/Source/Xyz.php create mode 100644 tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/config/some_config.php diff --git a/packages/better-php-doc-parser/src/PhpDocParser/BetterPhpDocParser.php b/packages/better-php-doc-parser/src/PhpDocParser/BetterPhpDocParser.php index 9dbb65d01be..ccc4749481c 100644 --- a/packages/better-php-doc-parser/src/PhpDocParser/BetterPhpDocParser.php +++ b/packages/better-php-doc-parser/src/PhpDocParser/BetterPhpDocParser.php @@ -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 */ diff --git a/packages/node-type-resolver/src/NodeTypeResolver/PropertyFetchTypeResolver.php b/packages/node-type-resolver/src/NodeTypeResolver/PropertyFetchTypeResolver.php index c753200f275..6cd35ad19fc 100644 --- a/packages/node-type-resolver/src/NodeTypeResolver/PropertyFetchTypeResolver.php +++ b/packages/node-type-resolver/src/NodeTypeResolver/PropertyFetchTypeResolver.php @@ -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(); } diff --git a/rules/coding-style/src/NodeFactory/JsonArrayFactory.php b/rules/coding-style/src/NodeFactory/JsonArrayFactory.php index c7621cde09f..3728caf070f 100644 --- a/rules/coding-style/src/NodeFactory/JsonArrayFactory.php +++ b/rules/coding-style/src/NodeFactory/JsonArrayFactory.php @@ -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(); } diff --git a/tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/DoNotThrowShouldNotHappenExceptionTest.php b/tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/DoNotThrowShouldNotHappenExceptionTest.php new file mode 100644 index 00000000000..2870735502c --- /dev/null +++ b/tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/DoNotThrowShouldNotHappenExceptionTest.php @@ -0,0 +1,31 @@ +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'); + } +} diff --git a/tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/Fixture/skip_throw_should_not_happen_exception.php.inc b/tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/Fixture/skip_throw_should_not_happen_exception.php.inc new file mode 100644 index 00000000000..f7a45258d72 --- /dev/null +++ b/tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/Fixture/skip_throw_should_not_happen_exception.php.inc @@ -0,0 +1,18 @@ +abc->get('xxx'); + } +} + + +?> diff --git a/tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/Source/Xyz.php b/tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/Source/Xyz.php new file mode 100644 index 00000000000..d4f2fb6cfe9 --- /dev/null +++ b/tests/Issues/Issue5267/DoNotThrowShouldNotHappenException/Source/Xyz.php @@ -0,0 +1,18 @@ +parameters(); + + $parameters->set(Option::SETS, [SetList::DEAD_CODE]); + $parameters->set(Option::AUTO_IMPORT_NAMES, true); +};