/** * Creates a function code from Reflection * * @param ParsedFunction $function Reflection for function * @param string $body Body of function * * @return string */ protected function getOverriddenFunction($function, $body) { static $inMemoryCache = array(); $functionName = $function->getName(); if (isset($inMemoryCache[$functionName])) { return $inMemoryCache[$functionName]; } $code = preg_replace('/ {4}|\\t/', '', $function->getDocComment()) . "\n" . 'function ' . ($function->returnsReference() ? '&' : '') . $functionName . '(' . join(', ', $this->getParameters($function->getParameters())) . ")\n" . "{\n" . $this->indent($body) . "\n" . "}\n"; $inMemoryCache[$functionName] = $code; return $code; }
/** * Parses child reflection objects from the token stream. * * @param \TokenReflection\Stream\StreamBase $tokenStream Token substream * @param \TokenReflection\IReflection $parent Parent reflection object * @return \TokenReflection\ReflectionFileNamespace * @throws \TokenReflection\Exception\ParseException If child elements could not be parsed. */ protected function parseChildren(Stream $tokenStream, IReflection $parent) { static $skipped = array(T_WHITESPACE => true, T_COMMENT => true, T_DOC_COMMENT => true); $depth = 0; $firstChild = null; while (true) { switch ($tokenStream->getType()) { case T_USE: while (true) { $namespaceName = ''; $alias = null; $tokenStream->skipWhitespaces(true); while (true) { switch ($tokenStream->getType()) { case T_STRING: case T_NS_SEPARATOR: $namespaceName .= $tokenStream->getTokenValue(); break; case T_FUNCTION: // "use function" in 5.6+ break; default: break 2; } $tokenStream->skipWhitespaces(true); } $namespaceName = ltrim($namespaceName, '\\'); if (empty($namespaceName)) { throw new Exception\ParseException($this, $tokenStream, 'Imported namespace name could not be determined.', Exception\ParseException::LOGICAL_ERROR); } elseif ('\\' === substr($namespaceName, -1)) { throw new Exception\ParseException($this, $tokenStream, sprintf('Invalid namespace name "%s".', $namespaceName), Exception\ParseException::LOGICAL_ERROR); } if ($tokenStream->is(T_AS)) { // Alias defined $tokenStream->skipWhitespaces(true); if (!$tokenStream->is(T_STRING)) { throw new Exception\ParseException($this, $tokenStream, sprintf('The imported namespace "%s" seems aliased but the alias name could not be determined.', $namespaceName), Exception\ParseException::LOGICAL_ERROR); } $alias = $tokenStream->getTokenValue(); $tokenStream->skipWhitespaces(true); } else { // No explicit alias if (false !== ($pos = strrpos($namespaceName, '\\'))) { $alias = substr($namespaceName, $pos + 1); } else { $alias = $namespaceName; } } if (isset($this->aliases[$alias])) { throw new Exception\ParseException($this, $tokenStream, sprintf('Namespace alias "%s" already defined.', $alias), Exception\ParseException::LOGICAL_ERROR); } $this->aliases[$alias] = $namespaceName; $type = $tokenStream->getType(); if (';' === $type) { $tokenStream->skipWhitespaces(); break 2; } elseif (',' === $type) { // Next namespace in the current "use" definition continue; } throw new Exception\ParseException($this, $tokenStream, 'Unexpected token found.', Exception\ParseException::UNEXPECTED_TOKEN); } case T_COMMENT: case T_DOC_COMMENT: $docblock = $tokenStream->getTokenValue(); if (preg_match('~^' . preg_quote(self::DOCBLOCK_TEMPLATE_START, '~') . '~', $docblock)) { array_unshift($this->docblockTemplates, new ReflectionAnnotation($this, $docblock)); } elseif (self::DOCBLOCK_TEMPLATE_END === $docblock) { array_shift($this->docblockTemplates); } $tokenStream->next(); break; case '{': $tokenStream->next(); $depth++; break; case '}': if (0 === $depth--) { break 2; } $tokenStream->next(); break; case null: case T_NAMESPACE: break 2; case T_ABSTRACT: case T_FINAL: case T_CLASS: case T_TRAIT: case T_INTERFACE: $class = new ReflectionClass($tokenStream, $this->getBroker(), $this); $firstChild = $firstChild ?: $class; $className = $class->getName(); if (isset($this->classes[$className])) { if (!$this->classes[$className] instanceof Invalid\ReflectionClass) { $this->classes[$className] = new Invalid\ReflectionClass($className, $this->classes[$className]->getFileName(), $this->getBroker()); } if (!$this->classes[$className]->hasReasons()) { $this->classes[$className]->addReason(new Exception\ParseException($this, $tokenStream, sprintf('Class %s is defined multiple times in the file.', $className), Exception\ParseException::ALREADY_EXISTS)); } } else { $this->classes[$className] = $class; } $tokenStream->next(); break; case T_CONST: $tokenStream->skipWhitespaces(true); do { $constant = new ReflectionConstant($tokenStream, $this->getBroker(), $this); $firstChild = $firstChild ?: $constant; $constantName = $constant->getName(); if (isset($this->constants[$constantName])) { if (!$this->constants[$constantName] instanceof Invalid\ReflectionConstant) { $this->constants[$constantName] = new Invalid\ReflectionConstant($constantName, $this->constants[$constantName]->getFileName(), $this->getBroker()); } if (!$this->constants[$constantName]->hasReasons()) { $this->constants[$constantName]->addReason(new Exception\ParseException($this, $tokenStream, sprintf('Constant %s is defined multiple times in the file.', $constantName), Exception\ParseException::ALREADY_EXISTS)); } } else { $this->constants[$constantName] = $constant; } if ($tokenStream->is(',')) { $tokenStream->skipWhitespaces(true); } else { $tokenStream->next(); } } while ($tokenStream->is(T_STRING)); break; case T_STRING: switch ($tokenStream->getTokenValue()) { case 'define': // definition case // definition case default: break; } $tokenStream->next(); break; case T_FUNCTION: $position = $tokenStream->key() + 1; while (isset($skipped[$type = $tokenStream->getType($position)])) { $position++; } if ('(' === $type) { // Skipping anonymous functions $tokenStream->seek($position)->findMatchingBracket()->skipWhiteSpaces(true); if ($tokenStream->is(T_USE)) { $tokenStream->skipWhitespaces(true)->findMatchingBracket()->skipWhitespaces(true); } $tokenStream->findMatchingBracket()->next(); continue; } $function = new ReflectionFunction($tokenStream, $this->getBroker(), $this); $firstChild = $firstChild ?: $function; $functionName = $function->getName(); if (isset($this->functions[$functionName])) { if (!$this->functions[$functionName] instanceof Invalid\ReflectionFunction) { $this->functions[$functionName] = new Invalid\ReflectionFunction($functionName, $this->functions[$functionName]->getFileName(), $this->getBroker()); } if (!$this->functions[$functionName]->hasReasons()) { $this->functions[$functionName]->addReason(new Exception\ParseException($this, $tokenStream, sprintf('Function %s is defined multiple times in the file.', $functionName), Exception\ParseException::ALREADY_EXISTS)); } } else { $this->functions[$functionName] = $function; } $tokenStream->next(); break; default: $tokenStream->next(); break; } } if ($firstChild) { $this->startPosition = min($this->startPosition, $firstChild->getStartPosition()); } return $this; }