diff options
Diffstat (limited to 'plugins/proguard/build')
-rw-r--r-- | plugins/proguard/build/build.scala | 129 | ||||
-rw-r--r-- | plugins/proguard/build/build/build.scala | 13 |
2 files changed, 142 insertions, 0 deletions
diff --git a/plugins/proguard/build/build.scala b/plugins/proguard/build/build.scala new file mode 100644 index 0000000..5edd7a8 --- /dev/null +++ b/plugins/proguard/build/build.scala @@ -0,0 +1,129 @@ +package cbt_build.proguard +import cbt._ +import java.nio.file.Files._ +import java.net._ +import java.io._ +import scala.xml._ +class Build(val context: Context) extends Plugin with Scalafmt{ + override def dependencies = ( + super.dependencies ++ // don't forget super.dependencies here for scala-library, etc. + Resolver( mavenCentral ).bind( + MavenDependency("net.sf.proguard","proguard-base","5.3.2") + ) :+ libraries.captureArgs + ) + + def refcard = projectDirectory / "spec/refcard.html" + + /** downloads html proguard parameter specification */ + def updateSpec = { + System.err.println(lib.blue("downloading ")+refcard) + lib.download( + new URL("https://www.guardsquare.com/en/proguard/manual/refcard"), + refcard, + None, + replace = true + ) + System.err.println("simplifying html") + val tables = ( + loadSloppyHtml( new String( readAllBytes( refcard.toPath ) ) ) \ "body" \\ "table" + ) + val s = ( + "<html><body>\n" ++ tables.map( table => + " <table>\n" ++ (table \\ "tr").map( tr => + " <tr>\n" ++ (tr \\ "td").map( td => + " <td>" ++ td.text ++ "</td>\n" + ).mkString ++ " </tr>\n" + ).mkString ++ " </table>\n" + ).mkString ++ "</body></html>\n" + ) + System.err.println("writing file") + write( refcard.toPath, s.getBytes) + } + + private def loadSloppyHtml(html: String): scala.xml.Elem = { + object XmlNotDownloadingDTD extends scala.xml.factory.XMLLoader[scala.xml.Elem] { + override def parser: javax.xml.parsers.SAXParser = { + val f = javax.xml.parsers.SAXParserFactory.newInstance() + f.setNamespaceAware(false) + f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + f.newSAXParser() + } + } + + val p = new org.ccil.cowan.tagsoup.Parser + val w = new StringWriter + p.setContentHandler(new org.ccil.cowan.tagsoup.XMLWriter(w)) + p.parse( + new org.xml.sax.InputSource( + new ByteArrayInputStream( "<!DOCTYPE[^<]*>".r.replaceFirstIn( html, "" ).getBytes ) + ) + ) + XmlNotDownloadingDTD.loadString( w.toString ) + } + + /** generates Scala code from parameter specification html */ + def generate = { + val tables = XML.loadFile(refcard) \\ "table" + def cellsToSeq( node: Node ) = (node \\ "tr").map( + tr => (tr \\ "td").map( td => td.text ) match { + case Seq( k, v ) => k -> v + } + ) + val options = cellsToSeq( tables(0) ).collect{ + case (k, v) if k.startsWith("-") => k.drop(1).split(" ").toList -> v + }.map{ + case (k,description) => + val name = k(0) + val tpe = k.drop(1).mkString(" ") match { + case "" => "Boolean" + case "n" => "Int" + case "class_specification" | "version" | "optimization_filter" => "String" + case "filename" | "directoryname" => "File" + case "class_path" if name === "outjars" => "Seq[File]" + case "class_path" => "ClassPath" + case "[filename]" => "Option[File]" + case "[directory_filter]" | "[package_filter]" | "[package_name]" + | "[attribute_filter]" | "[string]" | "[class_filter]" | "[file_filter]" + => "Option[String]" + case "[,modifier,...] class_specification" => "(Seq[KeepOptionModifier], String)" + } + (name, tpe, description.split("\n").mkString(" ")) + }.sortBy(_._1) + + val docs = options.map{ + case (name, tpe, description) => s" @param $name $description" + }.mkString("\n") + + val args = options.map{ + case v@(_, "Boolean", _) => v -> Some("false") + case v@("injars" | "libraryjars" | "keep" | "outjars", _, _) => v -> None + case (n, t, d) => (n, s"Option[$t]", d) -> Some("None") + }.map{ + case ((name, tpe, description), default) => s" $name: $tpe" ++ default.map(" = "++_).getOrElse("") + }.mkString(",\n") + + val keepModifiers = cellsToSeq( tables(2) ).map{ + case (k, v) => s""" /** $v */\n object $k extends KeepOptionModifier("$k")""" + }.mkString("\n") + + val template = new String( + readAllBytes( + (projectDirectory / "templates/Proguard.scala").toPath + ) + ) + val code = ( + "/* automatically generated by build/build.scala from templates/Proguard.scala */\n" ++ + template + .replace ("/* ${generated-top-level} */", keepModifiers ) + .replace( "${generated-docs}", docs ) + .replace( "/* ${generated-args} */", args ) + ) + + val targetFile = projectDirectory / "src/generated/Proguard.scala" + targetFile.getParentFile.mkdirs + write( targetFile.toPath, code.getBytes ) + + scalafmt + compile + } +} diff --git a/plugins/proguard/build/build/build.scala b/plugins/proguard/build/build/build.scala new file mode 100644 index 0000000..7928cfa --- /dev/null +++ b/plugins/proguard/build/build/build.scala @@ -0,0 +1,13 @@ +package cbt_build.proguard.build +import cbt._ +class Build(val context: Context) extends BuildBuild{ + override def dependencies = ( + super.dependencies ++ // don't forget super.dependencies here for scala-library, etc. + Resolver( mavenCentral, sonatypeReleases ).bind( + ScalaDependency("org.scala-lang.modules","scala-xml","1.0.5"), + "org.ccil.cowan.tagsoup" % "tagsoup" % "1.2.1" + ) ++ Seq( + plugins.scalafmt + ) + ) +} |