My first commit of codes
This commit is contained in:
		
							
								
								
									
										129
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/AstAnalyzer.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/AstAnalyzer.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| <?php namespace SuperClosure\Analyzer; | ||||
|  | ||||
| use SuperClosure\Analyzer\Visitor\ThisDetectorVisitor; | ||||
| use SuperClosure\Exception\ClosureAnalysisException; | ||||
| use SuperClosure\Analyzer\Visitor\ClosureLocatorVisitor; | ||||
| use SuperClosure\Analyzer\Visitor\MagicConstantVisitor; | ||||
| use PhpParser\NodeTraverser; | ||||
| use PhpParser\PrettyPrinter\Standard as NodePrinter; | ||||
| use PhpParser\Error as ParserError; | ||||
| use PhpParser\NodeVisitor\NameResolver; | ||||
| use PhpParser\Parser as CodeParser; | ||||
| use PhpParser\Lexer\Emulative as EmulativeLexer; | ||||
|  | ||||
| /** | ||||
|  * This is the AST based analyzer. | ||||
|  * | ||||
|  * We're using reflection and AST-based code parser to analyze a closure and | ||||
|  * determine its code and context using the nikic/php-parser library. The AST | ||||
|  * based analyzer and has more capabilities than the token analyzer, but is, | ||||
|  * unfortunately, about 25 times slower. | ||||
|  */ | ||||
| class AstAnalyzer extends ClosureAnalyzer | ||||
| { | ||||
|     protected function determineCode(array &$data) | ||||
|     { | ||||
|         // Find the closure by traversing through a AST of the code. | ||||
|         // Note: This also resolves class names to their FQCNs while traversing. | ||||
|         $this->locateClosure($data); | ||||
|  | ||||
|         // Make a second pass through the AST, but only through the closure's | ||||
|         // nodes, to resolve any magic constants to literal values. | ||||
|         $traverser = new NodeTraverser; | ||||
|         $traverser->addVisitor(new MagicConstantVisitor($data['location'])); | ||||
|         $traverser->addVisitor($thisDetector = new ThisDetectorVisitor); | ||||
|         $data['ast'] = $traverser->traverse([$data['ast']])[0]; | ||||
|         $data['hasThis'] = $thisDetector->detected; | ||||
|  | ||||
|         // Bounce the updated AST down to a string representation of the code. | ||||
|         $data['code'] = (new NodePrinter)->prettyPrint([$data['ast']]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parses the closure's code and produces an abstract syntax tree (AST). | ||||
|      * | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @throws ClosureAnalysisException if there is an issue finding the closure | ||||
|      */ | ||||
|     private function locateClosure(array &$data) | ||||
|     { | ||||
|         try { | ||||
|             $locator = new ClosureLocatorVisitor($data['reflection']); | ||||
|             $fileAst = $this->getFileAst($data['reflection']); | ||||
|  | ||||
|             $fileTraverser = new NodeTraverser; | ||||
|             $fileTraverser->addVisitor(new NameResolver); | ||||
|             $fileTraverser->addVisitor($locator); | ||||
|             $fileTraverser->traverse($fileAst); | ||||
|         } catch (ParserError $e) { | ||||
|             // @codeCoverageIgnoreStart | ||||
|             throw new ClosureAnalysisException( | ||||
|                 'There was an error analyzing the closure code.', 0, $e | ||||
|             ); | ||||
|             // @codeCoverageIgnoreEnd | ||||
|         } | ||||
|  | ||||
|         $data['ast'] = $locator->closureNode; | ||||
|         if (!$data['ast']) { | ||||
|             // @codeCoverageIgnoreStart | ||||
|             throw new ClosureAnalysisException( | ||||
|                 'The closure was not found within the abstract syntax tree.' | ||||
|             ); | ||||
|             // @codeCoverageIgnoreEnd | ||||
|         } | ||||
|  | ||||
|         $data['location'] = $locator->location; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the variables that in the "use" clause of the closure definition. | ||||
|      * These are referred to as the "used variables", "static variables", or | ||||
|      * "closed upon variables", "context" of the closure. | ||||
|      * | ||||
|      * @param array $data | ||||
|      */ | ||||
|     protected function determineContext(array &$data) | ||||
|     { | ||||
|         // Get the variable names defined in the AST | ||||
|         $refs = 0; | ||||
|         $vars = array_map(function ($node) use (&$refs) { | ||||
|             if ($node->byRef) { | ||||
|                 $refs++; | ||||
|             } | ||||
|             return $node->var; | ||||
|         }, $data['ast']->uses); | ||||
|         $data['hasRefs'] = ($refs > 0); | ||||
|  | ||||
|         // Get the variable names and values using reflection | ||||
|         $values = $data['reflection']->getStaticVariables(); | ||||
|  | ||||
|         // Combine the names and values to create the canonical context. | ||||
|         foreach ($vars as $name) { | ||||
|             if (isset($values[$name])) { | ||||
|                 $data['context'][$name] = $values[$name]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param \ReflectionFunction $reflection | ||||
|      * | ||||
|      * @throws ClosureAnalysisException | ||||
|      * | ||||
|      * @return \PhpParser\Node[] | ||||
|      */ | ||||
|     private function getFileAst(\ReflectionFunction $reflection) | ||||
|     { | ||||
|         $fileName = $reflection->getFileName(); | ||||
|         if (!file_exists($fileName)) { | ||||
|             throw new ClosureAnalysisException( | ||||
|                 "The file containing the closure, \"{$fileName}\" did not exist." | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $parser = new CodeParser(new EmulativeLexer); | ||||
|  | ||||
|         return $parser->parse(file_get_contents($fileName)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										62
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/ClosureAnalyzer.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/ClosureAnalyzer.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| <?php namespace SuperClosure\Analyzer; | ||||
|  | ||||
| use SuperClosure\Exception\ClosureAnalysisException; | ||||
|  | ||||
| abstract class ClosureAnalyzer | ||||
| { | ||||
|     /** | ||||
|      * Analyzer a given closure. | ||||
|      * | ||||
|      * @param \Closure $closure | ||||
|      * | ||||
|      * @throws ClosureAnalysisException | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function analyze(\Closure $closure) | ||||
|     { | ||||
|         $data = [ | ||||
|             'reflection' => new \ReflectionFunction($closure), | ||||
|             'code'       => null, | ||||
|             'hasThis'    => false, | ||||
|             'context'    => [], | ||||
|             'hasRefs'    => false, | ||||
|             'binding'    => null, | ||||
|             'scope'      => null, | ||||
|             'isStatic'   => $this->isClosureStatic($closure), | ||||
|         ]; | ||||
|  | ||||
|         $this->determineCode($data); | ||||
|         $this->determineContext($data); | ||||
|         $this->determineBinding($data); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     abstract protected function determineCode(array &$data); | ||||
|  | ||||
|     /** | ||||
|      * Returns the variables that are in the "use" clause of the closure. | ||||
|      * | ||||
|      * These variables are referred to as the "used variables", "static | ||||
|      * variables", "closed upon variables", or "context" of the closure. | ||||
|      * | ||||
|      * @param array $data | ||||
|      */ | ||||
|     abstract protected function determineContext(array &$data); | ||||
|  | ||||
|     private function determineBinding(array &$data) | ||||
|     { | ||||
|         $data['binding'] = $data['reflection']->getClosureThis(); | ||||
|         if ($scope = $data['reflection']->getClosureScopeClass()) { | ||||
|             $data['scope'] = $scope->getName(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private function isClosureStatic(\Closure $closure) | ||||
|     { | ||||
|         $rebound = new \ReflectionFunction(@$closure->bindTo(new \stdClass)); | ||||
|  | ||||
|         return $rebound->getClosureThis() === null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										70
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/Token.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/Token.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| <?php namespace SuperClosure\Analyzer; | ||||
|  | ||||
| /** | ||||
|  * A Token object represents and individual token parsed from PHP code. | ||||
|  * | ||||
|  * Each Token object is a normalized token created from the result of the | ||||
|  * `get_token_all()`. function, which is part of PHP's tokenizer. | ||||
|  * | ||||
|  * @link http://us2.php.net/manual/en/tokens.php | ||||
|  */ | ||||
| class Token | ||||
| { | ||||
|     /** | ||||
|      * @var string The token name. Always null for literal tokens. | ||||
|      */ | ||||
|     public $name; | ||||
|  | ||||
|     /** | ||||
|      * @var int|null The token's integer value. Always null for literal tokens. | ||||
|      */ | ||||
|     public $value; | ||||
|  | ||||
|     /** | ||||
|      * @var string The PHP code of the token. | ||||
|      */ | ||||
|     public $code; | ||||
|  | ||||
|     /** | ||||
|      * @var int|null The line number of the token in the original code. | ||||
|      */ | ||||
|     public $line; | ||||
|  | ||||
|     /** | ||||
|      * Constructs a token object. | ||||
|      * | ||||
|      * @param string   $code | ||||
|      * @param int|null $value | ||||
|      * @param int|null $line | ||||
|      * | ||||
|      * @throws \InvalidArgumentException | ||||
|      */ | ||||
|     public function __construct($code, $value = null, $line = null) | ||||
|     { | ||||
|         if (is_array($code)) { | ||||
|             list($value, $code, $line) = array_pad($code, 3, null); | ||||
|         } | ||||
|  | ||||
|         $this->code = $code; | ||||
|         $this->value = $value; | ||||
|         $this->line = $line; | ||||
|         $this->name = $value ? token_name($value) : null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Determines if the token's value/code is equal to the specified value. | ||||
|      * | ||||
|      * @param mixed $value The value to check. | ||||
|      * | ||||
|      * @return bool True if the token is equal to the value. | ||||
|      */ | ||||
|     public function is($value) | ||||
|     { | ||||
|         return ($this->code === $value || $this->value === $value); | ||||
|     } | ||||
|  | ||||
|     public function __toString() | ||||
|     { | ||||
|         return $this->code; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										118
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/TokenAnalyzer.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/TokenAnalyzer.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| <?php namespace SuperClosure\Analyzer; | ||||
|  | ||||
| use SuperClosure\Exception\ClosureAnalysisException; | ||||
|  | ||||
| /** | ||||
|  * This is the token based analyzer. | ||||
|  * | ||||
|  * We're using Uses reflection and tokenization to analyze a closure and | ||||
|  * determine its code and context. This is much faster than the AST based | ||||
|  * implementation. | ||||
|  */ | ||||
| class TokenAnalyzer extends ClosureAnalyzer | ||||
| { | ||||
|     public function determineCode(array &$data) | ||||
|     { | ||||
|         $this->determineTokens($data); | ||||
|         $data['code'] = implode('', $data['tokens']); | ||||
|         $data['hasThis'] = (strpos($data['code'], '$this') !== false); | ||||
|     } | ||||
|  | ||||
|     private function determineTokens(array &$data) | ||||
|     { | ||||
|         $potential = $this->determinePotentialTokens($data['reflection']); | ||||
|         $braceLevel = $index = $step = $insideUse = 0; | ||||
|         $data['tokens'] = $data['context'] = []; | ||||
|  | ||||
|         foreach ($potential as $token) { | ||||
|             $token = new Token($token); | ||||
|             switch ($step) { | ||||
|                 // Handle tokens before the function declaration. | ||||
|                 case 0: | ||||
|                     if ($token->is(T_FUNCTION)) { | ||||
|                         $data['tokens'][] = $token; | ||||
|                         $step++; | ||||
|                     } | ||||
|                     break; | ||||
|                 // Handle tokens inside the function signature. | ||||
|                 case 1: | ||||
|                     $data['tokens'][] = $token; | ||||
|                     if ($insideUse) { | ||||
|                         if ($token->is(T_VARIABLE)) { | ||||
|                             $varName = trim($token, '$ '); | ||||
|                             $data['context'][$varName] = null; | ||||
|                         } elseif ($token->is('&')) { | ||||
|                             $data['hasRefs'] = true; | ||||
|                         } | ||||
|                     } elseif ($token->is(T_USE)) { | ||||
|                         $insideUse++; | ||||
|                     } | ||||
|                     if ($token->is('{')) { | ||||
|                         $step++; | ||||
|                         $braceLevel++; | ||||
|                     } | ||||
|                     break; | ||||
|                 // Handle tokens inside the function body. | ||||
|                 case 2: | ||||
|                     $data['tokens'][] = $token; | ||||
|                     if ($token->is('{')) { | ||||
|                         $braceLevel++; | ||||
|                     } elseif ($token->is('}')) { | ||||
|                         $braceLevel--; | ||||
|                         if ($braceLevel === 0) { | ||||
|                             $step++; | ||||
|                         } | ||||
|                     } | ||||
|                     break; | ||||
|                 // Handle tokens after the function declaration. | ||||
|                 case 3: | ||||
|                     if ($token->is(T_FUNCTION)) { | ||||
|                         throw new ClosureAnalysisException('Multiple closures ' | ||||
|                             . 'were declared on the same line of code. Could ' | ||||
|                             . 'determine which closure was the intended target.' | ||||
|                         ); | ||||
|                     } | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private function determinePotentialTokens(\ReflectionFunction $reflection) | ||||
|     { | ||||
|         // Load the file containing the code for the function. | ||||
|         $fileName = $reflection->getFileName(); | ||||
|         if (!is_readable($fileName)) { | ||||
|             throw new ClosureAnalysisException( | ||||
|                 "Cannot read the file containing the closure: \"{$fileName}\"." | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $code = ''; | ||||
|         $file = new \SplFileObject($fileName); | ||||
|         $file->seek($reflection->getStartLine() - 1); | ||||
|         while ($file->key() < $reflection->getEndLine()) { | ||||
|             $code .= $file->current(); | ||||
|             $file->next(); | ||||
|         } | ||||
|  | ||||
|         $code = trim($code); | ||||
|         if (strpos($code, '<?php') !== 0) { | ||||
|             $code = "<?php\n" . $code; | ||||
|         } | ||||
|  | ||||
|         return token_get_all($code); | ||||
|     } | ||||
|  | ||||
|     protected function determineContext(array &$data) | ||||
|     { | ||||
|         // Get the values of the variables that are closed upon in "use". | ||||
|         $values = $data['reflection']->getStaticVariables(); | ||||
|  | ||||
|         // Construct the context by combining the variable names and values. | ||||
|         foreach ($data['context'] as $name => &$value) { | ||||
|             if (isset($values[$name])) { | ||||
|                 $value = $values[$name]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										117
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/Visitor/ClosureLocatorVisitor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/Visitor/ClosureLocatorVisitor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| <?php namespace SuperClosure\Analyzer\Visitor; | ||||
|  | ||||
| use SuperClosure\Exception\ClosureAnalysisException; | ||||
| use PhpParser\Node\Stmt\Namespace_ as NamespaceNode; | ||||
| use PhpParser\Node\Stmt\Trait_ as TraitNode; | ||||
| use PhpParser\Node\Stmt\Class_ as ClassNode; | ||||
| use PhpParser\Node\Expr\Closure as ClosureNode; | ||||
| use PhpParser\Node as AstNode; | ||||
| use PhpParser\NodeVisitorAbstract as NodeVisitor; | ||||
|  | ||||
| /** | ||||
|  * This is a visitor that extends the nikic/php-parser library and looks for a | ||||
|  * closure node and its location. | ||||
|  * | ||||
|  * @internal | ||||
|  */ | ||||
| final class ClosureLocatorVisitor extends NodeVisitor | ||||
| { | ||||
|     /** | ||||
|      * @var \ReflectionFunction | ||||
|      */ | ||||
|     private $reflection; | ||||
|  | ||||
|     /** | ||||
|      * @var ClosureNode | ||||
|      */ | ||||
|     public $closureNode; | ||||
|  | ||||
|     /** | ||||
|      * @var array | ||||
|      */ | ||||
|     public $location; | ||||
|  | ||||
|     /** | ||||
|      * @param \ReflectionFunction $reflection | ||||
|      */ | ||||
|     public function __construct($reflection) | ||||
|     { | ||||
|         $this->reflection = $reflection; | ||||
|         $this->location = [ | ||||
|             'class'     => null, | ||||
|             'directory' => dirname($this->reflection->getFileName()), | ||||
|             'file'      => $this->reflection->getFileName(), | ||||
|             'function'  => $this->reflection->getName(), | ||||
|             'line'      => $this->reflection->getStartLine(), | ||||
|             'method'    => null, | ||||
|             'namespace' => null, | ||||
|             'trait'     => null, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     public function enterNode(AstNode $node) | ||||
|     { | ||||
|         // Determine information about the closure's location | ||||
|         if (!$this->closureNode) { | ||||
|             if ($node instanceof NamespaceNode) { | ||||
|                 $namespace = ($node->name && is_array($node->name->parts)) | ||||
|                     ? implode('\\', $node->name->parts) | ||||
|                     : null; | ||||
|                 $this->location['namespace'] = $namespace; | ||||
|             } | ||||
|             if ($node instanceof TraitNode) { | ||||
|                 $this->location['trait'] = $node->name; | ||||
|                 $this->location['class'] = null; | ||||
|             } elseif ($node instanceof ClassNode) { | ||||
|                 $this->location['class'] = $node->name; | ||||
|                 $this->location['trait'] = null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Locate the node of the closure | ||||
|         if ($node instanceof ClosureNode) { | ||||
|             if ($node->getAttribute('startLine') == $this->location['line']) { | ||||
|                 if ($this->closureNode) { | ||||
|                     $line = $this->location['file'] . ':' . $node->getAttribute('startLine'); | ||||
|                     throw new ClosureAnalysisException("Two closures were " | ||||
|                         . "declared on the same line ({$line}) of code. Cannot " | ||||
|                         . "determine which closure was the intended target."); | ||||
|                 } else { | ||||
|                     $this->closureNode = $node; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function leaveNode(AstNode $node) | ||||
|     { | ||||
|         // Determine information about the closure's location | ||||
|         if (!$this->closureNode) { | ||||
|             if ($node instanceof NamespaceNode) { | ||||
|                 $this->location['namespace'] = null; | ||||
|             } | ||||
|             if ($node instanceof TraitNode) { | ||||
|                 $this->location['trait'] = null; | ||||
|             } elseif ($node instanceof ClassNode) { | ||||
|                 $this->location['class'] = null; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function afterTraverse(array $nodes) | ||||
|     { | ||||
|         if ($this->location['class']) { | ||||
|             $this->location['class'] = $this->location['namespace'] . '\\' . $this->location['class']; | ||||
|             $this->location['method'] = "{$this->location['class']}::{$this->location['function']}"; | ||||
|         } elseif ($this->location['trait']) { | ||||
|             $this->location['trait'] = $this->location['namespace'] . '\\' . $this->location['trait']; | ||||
|             $this->location['method'] = "{$this->location['trait']}::{$this->location['function']}"; | ||||
|         } | ||||
|  | ||||
|         if (!$this->location['class']) { | ||||
|             /** @var \ReflectionClass $closureScopeClass */ | ||||
|             $closureScopeClass = $this->reflection->getClosureScopeClass(); | ||||
|             $this->location['class'] = $closureScopeClass ? $closureScopeClass->getName() : null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										50
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/Visitor/MagicConstantVisitor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/Visitor/MagicConstantVisitor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| <?php namespace SuperClosure\Analyzer\Visitor; | ||||
|  | ||||
| use PhpParser\Node\Scalar\LNumber as NumberNode; | ||||
| use PhpParser\Node\Scalar\String as StringNode; | ||||
| use PhpParser\Node as AstNode; | ||||
| use PhpParser\NodeVisitorAbstract as NodeVisitor; | ||||
|  | ||||
| /** | ||||
|  * This is a visitor that resolves magic constants (e.g., __FILE__) to their | ||||
|  * intended values within a closure's AST. | ||||
|  * | ||||
|  * @internal | ||||
|  */ | ||||
| final class MagicConstantVisitor extends NodeVisitor | ||||
| { | ||||
|     /** | ||||
|      * @var array | ||||
|      */ | ||||
|     private $location; | ||||
|  | ||||
|     /** | ||||
|      * @param array $location | ||||
|      */ | ||||
|     public function __construct(array $location) | ||||
|     { | ||||
|         $this->location = $location; | ||||
|     } | ||||
|  | ||||
|     public function leaveNode(AstNode $node) | ||||
|     { | ||||
|         switch ($node->getType()) { | ||||
|             case 'Scalar_MagicConst_Class' : | ||||
|                 return new StringNode($this->location['class']); | ||||
|             case 'Scalar_MagicConst_Dir' : | ||||
|                 return new StringNode($this->location['directory']); | ||||
|             case 'Scalar_MagicConst_File' : | ||||
|                 return new StringNode($this->location['file']); | ||||
|             case 'Scalar_MagicConst_Function' : | ||||
|                 return new StringNode($this->location['function']); | ||||
|             case 'Scalar_MagicConst_Line' : | ||||
|                 return new NumberNode($node->getAttribute('startLine')); | ||||
|             case 'Scalar_MagicConst_Method' : | ||||
|                 return new StringNode($this->location['method']); | ||||
|             case 'Scalar_MagicConst_Namespace' : | ||||
|                 return new StringNode($this->location['namespace']); | ||||
|             case 'Scalar_MagicConst_Trait' : | ||||
|                 return new StringNode($this->location['trait']); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										27
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/Visitor/ThisDetectorVisitor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/jeremeamia/SuperClosure/src/Analyzer/Visitor/ThisDetectorVisitor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| <?php namespace SuperClosure\Analyzer\Visitor; | ||||
|  | ||||
| use PhpParser\Node as AstNode; | ||||
| use PhpParser\Node\Expr\Variable as VariableNode; | ||||
| use PhpParser\NodeVisitorAbstract as NodeVisitor; | ||||
|  | ||||
| /** | ||||
|  * Detects if the closure's AST contains a $this variable. | ||||
|  * | ||||
|  * @internal | ||||
|  */ | ||||
| final class ThisDetectorVisitor extends NodeVisitor | ||||
| { | ||||
|     /** | ||||
|      * @var bool | ||||
|      */ | ||||
|     public $detected = false; | ||||
|  | ||||
|     public function leaveNode(AstNode $node) | ||||
|     { | ||||
|         if ($node instanceof VariableNode) { | ||||
|             if ($node->name === 'this') { | ||||
|                 $this->detected = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 sujitprasad
					sujitprasad