class PHP_Token_Stream in Zircon Profile 8
Same name and namespace in other branches
- 8.0 vendor/phpunit/php-token-stream/src/Token/Stream.php \PHP_Token_Stream
A stream of PHP tokens.
@author Sebastian Bergmann <sebastian@phpunit.de> @copyright Sebastian Bergmann <sebastian@phpunit.de> @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License @link http://github.com/sebastianbergmann/php-token-stream/tree @since Class available since Release 1.0.0
Hierarchy
- class \PHP_Token_Stream implements \ArrayAccess, \Countable, \SeekableIterator
Expanded class hierarchy of PHP_Token_Stream
File
- vendor/
phpunit/ php-token-stream/ src/ Token/ Stream.php, line 20
View source
class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator {
/**
* @var array
*/
protected static $customTokens = array(
'(' => 'PHP_Token_OPEN_BRACKET',
')' => 'PHP_Token_CLOSE_BRACKET',
'[' => 'PHP_Token_OPEN_SQUARE',
']' => 'PHP_Token_CLOSE_SQUARE',
'{' => 'PHP_Token_OPEN_CURLY',
'}' => 'PHP_Token_CLOSE_CURLY',
';' => 'PHP_Token_SEMICOLON',
'.' => 'PHP_Token_DOT',
',' => 'PHP_Token_COMMA',
'=' => 'PHP_Token_EQUAL',
'<' => 'PHP_Token_LT',
'>' => 'PHP_Token_GT',
'+' => 'PHP_Token_PLUS',
'-' => 'PHP_Token_MINUS',
'*' => 'PHP_Token_MULT',
'/' => 'PHP_Token_DIV',
'?' => 'PHP_Token_QUESTION_MARK',
'!' => 'PHP_Token_EXCLAMATION_MARK',
':' => 'PHP_Token_COLON',
'"' => 'PHP_Token_DOUBLE_QUOTES',
'@' => 'PHP_Token_AT',
'&' => 'PHP_Token_AMPERSAND',
'%' => 'PHP_Token_PERCENT',
'|' => 'PHP_Token_PIPE',
'$' => 'PHP_Token_DOLLAR',
'^' => 'PHP_Token_CARET',
'~' => 'PHP_Token_TILDE',
'`' => 'PHP_Token_BACKTICK',
);
/**
* @var string
*/
protected $filename;
/**
* @var array
*/
protected $tokens = array();
/**
* @var integer
*/
protected $position = 0;
/**
* @var array
*/
protected $linesOfCode = array(
'loc' => 0,
'cloc' => 0,
'ncloc' => 0,
);
/**
* @var array
*/
protected $classes;
/**
* @var array
*/
protected $functions;
/**
* @var array
*/
protected $includes;
/**
* @var array
*/
protected $interfaces;
/**
* @var array
*/
protected $traits;
/**
* @var array
*/
protected $lineToFunctionMap = array();
/**
* Constructor.
*
* @param string $sourceCode
*/
public function __construct($sourceCode) {
if (is_file($sourceCode)) {
$this->filename = $sourceCode;
$sourceCode = file_get_contents($sourceCode);
}
$this
->scan($sourceCode);
}
/**
* Destructor.
*/
public function __destruct() {
$this->tokens = array();
}
/**
* @return string
*/
public function __toString() {
$buffer = '';
foreach ($this as $token) {
$buffer .= $token;
}
return $buffer;
}
/**
* @return string
* @since Method available since Release 1.1.0
*/
public function getFilename() {
return $this->filename;
}
/**
* Scans the source for sequences of characters and converts them into a
* stream of tokens.
*
* @param string $sourceCode
*/
protected function scan($sourceCode) {
$line = 1;
$tokens = token_get_all($sourceCode);
$numTokens = count($tokens);
$lastNonWhitespaceTokenWasDoubleColon = false;
for ($i = 0; $i < $numTokens; ++$i) {
$token = $tokens[$i];
unset($tokens[$i]);
if (is_array($token)) {
$name = substr(token_name($token[0]), 2);
$text = $token[1];
if ($lastNonWhitespaceTokenWasDoubleColon && $name == 'CLASS') {
$name = 'CLASS_NAME_CONSTANT';
}
$tokenClass = 'PHP_Token_' . $name;
}
else {
$text = $token;
$tokenClass = self::$customTokens[$token];
}
$this->tokens[] = new $tokenClass($text, $line, $this, $i);
$lines = substr_count($text, "\n");
$line += $lines;
if ($tokenClass == 'PHP_Token_HALT_COMPILER') {
break;
}
elseif ($tokenClass == 'PHP_Token_COMMENT' || $tokenClass == 'PHP_Token_DOC_COMMENT') {
$this->linesOfCode['cloc'] += $lines + 1;
}
if ($name == 'DOUBLE_COLON') {
$lastNonWhitespaceTokenWasDoubleColon = true;
}
elseif ($name != 'WHITESPACE') {
$lastNonWhitespaceTokenWasDoubleColon = false;
}
}
$this->linesOfCode['loc'] = substr_count($sourceCode, "\n");
$this->linesOfCode['ncloc'] = $this->linesOfCode['loc'] - $this->linesOfCode['cloc'];
}
/**
* @return integer
*/
public function count() {
return count($this->tokens);
}
/**
* @return PHP_Token[]
*/
public function tokens() {
return $this->tokens;
}
/**
* @return array
*/
public function getClasses() {
if ($this->classes !== null) {
return $this->classes;
}
$this
->parse();
return $this->classes;
}
/**
* @return array
*/
public function getFunctions() {
if ($this->functions !== null) {
return $this->functions;
}
$this
->parse();
return $this->functions;
}
/**
* @return array
*/
public function getInterfaces() {
if ($this->interfaces !== null) {
return $this->interfaces;
}
$this
->parse();
return $this->interfaces;
}
/**
* @return array
* @since Method available since Release 1.1.0
*/
public function getTraits() {
if ($this->traits !== null) {
return $this->traits;
}
$this
->parse();
return $this->traits;
}
/**
* Gets the names of all files that have been included
* using include(), include_once(), require() or require_once().
*
* Parameter $categorize set to TRUE causing this function to return a
* multi-dimensional array with categories in the keys of the first dimension
* and constants and their values in the second dimension.
*
* Parameter $category allow to filter following specific inclusion type
*
* @param bool $categorize OPTIONAL
* @param string $category OPTIONAL Either 'require_once', 'require',
* 'include_once', 'include'.
* @return array
* @since Method available since Release 1.1.0
*/
public function getIncludes($categorize = false, $category = null) {
if ($this->includes === null) {
$this->includes = array(
'require_once' => array(),
'require' => array(),
'include_once' => array(),
'include' => array(),
);
foreach ($this->tokens as $token) {
switch (get_class($token)) {
case 'PHP_Token_REQUIRE_ONCE':
case 'PHP_Token_REQUIRE':
case 'PHP_Token_INCLUDE_ONCE':
case 'PHP_Token_INCLUDE':
$this->includes[$token
->getType()][] = $token
->getName();
break;
}
}
}
if (isset($this->includes[$category])) {
$includes = $this->includes[$category];
}
elseif ($categorize === false) {
$includes = array_merge($this->includes['require_once'], $this->includes['require'], $this->includes['include_once'], $this->includes['include']);
}
else {
$includes = $this->includes;
}
return $includes;
}
/**
* Returns the name of the function or method a line belongs to.
*
* @return string or null if the line is not in a function or method
* @since Method available since Release 1.2.0
*/
public function getFunctionForLine($line) {
$this
->parse();
if (isset($this->lineToFunctionMap[$line])) {
return $this->lineToFunctionMap[$line];
}
}
protected function parse() {
$this->interfaces = array();
$this->classes = array();
$this->traits = array();
$this->functions = array();
$class = array();
$classEndLine = array();
$trait = false;
$traitEndLine = false;
$interface = false;
$interfaceEndLine = false;
foreach ($this->tokens as $token) {
switch (get_class($token)) {
case 'PHP_Token_HALT_COMPILER':
return;
case 'PHP_Token_INTERFACE':
$interface = $token
->getName();
$interfaceEndLine = $token
->getEndLine();
$this->interfaces[$interface] = array(
'methods' => array(),
'parent' => $token
->getParent(),
'keywords' => $token
->getKeywords(),
'docblock' => $token
->getDocblock(),
'startLine' => $token
->getLine(),
'endLine' => $interfaceEndLine,
'package' => $token
->getPackage(),
'file' => $this->filename,
);
break;
case 'PHP_Token_CLASS':
case 'PHP_Token_TRAIT':
$tmp = array(
'methods' => array(),
'parent' => $token
->getParent(),
'interfaces' => $token
->getInterfaces(),
'keywords' => $token
->getKeywords(),
'docblock' => $token
->getDocblock(),
'startLine' => $token
->getLine(),
'endLine' => $token
->getEndLine(),
'package' => $token
->getPackage(),
'file' => $this->filename,
);
if ($token instanceof PHP_Token_CLASS) {
$class[] = $token
->getName();
$classEndLine[] = $token
->getEndLine();
if ($class[count($class) - 1] != 'anonymous class') {
$this->classes[$class[count($class) - 1]] = $tmp;
}
}
else {
$trait = $token
->getName();
$traitEndLine = $token
->getEndLine();
$this->traits[$trait] = $tmp;
}
break;
case 'PHP_Token_FUNCTION':
$name = $token
->getName();
$tmp = array(
'docblock' => $token
->getDocblock(),
'keywords' => $token
->getKeywords(),
'visibility' => $token
->getVisibility(),
'signature' => $token
->getSignature(),
'startLine' => $token
->getLine(),
'endLine' => $token
->getEndLine(),
'ccn' => $token
->getCCN(),
'file' => $this->filename,
);
if (empty($class) && $trait === false && $interface === false) {
$this->functions[$name] = $tmp;
$this
->addFunctionToMap($name, $tmp['startLine'], $tmp['endLine']);
}
elseif (!empty($class) && $class[count($class) - 1] != 'anonymous class') {
$this->classes[$class[count($class) - 1]]['methods'][$name] = $tmp;
$this
->addFunctionToMap($class[count($class) - 1] . '::' . $name, $tmp['startLine'], $tmp['endLine']);
}
elseif ($trait !== false) {
$this->traits[$trait]['methods'][$name] = $tmp;
$this
->addFunctionToMap($trait . '::' . $name, $tmp['startLine'], $tmp['endLine']);
}
else {
$this->interfaces[$interface]['methods'][$name] = $tmp;
}
break;
case 'PHP_Token_CLOSE_CURLY':
if (!empty($classEndLine) && $classEndLine[count($classEndLine) - 1] == $token
->getLine()) {
array_pop($classEndLine);
array_pop($class);
}
elseif ($traitEndLine !== false && $traitEndLine == $token
->getLine()) {
$trait = false;
$traitEndLine = false;
}
elseif ($interfaceEndLine !== false && $interfaceEndLine == $token
->getLine()) {
$interface = false;
$interfaceEndLine = false;
}
break;
}
}
}
/**
* @return array
*/
public function getLinesOfCode() {
return $this->linesOfCode;
}
/**
*/
public function rewind() {
$this->position = 0;
}
/**
* @return boolean
*/
public function valid() {
return isset($this->tokens[$this->position]);
}
/**
* @return integer
*/
public function key() {
return $this->position;
}
/**
* @return PHP_Token
*/
public function current() {
return $this->tokens[$this->position];
}
/**
*/
public function next() {
$this->position++;
}
/**
* @param integer $offset
* @return boolean
*/
public function offsetExists($offset) {
return isset($this->tokens[$offset]);
}
/**
* @param integer $offset
* @return mixed
* @throws OutOfBoundsException
*/
public function offsetGet($offset) {
if (!$this
->offsetExists($offset)) {
throw new OutOfBoundsException(sprintf('No token at position "%s"', $offset));
}
return $this->tokens[$offset];
}
/**
* @param integer $offset
* @param mixed $value
*/
public function offsetSet($offset, $value) {
$this->tokens[$offset] = $value;
}
/**
* @param integer $offset
* @throws OutOfBoundsException
*/
public function offsetUnset($offset) {
if (!$this
->offsetExists($offset)) {
throw new OutOfBoundsException(sprintf('No token at position "%s"', $offset));
}
unset($this->tokens[$offset]);
}
/**
* Seek to an absolute position.
*
* @param integer $position
* @throws OutOfBoundsException
*/
public function seek($position) {
$this->position = $position;
if (!$this
->valid()) {
throw new OutOfBoundsException(sprintf('No token at position "%s"', $this->position));
}
}
/**
* @param string $name
* @param integer $startLine
* @param integer $endLine
*/
private function addFunctionToMap($name, $startLine, $endLine) {
for ($line = $startLine; $line <= $endLine; $line++) {
$this->lineToFunctionMap[$line] = $name;
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
protected static | property | ||
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
protected | property | ||
PHP_Token_Stream:: |
private | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | @since Method available since Release 1.1.0 | |
PHP_Token_Stream:: |
public | function | Returns the name of the function or method a line belongs to. | |
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | Gets the names of all files that have been included using include(), include_once(), require() or require_once(). | |
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | @since Method available since Release 1.1.0 | |
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
protected | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
protected | function | Scans the source for sequences of characters and converts them into a stream of tokens. | |
PHP_Token_Stream:: |
public | function | Seek to an absolute position. | |
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | ||
PHP_Token_Stream:: |
public | function | Constructor. | |
PHP_Token_Stream:: |
public | function | Destructor. | |
PHP_Token_Stream:: |
public | function |