wake-up-neo.com

-Ywarn-unbenutzte-Import-Triggerung auf Play-Routen-Datei

Ich möchte -Xfatal-warnings und -Ywarn-unused-import verwenden können. Das Problem ist, dass der Compiler einen Fehler in der Datei auslöst, die die Wiedergaberouten für meine Anwendung enthält:

[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)

gleiches gilt für andere Strecken.

Ist es möglich, scalac anzuweisen, eine Datei zu ignorieren?

Die Scala-Version ist 2.11.8.

49
Ende Neu

Eine schreckliche "Lösung" könnte darin bestehen, diese nicht verwendeten Importe zu entfernen, nachdem die Routen generiert wurden, aber bevor die Kompilierungsaufgabe ausgeführt wird. Hier ist eine Skizze:

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())
}

Sie werden dann die Aufgabenabhängigkeiten sortieren wollen:

// 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

Sie müssen wahrscheinlich auch TwirlKeys.templateImports auf eine konservative Liste setzen, bevor Sie -Ywarn-unused-import aktivieren. So etwas hängt davon ab, welche Typen in Ihren Ansichten verwendet werden:

TwirlKeys.templateImports := Seq("play.api.mvc._", "play.api.i18n.Messages", "controllers.routes")

Ich musste auch nicht verwendete TemplateMagic-Importe aus Twirl-Vorlagen (YMMV) klopfen:

  removeUnusedImports(
    _ / "twirl" ** "*.template.scala",
    Set("import play.twirl.api.TemplateMagic._"),
    Map())

Stellen Sie in diesem Fall sicher, dass die Aufgabenabhängigkeiten ordnungsgemäß eingerichtet sind.

Das funktioniert bei mir. Scala 2.11.8, Play 2.5.10, sowohl -Xfatal-warnings als auch -Ywarn-unused-import aktiviert. Es ist abscheulich, aber es funktioniert.

4
danielnixon

Ich bin gerade auf das gleiche Problem mit Scala 2.12 und Play 2.6 gestoßen (die Sie wahrscheinlich jetzt verwenden).

Ein Scala-Compiler-Plugin namens Silencer sortiert es aus: https://github.com/ghik/silencer

Fügen Sie in build.sbt die folgende Abhängigkeit hinzu:

val silencerVersion = "1.2.1"

libraryDependencies ++= Seq(
    compilerPlugin("com.github.ghik" %% "silencer-plugin" % silencerVersion),
    "com.github.ghik" %% "silencer-lib" % silencerVersion % Provided
)

Dann füge hinzu (auch in build.sbt):

scalacOptions += "-P:silencer:globalFilters=Unused import"

Der Text nach dem globalFilters= ist eine Liste von Regex-Übereinstimmungen für Compiler-Warnungen, die stummgeschaltet werden sollen. Diese können durch Kommas getrennt werden. Möglicherweise müssen Sie den regulären Ausdruck für Ihren eigenen Fall optimieren, aber ich fand, dass das obige Beispiel gut funktioniert hat.

Dies bedeutet, dass alle Warnungen zu "Nicht verwendetem Import" stummgeschaltet werden. Wenn Sie es jedoch gewohnt sind, Ihren Code (ctrl+alt+L in Intellij) automatisch zu formatieren, einschließlich des Aufräumens nicht verwendeter Importe, sollte dies kein Problem verursachen.

3
Matt Stephens

Hier ist eine andere Option (möglicherweise schlechter als die von Danielnixon)

Ich habe Folgendes zu build.sbt hinzugefügt:

import CustomGenerator._

import play.sbt.routes.RoutesKeys
RoutesKeys.routesImport := Seq.empty
routesGenerator := ModifiedInjectedRoutesGenerator

Dann fügte dies zu project/CustomGenerator.scala hinzu (immer oberste Ebene 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+"
  }
}

Das Play sbt Plugin generiert einen Routencode (zu sehen unter target/scala-2.11/routes). Dieses Code-Snippet entfernt oder fügt alle nicht verwendeten Importe ein. Möglicherweise müssen Sie es für Ihre Routen anpassen.

0
Pavel