Skip to content

Commit

Permalink
Merge pull request sbt#140 from magneticflux-/feature/fix#127-add-fin…
Browse files Browse the repository at this point in the history
…al-modifier

Created a renderer that make final fields
  • Loading branch information
eed3si9n authored Oct 1, 2018
2 parents 7a3fc75 + 0aeb9e4 commit 1acf504
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 0 deletions.
88 changes: 88 additions & 0 deletions src/main/scala/sbtbuildinfo/ScalaFinalCaseObjectRenderer.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package sbtbuildinfo

case class ScalaFinalCaseObjectRenderer(options: Seq[BuildInfoOption], pkg: String, obj: String) extends ScalaRenderer {

override def fileType = BuildInfoType.Source
override def extension = "scala"
val traitNames = options.collect{case BuildInfoOption.Traits(ts @ _*) => ts}.flatten
val objTraits = if (traitNames.isEmpty) "" else " extends " ++ traitNames.mkString(" with ")

// It is safe to add `import scala.Predef` even though we need to keep `-Ywarn-unused-import` in mind
// because we always generate code that has a reference to `String`. If the "base" generated code were to be
// changed and no longer contain a reference to `String`, we would need to remove `import scala.Predef` and
// fully qualify every reference. Note it is NOT safe to use `import scala._` because of the possibility of
// the project using `-Ywarn-unused-import` because we do not always generated references that are part of
// `scala` such as `scala.Option`.
def header = List(
s"package $pkg",
"",
"import scala.Predef._",
"",
s"/** This object was generated by sbt-buildinfo. */",
s"case object $obj$objTraits {"
)

def footer = List("}")

override def renderKeys(buildInfoResults: Seq[BuildInfoResult]) =
header ++
buildInfoResults.flatMap(line) ++ Seq(toStringLines(buildInfoResults)) ++
toMapLine(buildInfoResults) ++ toJsonLine ++
footer

private def line(result: BuildInfoResult): Seq[String] = {
import result._
val typeDecl = getType(result.typeExpr) map { ": " + _ } getOrElse ""

List(
s" /** The value is ${quote(value)}. */",
s" final val $identifier$typeDecl = ${quote(value)}"
)
}

def toStringLines(results: Seq[BuildInfoResult]): String = {
val idents = results.map(_.identifier)
val fmt = idents.map("%s: %%s" format _).mkString(", ")
val vars = idents.mkString(", ")
s""" override val toString: String = {
| "$fmt".format(
| $vars
| )
| }""".stripMargin
}

def toMapLine(results: Seq[BuildInfoResult]): Seq[String] =
if (options.contains(BuildInfoOption.ToMap) || options.contains(BuildInfoOption.ToJson))
results
.map(result => " \"%s\" -> %s".format(result.identifier, result.identifier))
.mkString(" val toMap: Map[String, Any] = Map[String, Any](\n", ",\n", ")")
.split("\n")
.toList ::: List("")
else Nil

def toJsonLine: Seq[String] =
if (options contains BuildInfoOption.ToJson)
List(
"""| private def quote(x: Any): String = "\"" + x + "\""
| private def toJsonValue(value: Any): String = {
| value match {
| case elem: Seq[_] => elem.map(toJsonValue).mkString("[", ",", "]")
| case elem: Option[_] => elem.map(toJsonValue).getOrElse("null")
| case elem: Map[String, Any] => elem.map {
| case (k, v) => toJsonValue(k) + ":" + toJsonValue(v)
| }.mkString("{", ", ", "}")
| case d: Double => d.toString
| case f: Float => f.toString
| case l: Long => l.toString
| case i: Int => i.toString
| case s: Short => s.toString
| case bool: Boolean => bool.toString
| case str: String => quote(str)
| case other => quote(other.toString)
| }
| }
|
| val toJson: String = toJsonValue(toMap)""".stripMargin)
else Nil

}
79 changes: 79 additions & 0 deletions src/sbt-test/sbt-buildinfo/finalcaseobjectrenderer/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import sbtbuildinfo.ScalaFinalCaseObjectRenderer

lazy val check = taskKey[Unit]("checks this plugin")

lazy val root = (project in file(".")).
enablePlugins(BuildInfoPlugin).
settings(
name := "helloworld",
version := "0.1",
scalaVersion := "2.12.6",
TaskKey[Classpath]("someCp") := Seq(Attributed.blank(file("/tmp/f.txt"))),
buildInfoKeys := BuildInfoKey.ofN(
name,
BuildInfoKey.map(version) { case (n, v) => "projectVersion" -> v.toDouble },
scalaVersion,
ivyXML,
homepage,
licenses,
apiMappings,
isSnapshot,
"year" -> 2012,
"sym" -> 'Foo,
BuildInfoKey.action("buildTime") { 1234L },
TaskKey[Classpath]("someCp"),
target),
buildInfoOptions += BuildInfoOption.Traits("traits.MyCustomTrait"),
buildInfoRenderFactory := ScalaFinalCaseObjectRenderer.apply,
buildInfoPackage := "hello",
homepage := Some(url("http://example.com")),
licenses := Seq("MIT License" -> url("https://github.com/sbt/sbt-buildinfo/blob/master/LICENSE")),
scalacOptions ++= Seq("-Ywarn-unused-import", "-Xfatal-warnings", "-Yno-imports"),
libraryDependencies += "org.scala-lang.modules" %% "scala-xml" % "1.0.5",
check := {
val f = (sourceManaged in Compile).value / "sbt-buildinfo" / ("%s.scala" format "BuildInfo")
val lines = scala.io.Source.fromFile(f).getLines.toList
lines match {
case """package hello""" ::
"""""" ::
"""import scala.Predef._""" ::
"""""" ::
"""/** This object was generated by sbt-buildinfo. */""" ::
"""case object BuildInfo extends traits.MyCustomTrait {""" ::
""" /** The value is "helloworld". */"""::
""" final val name: String = "helloworld"""" ::
""" /** The value is 0.1. */"""::
""" final val projectVersion = 0.1""" ::
""" /** The value is "2.12.6". */""" ::
""" final val scalaVersion: String = "2.12.6"""" ::
""" /** The value is scala.collection.Seq(). */""" ::
""" final val ivyXML: scala.xml.NodeSeq = scala.collection.Seq()""" ::
""" /** The value is scala.Some(new java.net.URL("http://example.com")). */""" ::
""" final val homepage: scala.Option[java.net.URL] = scala.Some(new java.net.URL("http://example.com"))""" ::
""" /** The value is scala.collection.Seq(("MIT License" -> new java.net.URL("https://github.com/sbt/sbt-buildinfo/blob/master/LICENSE"))). */""" ::
""" final val licenses: scala.collection.Seq[(String, java.net.URL)] = scala.collection.Seq(("MIT License" -> new java.net.URL("https://github.com/sbt/sbt-buildinfo/blob/master/LICENSE")))""" ::
""" /** The value is Map(). */""" ::
""" final val apiMappings: Map[java.io.File, java.net.URL] = Map()""" ::
""" /** The value is false. */""" ::
""" final val isSnapshot: scala.Boolean = false""" ::
""" /** The value is 2012. */""" ::
""" final val year: scala.Int = 2012""" ::
""" /** The value is 'Foo. */""" ::
""" final val sym: scala.Symbol = 'Foo""" ::
""" /** The value is 1234L. */""" ::
""" final val buildTime: scala.Long = 1234L""" ::
""" /** The value is scala.collection.Seq(new java.io.File("/tmp/f.txt")). */""" ::
""" final val someCp: scala.collection.Seq[java.io.File] = scala.collection.Seq(new java.io.File("/tmp/f.txt"))""" ::
targetInfoComment ::
targetInfo :: // """
""" override val toString: String = {""" ::
""" "name: %s, projectVersion: %s, scalaVersion: %s, ivyXML: %s, homepage: %s, licenses: %s, apiMappings: %s, isSnapshot: %s, year: %s, sym: %s, buildTime: %s, someCp: %s, target: %s".format(""" ::
""" name, projectVersion, scalaVersion, ivyXML, homepage, licenses, apiMappings, isSnapshot, year, sym, buildTime, someCp, target""" ::
""" )""" ::
""" }""" ::
"""}""" :: Nil if targetInfo contains "target: java.io.File = new java.io.File(" =>
case _ => sys.error("unexpected output: \n" + lines.mkString("\n"))
}
()
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
val pluginVersion = System.getProperty("plugin.version")
if(pluginVersion == null)
throw new RuntimeException("""|The system property 'plugin.version' is not defined.
|Specify this property using the scriptedLaunchOpts -D.""".stripMargin)
else addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % pluginVersion)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package traits

trait MyCustomTrait {}
4 changes: 4 additions & 0 deletions src/sbt-test/sbt-buildinfo/finalcaseobjectrenderer/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
> compile
$ exists target/scala-2.12/src_managed/main/sbt-buildinfo/BuildInfo.scala

> check

0 comments on commit 1acf504

Please sign in to comment.