| [ Index ] |
|
Code source de Symfony 1.0.0 |
1 <?php 2 /** 3 * $Id: CoverageReportTask.php 3076 2006-12-18 08:52:12Z fabien $ 4 * 5 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 6 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 7 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 8 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 9 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 10 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 11 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 12 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 13 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 14 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 15 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 * 17 * This software consists of voluntary contributions made by many individuals 18 * and is licensed under the LGPL. For more information please see 19 * <http://phing.info>. 20 */ 21 22 require_once 'phing/Task.php'; 23 require_once 'phing/system/io/PhingFile.php'; 24 require_once 'phing/system/io/Writer.php'; 25 require_once 'phing/system/util/Properties.php'; 26 require_once 'phing/tasks/ext/phpunit2/PHPUnit2Util.php'; 27 require_once 'phing/tasks/ext/coverage/CoverageReportTransformer.php'; 28 29 /** 30 * Transforms information in a code coverage database to XML 31 * 32 * @author Michiel Rook <michiel.rook@gmail.com> 33 * @version $Id: CoverageReportTask.php 3076 2006-12-18 08:52:12Z fabien $ 34 * @package phing.tasks.ext.coverage 35 * @since 2.1.0 36 */ 37 class CoverageReportTask extends Task 38 { 39 private $outfile = "coverage.xml"; 40 41 private $transformers = array(); 42 43 /** the classpath to use (optional) */ 44 private $classpath = NULL; 45 46 /** the path to the GeSHi library (optional) */ 47 private $geshipath = ""; 48 49 /** the path to the GeSHi language files (optional) */ 50 private $geshilanguagespath = ""; 51 52 function setClasspath(Path $classpath) 53 { 54 if ($this->classpath === null) 55 { 56 $this->classpath = $classpath; 57 } 58 else 59 { 60 $this->classpath->append($classpath); 61 } 62 } 63 64 function createClasspath() 65 { 66 $this->classpath = new Path(); 67 return $this->classpath; 68 } 69 70 function setGeshiPath($path) 71 { 72 $this->geshipath = $path; 73 } 74 75 function setGeshiLanguagesPath($path) 76 { 77 $this->geshilanguagespath = $path; 78 } 79 80 function __construct() 81 { 82 $this->doc = new DOMDocument(); 83 $this->doc->encoding = 'UTF-8'; 84 $this->doc->formatOutput = true; 85 $this->doc->appendChild($this->doc->createElement('snapshot')); 86 } 87 88 function setOutfile($outfile) 89 { 90 $this->outfile = $outfile; 91 } 92 93 /** 94 * Generate a report based on the XML created by this task 95 */ 96 function createReport() 97 { 98 $transformer = new CoverageReportTransformer($this); 99 $this->transformers[] = $transformer; 100 return $transformer; 101 } 102 103 protected function getPackageElement($packageName) 104 { 105 $packages = $this->doc->documentElement->getElementsByTagName('package'); 106 107 foreach ($packages as $package) 108 { 109 if ($package->getAttribute('name') == $packageName) 110 { 111 return $package; 112 } 113 } 114 115 return NULL; 116 } 117 118 protected function addClassToPackage($classname, $element) 119 { 120 $packageName = PHPUnit2Util::getPackageName($classname); 121 122 $package = $this->getPackageElement($packageName); 123 124 if ($package === NULL) 125 { 126 $package = $this->doc->createElement('package'); 127 $package->setAttribute('name', $packageName); 128 $this->doc->documentElement->appendChild($package); 129 } 130 131 $package->appendChild($element); 132 } 133 134 protected function stripDiv($source) 135 { 136 $openpos = strpos($source, "<div"); 137 $closepos = strpos($source, ">", $openpos); 138 139 $line = substr($source, $closepos + 1); 140 141 $tagclosepos = strpos($line, "</div>"); 142 143 $line = substr($line, 0, $tagclosepos); 144 145 return $line; 146 } 147 148 protected function highlightSourceFile($filename) 149 { 150 if ($this->geshipath) 151 { 152 require_once $this->geshipath . '/geshi.php'; 153 154 $source = file_get_contents($filename); 155 156 $geshi = new GeSHi($source, 'php', $this->geshilanguagespath); 157 158 $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); 159 160 $geshi->enable_strict_mode(true); 161 162 $geshi->enable_classes(true); 163 164 $geshi->set_url_for_keyword_group(3, ''); 165 166 $html = $geshi->parse_code(); 167 168 $lines = split("<li>|</li>", $html); 169 170 // skip first and last line 171 array_pop($lines); 172 array_shift($lines); 173 174 $lines = array_filter($lines); 175 176 $lines = array_map(array($this, 'stripDiv'), $lines); 177 178 return $lines; 179 } 180 else 181 { 182 $lines = file($filename); 183 184 for ($i = 0; $i < count($lines); $i++) 185 { 186 $line = $lines[$i]; 187 188 $line = rtrim($line); 189 190 $lines[$i] = utf8_encode($line); 191 } 192 193 return $lines; 194 } 195 } 196 197 protected function transformSourceFile($filename, $coverageInformation, $classStartLine = 1) 198 { 199 $sourceElement = $this->doc->createElement('sourcefile'); 200 $sourceElement->setAttribute('name', basename($filename)); 201 202 $filelines = $this->highlightSourceFile($filename); 203 204 $linenr = 1; 205 206 foreach ($filelines as $line) 207 { 208 $lineElement = $this->doc->createElement('sourceline'); 209 $lineElement->setAttribute('coveredcount', (isset($coverageInformation[$linenr]) ? $coverageInformation[$linenr] : '0')); 210 211 if ($linenr == $classStartLine) 212 { 213 $lineElement->setAttribute('startclass', 1); 214 } 215 216 $textnode = $this->doc->createTextNode($line); 217 $lineElement->appendChild($textnode); 218 219 $sourceElement->appendChild($lineElement); 220 221 $linenr++; 222 } 223 224 return $sourceElement; 225 } 226 227 protected function filterCovered($var) 228 { 229 return ($var >= 0); 230 } 231 232 protected function transformCoverageInformation($filename, $coverageInformation) 233 { 234 // Strip last line of coverage information 235 end($coverageInformation); 236 unset($coverageInformation[key($coverageInformation)]); 237 238 $classes = PHPUnit2Util::getDefinedClasses($filename, $this->classpath); 239 240 if (is_array($classes)) 241 { 242 foreach ($classes as $classname) 243 { 244 $reflection = new ReflectionClass($classname); 245 246 $methods = $reflection->getMethods(); 247 248 $classElement = $this->doc->createElement('class'); 249 $classElement->setAttribute('name', $reflection->getName()); 250 251 $this->addClassToPackage($reflection->getName(), $classElement); 252 253 $classStartLine = $reflection->getStartLine(); 254 255 $methodscovered = 0; 256 $methodcount = 0; 257 258 // Strange PHP5 reflection bug, classes without parent class or implemented interfaces seem to start one line off 259 if ($reflection->getParentClass() == NULL && count($reflection->getInterfaces()) == 0) 260 { 261 unset($coverageInformation[$classStartLine + 1]); 262 } 263 else 264 { 265 unset($coverageInformation[$classStartLine]); 266 } 267 268 reset($coverageInformation); 269 270 foreach ($methods as $method) 271 { 272 // PHP5 reflection considers methods of a parent class to be part of a subclass, we don't 273 if ($method->getDeclaringClass()->getName() != $reflection->getName()) 274 { 275 continue; 276 } 277 278 // small fix for XDEBUG_CC_UNUSED 279 if (isset($coverageInformation[$method->getStartLine()])) 280 { 281 unset($coverageInformation[$method->getStartLine()]); 282 } 283 284 if (isset($coverageInformation[$method->getEndLine()])) 285 { 286 unset($coverageInformation[$method->getEndLine()]); 287 } 288 289 if ($method->isAbstract()) 290 { 291 continue; 292 } 293 294 $linenr = key($coverageInformation); 295 296 while ($linenr !== null && $linenr < $method->getStartLine()) 297 { 298 next($coverageInformation); 299 $linenr = key($coverageInformation); 300 } 301 302 if (current($coverageInformation) > 0 && $method->getStartLine() <= $linenr && $linenr <= $method->getEndLine()) 303 { 304 $methodscovered++; 305 } 306 307 $methodcount++; 308 } 309 310 $statementcount = count($coverageInformation); 311 $statementscovered = count(array_filter($coverageInformation, array($this, 'filterCovered'))); 312 313 $classElement->appendChild($this->transformSourceFile($filename, $coverageInformation, $classStartLine)); 314 315 $classElement->setAttribute('methodcount', $methodcount); 316 $classElement->setAttribute('methodscovered', $methodscovered); 317 $classElement->setAttribute('statementcount', $statementcount); 318 $classElement->setAttribute('statementscovered', $statementscovered); 319 $classElement->setAttribute('totalcount', $methodcount + $statementcount); 320 $classElement->setAttribute('totalcovered', $methodscovered + $statementscovered); 321 } 322 } 323 } 324 325 protected function calculateStatistics() 326 { 327 $packages = $this->doc->documentElement->getElementsByTagName('package'); 328 329 $totalmethodcount = 0; 330 $totalmethodscovered = 0; 331 332 $totalstatementcount = 0; 333 $totalstatementscovered = 0; 334 335 foreach ($packages as $package) 336 { 337 $methodcount = 0; 338 $methodscovered = 0; 339 340 $statementcount = 0; 341 $statementscovered = 0; 342 343 $classes = $package->getElementsByTagName('class'); 344 345 foreach ($classes as $class) 346 { 347 $methodcount += $class->getAttribute('methodcount'); 348 $methodscovered += $class->getAttribute('methodscovered'); 349 350 $statementcount += $class->getAttribute('statementcount'); 351 $statementscovered += $class->getAttribute('statementscovered'); 352 } 353 354 $package->setAttribute('methodcount', $methodcount); 355 $package->setAttribute('methodscovered', $methodscovered); 356 357 $package->setAttribute('statementcount', $statementcount); 358 $package->setAttribute('statementscovered', $statementscovered); 359 360 $package->setAttribute('totalcount', $methodcount + $statementcount); 361 $package->setAttribute('totalcovered', $methodscovered + $statementscovered); 362 363 $totalmethodcount += $methodcount; 364 $totalmethodscovered += $methodscovered; 365 366 $totalstatementcount += $statementcount; 367 $totalstatementscovered += $statementscovered; 368 } 369 370 $this->doc->documentElement->setAttribute('methodcount', $totalmethodcount); 371 $this->doc->documentElement->setAttribute('methodscovered', $totalmethodscovered); 372 373 $this->doc->documentElement->setAttribute('statementcount', $totalstatementcount); 374 $this->doc->documentElement->setAttribute('statementscovered', $totalstatementscovered); 375 376 $this->doc->documentElement->setAttribute('totalcount', $totalmethodcount + $totalstatementcount); 377 $this->doc->documentElement->setAttribute('totalcovered', $totalmethodscovered + $totalstatementscovered); 378 } 379 380 function main() 381 { 382 $this->log("Transforming coverage report"); 383 384 $database = new PhingFile($this->project->getProperty('coverage.database')); 385 386 $props = new Properties(); 387 $props->load($database); 388 389 foreach ($props->keys() as $filename) 390 { 391 $file = unserialize($props->getProperty($filename)); 392 393 $this->transformCoverageInformation($file['fullname'], $file['coverage']); 394 } 395 396 $this->calculateStatistics(); 397 398 $this->doc->save($this->outfile); 399 400 foreach ($this->transformers as $transformer) 401 { 402 $transformer->setXmlDocument($this->doc); 403 $transformer->transform(); 404 } 405 } 406 } 407 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Fri Mar 16 22:42:14 2007 | par Balluche grâce à PHPXref 0.7 |