SBT 错误的编译顺序

SBT incorrect order of compilation

TL/DR:检查最后两次提交和 运行 sbt clean compilehttps://github.com/mirelon/akka-in-action/tree/json/chapter2

有RestInterface.scala:

package com.goticks

import akka.actor._

import spray.routing._
import spray.http.StatusCodes
import spray.httpx.SprayJsonSupport._
import spray.routing.RequestContext
import akka.util.Timeout
import scala.concurrent.duration._
import scala.language.postfixOps

class RestInterface extends HttpServiceActor
                    with RestApi {
  def receive = runRoute(routes)
}

trait RestApi extends HttpService { actor: Actor =>
  import context.dispatcher
  import com.goticks.TicketProtocol._

  implicit val timeout = Timeout(10 seconds)
  import akka.pattern.ask

  def routes: Route =

    path("events") {
      get { requestContext =>
        context.actorOf(Props[Resu]).ask(GetEvents)
      }
    }

}

class Responder(requestContext:RequestContext) extends Actor {
  import TicketProtocol._

  def receive = {

    case Events(events) =>
      requestContext.complete(StatusCodes.OK, events)
      self ! PoisonPill

  }
}

和Resu.scala(注意Resu按字母顺序排在RestInterface之后)

package com.goticks

import akka.actor.Actor

class Resu extends Actor {
  import TicketProtocol._
  import spray.json._

  def receive = {

    case GetEvents => {
      println(Event(event = "E").toJson)
    }
  }
}

object TicketProtocol {
  import spray.json._

  case class Event(event:String)

  case object GetEvents

  case class Events(events:List[Event])

  object Event extends DefaultJsonProtocol {
    implicit val format = jsonFormat1(Event.apply)
  }

}

build.sbt:

name := "goticks"

version := "0.1-SNAPSHOT"

organization := "com.goticks"

scalaVersion := "2.11.1"

libraryDependencies ++= {
  val akkaVersion = "2.3.4"
  val sprayVersion = "1.3.1"
  Seq(
    "com.typesafe.akka" %% "akka-actor" % akkaVersion,
    "io.spray" %% "spray-can" % sprayVersion,
    "io.spray" %% "spray-routing" % sprayVersion,
    "io.spray" %% "spray-json" % "1.2.6"
  )
}

build.properties;

sbt.version=0.13.7

plugins.sbt:

resolvers += Classpaths.typesafeResolver

resolvers += "sbt-idea" at "http://mpeltonen.github.com/maven/"

addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")

addSbtPlugin("com.typesafe.sbt" % "sbt-start-script" % "0.10.0")

addSbtPlugin("com.typesafe.sbt" % "sbt-multi-jvm" % "0.3.8")

编译问题

当我运行sbt clean compile时,一切正常。但是当我将 Resu class 重构为 Ress 时(请注意 Ress 按字母顺序排列在 RestInterface 之前)(同时重命名其文件,可以在此处查看差异:https://github.com/mirelon/akka-in-action/commit/583ca801fb7d1564024eee2f98d57f03ecacc6e5),则出现编译错误:

[error] /home/miso/IdeaProjects/akka-in-action/chapter2/src/main/scala/com/goticks/Ress.scala:12: Cannot find JsonWriter or JsonFormat type class for com.goticks.TicketProtocol.Event
[error]       println(Event(event = "E").toJson)
[error]                                  ^
[error] one error found
[error] (compile:compile) Compilation failed

显然缺少一个隐含的 json 作者。可能是由于编译顺序不正确吗? sbt 能否按字母顺序编译 classes,忽略导入?

是的,sbt 总是按字母顺序编译。问题是 sbt 在运行编译器之前不知道文件之间的依赖关系。

您看到的是 Scala 编译器本身依赖于源文件的顺序。 Sbt 总是对源文件进行排序,因此您至少可以通过将代码置于有效的顺序来解决这些问题。

我不是 100% 确定你为什么会从一些隐式 + 宏 hackery 中遇到这样的问题,但这可能是错误的。