*/ class Reader { /** * @var Namespace_[] Collection of definitions in snippet */ private $defs = []; /** * @var string[] Case sensitive definition names */ private $names = []; /** * @var \PhpParser\Node[] The global statement object */ private $global; /** * Optionally inject parser * * @param string $snippet * @param Parser $parser * @throws ReaderException If snippet contains a syntax error */ public function __construct($snippet, Parser $parser = null) { if (is_null($parser)) { $parserFactory = new ParserFactory(); $parser = $parserFactory->create(ParserFactory::PREFER_PHP5); } try { $this->global = $parser->parse($snippet); } catch (\PhpParser\Error $exception) { throw new ReaderException($exception->getRawMessage() . ' on line ' . $exception->getStartLine()); } $this->findDefinitions($this->global, new Name('')); } /** * Find class, interface and trait definitions in statemnts * * @param array $stmts * @param Name $namespace * @return void */ private function findDefinitions(array $stmts, Name $namespace) { $useStmts = []; foreach ($stmts as $stmt) { // Restart if namespace statement is found if ($stmt instanceof Namespace_) { $this->findDefinitions($stmt->stmts, new Name((string)$stmt->name)); // Save use statement } elseif ($stmt instanceof Use_) { $useStmts[] = $stmt; // Save classes, interfaces and traits } elseif ($stmt instanceof Class_ or $stmt instanceof Interface_ or $stmt instanceof Trait_) { $defName = new Name("{$namespace}\\{$stmt->name}"); $this->names[$defName->keyize()] = $defName->normalize(); $this->defs[$defName->keyize()] = new Namespace_( $namespace->normalize() ? $namespace->createNode() : null, $useStmts ); $this->defs[$defName->keyize()]->stmts[] = $stmt; } } } /** * Get names of definitions in snippet * * @return string[] */ public function getDefinitionNames() { return array_values($this->names); } /** * Check if snippet contains definition * * @param string $name Fully qualified name * @return boolean */ public function hasDefinition($name) { return isset($this->defs[(new Name($name))->keyize()]); } /** * Get pars tree for class/interface/trait * * @param string $name Name of class/interface/trait * @return Namespace_[] * @throws RuntimeException If $name does not exist */ public function read($name) { if (!$this->hasDefinition($name)) { throw new RuntimeException("Unable to read <$name>, not found."); } return [$this->defs[(new Name($name))->keyize()]]; } /** * Get parse tree for the complete snippet * * @return PhpParser\Node[] */ public function readAll() { return $this->global; } }