Last active
February 24, 2023 23:49
-
-
Save ches/8f014efac55f61bbd39a14546bb8943f to your computer and use it in GitHub Desktop.
sbt mini-plugin for a tool needing compile-time only Maven dependencies, in this case custom WartRemover extension lints
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sbt._, Keys._ | |
import wartremover.WartRemover, WartRemover.autoImport.wartremoverClasspaths | |
trait CustomWartsKeys { | |
lazy val customWartsVersion = settingKey[String]("Version of the my-warts library dependency") | |
} | |
/** sbt plugin to integrate a package of custom WartRemover extension lints into a project's build. | |
* | |
* The purpose of an sbt plugin for this is to solve a problem with WartRemover's [[$custom-warts | |
* official guidance for custom warts]]: it uses `libraryDependencies` in the `Compile` classpath, | |
* which means that a published library project that uses custom warts in this way will have a POM | |
* runtime dependency on the custom warts and thus transitively on wartremover and scala-compiler | |
* as well. That is bloat, potential dependency headaches for users, and compilers in runtime could | |
* be exploited. | |
* | |
* This implementation follows [[$tool-deps the pattern for compile time-only tools]] in a | |
* dedicated configuration whose dependencies won't be on Runtime classpath during dev, nor | |
* included in POM. | |
* | |
* @define custom-warts https://web.archive.org/web/20220823060857/https://www.wartremover.org/doc/adding-your-own-warts.html | |
* @define tool-deps https://www.scala-sbt.org/1.x/docs/Faq.html#How+should+I+express+a+dependency+on+an+outside+tool+such+as+proguard%3F | |
*/ | |
object CustomWartsPlugin extends AutoPlugin { | |
override def requires = WartRemover | |
override def trigger = allRequirements | |
object autoImport extends CustomWartsKeys { | |
val CustomWarts: Configuration = config("custom-warts").hide | |
} | |
import autoImport._ | |
override def globalSettings: Seq[Def.Setting[_]] = List( | |
customWartsVersion := "0.1.0", // Use BuildInfo from your my-warts lib | |
) | |
override def projectConfigurations: Seq[Configuration] = Seq(CustomWarts) | |
override def projectSettings: Seq[Def.Setting[_]] = List( | |
libraryDependencies += "net.example" %% "my-warts" % customWartsVersion.value % CustomWarts, | |
// Construct config's classpath from dependencies scoped to it | |
CustomWarts / managedClasspath := { | |
val artifactTypes: Set[String] = (CustomWarts / classpathTypes).value | |
Classpaths.managedJars(CustomWarts, artifactTypes, update.value) | |
}, | |
wartremoverClasspaths ++= (CustomWarts / managedClasspath).value.files.map(_.toURI.toString).toList | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For WartRemover you should use the built-in
wartremoverDependencies
setting instead of this.I discovered the existence of that currently undocumented setting, which solves the problem described in the Gist, approximately two minutes after I made my plugin work… 😩
This pattern is reusable though as noted in the sbt FAQ link. Plugins don't need to be published, you can just drop the
.scala
file inproject/
.