.scala-fortify_2.13.15.1.1.4.source-code.FortifyComponent.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright © 2016-2024 Lightbend, Inc. All rights reserved.
* No information contained herein may be reproduced or transmitted in any form
* or by any means without the express written permission of Lightbend, Inc.
*/
package com.lightbend.tools.fortify.plugin
import java.io.{File, FileOutputStream, OutputStreamWriter, PrintWriter}
import java.nio.charset.StandardCharsets
import scala.tools.nsc
import nsc.plugins._
abstract class FortifyComponent extends PluginComponent with PluginOptions {
override def description = "compiler phase for Scala -> Fortify NST"
/** the following two members override abstract members in Transform */
val phaseName: String = "compile-to-nst"
/** Create a new phase which applies transformer */
def newPhase(prev: nsc.Phase): StdPhase = new FortifyPhase(prev)
val session = collection.mutable.Buffer[SessionWriter.Entry]()
/** The phase defined by this transform */
class FortifyPhase(prev: nsc.Phase) extends StdPhase(prev) {
val translator = new Translator[global.type](global, showSourceInfo)
override def apply(unit: global.CompilationUnit): Unit = {
if (unit.source.file.file == null) // e.g. in REPL
return
if (Paths.isExcluded(excludes, unit.source.file.file))
return
val actualOutputDir = outputDir.getOrElse(new File("."))
val outputPath =
Paths.sourcePathToNstPath(unit.source.file.file, actualOutputDir)
outputPath.getParentFile.mkdirs()
val writer: java.io.PrintWriter =
new scala.reflect.io.File(outputPath)(io.Codec.UTF8).printWriter()
session +=
SessionWriter.Entry(unit.source.file.file, outputPath, countLines(unit.source.file.file))
val (originalPath, lineMapper) = {
val twirl = new Twirl(unit.source.content.mkString)
twirl.originalPath match {
case Some(path) =>
(path, twirl.mapLine _)
case None =>
(unit.source.file.path, identity[Int] _)
}
}
try translator.apply(originalPath, unit.source, unit.body, lineMapper, writer)
finally writer.close()
}
override def run(): Unit = {
super.run()
if (session.isEmpty) // e.g. in REPL
return
for (id <- buildId; dir <- outputDir)
SessionWriter.synchronized {
val sessionFile =
new File(dir.getParent, s"$id.scasession.increment")
// maybe a bit janky to reuse this flag for this, but we don't want this
// noise when doing development work
if (!suppressEntitlementCheck)
println(s"scala-fortify: writing translated files to ${dir.getAbsolutePath}")
val exists = sessionFile.exists
val foStream = new FileOutputStream(sessionFile, true) // append = true
val osWriter = new OutputStreamWriter(foStream, StandardCharsets.UTF_8)
val writer = new PrintWriter(osWriter)
// not sure if it's important to match the Java translator's behavior
// of starting a new file with a blank line, but we might as well
if (!exists)
writer.println()
try SessionWriter.write(
writer,
buildId.getOrElse(""),
session.toSeq,
global.settings.encoding.value)
finally writer.close()
}
}
}
private def countLines(file: File): Int = {
val source = io.Source.fromFile(file)(global.settings.encoding.value)
try source.getLines().size
finally source.close()
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy