PageRenderTime 28ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/phpunit/php-code-coverage/PHP/CodeCoverage/Util.php

https://gitlab.com/karora/awl
PHP | 272 lines | 159 code | 35 blank | 78 comment | 44 complexity | 83fb9ec8e329121f91bfd0d89c7cdfd8 MD5 | raw file
  1. <?php
  2. /**
  3. * PHP_CodeCoverage
  4. *
  5. * Copyright (c) 2009-2013, Sebastian Bergmann <sebastian@phpunit.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. * @category PHP
  38. * @package CodeCoverage
  39. * @author Sebastian Bergmann <sebastian@phpunit.de>
  40. * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
  41. * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
  42. * @link http://github.com/sebastianbergmann/php-code-coverage
  43. * @since File available since Release 1.0.0
  44. */
  45. /**
  46. * Utility methods.
  47. *
  48. * @category PHP
  49. * @package CodeCoverage
  50. * @author Sebastian Bergmann <sebastian@phpunit.de>
  51. * @copyright 2009-2013 Sebastian Bergmann <sebastian@phpunit.de>
  52. * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
  53. * @link http://github.com/sebastianbergmann/php-code-coverage
  54. * @since Class available since Release 1.0.0
  55. */
  56. class PHP_CodeCoverage_Util
  57. {
  58. /**
  59. * @var array
  60. */
  61. protected static $ignoredLines = array();
  62. /**
  63. * @var array
  64. */
  65. protected static $ids = array();
  66. /**
  67. * Returns the lines of a source file that should be ignored.
  68. *
  69. * @param string $filename
  70. * @param boolean $cacheTokens
  71. * @return array
  72. * @throws PHP_CodeCoverage_Exception
  73. */
  74. public static function getLinesToBeIgnored($filename, $cacheTokens = TRUE)
  75. {
  76. if (!is_string($filename)) {
  77. throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
  78. 1, 'string'
  79. );
  80. }
  81. if (!is_bool($cacheTokens)) {
  82. throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory(
  83. 2, 'boolean'
  84. );
  85. }
  86. if (!isset(self::$ignoredLines[$filename])) {
  87. self::$ignoredLines[$filename] = array();
  88. $ignore = FALSE;
  89. $stop = FALSE;
  90. $lines = file($filename);
  91. foreach ($lines as $index => $line) {
  92. if (!trim($line)) {
  93. self::$ignoredLines[$filename][$index+1] = TRUE;
  94. }
  95. }
  96. if ($cacheTokens) {
  97. $tokens = PHP_Token_Stream_CachingFactory::get($filename);
  98. } else {
  99. $tokens = new PHP_Token_Stream($filename);
  100. }
  101. $classes = array_merge($tokens->getClasses(), $tokens->getTraits());
  102. $tokens = $tokens->tokens();
  103. foreach ($tokens as $token) {
  104. switch (get_class($token)) {
  105. case 'PHP_Token_COMMENT':
  106. case 'PHP_Token_DOC_COMMENT': {
  107. $_token = trim($token);
  108. $_line = trim($lines[$token->getLine() - 1]);
  109. if ($_token == '// @codeCoverageIgnore' ||
  110. $_token == '//@codeCoverageIgnore') {
  111. $ignore = TRUE;
  112. $stop = TRUE;
  113. }
  114. else if ($_token == '// @codeCoverageIgnoreStart' ||
  115. $_token == '//@codeCoverageIgnoreStart') {
  116. $ignore = TRUE;
  117. }
  118. else if ($_token == '// @codeCoverageIgnoreEnd' ||
  119. $_token == '//@codeCoverageIgnoreEnd') {
  120. $stop = TRUE;
  121. }
  122. // be sure the comment doesn't have some token BEFORE it on the same line...
  123. // it would not be safe to ignore the whole line in those cases.
  124. if (0 === strpos($_token, $_line)) {
  125. $count = substr_count($token, "\n");
  126. $line = $token->getLine();
  127. for ($i = $line; $i < $line + $count; $i++) {
  128. self::$ignoredLines[$filename][$i] = TRUE;
  129. }
  130. if ($token instanceof PHP_Token_DOC_COMMENT) {
  131. // Workaround for the fact the DOC_COMMENT token
  132. // does not include the final \n character in its
  133. // text.
  134. if (substr(trim($lines[$i-1]), -2) == '*/') {
  135. self::$ignoredLines[$filename][$i] = TRUE;
  136. }
  137. }
  138. }
  139. }
  140. break;
  141. case 'PHP_Token_INTERFACE':
  142. case 'PHP_Token_TRAIT':
  143. case 'PHP_Token_CLASS':
  144. case 'PHP_Token_FUNCTION': {
  145. $docblock = $token->getDocblock();
  146. if (strpos($docblock, '@codeCoverageIgnore')) {
  147. $endLine = $token->getEndLine();
  148. for ($i = $token->getLine(); $i <= $endLine; $i++) {
  149. self::$ignoredLines[$filename][$i] = TRUE;
  150. }
  151. }
  152. else if ($token instanceof PHP_Token_INTERFACE ||
  153. $token instanceof PHP_Token_TRAIT ||
  154. $token instanceof PHP_Token_CLASS) {
  155. if (empty($classes[$token->getName()]['methods'])) {
  156. for ($i = $token->getLine();
  157. $i <= $token->getEndLine();
  158. $i++) {
  159. self::$ignoredLines[$filename][$i] = TRUE;
  160. }
  161. } else {
  162. $firstMethod = array_shift(
  163. $classes[$token->getName()]['methods']
  164. );
  165. $lastMethod = array_pop(
  166. $classes[$token->getName()]['methods']
  167. );
  168. if ($lastMethod === NULL) {
  169. $lastMethod = $firstMethod;
  170. }
  171. for ($i = $token->getLine();
  172. $i < $firstMethod['startLine'];
  173. $i++) {
  174. self::$ignoredLines[$filename][$i] = TRUE;
  175. }
  176. for ($i = $token->getEndLine();
  177. $i > $lastMethod['endLine'];
  178. $i--) {
  179. self::$ignoredLines[$filename][$i] = TRUE;
  180. }
  181. }
  182. }
  183. }
  184. break;
  185. case 'PHP_Token_INTERFACE': {
  186. $endLine = $token->getEndLine();
  187. for ($i = $token->getLine(); $i <= $endLine; $i++) {
  188. self::$ignoredLines[$filename][$i] = TRUE;
  189. }
  190. }
  191. break;
  192. case 'PHP_Token_NAMESPACE': {
  193. self::$ignoredLines[$filename][$token->getEndLine()] = TRUE;
  194. } // Intentional fallthrough
  195. case 'PHP_Token_OPEN_TAG':
  196. case 'PHP_Token_CLOSE_TAG':
  197. case 'PHP_Token_USE': {
  198. self::$ignoredLines[$filename][$token->getLine()] = TRUE;
  199. }
  200. break;
  201. }
  202. if ($ignore) {
  203. self::$ignoredLines[$filename][$token->getLine()] = TRUE;
  204. if ($stop) {
  205. $ignore = FALSE;
  206. $stop = FALSE;
  207. }
  208. }
  209. }
  210. }
  211. return self::$ignoredLines[$filename];
  212. }
  213. /**
  214. * @param float $a
  215. * @param float $b
  216. * @return float ($a / $b) * 100
  217. */
  218. public static function percent($a, $b, $asString = FALSE, $fixedWidth = FALSE)
  219. {
  220. if ($asString && $b == 0) {
  221. return '';
  222. }
  223. if ($b > 0) {
  224. $percent = ($a / $b) * 100;
  225. } else {
  226. $percent = 100;
  227. }
  228. if ($asString) {
  229. if ($fixedWidth) {
  230. return sprintf('%6.2F%%', $percent);
  231. }
  232. return sprintf('%01.2F%%', $percent);
  233. } else {
  234. return $percent;
  235. }
  236. }
  237. }