Mercurial > hg > cmmr2012-drupal-site
comparison vendor/psy/psysh/src/Command/TimeitCommand/TimeitVisitor.php @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children | a9cd425dd02b |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c75dbcec494b |
---|---|
1 <?php | |
2 | |
3 /* | |
4 * This file is part of Psy Shell. | |
5 * | |
6 * (c) 2012-2018 Justin Hileman | |
7 * | |
8 * For the full copyright and license information, please view the LICENSE | |
9 * file that was distributed with this source code. | |
10 */ | |
11 | |
12 namespace Psy\Command\TimeitCommand; | |
13 | |
14 use PhpParser\Node; | |
15 use PhpParser\Node\Arg; | |
16 use PhpParser\Node\Expr; | |
17 use PhpParser\Node\Expr\StaticCall; | |
18 use PhpParser\Node\FunctionLike; | |
19 use PhpParser\Node\Name\FullyQualified as FullyQualifiedName; | |
20 use PhpParser\Node\Stmt\Expression; | |
21 use PhpParser\Node\Stmt\Return_; | |
22 use PhpParser\NodeVisitorAbstract; | |
23 use Psy\CodeCleaner\NoReturnValue; | |
24 | |
25 /** | |
26 * A node visitor for instrumenting code to be executed by the `timeit` command. | |
27 * | |
28 * Injects `TimeitCommand::markStart()` at the start of code to be executed, and | |
29 * `TimeitCommand::markEnd()` at the end, and on top-level return statements. | |
30 */ | |
31 class TimeitVisitor extends NodeVisitorAbstract | |
32 { | |
33 private $functionDepth; | |
34 | |
35 /** | |
36 * {@inheritdoc} | |
37 */ | |
38 public function beforeTraverse(array $nodes) | |
39 { | |
40 $this->functionDepth = 0; | |
41 } | |
42 | |
43 /** | |
44 * {@inheritdoc} | |
45 */ | |
46 public function enterNode(Node $node) | |
47 { | |
48 // keep track of nested function-like nodes, because they can have | |
49 // returns statements... and we don't want to call markEnd for those. | |
50 if ($node instanceof FunctionLike) { | |
51 $this->functionDepth++; | |
52 | |
53 return; | |
54 } | |
55 | |
56 // replace any top-level `return` statements with a `markEnd` call | |
57 if ($this->functionDepth === 0 && $node instanceof Return_) { | |
58 return new Return_($this->getEndCall($node->expr), $node->getAttributes()); | |
59 } | |
60 } | |
61 | |
62 /** | |
63 * {@inheritdoc} | |
64 */ | |
65 public function leaveNode(Node $node) | |
66 { | |
67 if ($node instanceof FunctionLike) { | |
68 $this->functionDepth--; | |
69 } | |
70 } | |
71 | |
72 /** | |
73 * {@inheritdoc} | |
74 */ | |
75 public function afterTraverse(array $nodes) | |
76 { | |
77 // prepend a `markStart` call | |
78 array_unshift($nodes, $this->maybeExpression($this->getStartCall())); | |
79 | |
80 // append a `markEnd` call (wrapping the final node, if it's an expression) | |
81 $last = $nodes[count($nodes) - 1]; | |
82 if ($last instanceof Expr) { | |
83 array_pop($nodes); | |
84 $nodes[] = $this->getEndCall($last); | |
85 } elseif ($last instanceof Expression) { | |
86 array_pop($nodes); | |
87 $nodes[] = new Expression($this->getEndCall($last->expr), $last->getAttributes()); | |
88 } elseif ($last instanceof Return_) { | |
89 // nothing to do here, we're already ending with a return call | |
90 } else { | |
91 $nodes[] = $this->maybeExpression($this->getEndCall()); | |
92 } | |
93 | |
94 return $nodes; | |
95 } | |
96 | |
97 /** | |
98 * Get PhpParser AST nodes for a `markStart` call. | |
99 * | |
100 * @return PhpParser\Node\Expr\StaticCall | |
101 */ | |
102 private function getStartCall() | |
103 { | |
104 return new StaticCall(new FullyQualifiedName('Psy\Command\TimeitCommand'), 'markStart'); | |
105 } | |
106 | |
107 /** | |
108 * Get PhpParser AST nodes for a `markEnd` call. | |
109 * | |
110 * Optionally pass in a return value. | |
111 * | |
112 * @param Expr|null $arg | |
113 * | |
114 * @return PhpParser\Node\Expr\StaticCall | |
115 */ | |
116 private function getEndCall(Expr $arg = null) | |
117 { | |
118 if ($arg === null) { | |
119 $arg = NoReturnValue::create(); | |
120 } | |
121 | |
122 return new StaticCall(new FullyQualifiedName('Psy\Command\TimeitCommand'), 'markEnd', [new Arg($arg)]); | |
123 } | |
124 | |
125 /** | |
126 * Compatibility shim for PHP Parser 3.x. | |
127 * | |
128 * Wrap $expr in a PhpParser\Node\Stmt\Expression if the class exists. | |
129 * | |
130 * @param PhpParser\Node $expr | |
131 * @param array $attrs | |
132 * | |
133 * @return PhpParser\Node\Expr|PhpParser\Node\Stmt\Expression | |
134 */ | |
135 private function maybeExpression($expr, $attrs = []) | |
136 { | |
137 return class_exists('PhpParser\Node\Stmt\Expression') ? new Expression($expr, $attrs) : $expr; | |
138 } | |
139 } |