All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scoverage.report.ScoverageHtmlWriter.scala Maven / Gradle / Ivy

The newest version!
package scoverage.report

import java.io.File
import java.util.Date

import scoverage._

import scala.xml.Node

/** @author Stephen Samuel */
class ScoverageHtmlWriter(sourceDirectories: Seq[File], outputDir: File, sourceEncoding: Option[String]) extends BaseReportWriter(sourceDirectories, outputDir) {

  // for backward compatibility only
  def this (sourceDirectories: Seq[File], outputDir: File) {
    this(sourceDirectories, outputDir, None);
  }
  
  // for backward compatibility only
  def this (sourceDirectory: File, outputDir: File) {
    this(Seq(sourceDirectory), outputDir)
  }
  
  def write(coverage: Coverage): Unit = {
    val indexFile = new File(outputDir.getAbsolutePath + "/index.html")
    val packageFile = new File(outputDir.getAbsolutePath + "/packages.html")
    val overviewFile = new File(outputDir.getAbsolutePath + "/overview.html")

    val index = IOUtils.readStreamAsString(getClass.getResourceAsStream("/scoverage/index.html"))
    IOUtils.writeToFile(indexFile, index)
    IOUtils.writeToFile(packageFile, packageList(coverage).toString())
    IOUtils.writeToFile(overviewFile, overview(coverage).toString())

    coverage.packages.foreach(writePackage)
  }

  private def writePackage(pkg: MeasuredPackage): Unit = {
    // package overview files are written out using a filename that respects the package name
    // that means package com.example declared in a class at src/main/scala/mystuff/MyClass.scala will be written
    // to com.example.html
    val file = new File(outputDir, packageOverviewRelativePath(pkg))
    file.getParentFile.mkdirs()
    IOUtils.writeToFile(file, packageOverview(pkg).toString())
    pkg.files.foreach(writeFile)
  }

  private def writeFile(mfile: MeasuredFile): Unit = {
    // each highlighted file is written out using the same structure as the original file.
    val file = new File(outputDir, relativeSource(mfile.source) + ".html")
    file.getParentFile.mkdirs()
    IOUtils.writeToFile(file, filePage(mfile).toString())
  }

  private def packageOverviewRelativePath(pkg: MeasuredPackage) = pkg.name.replace("", "(empty)") + ".html"

  private def filePage(mfile: MeasuredFile): Node = {
    val filename = relativeSource(mfile.source) + ".html"
    val css =
      "table.codegrid { font-family: monospace; font-size: 12px; width: auto!important; }" +
        "table.statementlist { width: auto!important; font-size: 13px; } " +
        "table.codegrid td { padding: 0!important; border: 0!important } " +
        "table td.linenumber { width: 40px!important; } "
    
      
        
        
          {filename}
        
        {plugins}
        
      
      
        
        
{xml.Unparsed(new CodeGrid(mfile, sourceEncoding).highlighted)}
{new StatementWriter(mfile).output}
} def header = { val css = """.meter { | height: 14px; | position: relative; | background: #BB2020; |} | |.meter span { | display: block; | height: 100%; | background-color: rgb(43,194,83); | background-image: -webkit-gradient( | linear, | left bottom, | left top, | color-stop(0, rgb(43,194,83)), | color-stop(1, rgb(84,240,84)) | ); | background-image: -webkit-linear-gradient( | center bottom, | rgb(43,194,83) 37%, | rgb(84,240,84) 69% | ); | background-image: -moz-linear-gradient( | center bottom, | rgb(43,194,83) 37%, | rgb(84,240,84) 69% | ); | background-image: -ms-linear-gradient( | center bottom, | rgb(43,194,83) 37%, | rgb(84,240,84) 69% | ); | background-image: -o-linear-gradient( | center bottom, | rgb(43,194,83) 37%, | rgb(84,240,84) 69% | ); | -webkit-box-shadow: | inset 0 2px 9px rgba(255,255,255,0.3), | inset 0 -2px 6px rgba(0,0,0,0.4); | -moz-box-shadow: | inset 0 2px 9px rgba(255,255,255,0.3), | inset 0 -2px 6px rgba(0,0,0,0.4); | position: relative; | overflow: hidden; |}""".stripMargin Scoverage Code Coverage {plugins} } def packageOverview(pack: MeasuredPackage): Node = { {header} {classesTable(pack.classes, addPath = false)} } def classesTable(classes: Iterable[MeasuredClass], addPath: Boolean): Node = { {classes.toSeq.sortBy(_.fullClassName) map classRow}
Class Source file Lines Methods Statements Invoked Coverage Branches Invoked Coverage
} def classRow(klass: MeasuredClass): Node = { val filename: String = { val fileRelativeToSource = new File(relativeSource(klass.source) + ".html") val path = fileRelativeToSource.getParent val value = fileRelativeToSource.getName if (path.ne("")) { // (Normalise the pathSeparator to "/" in case we are running on Windows) fileRelativeToSource.toString.replace(File.separator, "/") } else { value } } val statement0f = Math.round(klass.statementCoveragePercent).toInt.toString val branch0f = Math.round(klass.branchCoveragePercent).toInt.toString {klass.displayClassName} {klass.statements.headOption.map(_.source.split(File.separatorChar).last).getOrElse("")} {klass.loc.toString} {klass.methodCount.toString} {klass.statementCount.toString} {klass.invokedStatementCount.toString}
{klass.statementCoverageFormatted} % {klass.branchCount.toString} {klass.invokedBranchesCount.toString}
{klass.branchCoverageFormatted} % } def packageList(coverage: Coverage): Node = { Scoverage Code Coverage {plugins} {coverage.packages.map(arg => )}
All packages {coverage.statementCoverageFormatted}%
{arg.name} {arg.statementCoverageFormatted}%
} def risks(coverage: Coverage, limit: Int) = { {coverage.risks(limit).map(klass => )}
Class Lines Methods Statements Statement Rate Branches Branch Rate
{klass.displayClassName} {klass.loc.toString} {klass.methodCount.toString} {klass.statementCount.toString} {klass.statementCoverageFormatted} % {klass.branchCount.toString} {klass.branchCoverageFormatted} %
} def packages2(coverage: Coverage) = { val rows = coverage.packages.map(arg => { {arg.name} {arg.invokedClasses.toString} / {arg.classCount} ( {arg.classCoverage.toString} %) {arg.invokedStatements.toString()} / {arg.statementCount} ( {arg.statementCoverageFormatted} %) }) {rows}
} def overview(coverage: Coverage): Node = { {header}
SCoverage generated at {new Date().toString}
{stats(coverage)}
{classesTable(coverage.classes, addPath = true)}
} def stats(coverage: Coverage): Node = { val statement0f = Math.round(coverage.statementCoveragePercent).toInt.toString val branch0f = Math.round(coverage.branchCoveragePercent).toInt.toString
Lines of code: {coverage.loc.toString} Files: {coverage.fileCount.toString} Classes: {coverage.classCount.toString} Methods: {coverage.methodCount.toString}
Lines per file: {coverage.linesPerFileFormatted} Packages: {coverage.packageCount.toString} Classes per package: {coverage.avgClassesPerPackageFormatted} Methods per class: {coverage.avgMethodsPerClassFormatted}
Total statements: {coverage.statementCount.toString} Invoked statements: {coverage.invokedStatementCount.toString} Total branches: {coverage.branchCount.toString} Invoked branches: {coverage.invokedBranchesCount.toString}
Ignored statements: {coverage.ignoredStatementCount.toString}
Statement coverage: {coverage.statementCoverageFormatted} %
Branch coverage: {coverage.branchCoverageFormatted} %
} def plugins = { } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy