Skip to content

Commit

Permalink
Merge pull request #410 from kukulich/php-parser4
Browse files Browse the repository at this point in the history
Updated to PHP-Parser 4
  • Loading branch information
Ocramius authored May 8, 2018
2 parents d9cc5fc + 31129a7 commit f8b3fc6
Show file tree
Hide file tree
Showing 23 changed files with 81 additions and 296 deletions.
12 changes: 6 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
220 changes: 20 additions & 200 deletions src/NodeCompiler/CompileNodeToValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
*
Expand All @@ -36,63 +30,31 @@ class CompileNodeToValue
*/
public function __invoke(Node $node, CompilerContext $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\Stmt\Expression) {
return $this($node->expr, $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);
}

/**
Expand Down Expand Up @@ -131,7 +93,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') {
Expand All @@ -158,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
*/
Expand All @@ -208,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);
},
];
}
}
12 changes: 6 additions & 6 deletions src/Reflection/ReflectionClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -745,15 +745,15 @@ public function getLocatedSource() : LocatedSource
*/
public function getStartLine() : int
{
return (int) $this->node->getAttribute('startLine', -1);
return $this->node->getStartLine();
}

/**
* Get the line number that this class ends on.
*/
public function getEndLine() : int
{
return (int) $this->node->getAttribute('endLine', -1);
return $this->node->getEndLine();
}

public function getStartColumn() : int
Expand Down Expand Up @@ -973,7 +973,7 @@ public function getTraitAliases() : array
continue;
}

$resolvedAliases[$adaptation->newName] = sprintf(
$resolvedAliases[$adaptation->newName->name] = sprintf(
'%s::%s',
$usedTrait->toString(),
$adaptation->method
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)) {
Expand Down
6 changes: 3 additions & 3 deletions src/Reflection/ReflectionClassConstant.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -128,15 +128,15 @@ public function getModifiers() : int
*/
public function getStartLine() : int
{
return (int) $this->node->getAttribute('startLine', -1);
return $this->node->getStartLine();
}

/**
* Get the line number that this constant ends on.
*/
public function getEndLine() : int
{
return (int) $this->node->getAttribute('endLine', -1);
return $this->node->getEndLine();
}

public function getStartColumn() : int
Expand Down
Loading

0 comments on commit f8b3fc6

Please sign in to comment.