PageRenderTime 26ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/unit-test/phpunit-portable/PHP/Token/Stream.php

http://buddypress-media.googlecode.com/
PHP | 378 lines | 202 code | 45 blank | 131 comment | 18 complexity | 5961eb46fb06bae7a4d2aedc0eb9240d MD5 | raw file
Possible License(s): AGPL-1.0, Apache-2.0, GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * php-token-stream
  4. *
  5. * Copyright (c) 2009-2010, Sebastian Bergmann <sb@sebastian-bergmann.de>.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * * Neither the name of Sebastian Bergmann nor the names of his
  21. * contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  27. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  28. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  29. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  30. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  31. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  34. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. * @package PHP_TokenStream
  38. * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
  39. * @copyright 2009-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
  40. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  41. * @since File available since Release 1.0.0
  42. */
  43. require_once ( PHPU_BASE_PATH . '/PHP/Token.php' );
  44. /**
  45. * A stream of PHP tokens.
  46. *
  47. * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
  48. * @copyright 2009-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
  49. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  50. * @version Release: 1.0.1
  51. * @link http://github.com/sebastianbergmann/php-token-stream/tree
  52. * @since Class available since Release 1.0.0
  53. */
  54. class PHP_Token_Stream implements ArrayAccess, Countable, SeekableIterator
  55. {
  56. /**
  57. * @var array
  58. */
  59. protected static $customTokens = array(
  60. '(' => 'PHP_Token_OPEN_BRACKET',
  61. ')' => 'PHP_Token_CLOSE_BRACKET',
  62. '[' => 'PHP_Token_OPEN_SQUARE',
  63. ']' => 'PHP_Token_CLOSE_SQUARE',
  64. '{' => 'PHP_Token_OPEN_CURLY',
  65. '}' => 'PHP_Token_CLOSE_CURLY',
  66. ';' => 'PHP_Token_SEMICOLON',
  67. '.' => 'PHP_Token_DOT',
  68. ',' => 'PHP_Token_COMMA',
  69. '=' => 'PHP_Token_EQUAL',
  70. '<' => 'PHP_Token_LT',
  71. '>' => 'PHP_Token_GT',
  72. '+' => 'PHP_Token_PLUS',
  73. '-' => 'PHP_Token_MINUS',
  74. '*' => 'PHP_Token_MULT',
  75. '/' => 'PHP_Token_DIV',
  76. '?' => 'PHP_Token_QUESTION_MARK',
  77. '!' => 'PHP_Token_EXCLAMATION_MARK',
  78. ':' => 'PHP_Token_COLON',
  79. '"' => 'PHP_Token_DOUBLE_QUOTES',
  80. '@' => 'PHP_Token_AT',
  81. '&' => 'PHP_Token_AMPERSAND',
  82. '%' => 'PHP_Token_PERCENT',
  83. '|' => 'PHP_Token_PIPE',
  84. '$' => 'PHP_Token_DOLLAR',
  85. '^' => 'PHP_Token_CARET',
  86. '~' => 'PHP_Token_TILDE',
  87. '`' => 'PHP_Token_BACKTICK'
  88. );
  89. /**
  90. * @var array
  91. */
  92. protected $tokens = array();
  93. /**
  94. * @var integer
  95. */
  96. protected $position = 0;
  97. /**
  98. * @var array
  99. */
  100. protected $linesOfCode = array('loc' => 0, 'cloc' => 0, 'ncloc' => 0);
  101. /**
  102. * @var array
  103. */
  104. protected $classes;
  105. /**
  106. * @var array
  107. */
  108. protected $functions;
  109. /**
  110. * Constructor.
  111. *
  112. * @param string $sourceCode
  113. */
  114. public function __construct($sourceCode)
  115. {
  116. if (is_file($sourceCode)) {
  117. $sourceCode = file_get_contents($sourceCode);
  118. }
  119. $this->scan($sourceCode);
  120. }
  121. /**
  122. * Scans the source for sequences of characters and converts them into a
  123. * stream of tokens.
  124. *
  125. * @param string $sourceCode
  126. */
  127. protected function scan($sourceCode)
  128. {
  129. $line = 1;
  130. $tokens = token_get_all($sourceCode);
  131. $numTokens = count($tokens);
  132. for ($i = 0; $i < $numTokens; ++$i) {
  133. $token = $tokens[$i];
  134. unset($tokens[$i]);
  135. if (is_array($token)) {
  136. $text = $token[1];
  137. $tokenClass = 'PHP_Token_' . substr(token_name($token[0]), 2);
  138. } else {
  139. $text = $token;
  140. $tokenClass = self::$customTokens[$token];
  141. }
  142. $this->tokens[] = new $tokenClass($text, $line, $this, $i);
  143. $lines = substr_count($text, "\n");
  144. $line += $lines;
  145. if ($tokenClass == 'PHP_Token_HALT_COMPILER') {
  146. break;
  147. }
  148. else if ($tokenClass == 'PHP_Token_COMMENT' ||
  149. $tokenClass == 'PHP_Token_DOC_COMMENT') {
  150. $this->linesOfCode['cloc'] += $lines + 1;
  151. }
  152. }
  153. $this->linesOfCode['loc'] = substr_count($sourceCode, "\n");
  154. $this->linesOfCode['ncloc'] = $this->linesOfCode['loc'] -
  155. $this->linesOfCode['cloc'];
  156. }
  157. /**
  158. * @return string
  159. */
  160. public function __toString()
  161. {
  162. $buffer = '';
  163. foreach ($this as $token) {
  164. $buffer .= $token;
  165. }
  166. return $buffer;
  167. }
  168. /**
  169. * @return integer
  170. */
  171. public function count()
  172. {
  173. return count($this->tokens);
  174. }
  175. /**
  176. * @return PHP_Token[]
  177. */
  178. public function tokens()
  179. {
  180. return $this->tokens;
  181. }
  182. /**
  183. * @return array
  184. */
  185. public function getClasses()
  186. {
  187. if ($this->classes !== NULL) {
  188. return $this->classes;
  189. }
  190. $this->parseClassesFunctions();
  191. return $this->classes;
  192. }
  193. /**
  194. * @return array
  195. */
  196. public function getFunctions()
  197. {
  198. if ($this->functions !== NULL) {
  199. return $this->functions;
  200. }
  201. $this->parseClassesFunctions();
  202. return $this->functions;
  203. }
  204. protected function parseClassesFunctions()
  205. {
  206. $this->classes = array();
  207. $this->functions = array();
  208. $class = FALSE;
  209. $classEndLine = FALSE;
  210. foreach ($this->tokens as $token) {
  211. switch (get_class($token)) {
  212. case 'PHP_Token_CLASS': {
  213. $class = $token->getName();
  214. $classEndLine = $token->getEndLine();
  215. $this->classes[$class] = array(
  216. 'methods' => array(),
  217. 'docblock' => $token->getDocblock(),
  218. 'startLine' => $token->getLine(),
  219. 'endLine' => $classEndLine
  220. );
  221. }
  222. break;
  223. case 'PHP_Token_FUNCTION': {
  224. $name = $token->getName();
  225. $tmp = array(
  226. 'docblock' => $token->getDocblock(),
  227. 'signature' => $token->getSignature(),
  228. 'startLine' => $token->getLine(),
  229. 'endLine' => $token->getEndLine(),
  230. 'ccn' => $token->getCCN()
  231. );
  232. if ($class === FALSE) {
  233. $this->functions[$name] = $tmp;
  234. } else {
  235. $this->classes[$class]['methods'][$name] = $tmp;
  236. }
  237. }
  238. break;
  239. case 'PHP_Token_CLOSE_CURLY': {
  240. if ($classEndLine !== FALSE &&
  241. $classEndLine == $token->getLine()) {
  242. $class = FALSE;
  243. $classEndLine = FALSE;
  244. }
  245. }
  246. break;
  247. }
  248. }
  249. }
  250. /**
  251. * @return array
  252. */
  253. public function getLinesOfCode()
  254. {
  255. return $this->linesOfCode;
  256. }
  257. /**
  258. */
  259. public function rewind()
  260. {
  261. $this->position = 0;
  262. }
  263. /**
  264. * @return boolean
  265. */
  266. public function valid()
  267. {
  268. return isset($this->tokens[$this->position]);
  269. }
  270. /**
  271. * @return integer
  272. */
  273. public function key()
  274. {
  275. return $this->position;
  276. }
  277. /**
  278. * @return PHP_Token
  279. */
  280. public function current()
  281. {
  282. return $this->tokens[$this->position];
  283. }
  284. /**
  285. */
  286. public function next()
  287. {
  288. $this->position++;
  289. }
  290. /**
  291. * @param mixed $offset
  292. */
  293. public function offsetExists($offset)
  294. {
  295. return isset($this->tokens[$offset]);
  296. }
  297. /**
  298. * @param mixed $offset
  299. * @return mixed
  300. */
  301. public function offsetGet($offset)
  302. {
  303. return $this->tokens[$offset];
  304. }
  305. /**
  306. * @param mixed $offset
  307. * @param mixed $value
  308. */
  309. public function offsetSet($offset, $value)
  310. {
  311. $this->tokens[$offset] = $value;
  312. }
  313. /**
  314. * @param mixed $offset
  315. */
  316. public function offsetUnset($offset)
  317. {
  318. unset($this->tokens[$offset]);
  319. }
  320. /**
  321. * Seek to an absolute position.
  322. *
  323. * @param integer $position
  324. * @throws OutOfBoundsException
  325. */
  326. public function seek($position)
  327. {
  328. $this->position = $position;
  329. if (!$this->valid()) {
  330. throw new OutOfBoundsException('Invalid seek position');
  331. }
  332. }
  333. }