Je veux pouvoir utiliser -Xfatal-warnings
et -Ywarn-unused-import
, le problème est que le compilateur déclenche une erreur sur le fichier qui contient les routes de lecture de mon application:
[error] /path/to/app/conf/routes: Unused import
[error] /path/to/app/conf/routes: Unused import
[error] /path/to/app/conf/routes:1: Unused import
[error] GET /document/:id my.app.controllers.MyController.getById(id: Int)
il en va de même pour les autres itinéraires.
Est-il possible de dire à scalac d'ignorer un fichier?
La version Scala est 2.11.8
.
Une "solution" horrible pourrait être de supprimer ces importations inutilisées après la génération des itinéraires mais avant l'exécution de la tâche de compilation. Voici un croquis:
lazy val optimizeRoutesImports = taskKey[Unit]("Remove unused imports from generated routes sources.")
optimizeRoutesImports := {
def removeUnusedImports(targetFiles: (File) => PathFinder, linesToRemove: Set[String], linesToReplace: Map[String, String]) = {
val files = targetFiles(crossTarget.value).get
files foreach { file =>
val lines = sbt.IO.readLines(file)
val updatedLines = lines map { line =>
linesToReplace.getOrElse(line, line)
} filterNot { line =>
linesToRemove.contains(line.trim)
}
sbt.IO.writeLines(file, updatedLines, append = false)
}
}
removeUnusedImports(
_ / "routes" / "main" / "controllers" / "ReverseRoutes.scala",
Set("import ReverseRouteContext.empty"),
Map(
"import play.api.mvc.{ QueryStringBindable, PathBindable, Call, JavascriptLiteral }" ->
"import play.api.mvc.{ QueryStringBindable, PathBindable, Call }",
"import play.core.routing.{ HandlerDef, ReverseRouteContext, queryString, dynamicString }" ->
"import play.core.routing.{ ReverseRouteContext, queryString, dynamicString }"
)
)
removeUnusedImports(
_ / "routes" / "main" / "controllers" / "javascript" / "JavaScriptReverseRoutes.scala",
Set(
"import play.core.routing.{ HandlerDef, ReverseRouteContext, queryString, dynamicString }",
"import ReverseRouteContext.empty"
),
Map(
"import play.api.mvc.{ QueryStringBindable, PathBindable, Call, JavascriptLiteral }" ->
"import play.api.mvc.{ QueryStringBindable, PathBindable }"
)
)
removeUnusedImports(
_ / "routes" / "main" / "router" / "Routes.scala",
Set("import play.core.j._"),
Map())
}
Vous aurez ensuite envie de trier les dépendances de tâches:
// Our optimize routes imports task depends on the routes task.
optimizeRoutesImports := (optimizeRoutesImports dependsOn (play.sbt.routes.RoutesKeys.routes in Compile)).value
// And compilation depends on the unused routes having been removed.
compile := ((compile in Compile) dependsOn optimizeRoutesImports).value
Vous devrez également probablement définir TwirlKeys.templateImports
sur une liste conservatrice avant d'activer -Ywarn-unused-import
. Quelque chose comme ça, selon les types utilisés dans vos vues:
TwirlKeys.templateImports := Seq("play.api.mvc._", "play.api.i18n.Messages", "controllers.routes")
J'ai également dû supprimer les importations TemplateMagic
non utilisées des modèles Twirl (YMMV):
removeUnusedImports(
_ / "twirl" ** "*.template.scala",
Set("import play.twirl.api.TemplateMagic._"),
Map())
Si vous faites cela, assurez-vous que les dépendances de tâches sont configurées correctement.
Cela fonctionne pour moi. Scala 2.11.8, Play 2.5.10, -Xfatal-warnings
et -Ywarn-unused-import
activés. C'est hideux, mais ça marche.
Je viens de rencontrer le même problème avec Scala 2.12 et Play 2.6 (que vous utilisez probablement maintenant).
Un compilateur Scala appelé Silencer trie le problème: https://github.com/ghik/silencer
Ajoutez la dépendance suivante dans build.sbt:
val silencerVersion = "1.2.1"
libraryDependencies ++= Seq(
compilerPlugin("com.github.ghik" %% "silencer-plugin" % silencerVersion),
"com.github.ghik" %% "silencer-lib" % silencerVersion % Provided
)
Ajoutez ensuite (également dans build.sbt):
scalacOptions += "-P:silencer:globalFilters=Unused import"
Le texte après le globalFilters=
est une liste de correspondances regex pour que les avertissements du compilateur à couper, puissent être séparés par des virgules. Vous aurez peut-être besoin d'ajuster la regex pour votre propre cas, mais j'ai trouvé que l'exemple ci-dessus fonctionnait bien.
Cela signifie que cela supprime tous les avertissements "Importation non utilisée", mais si vous avez l'habitude de formater automatiquement votre code (ctrl+alt+L
dans Intellij), y compris de ranger les importations inutilisées, cela ne devrait pas poser de problème.
Voici une autre option (éventuellement inférieure à celle de danielnixon)
J'ai ajouté ce qui suit à build.sbt
:
import CustomGenerator._
import play.sbt.routes.RoutesKeys
RoutesKeys.routesImport := Seq.empty
routesGenerator := ModifiedInjectedRoutesGenerator
Puis ajouté ceci à project/CustomGenerator.scala
(toujours le niveau supérieur project/
):
object CustomGenerator {
object ModifiedInjectedRoutesGenerator extends play.routes.compiler.RoutesGenerator {
import play.routes.compiler._
import play.routes.compiler.RoutesCompiler.RoutesCompilerTask
def generate(task: RoutesCompilerTask, namespace: Option[String], rules: List[Rule]): Seq[(String, String)] = {
play.routes.compiler.InjectedRoutesGenerator.generate(task, namespace, rules) map { case(key, value) =>
var v = value
if(key.endsWith("/ReverseRoutes.scala")) {
v = v.replace("import ReverseRouteContext.empty", "implicit val empty = ReverseRouteContext(Map())")
v = v.replace("import play.core.routing.{ HandlerDef, ReverseRouteContext, queryString, dynamicString }", "import play.core.routing.{ ReverseRouteContext, queryString }")
v = v.replace("import play.api.mvc.{ QueryStringBindable, PathBindable, Call, JavascriptLiteral }", "import play.api.mvc.{ QueryStringBindable, Call }")
}
if(key.endsWith("migrations/ReverseRoutes.scala")) {
v = v.replace("import play.api.mvc.{ QueryStringBindable, Call }", "import play.api.mvc.{ Call }")
v = v.replace("import play.core.routing.{ ReverseRouteContext, queryString }", "import play.core.routing.{ ReverseRouteContext }")
}
if(key.endsWith("/JavaScriptReverseRoutes.scala")) {
v = v.replace("import ReverseRouteContext.empty", "")
v = v.replace("import play.api.mvc.{ QueryStringBindable, PathBindable, Call, JavascriptLiteral }", "import play.api.mvc.{ QueryStringBindable, JavascriptLiteral }")
v = v.replace("import play.core.routing.{ HandlerDef, ReverseRouteContext, queryString, dynamicString }", "")
}
if(key.endsWith("migrations/javascript/JavaScriptReverseRoutes.scala")) {
v = v.replace("import play.api.mvc.{ QueryStringBindable, JavascriptLiteral }", "")
}
if(key.endsWith("/Routes.scala")) {
v = v.replace("import play.core.routing.HandlerInvokerFactory._", "")
v = v.replace("import play.core.j._", "")
v = v.replace("import ReverseRouteContext.empty", "implicit val empty = ReverseRouteContext(Map())")
}
(key, v)
}
}
def id: String = "injected+"
}
}
Le plug-in sbt génère un code de route (visible sous target/scala-2.11/routes
). Cet extrait de code supprime ou insère toutes les importations non utilisées. Vous devrez peut-être l'adapter à vos itinéraires.