Skip to content

Commit f8b3fc6

Browse files
authored
Merge pull request #410 from kukulich/php-parser4
Updated to PHP-Parser 4
2 parents d9cc5fc + 31129a7 commit f8b3fc6

23 files changed

+81
-296
lines changed

.travis.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ jobs:
7272
- travis_retry composer require --dev --prefer-dist --prefer-stable doctrine/coding-standard:^4.0.0
7373
script: vendor/bin/phpcs
7474

75-
- stage: Static Analysis
76-
php: 7.1
77-
env: DEPENDENCIES=""
78-
before_script:
79-
- travis_retry composer require --dev --prefer-dist --prefer-stable phpstan/phpstan:^0.9.2
80-
script: vendor/bin/phpstan analyse -l 5 -c phpstan.neon src
75+
#- stage: Static Analysis
76+
# php: 7.1
77+
# env: DEPENDENCIES=""
78+
# before_script:
79+
# - travis_retry composer require --dev --prefer-dist --prefer-stable phpstan/phpstan:^0.9.2
80+
# script: vendor/bin/phpstan analyse -l 5 -c phpstan.neon src
8181

8282
- stage: Run benchmarks
8383
php: 7.1

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"license": "MIT",
55
"require": {
66
"php": ">=7.1.0,<7.3.0",
7-
"nikic/php-parser": "^3.1.1",
7+
"nikic/php-parser": "^4.0.0",
88
"phpdocumentor/reflection-docblock": "^4.1.1",
99
"phpdocumentor/type-resolver": "^0.4.0",
1010
"roave/signature": "^1.0"

src/NodeCompiler/CompileNodeToValue.php

Lines changed: 20 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@
44

55
namespace Roave\BetterReflection\NodeCompiler;
66

7+
use PhpParser\ConstExprEvaluator;
78
use PhpParser\Node;
8-
use ReflectionFunction;
9-
use Roave\BetterReflection\NodeCompiler\Exception\UnableToCompileNode;
109
use Roave\BetterReflection\Reflection\ReflectionClass;
1110
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
1211
use Roave\BetterReflection\Util\FileHelper;
13-
use function array_combine;
14-
use function array_map;
1512
use function constant;
1613
use function defined;
1714
use function dirname;
@@ -22,9 +19,6 @@
2219

2320
class CompileNodeToValue
2421
{
25-
/** @var callable[]|null indexed by supported expression node class name */
26-
private static $nodeEvaluators;
27-
2822
/**
2923
* Compile an expression from a node into a value.
3024
*
@@ -36,63 +30,31 @@ class CompileNodeToValue
3630
*/
3731
public function __invoke(Node $node, CompilerContext $context)
3832
{
39-
if ($node instanceof Node\Scalar\String_
40-
|| $node instanceof Node\Scalar\DNumber
41-
|| $node instanceof Node\Scalar\LNumber) {
42-
return $node->value;
43-
}
44-
45-
// common edge case - negative numbers
46-
if ($node instanceof Node\Expr\UnaryMinus) {
47-
return $this($node->expr, $context) * -1;
48-
}
49-
50-
if ($node instanceof Node\Expr\Array_) {
51-
return $this->compileArray($node, $context);
52-
}
53-
54-
if ($node instanceof Node\Expr\ConstFetch) {
55-
return $this->compileConstFetch($node);
56-
}
57-
58-
if ($node instanceof Node\Expr\ClassConstFetch) {
59-
return $this->compileClassConstFetch($node, $context);
60-
}
61-
62-
if ($node instanceof Node\Expr\BinaryOp) {
63-
return $this->compileBinaryOperator($node, $context);
64-
}
65-
66-
if ($node instanceof Node\Scalar\MagicConst\Dir) {
67-
return $this->compileDirConstant($context);
33+
if ($node instanceof Node\Stmt\Expression) {
34+
return $this($node->expr, $context);
6835
}
6936

70-
if ($node instanceof Node\Scalar\MagicConst\Class_) {
71-
return $this->compileClassConstant($context);
72-
}
37+
$constExprEvaluator = new ConstExprEvaluator(function (Node\Expr $node) use ($context) {
38+
if ($node instanceof Node\Expr\ConstFetch) {
39+
return $this->compileConstFetch($node);
40+
}
7341

74-
throw new Exception\UnableToCompileNode('Unable to compile expression: ' . get_class($node));
75-
}
42+
if ($node instanceof Node\Expr\ClassConstFetch) {
43+
return $this->compileClassConstFetch($node, $context);
44+
}
7645

77-
/**
78-
* Compile arrays
79-
*
80-
* @return mixed[]
81-
*/
82-
private function compileArray(Node\Expr\Array_ $arrayNode, CompilerContext $context) : array
83-
{
84-
$compiledArray = [];
85-
foreach ($arrayNode->items as $arrayItem) {
86-
$compiledValue = $this($arrayItem->value, $context);
46+
if ($node instanceof Node\Scalar\MagicConst\Dir) {
47+
return $this->compileDirConstant($context);
48+
}
8749

88-
if ($arrayItem->key === null) {
89-
$compiledArray[] = $compiledValue;
90-
continue;
50+
if ($node instanceof Node\Scalar\MagicConst\Class_) {
51+
return $this->compileClassConstant($context);
9152
}
9253

93-
$compiledArray[$this($arrayItem->key, $context)] = $compiledValue;
94-
}
95-
return $compiledArray;
54+
throw new Exception\UnableToCompileNode('Unable to compile expression: ' . get_class($node));
55+
});
56+
57+
return $constExprEvaluator->evaluateDirectly($node);
9658
}
9759

9860
/**
@@ -131,7 +93,7 @@ private function compileConstFetch(Node\Expr\ConstFetch $constNode)
13193
private function compileClassConstFetch(Node\Expr\ClassConstFetch $node, CompilerContext $context)
13294
{
13395
/** @var string $nodeName */
134-
$nodeName = $node->name;
96+
$nodeName = $node->name->name;
13597
$className = $node->class->toString();
13698

13799
if ($nodeName === 'class') {
@@ -158,30 +120,6 @@ private function compileClassConstFetch(Node\Expr\ClassConstFetch $node, Compile
158120
);
159121
}
160122

161-
/**
162-
* Compile a binary operator node
163-
*
164-
*
165-
* @return mixed
166-
*
167-
* @throws UnableToCompileNode
168-
*/
169-
private function compileBinaryOperator(Node\Expr\BinaryOp $node, CompilerContext $context)
170-
{
171-
$evaluators = self::loadEvaluators();
172-
$nodeClass = get_class($node);
173-
174-
if (! isset($evaluators[$nodeClass])) {
175-
throw new Exception\UnableToCompileNode(sprintf(
176-
'Unable to compile binary operator: %s',
177-
$nodeClass
178-
));
179-
}
180-
181-
// Welcome to method overloading implemented PHP-style. Yay?
182-
return $evaluators[$nodeClass]($node, $context, $this);
183-
}
184-
185123
/**
186124
* Compile a __DIR__ node
187125
*/
@@ -208,122 +146,4 @@ private function getConstantDeclaringClass(string $constantName, ReflectionClass
208146

209147
return $parentClass ? $this->getConstantDeclaringClass($constantName, $parentClass) : null;
210148
}
211-
212-
/**
213-
* @return callable[] indexed by node class name
214-
*/
215-
private static function loadEvaluators() : array
216-
{
217-
if (self::$nodeEvaluators) {
218-
return self::$nodeEvaluators;
219-
}
220-
221-
$evaluators = self::makeEvaluators();
222-
223-
return self::$nodeEvaluators = array_combine(
224-
array_map(function (callable $nodeEvaluator) : string {
225-
/** @noinspection ExceptionsAnnotatingAndHandlingInspection */
226-
/** @noinspection NullPointerExceptionInspection */
227-
return (new ReflectionFunction($nodeEvaluator))->getParameters()[0]->getType()->getName();
228-
}, $evaluators),
229-
$evaluators
230-
);
231-
}
232-
233-
/**
234-
* @return callable[]
235-
*/
236-
private static function makeEvaluators() : array
237-
{
238-
return [
239-
function (Node\Expr\BinaryOp\Plus $node, CompilerContext $context, self $next) {
240-
return $next($node->left, $context) + $next($node->right, $context);
241-
},
242-
function (Node\Expr\BinaryOp\Mul $node, CompilerContext $context, self $next) {
243-
return $next($node->left, $context) * $next($node->right, $context);
244-
},
245-
function (Node\Expr\BinaryOp\Minus $node, CompilerContext $context, self $next) {
246-
return $next($node->left, $context) - $next($node->right, $context);
247-
},
248-
function (Node\Expr\BinaryOp\Div $node, CompilerContext $context, self $next) {
249-
return $next($node->left, $context) / $next($node->right, $context);
250-
},
251-
function (Node\Expr\BinaryOp\Concat $node, CompilerContext $context, self $next) {
252-
return $next($node->left, $context) . $next($node->right, $context);
253-
},
254-
function (Node\Expr\BinaryOp\BooleanAnd $node, CompilerContext $context, self $next) {
255-
return $next($node->left, $context) && $next($node->right, $context);
256-
},
257-
function (Node\Expr\BinaryOp\BooleanOr $node, CompilerContext $context, self $next) {
258-
return $next($node->left, $context) || $next($node->right, $context);
259-
},
260-
function (Node\Expr\BinaryOp\BitwiseAnd $node, CompilerContext $context, self $next) {
261-
return $next($node->left, $context) & $next($node->right, $context);
262-
},
263-
function (Node\Expr\BinaryOp\BitwiseOr $node, CompilerContext $context, self $next) {
264-
return $next($node->left, $context) | $next($node->right, $context);
265-
},
266-
function (Node\Expr\BinaryOp\BitwiseXor $node, CompilerContext $context, self $next) {
267-
return $next($node->left, $context) ^ $next($node->right, $context);
268-
},
269-
function (Node\Expr\BinaryOp\Equal $node, CompilerContext $context, self $next) {
270-
/** @noinspection TypeUnsafeComparisonInspection */
271-
// phpcs:disable SlevomatCodingStandard.ControlStructures.DisallowEqualOperators
272-
return $next($node->left, $context) == $next($node->right, $context);
273-
// phpcs:enable
274-
},
275-
function (Node\Expr\BinaryOp\Greater $node, CompilerContext $context, self $next) {
276-
return $next($node->left, $context) > $next($node->right, $context);
277-
},
278-
function (Node\Expr\BinaryOp\GreaterOrEqual $node, CompilerContext $context, self $next) {
279-
return $next($node->left, $context) >= $next($node->right, $context);
280-
},
281-
function (Node\Expr\BinaryOp\Identical $node, CompilerContext $context, self $next) {
282-
return $next($node->left, $context) === $next($node->right, $context);
283-
},
284-
function (Node\Expr\BinaryOp\LogicalAnd $node, CompilerContext $context, self $next) {
285-
// phpcs:disable Squiz.Operators.ValidLogicalOperators.NotAllowed
286-
return $next($node->left, $context) and $next($node->right, $context);
287-
// phpcs:enable
288-
},
289-
function (Node\Expr\BinaryOp\LogicalOr $node, CompilerContext $context, self $next) {
290-
// phpcs:disable Squiz.Operators.ValidLogicalOperators.NotAllowed
291-
return $next($node->left, $context) or $next($node->right, $context);
292-
// phpcs:enable
293-
},
294-
function (Node\Expr\BinaryOp\LogicalXor $node, CompilerContext $context, self $next) {
295-
return $next($node->left, $context) xor $next($node->right, $context);
296-
},
297-
function (Node\Expr\BinaryOp\Mod $node, CompilerContext $context, self $next) {
298-
return $next($node->left, $context) % $next($node->right, $context);
299-
},
300-
function (Node\Expr\BinaryOp\NotEqual $node, CompilerContext $context, self $next) {
301-
/** @noinspection TypeUnsafeComparisonInspection */
302-
// phpcs:disable SlevomatCodingStandard.ControlStructures.DisallowEqualOperators
303-
return $next($node->left, $context) != $next($node->right, $context);
304-
// phpcs:enable
305-
},
306-
function (Node\Expr\BinaryOp\NotIdentical $node, CompilerContext $context, self $next) {
307-
return $next($node->left, $context) !== $next($node->right, $context);
308-
},
309-
function (Node\Expr\BinaryOp\Pow $node, CompilerContext $context, self $next) {
310-
return $next($node->left, $context) ** $next($node->right, $context);
311-
},
312-
function (Node\Expr\BinaryOp\ShiftLeft $node, CompilerContext $context, self $next) {
313-
return $next($node->left, $context) << $next($node->right, $context);
314-
},
315-
function (Node\Expr\BinaryOp\ShiftRight $node, CompilerContext $context, self $next) {
316-
return $next($node->left, $context) >> $next($node->right, $context);
317-
},
318-
function (Node\Expr\BinaryOp\Smaller $node, CompilerContext $context, self $next) {
319-
return $next($node->left, $context) < $next($node->right, $context);
320-
},
321-
function (Node\Expr\BinaryOp\SmallerOrEqual $node, CompilerContext $context, self $next) {
322-
return $next($node->left, $context) <= $next($node->right, $context);
323-
},
324-
function (Node\Expr\BinaryOp\Spaceship $node, CompilerContext $context, self $next) {
325-
return $next($node->left, $context) <=> $next($node->right, $context);
326-
},
327-
];
328-
}
329149
}

src/Reflection/ReflectionClass.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public static function createFromNode(
166166
public function getShortName() : string
167167
{
168168
if (! $this->isAnonymous()) {
169-
return $this->node->name;
169+
return $this->node->name->name;
170170
}
171171

172172
$fileName = $this->getFileName();
@@ -745,15 +745,15 @@ public function getLocatedSource() : LocatedSource
745745
*/
746746
public function getStartLine() : int
747747
{
748-
return (int) $this->node->getAttribute('startLine', -1);
748+
return $this->node->getStartLine();
749749
}
750750

751751
/**
752752
* Get the line number that this class ends on.
753753
*/
754754
public function getEndLine() : int
755755
{
756-
return (int) $this->node->getAttribute('endLine', -1);
756+
return $this->node->getEndLine();
757757
}
758758

759759
public function getStartColumn() : int
@@ -973,7 +973,7 @@ public function getTraitAliases() : array
973973
continue;
974974
}
975975

976-
$resolvedAliases[$adaptation->newName] = sprintf(
976+
$resolvedAliases[$adaptation->newName->name] = sprintf(
977977
'%s::%s',
978978
$usedTrait->toString(),
979979
$adaptation->method
@@ -1321,7 +1321,7 @@ public function removeMethod(string $methodName) : bool
13211321
{
13221322
$lowerName = strtolower($methodName);
13231323
foreach ($this->node->stmts as $key => $stmt) {
1324-
if ($stmt instanceof ClassMethod && $lowerName === strtolower($stmt->name)) {
1324+
if ($stmt instanceof ClassMethod && $lowerName === $stmt->name->toLowerString()) {
13251325
unset($this->node->stmts[$key], $this->cachedMethods);
13261326
return true;
13271327
}
@@ -1383,7 +1383,7 @@ public function removeProperty(string $propertyName) : bool
13831383
}
13841384

13851385
$propertyNames = array_map(function (Node\Stmt\PropertyProperty $propertyProperty) : string {
1386-
return strtolower($propertyProperty->name);
1386+
return $propertyProperty->name->toLowerString();
13871387
}, $stmt->props);
13881388

13891389
if (in_array($lowerName, $propertyNames, true)) {

src/Reflection/ReflectionClassConstant.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public static function createFromNode(
6565
*/
6666
public function getName() : string
6767
{
68-
return $this->node->consts[$this->positionInNode]->name;
68+
return $this->node->consts[$this->positionInNode]->name->name;
6969
}
7070

7171
/**
@@ -128,15 +128,15 @@ public function getModifiers() : int
128128
*/
129129
public function getStartLine() : int
130130
{
131-
return (int) $this->node->getAttribute('startLine', -1);
131+
return $this->node->getStartLine();
132132
}
133133

134134
/**
135135
* Get the line number that this constant ends on.
136136
*/
137137
public function getEndLine() : int
138138
{
139-
return (int) $this->node->getAttribute('endLine', -1);
139+
return $this->node->getEndLine();
140140
}
141141

142142
public function getStartColumn() : int

0 commit comments

Comments
 (0)