private function getUseImports(ReflectionClass $class) { if (isset($this->useImports[$class->class])) { return $this->useImports[$class->class]; } $content = file_get_contents($class->path); $tokenizer = new TokenParser('<?php ' . $content); $useImports = $tokenizer->parseUseStatements($class->namespace); $this->useImports[$class->class] = $useImports; return $useImports; }
/** * {@inheritdoc} */ public function process($context, Result $result, Collection $collection) { $this->result = $result; $this->collection = $collection; $this->docParser = new DocParser(); $this->docParser->setIgnoreNotImportedAnnotations(true); $phpdoc = $namespace = false; $tokenParser = new TokenParser($context->getFileContent()); while ($token = $tokenParser->next(false)) { if (false === is_array($token)) { continue; } switch ($token[0]) { case T_DOC_COMMENT: if ($phpdoc !== false) { $this->processDocComment($phpdoc); $phpdoc = false; } $phpdoc = $token[1]; break; case T_NAMESPACE: $namespace = $tokenParser->parseNamespace(); break; case T_USE: // add imports to doc parser to be able to use annotation without FQCN. foreach ($tokenParser->parseUseStatement() as $alias => $target) { if ($target[0] === '\\') { $target = substr($target, 1); } $imports[$alias] = $target; } $this->docParser->setImports($imports); break; case T_CLASS: $token = $tokenParser->next(false); $class = $namespace ? $namespace . '\\' . $token[1] : $token[1]; $this->dispatchEvent(Events::TOKEN_PHP_CLASS, new Context\PHP\PHPClass($class, $phpdoc), $phpdoc); break; case T_VARIABLE: $this->dispatchEvent(Events::TOKEN_PHP_VARIABLE, new Context\PHP\PHPVariable(substr($token[1], 1), isset($class) ? $class : null, $phpdoc), $phpdoc); break; case T_FUNCTION: $token = $tokenParser->next(false); if (!is_array($token)) { continue; } $this->dispatchEvent(Events::TOKEN_PHP_FUNCTION, new Context\PHP\PHPFunction($token[1], isset($class) ? $class : null, $phpdoc), $phpdoc); break; } } }
/** * Parses a class. * * @param \ReflectionClass $class A <code>ReflectionClass</code> object. * @return array A list with use statements in the form (Alias => FQN). */ public function parseClass(\ReflectionClass $class) { if (method_exists($class, 'getUseStatements')) { return $class->getUseStatements(); } if (false === ($filename = $class->getFilename())) { return array(); } $content = $this->getFileContent($filename, $class->getStartLine()); $namespace = str_replace('\\', '\\\\', $class->getNamespaceName()); $content = preg_replace('/^.*?(\\bnamespace\\s+' . $namespace . '\\s*[;{].*)$/s', '\\1', $content); $tokenizer = new TokenParser('<?php ' . $content); $statements = $tokenizer->parseUseStatements($class->getNamespaceName()); return $statements; }
/** * Class constructor. * * @param \Reflector $context A reflection of the context in which the types will be resolved. * The context can be a class, property, method or parameter. * * @throws \InvalidArgumentException If the class or file name cannot be inferred from the context. */ public function __construct(\Reflector $context) { $class = $this->getDeclaringClass($context); if ($class === null) { throw $this->invalidArgumentException('declaring class', $context); } $fileName = $class->getFileName(); if ($fileName === false) { throw $this->invalidArgumentException('file name', $context); } $source = @file_get_contents($fileName); if ($source === false) { throw new \RuntimeException('Could not read ' . $fileName); } $parser = new TokenParser($source); $this->namespace = $class->getNamespaceName(); $this->aliases = $parser->parseUseStatements($this->namespace); }
/** * @return void */ protected function parse() { if ($this->parsed || !($fileName = $this->finder->findFile($this->className))) { return; } $this->parsed = true; $contents = file_get_contents($fileName); if ($this->classAnnotationOptimize) { if (preg_match("/\\A.*^\\s*((abstract|final)\\s+)?class\\s+{$this->shortClassName}\\s+/sm", $contents, $matches)) { $contents = $matches[0]; } } $tokenParser = new TokenParser($contents); $docComment = ''; while ($token = $tokenParser->next(false)) { if (is_array($token)) { switch ($token[0]) { case T_USE: $this->useStatements = array_merge($this->useStatements, $tokenParser->parseUseStatement()); break; case T_DOC_COMMENT: $docComment = $token[1]; break; case T_CLASS: $this->docComment['class'] = $docComment; $docComment = ''; break; case T_VAR: case T_PRIVATE: case T_PROTECTED: case T_PUBLIC: $token = $tokenParser->next(); if ($token[0] === T_VARIABLE) { $propertyName = substr($token[1], 1); $this->docComment['property'][$propertyName] = $docComment; continue 2; } if ($token[0] !== T_FUNCTION) { // For example, it can be T_FINAL. continue 2; } // No break. // No break. case T_FUNCTION: // The next string after function is the name, but // there can be & before the function name so find the // string. while (($token = $tokenParser->next()) && $token[0] !== T_STRING) { } $methodName = $token[1]; $this->docComment['method'][$methodName] = $docComment; $docComment = ''; break; case T_EXTENDS: $this->parentClassName = $tokenParser->parseClass(); $nsPos = strpos($this->parentClassName, '\\'); $fullySpecified = false; if ($nsPos === 0) { $fullySpecified = true; } else { if ($nsPos) { $prefix = strtolower(substr($this->parentClassName, 0, $nsPos)); $postfix = substr($this->parentClassName, $nsPos); } else { $prefix = strtolower($this->parentClassName); $postfix = ''; } foreach ($this->useStatements as $alias => $use) { if ($alias == $prefix) { $this->parentClassName = '\\' . $use . $postfix; $fullySpecified = true; } } } if (!$fullySpecified) { $this->parentClassName = '\\' . $this->namespace . '\\' . $this->parentClassName; } break; } } } }
/** * @param mixed $value * @param array $annotations * @param ReflectionClass $reflection * * @return object */ protected static function parseAnnotation($value, array $annotations, ReflectionClass $reflection) { if (null !== $value && !empty($annotations)) { $tokenParse = new TokenParser(file_get_contents($reflection->getFileName())); $useStatements = $tokenParse->parseUseStatements($reflection->getNamespaceName()); foreach ($annotations as $annotation) { if (false !== strrpos($annotation, 'var')) { $class = trim(str_replace('var ', '', $annotation)); if (class_exists($class)) { $value = static::deserializeValue($class, $value); } elseif (class_exists(sprintf('%s\\%s', $reflection->getNamespaceName(), $class))) { $class = sprintf('%s\\%s', $reflection->getNamespaceName(), $class); $value = static::deserializeValue($class, $value); } elseif (isset($useStatements[strtolower($class)])) { $class = $useStatements[strtolower($class)]; $value = static::deserializeValue($class, $value); } break; } } } return $value; }