web-dev-qa-db-fra.com

Déclenchement -Ywarn-used-import sur le fichier des itinéraires de lecture

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.

49
Ende Neu

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.

4
danielnixon

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.

3
Matt Stephens

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.

0
Pavel