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

mill.contrib.checkstyle.CheckstyleXsltModule.scala Maven / Gradle / Ivy

The newest version!
package mill
package contrib.checkstyle

import javax.xml.transform.TransformerFactory
import javax.xml.transform.stream.{StreamResult, StreamSource}

/**
 * Extends [[CheckstyleModule]] with the ability to generate [[CheckstyleXsltReport]]s.
 */
trait CheckstyleXsltModule extends CheckstyleModule {

  /**
   * Runs [[CheckstyleModule.checkstyle]] and uses [[CheckstyleModule.checkstyleOutput]] to generate [[checkstyleXsltReports]].
   */
  override def checkstyle(@mainargs.arg checkstyleArgs: CheckstyleArgs): Command[Int] =
    Task.Command {
      val (output, exitCode) = checkstyle0(false, checkstyleArgs.sources)()

      val checkOutput = checkstyleOutput().path

      if (os.exists(checkOutput)) {
        checkstyleXsltReports().foreach {
          case CheckstyleXsltReport(xslt, output) =>
            val xsltSource = new StreamSource(xslt.path.getInputStream)
            xsltSource.setSystemId(
              xslt.path.toIO
            ) // so that relative URI references can be resolved

            val checkSource =
              new StreamSource(checkOutput.getInputStream)

            val outputResult =
              new StreamResult(os.write.outputStream(output.path, createFolders = true))

            T.log.info(s"transforming checkstyle output report with $xslt")

            TransformerFactory.newInstance()
              .newTransformer(xsltSource)
              .transform(checkSource, outputResult)

            T.log.info(s"transformed output report at $output")
        }
      }

      checkstyleHandleErrors(checkstyleArgs.stdout, checkstyleArgs.check, exitCode, output)
    }

  /**
   * Necessary in order to allow XSLT transformations on the results
   */
  final override def checkstyleFormat: T[String] = "xml"

  /**
   * Folder containing the XSLT transformations. Defaults to `checkstyle-xslt`
   * in  the workspace root, but can be overriden on a per-module basis
   */
  def checkstyleXsltfFolder = Task.Source(T.workspace / "checkstyle-xslt")

  /**
   * Set of [[CheckstyleXsltReport]]s.
   *
   * The default implementation maps XSLT files, under `checkstyle-xslt`, as depicted below:
   * {{{
   *
   * checkstyle-xslt
   *  ├─ html
   *  │   ├─ xslt0.xml
   *  │   └─ xslt1.xml
   *  └─ pdf
   *      ├─ xslt1.xml
   *      └─ xslt2.xml
   *
   * html/xslt0.xml -> xslt0.html
   * html/xslt1.xml -> xslt1.html
   * pdf/xslt1.xml  -> xslt1.pdf
   * pdf/xslt2.xml  -> xslt2.pdf
   *
   * }}}
   */
  def checkstyleXsltReports: T[Set[CheckstyleXsltReport]] = Task {
    val dir = checkstyleXsltfFolder().path

    if (os.exists(dir)) {
      val dest = T.dest
      os.list(dir)
        .iterator
        .filter(os.isDir)
        .flatMap(childDir =>
          os.list(childDir)
            .iterator
            .filter(os.isFile)
            .filter(_.ext == "xml")
            .map(xslt =>
              CheckstyleXsltReport(
                PathRef(xslt),
                PathRef(dest / s"${xslt.baseName}.${childDir.last}")
              )
            )
        )
        .toSet
    } else {
      T.log.info(s"expected XSLT files under $dir")
      Set.empty[CheckstyleXsltReport]
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy