From c6148825b6dbf0e77cc8c8aba10c39a5d040b348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20Hansl=C3=ADk?= Date: Wed, 28 Feb 2018 23:15:19 +0100 Subject: [PATCH 1/3] Updated to PHP-Parser 4 --- composer.json | 2 +- src/NodeCompiler/CompileNodeToValue.php | 6 ++++- src/Reflection/ReflectionClass.php | 12 +++++----- src/Reflection/ReflectionClassConstant.php | 6 ++--- src/Reflection/ReflectionFunctionAbstract.php | 10 ++++---- src/Reflection/ReflectionParameter.php | 6 ++--- src/Reflection/ReflectionProperty.php | 6 ++--- .../Ast/Parser/MemoizingParser.php | 6 ++--- .../Reflection/SourceStubber.php | 22 ++++------------- src/TypesFinder/FindParameterType.php | 2 +- .../NamespaceNodeToReflectionTypeContext.php | 4 ++-- src/Util/CalculateReflectionColum.php | 4 ++-- src/Util/GetFirstDocComment.php | 6 +---- .../ReflectionClassConstantTest.php | 2 +- test/unit/Reflection/ReflectionClassTest.php | 2 +- .../ReflectionFunctionAbstractTest.php | 6 ++--- .../Reflection/ReflectionParameterTest.php | 2 +- .../Reflection/ReflectionPropertyTest.php | 2 +- .../TypesFinder/FindParameterTypeTest.php | 9 +++---- ...mespaceNodeToReflectionTypeContextTest.php | 2 +- .../Util/CalculateReflectionColumnTest.php | 24 +++++++------------ 21 files changed, 59 insertions(+), 82 deletions(-) diff --git a/composer.json b/composer.json index 42d059e87..280a6724f 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "license": "MIT", "require": { "php": ">=7.1.0,<7.3.0", - "nikic/php-parser": "^3.1.1", + "nikic/php-parser": "^4.0.0", "phpdocumentor/reflection-docblock": "^4.1.1", "phpdocumentor/type-resolver": "^0.4.0", "roave/signature": "^1.0" diff --git a/src/NodeCompiler/CompileNodeToValue.php b/src/NodeCompiler/CompileNodeToValue.php index 8abdcfd12..62d05a2ad 100644 --- a/src/NodeCompiler/CompileNodeToValue.php +++ b/src/NodeCompiler/CompileNodeToValue.php @@ -36,6 +36,10 @@ class CompileNodeToValue */ public function __invoke(Node $node, CompilerContext $context) { + if ($node instanceof Node\Stmt\Expression) { + return $this($node->expr, $context); + } + if ($node instanceof Node\Scalar\String_ || $node instanceof Node\Scalar\DNumber || $node instanceof Node\Scalar\LNumber) { @@ -131,7 +135,7 @@ private function compileConstFetch(Node\Expr\ConstFetch $constNode) private function compileClassConstFetch(Node\Expr\ClassConstFetch $node, CompilerContext $context) { /** @var string $nodeName */ - $nodeName = $node->name; + $nodeName = $node->name->name; $className = $node->class->toString(); if ($nodeName === 'class') { diff --git a/src/Reflection/ReflectionClass.php b/src/Reflection/ReflectionClass.php index 4d4aef4d0..a1c4274d3 100644 --- a/src/Reflection/ReflectionClass.php +++ b/src/Reflection/ReflectionClass.php @@ -166,7 +166,7 @@ public static function createFromNode( public function getShortName() : string { if (! $this->isAnonymous()) { - return $this->node->name; + return $this->node->name->name; } $fileName = $this->getFileName(); @@ -745,7 +745,7 @@ public function getLocatedSource() : LocatedSource */ public function getStartLine() : int { - return (int) $this->node->getAttribute('startLine', -1); + return $this->node->getStartLine(); } /** @@ -753,7 +753,7 @@ public function getStartLine() : int */ public function getEndLine() : int { - return (int) $this->node->getAttribute('endLine', -1); + return $this->node->getEndLine(); } public function getStartColumn() : int @@ -973,7 +973,7 @@ public function getTraitAliases() : array continue; } - $resolvedAliases[$adaptation->newName] = sprintf( + $resolvedAliases[$adaptation->newName->name] = sprintf( '%s::%s', $usedTrait->toString(), $adaptation->method @@ -1321,7 +1321,7 @@ public function removeMethod(string $methodName) : bool { $lowerName = strtolower($methodName); foreach ($this->node->stmts as $key => $stmt) { - if ($stmt instanceof ClassMethod && $lowerName === strtolower($stmt->name)) { + if ($stmt instanceof ClassMethod && $lowerName === $stmt->name->toLowerString()) { unset($this->node->stmts[$key], $this->cachedMethods); return true; } @@ -1383,7 +1383,7 @@ public function removeProperty(string $propertyName) : bool } $propertyNames = array_map(function (Node\Stmt\PropertyProperty $propertyProperty) : string { - return strtolower($propertyProperty->name); + return $propertyProperty->name->toLowerString(); }, $stmt->props); if (in_array($lowerName, $propertyNames, true)) { diff --git a/src/Reflection/ReflectionClassConstant.php b/src/Reflection/ReflectionClassConstant.php index 0364bf864..687602fda 100644 --- a/src/Reflection/ReflectionClassConstant.php +++ b/src/Reflection/ReflectionClassConstant.php @@ -65,7 +65,7 @@ public static function createFromNode( */ public function getName() : string { - return $this->node->consts[$this->positionInNode]->name; + return $this->node->consts[$this->positionInNode]->name->name; } /** @@ -128,7 +128,7 @@ public function getModifiers() : int */ public function getStartLine() : int { - return (int) $this->node->getAttribute('startLine', -1); + return $this->node->getStartLine(); } /** @@ -136,7 +136,7 @@ public function getStartLine() : int */ public function getEndLine() : int { - return (int) $this->node->getAttribute('endLine', -1); + return $this->node->getEndLine(); } public function getStartColumn() : int diff --git a/src/Reflection/ReflectionFunctionAbstract.php b/src/Reflection/ReflectionFunctionAbstract.php index 0ad0d3198..b4939823a 100644 --- a/src/Reflection/ReflectionFunctionAbstract.php +++ b/src/Reflection/ReflectionFunctionAbstract.php @@ -141,7 +141,7 @@ public function getShortName() : string return self::CLOSURE_NAME; } - return $this->node->name; + return $this->node->name->name; } /** @@ -350,7 +350,7 @@ public function isGenerator() : bool */ public function getStartLine() : int { - return (int) $this->node->getAttribute('startLine', -1); + return $this->node->getStartLine(); } /** @@ -358,7 +358,7 @@ public function getStartLine() : int */ public function getEndLine() : int { - return (int) $this->node->getAttribute('endLine', -1); + return $this->node->getEndLine(); } public function getStartColumn() : int @@ -543,7 +543,7 @@ public function setBodyFromAst(array $nodes) : void */ public function addParameter(string $parameterName) : void { - $this->node->params[] = new ParamNode($parameterName); + $this->node->params[] = new ParamNode(new Node\Expr\Variable($parameterName)); } /** @@ -554,7 +554,7 @@ public function removeParameter(string $parameterName) : void $lowerName = strtolower($parameterName); foreach ($this->node->params as $key => $paramNode) { - if (strtolower($paramNode->name) !== $lowerName) { + if (strtolower($paramNode->var->name) !== $lowerName) { continue; } diff --git a/src/Reflection/ReflectionParameter.php b/src/Reflection/ReflectionParameter.php index e6fdd075e..3eb91d55b 100644 --- a/src/Reflection/ReflectionParameter.php +++ b/src/Reflection/ReflectionParameter.php @@ -181,13 +181,13 @@ private function parseDefaultValueNode() : void if ($className === 'self' || $className === 'static') { /** @var string $constantName */ - $constantName = $defaultValueNode->name; + $constantName = $defaultValueNode->name->name; $className = $this->findParentClassDeclaringConstant($constantName); } $this->isDefaultValueConstant = true; /** @var string $defaultValueNode->name */ - $this->defaultValueConstantName = $className . '::' . $defaultValueNode->name; + $this->defaultValueConstantName = $className . '::' . $defaultValueNode->name->name; } if ($defaultValueNode instanceof Node\Expr\ConstFetch @@ -230,7 +230,7 @@ private function findParentClassDeclaringConstant(string $constantName) : string */ public function getName() : string { - return $this->node->name; + return $this->node->var->name; } /** diff --git a/src/Reflection/ReflectionProperty.php b/src/Reflection/ReflectionProperty.php index d1905879f..21235d13c 100644 --- a/src/Reflection/ReflectionProperty.php +++ b/src/Reflection/ReflectionProperty.php @@ -169,7 +169,7 @@ public function getModifiers() : int */ public function getName() : string { - return $this->node->props[$this->positionInNode]->name; + return $this->node->props[$this->positionInNode]->name->name; } /** @@ -272,7 +272,7 @@ public function getDefaultValue() */ public function getStartLine() : int { - return (int) $this->node->getAttribute('startLine', -1); + return $this->node->getStartLine(); } /** @@ -280,7 +280,7 @@ public function getStartLine() : int */ public function getEndLine() : int { - return (int) $this->node->getAttribute('endLine', -1); + return $this->node->getEndLine(); } public function getStartColumn() : int diff --git a/src/SourceLocator/Ast/Parser/MemoizingParser.php b/src/SourceLocator/Ast/Parser/MemoizingParser.php index 40d09599c..6189d8151 100644 --- a/src/SourceLocator/Ast/Parser/MemoizingParser.php +++ b/src/SourceLocator/Ast/Parser/MemoizingParser.php @@ -16,7 +16,7 @@ */ final class MemoizingParser implements Parser { - /** @var Node[][]|null[] indexed by source hash */ + /** @var Node\Stmt[][]|null[] indexed by source hash */ private $sourceHashToAst = []; /** @var Parser */ @@ -29,10 +29,8 @@ public function __construct(Parser $wrappedParser) /** * {@inheritDoc} - * - * @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint */ - public function parse($code, ?ErrorHandler $errorHandler = null) : ?array + public function parse(string $code, ?ErrorHandler $errorHandler = null) : ?array { // note: this code is mathematically buggy by default, as we are using a hash to identify // cache entries. The string length is added to further reduce likeliness (although diff --git a/src/SourceLocator/Reflection/SourceStubber.php b/src/SourceLocator/Reflection/SourceStubber.php index f8a3b9f21..f7c09108d 100644 --- a/src/SourceLocator/Reflection/SourceStubber.php +++ b/src/SourceLocator/Reflection/SourceStubber.php @@ -4,6 +4,7 @@ namespace Roave\BetterReflection\SourceLocator\Reflection; +use PhpParser\Builder; use PhpParser\Builder\Class_; use PhpParser\Builder\Declaration; use PhpParser\Builder\Interface_; @@ -11,11 +12,10 @@ use PhpParser\Builder\Param; use PhpParser\Builder\Property; use PhpParser\Builder\Trait_; -use PhpParser\BuilderAbstract; use PhpParser\BuilderFactory; +use PhpParser\BuilderHelpers; use PhpParser\Comment\Doc; use PhpParser\Node\Const_; -use PhpParser\Node\Expr; use PhpParser\Node\Name; use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\NullableType; @@ -104,7 +104,7 @@ private function createClass(CoreReflectionClass $classReflection) : Declaration * @param Class_|Interface_|Trait_|Method|Property $node * @param CoreReflectionClass|CoreReflectionMethod|CoreReflectionProperty $reflection */ - private function addDocComment(BuilderAbstract $node, CoreReflector $reflection) : void + private function addDocComment(Builder $node, CoreReflector $reflection) : void { if ($reflection->getDocComment() === false) { return; @@ -240,7 +240,7 @@ private function addConstants(Declaration $classNode, CoreReflectionClass $class } $classConstantNode = new ClassConst( - [new Const_($constantReflection->getName(), $this->constantValueNode($constantReflection))], + [new Const_($constantReflection->getName(), BuilderHelpers::normalizeValue($constantReflection->getValue()))], $this->constantVisibilityFlags($constantReflection) ); @@ -252,20 +252,6 @@ private function addConstants(Declaration $classNode, CoreReflectionClass $class } } - /** - * A little hack so we don't have to copy the code in PhpParser\BuilderAbstract::normalizeValue() - */ - private function constantValueNode(ReflectionClassConstant $constant) : ?Expr - { - return $this - ->builderFactory - ->property('') - ->setDefault($constant->getValue()) - ->getNode() - ->props[0] - ->default; - } - private function constantVisibilityFlags(ReflectionClassConstant $constant) : int { if ($constant->isPrivate()) { diff --git a/src/TypesFinder/FindParameterType.php b/src/TypesFinder/FindParameterType.php index e10948d40..d19fb7048 100644 --- a/src/TypesFinder/FindParameterType.php +++ b/src/TypesFinder/FindParameterType.php @@ -53,7 +53,7 @@ public function __invoke(ReflectionFunctionAbstract $function, ?Namespace_ $name ->getTagsByName('param'); foreach ($paramTags as $paramTag) { - if ($paramTag->getVariableName() === $node->name) { + if ($paramTag->getVariableName() === $node->var->name) { return $this->resolveTypes->__invoke(explode('|', (string) $paramTag->getType()), $context); } } diff --git a/src/TypesFinder/PhpDocumentor/NamespaceNodeToReflectionTypeContext.php b/src/TypesFinder/PhpDocumentor/NamespaceNodeToReflectionTypeContext.php index 16b8b7f0d..67e739d9f 100644 --- a/src/TypesFinder/PhpDocumentor/NamespaceNodeToReflectionTypeContext.php +++ b/src/TypesFinder/PhpDocumentor/NamespaceNodeToReflectionTypeContext.php @@ -45,10 +45,10 @@ function ($use) : array { return array_map( function (UseUse $useUse) use ($use) : array { if ($use instanceof GroupUse) { - return [$useUse->alias => $use->prefix->toString() . '\\' . $useUse->name->toString()]; + return [$useUse->getAlias()->toString() => $use->prefix->toString() . '\\' . $useUse->name->toString()]; } - return [$useUse->alias => $useUse->name->toString()]; + return [$useUse->getAlias()->toString() => $useUse->name->toString()]; }, $use->uses ); diff --git a/src/Util/CalculateReflectionColum.php b/src/Util/CalculateReflectionColum.php index 412573886..0411c5047 100644 --- a/src/Util/CalculateReflectionColum.php +++ b/src/Util/CalculateReflectionColum.php @@ -25,7 +25,7 @@ public static function getStartColumn(string $source, Node $node) : int throw NoNodePosition::fromNode($node); } - return self::calculateColumn($source, $node->getAttribute('startFilePos')); + return self::calculateColumn($source, $node->getStartFilePos()); } /** @@ -38,7 +38,7 @@ public static function getEndColumn(string $source, Node $node) : int throw NoNodePosition::fromNode($node); } - return self::calculateColumn($source, $node->getAttribute('endFilePos')); + return self::calculateColumn($source, $node->getEndFilePos()); } /** diff --git a/src/Util/GetFirstDocComment.php b/src/Util/GetFirstDocComment.php index c1880ad48..7cd7d6cd6 100644 --- a/src/Util/GetFirstDocComment.php +++ b/src/Util/GetFirstDocComment.php @@ -14,11 +14,7 @@ final class GetFirstDocComment { public static function forNode(NodeAbstract $node) : string { - if (! $node->hasAttribute('comments')) { - return ''; - } - - foreach ($node->getAttribute('comments') as $comment) { + foreach ($node->getComments() as $comment) { if ($comment instanceof Doc) { return $comment->getReformattedText(); } diff --git a/test/unit/Reflection/ReflectionClassConstantTest.php b/test/unit/Reflection/ReflectionClassConstantTest.php index ed5b274b9..479cd48f7 100644 --- a/test/unit/Reflection/ReflectionClassConstantTest.php +++ b/test/unit/Reflection/ReflectionClassConstantTest.php @@ -172,6 +172,6 @@ class Foo self::assertInstanceOf(ClassConst::class, $ast); self::assertSame($positionInAst, $constantReflection->getPositionInAst()); - self::assertSame($constantName, $ast->consts[$positionInAst]->name); + self::assertSame($constantName, $ast->consts[$positionInAst]->name->name); } } diff --git a/test/unit/Reflection/ReflectionClassTest.php b/test/unit/Reflection/ReflectionClassTest.php index bee2e4839..e7c53d45c 100644 --- a/test/unit/Reflection/ReflectionClassTest.php +++ b/test/unit/Reflection/ReflectionClassTest.php @@ -1486,7 +1486,7 @@ class Foo {} $ast = $reflection->getAst(); self::assertInstanceOf(Class_::class, $ast); - self::assertSame('Foo', $ast->name); + self::assertSame('Foo', $ast->name->name); } public function testSetIsFinal() : void diff --git a/test/unit/Reflection/ReflectionFunctionAbstractTest.php b/test/unit/Reflection/ReflectionFunctionAbstractTest.php index 53b0b8888..582b539b8 100644 --- a/test/unit/Reflection/ReflectionFunctionAbstractTest.php +++ b/test/unit/Reflection/ReflectionFunctionAbstractTest.php @@ -560,7 +560,7 @@ function foo() {} $ast = $function->getAst(); self::assertInstanceOf(Function_::class, $ast); - self::assertSame('foo', $ast->name); + self::assertSame('foo', $ast->name->name); } public function testSetBodyFromClosure() : void @@ -699,7 +699,7 @@ public function __invoke() { $first = current($nodes); self::assertInstanceOf(Closure::class, $first->expr); - self::assertSame(8, $first->getAttribute('startLine')); - self::assertSame(10, $first->getAttribute('endLine')); + self::assertSame(8, $first->getStartLine()); + self::assertSame(10, $first->getEndLine()); } } diff --git a/test/unit/Reflection/ReflectionParameterTest.php b/test/unit/Reflection/ReflectionParameterTest.php index 1aeb58fae..c8e0b3ee7 100644 --- a/test/unit/Reflection/ReflectionParameterTest.php +++ b/test/unit/Reflection/ReflectionParameterTest.php @@ -700,6 +700,6 @@ public function testGetAst() : void $ast = $parameter->getAst(); self::assertInstanceOf(Param::class, $ast); - self::assertSame('boo', $ast->name); + self::assertSame('boo', $ast->var->name); } } diff --git a/test/unit/Reflection/ReflectionPropertyTest.php b/test/unit/Reflection/ReflectionPropertyTest.php index b71b6f6eb..cb0158831 100644 --- a/test/unit/Reflection/ReflectionPropertyTest.php +++ b/test/unit/Reflection/ReflectionPropertyTest.php @@ -393,7 +393,7 @@ class Foo self::assertInstanceOf(Property::class, $ast); self::assertSame($positionInAst, $propertyReflection->getPositionInAst()); - self::assertSame($propertyName, $ast->props[$positionInAst]->name); + self::assertSame($propertyName, $ast->props[$positionInAst]->name->name); } public function testGetDeclaringAndImplementingClassWithPropertyFromTrait() : void diff --git a/test/unit/TypesFinder/FindParameterTypeTest.php b/test/unit/TypesFinder/FindParameterTypeTest.php index 619a9a2f0..95bb0edad 100644 --- a/test/unit/TypesFinder/FindParameterTypeTest.php +++ b/test/unit/TypesFinder/FindParameterTypeTest.php @@ -8,6 +8,7 @@ use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\Types; use PhpParser\Builder\Use_; +use PhpParser\Node\Expr\Variable; use PhpParser\Node\Name; use PhpParser\Node\Param as ParamNode; use PhpParser\Node\Stmt\Namespace_; @@ -76,7 +77,7 @@ public function foo($bar) {} */ public function testFindParameterTypeForFunction(string $docBlock, string $nodeName, array $expectedInstances) : void { - $node = new ParamNode($nodeName); + $node = new ParamNode(new Variable($nodeName)); $docBlock = sprintf("/**\n * %s\n */", $docBlock); /* @var $function ReflectionFunctionAbstract|\PHPUnit_Framework_MockObject_MockObject */ @@ -102,7 +103,7 @@ public function testFindParameterTypeForFunction(string $docBlock, string $nodeN */ public function testFindParameterTypeForMethod(string $docBlock, string $nodeName, array $expectedInstances) : void { - $node = new ParamNode($nodeName); + $node = new ParamNode(new Variable($nodeName)); $docBlock = sprintf("/**\n * %s\n */", $docBlock); /* @var $method ReflectionFunctionAbstract|\PHPUnit_Framework_MockObject_MockObject */ @@ -124,7 +125,7 @@ public function testFindParameterTypeForMethod(string $docBlock, string $nodeNam public function testFindParameterTypeForFunctionWithNoDocBlock() : void { - $node = new ParamNode('foo'); + $node = new ParamNode(new Variable('foo')); /* @var $function ReflectionFunctionAbstract|\PHPUnit_Framework_MockObject_MockObject */ $function = $this->createMock(ReflectionFunctionAbstract::class); @@ -150,7 +151,7 @@ public function testWillResolveAliasedTypes( ) : void { $docBlock = sprintf("/**\n * @param %s \$foo\n */", $docBlockType); - $parameterNode = new ParamNode('foo'); + $parameterNode = new ParamNode(new Variable('foo')); /* @var $function ReflectionFunctionAbstract|\PHPUnit_Framework_MockObject_MockObject */ $function = $this->createMock(ReflectionFunctionAbstract::class); diff --git a/test/unit/TypesFinder/PhpDocumentor/NamespaceNodeToReflectionTypeContextTest.php b/test/unit/TypesFinder/PhpDocumentor/NamespaceNodeToReflectionTypeContextTest.php index fd7ce9153..81c3054eb 100644 --- a/test/unit/TypesFinder/PhpDocumentor/NamespaceNodeToReflectionTypeContextTest.php +++ b/test/unit/TypesFinder/PhpDocumentor/NamespaceNodeToReflectionTypeContextTest.php @@ -61,7 +61,7 @@ public function expectedContextsProvider() : array new Context(''), ], 'Empty namespace' => [ - new Namespace_(new Name('')), + new Namespace_(), new Context(''), ], 'Actual namespace' => [ diff --git a/test/unit/Util/CalculateReflectionColumnTest.php b/test/unit/Util/CalculateReflectionColumnTest.php index 73c9f9cac..e5222a5bf 100644 --- a/test/unit/Util/CalculateReflectionColumnTest.php +++ b/test/unit/Util/CalculateReflectionColumnTest.php @@ -25,8 +25,7 @@ public function testGetStartColumn() : void ->with('startFilePos') ->willReturn(true); $node - ->method('getAttribute') - ->with('startFilePos') + ->method('getStartFilePos') ->willReturn(10); self::assertSame(5, CalculateReflectionColum::getStartColumn($source, $node)); @@ -42,8 +41,7 @@ public function testGetStartColumnIfAtTheBeginningOfLine() : void ->with('startFilePos') ->willReturn(true); $node - ->method('getAttribute') - ->with('startFilePos') + ->method('getStartFilePos') ->willReturn(6); self::assertSame(1, CalculateReflectionColum::getStartColumn($source, $node)); @@ -59,8 +57,7 @@ public function testGetStartColumnIfOneLineSource() : void ->with('startFilePos') ->willReturn(true); $node - ->method('getAttribute') - ->with('startFilePos') + ->method('getStartFilePos') ->willReturn(6); self::assertSame(7, CalculateReflectionColum::getStartColumn($source, $node)); @@ -76,8 +73,7 @@ public function testGetStartColumnThrowsExceptionIfInvalidPosition() : void ->with('startFilePos') ->willReturn(true); $node - ->method('getAttribute') - ->with('startFilePos') + ->method('getStartFilePos') ->willReturn(10000); CalculateReflectionColum::getStartColumn('', $node); @@ -106,8 +102,7 @@ public function testGetEndColumn() : void ->with('endFilePos') ->willReturn(true); $node - ->method('getAttribute') - ->with('endFilePos') + ->method('getEndFilePos') ->willReturn(21); self::assertSame(16, CalculateReflectionColum::getEndColumn($source, $node)); @@ -123,8 +118,7 @@ public function testGetEndColumnIfAtTheEndOfLine() : void ->with('endFilePos') ->willReturn(true); $node - ->method('getAttribute') - ->with('endFilePos') + ->method('getEndFilePos') ->willReturn(17); self::assertSame(12, CalculateReflectionColum::getEndColumn($source, $node)); @@ -140,8 +134,7 @@ public function testGetEndColumnIfOneLineSource() : void ->with('endFilePos') ->willReturn(true); $node - ->method('getAttribute') - ->with('endFilePos') + ->method('getEndFilePos') ->willReturn(17); self::assertSame(18, CalculateReflectionColum::getEndColumn($source, $node)); @@ -157,8 +150,7 @@ public function testGetEndColumnThrowsExceptionIfInvalidPosition() : void ->with('endFilePos') ->willReturn(true); $node - ->method('getAttribute') - ->with('endFilePos') + ->method('getEndFilePos') ->willReturn(10000); CalculateReflectionColum::getEndColumn('', $node); From e3e814066e08df281ec10befed77d692dc282490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20Hansl=C3=ADk?= Date: Wed, 28 Feb 2018 23:53:31 +0100 Subject: [PATCH 2/3] Simplified CompileNodeToValue --- src/NodeCompiler/CompileNodeToValue.php | 218 ++---------------- .../NodeCompiler/CompileNodeToValueTest.php | 10 +- 2 files changed, 18 insertions(+), 210 deletions(-) diff --git a/src/NodeCompiler/CompileNodeToValue.php b/src/NodeCompiler/CompileNodeToValue.php index 62d05a2ad..18a5c8e8c 100644 --- a/src/NodeCompiler/CompileNodeToValue.php +++ b/src/NodeCompiler/CompileNodeToValue.php @@ -4,14 +4,11 @@ namespace Roave\BetterReflection\NodeCompiler; +use PhpParser\ConstExprEvaluator; use PhpParser\Node; -use ReflectionFunction; -use Roave\BetterReflection\NodeCompiler\Exception\UnableToCompileNode; use Roave\BetterReflection\Reflection\ReflectionClass; use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound; use Roave\BetterReflection\Util\FileHelper; -use function array_combine; -use function array_map; use function constant; use function defined; use function dirname; @@ -22,9 +19,6 @@ class CompileNodeToValue { - /** @var callable[]|null indexed by supported expression node class name */ - private static $nodeEvaluators; - /** * Compile an expression from a node into a value. * @@ -40,63 +34,27 @@ public function __invoke(Node $node, CompilerContext $context) return $this($node->expr, $context); } - if ($node instanceof Node\Scalar\String_ - || $node instanceof Node\Scalar\DNumber - || $node instanceof Node\Scalar\LNumber) { - return $node->value; - } - - // common edge case - negative numbers - if ($node instanceof Node\Expr\UnaryMinus) { - return $this($node->expr, $context) * -1; - } - - if ($node instanceof Node\Expr\Array_) { - return $this->compileArray($node, $context); - } - - if ($node instanceof Node\Expr\ConstFetch) { - return $this->compileConstFetch($node); - } - - if ($node instanceof Node\Expr\ClassConstFetch) { - return $this->compileClassConstFetch($node, $context); - } - - if ($node instanceof Node\Expr\BinaryOp) { - return $this->compileBinaryOperator($node, $context); - } - - if ($node instanceof Node\Scalar\MagicConst\Dir) { - return $this->compileDirConstant($context); - } - - if ($node instanceof Node\Scalar\MagicConst\Class_) { - return $this->compileClassConstant($context); - } + $constExprEvaluator = new ConstExprEvaluator(function (Node\Expr $node) use ($context) { + if ($node instanceof Node\Expr\ConstFetch) { + return $this->compileConstFetch($node); + } - throw new Exception\UnableToCompileNode('Unable to compile expression: ' . get_class($node)); - } + if ($node instanceof Node\Expr\ClassConstFetch) { + return $this->compileClassConstFetch($node, $context); + } - /** - * Compile arrays - * - * @return mixed[] - */ - private function compileArray(Node\Expr\Array_ $arrayNode, CompilerContext $context) : array - { - $compiledArray = []; - foreach ($arrayNode->items as $arrayItem) { - $compiledValue = $this($arrayItem->value, $context); + if ($node instanceof Node\Scalar\MagicConst\Dir) { + return $this->compileDirConstant($context); + } - if ($arrayItem->key === null) { - $compiledArray[] = $compiledValue; - continue; + if ($node instanceof Node\Scalar\MagicConst\Class_) { + return $this->compileClassConstant($context); } - $compiledArray[$this($arrayItem->key, $context)] = $compiledValue; - } - return $compiledArray; + throw new Exception\UnableToCompileNode('Unable to compile expression: ' . get_class($node)); + }); + + return $constExprEvaluator->evaluateDirectly($node); } /** @@ -162,30 +120,6 @@ private function compileClassConstFetch(Node\Expr\ClassConstFetch $node, Compile ); } - /** - * Compile a binary operator node - * - * - * @return mixed - * - * @throws UnableToCompileNode - */ - private function compileBinaryOperator(Node\Expr\BinaryOp $node, CompilerContext $context) - { - $evaluators = self::loadEvaluators(); - $nodeClass = get_class($node); - - if (! isset($evaluators[$nodeClass])) { - throw new Exception\UnableToCompileNode(sprintf( - 'Unable to compile binary operator: %s', - $nodeClass - )); - } - - // Welcome to method overloading implemented PHP-style. Yay? - return $evaluators[$nodeClass]($node, $context, $this); - } - /** * Compile a __DIR__ node */ @@ -212,122 +146,4 @@ private function getConstantDeclaringClass(string $constantName, ReflectionClass return $parentClass ? $this->getConstantDeclaringClass($constantName, $parentClass) : null; } - - /** - * @return callable[] indexed by node class name - */ - private static function loadEvaluators() : array - { - if (self::$nodeEvaluators) { - return self::$nodeEvaluators; - } - - $evaluators = self::makeEvaluators(); - - return self::$nodeEvaluators = array_combine( - array_map(function (callable $nodeEvaluator) : string { - /** @noinspection ExceptionsAnnotatingAndHandlingInspection */ - /** @noinspection NullPointerExceptionInspection */ - return (new ReflectionFunction($nodeEvaluator))->getParameters()[0]->getType()->getName(); - }, $evaluators), - $evaluators - ); - } - - /** - * @return callable[] - */ - private static function makeEvaluators() : array - { - return [ - function (Node\Expr\BinaryOp\Plus $node, CompilerContext $context, self $next) { - return $next($node->left, $context) + $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Mul $node, CompilerContext $context, self $next) { - return $next($node->left, $context) * $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Minus $node, CompilerContext $context, self $next) { - return $next($node->left, $context) - $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Div $node, CompilerContext $context, self $next) { - return $next($node->left, $context) / $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Concat $node, CompilerContext $context, self $next) { - return $next($node->left, $context) . $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\BooleanAnd $node, CompilerContext $context, self $next) { - return $next($node->left, $context) && $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\BooleanOr $node, CompilerContext $context, self $next) { - return $next($node->left, $context) || $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\BitwiseAnd $node, CompilerContext $context, self $next) { - return $next($node->left, $context) & $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\BitwiseOr $node, CompilerContext $context, self $next) { - return $next($node->left, $context) | $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\BitwiseXor $node, CompilerContext $context, self $next) { - return $next($node->left, $context) ^ $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Equal $node, CompilerContext $context, self $next) { - /** @noinspection TypeUnsafeComparisonInspection */ - // phpcs:disable SlevomatCodingStandard.ControlStructures.DisallowEqualOperators - return $next($node->left, $context) == $next($node->right, $context); - // phpcs:enable - }, - function (Node\Expr\BinaryOp\Greater $node, CompilerContext $context, self $next) { - return $next($node->left, $context) > $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\GreaterOrEqual $node, CompilerContext $context, self $next) { - return $next($node->left, $context) >= $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Identical $node, CompilerContext $context, self $next) { - return $next($node->left, $context) === $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\LogicalAnd $node, CompilerContext $context, self $next) { - // phpcs:disable Squiz.Operators.ValidLogicalOperators.NotAllowed - return $next($node->left, $context) and $next($node->right, $context); - // phpcs:enable - }, - function (Node\Expr\BinaryOp\LogicalOr $node, CompilerContext $context, self $next) { - // phpcs:disable Squiz.Operators.ValidLogicalOperators.NotAllowed - return $next($node->left, $context) or $next($node->right, $context); - // phpcs:enable - }, - function (Node\Expr\BinaryOp\LogicalXor $node, CompilerContext $context, self $next) { - return $next($node->left, $context) xor $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Mod $node, CompilerContext $context, self $next) { - return $next($node->left, $context) % $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\NotEqual $node, CompilerContext $context, self $next) { - /** @noinspection TypeUnsafeComparisonInspection */ - // phpcs:disable SlevomatCodingStandard.ControlStructures.DisallowEqualOperators - return $next($node->left, $context) != $next($node->right, $context); - // phpcs:enable - }, - function (Node\Expr\BinaryOp\NotIdentical $node, CompilerContext $context, self $next) { - return $next($node->left, $context) !== $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Pow $node, CompilerContext $context, self $next) { - return $next($node->left, $context) ** $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\ShiftLeft $node, CompilerContext $context, self $next) { - return $next($node->left, $context) << $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\ShiftRight $node, CompilerContext $context, self $next) { - return $next($node->left, $context) >> $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Smaller $node, CompilerContext $context, self $next) { - return $next($node->left, $context) < $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\SmallerOrEqual $node, CompilerContext $context, self $next) { - return $next($node->left, $context) <= $next($node->right, $context); - }, - function (Node\Expr\BinaryOp\Spaceship $node, CompilerContext $context, self $next) { - return $next($node->left, $context) <=> $next($node->right, $context); - }, - ]; - } } diff --git a/test/unit/NodeCompiler/CompileNodeToValueTest.php b/test/unit/NodeCompiler/CompileNodeToValueTest.php index c2cc1c26d..ffb4e7e0c 100644 --- a/test/unit/NodeCompiler/CompileNodeToValueTest.php +++ b/test/unit/NodeCompiler/CompileNodeToValueTest.php @@ -5,11 +5,9 @@ namespace Roave\BetterReflectionTest\NodeCompiler; use PhpParser\Node; -use PhpParser\Node\Expr\BinaryOp\Coalesce; use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Expr\Yield_; use PhpParser\Node\Name; -use PhpParser\Node\Scalar\LNumber; use PhpParser\Parser; use PHPUnit\Framework\TestCase; use Roave\BetterReflection\NodeCompiler\CompileNodeToValue; @@ -150,6 +148,7 @@ public function nodeProvider() : array ['1 <=> 4', -1], ['4 <=> 1', 1], ['1 <=> 1', 0], + ['5 ?? 4', 5], ]; } @@ -173,13 +172,6 @@ public function testExceptionThrownWhenInvalidNodeGiven() : void (new CompileNodeToValue())->__invoke(new Yield_(), $this->getDummyContext()); } - public function testExceptionThrownWhenCoalesceOperatorUsed() : void - { - $this->expectException(UnableToCompileNode::class); - $this->expectExceptionMessage('Unable to compile binary operator'); - (new CompileNodeToValue())->__invoke(new Coalesce(new LNumber(5), new LNumber(3)), $this->getDummyContext()); - } - public function testExceptionThrownWhenUndefinedConstUsed() : void { $this->expectException(UnableToCompileNode::class); From 31129a702cb15553b7260aca8df16e1d2a181d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20Hansl=C3=ADk?= Date: Tue, 8 May 2018 09:34:17 +0200 Subject: [PATCH 3/3] Disabled static analysis temporarily --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 98acd4b69..5525502b6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,12 +72,12 @@ jobs: - travis_retry composer require --dev --prefer-dist --prefer-stable doctrine/coding-standard:^4.0.0 script: vendor/bin/phpcs - - stage: Static Analysis - php: 7.1 - env: DEPENDENCIES="" - before_script: - - travis_retry composer require --dev --prefer-dist --prefer-stable phpstan/phpstan:^0.9.2 - script: vendor/bin/phpstan analyse -l 5 -c phpstan.neon src + #- stage: Static Analysis + # php: 7.1 + # env: DEPENDENCIES="" + # before_script: + # - travis_retry composer require --dev --prefer-dist --prefer-stable phpstan/phpstan:^0.9.2 + # script: vendor/bin/phpstan analyse -l 5 -c phpstan.neon src - stage: Run benchmarks php: 7.1