sbt / sbt-remote-control

Create and manage sbt process using unicorns and forks
Other
74 stars 14 forks source link

Add serialization logic for sbt.Attributed #284

Closed kiritsuku closed 9 years ago

kiritsuku commented 9 years ago
kiritsuku commented 9 years ago

This pickling stuff is more complicated than anything else ;)

I have now:

final case class Attributed[T](data: T)
object Attributed {

  implicit def unpickler[T: Unpickler]: Unpickler[Attributed[T]] = new Unpickler[Attributed[T]] {

    override val tag = implicitly[FastTypeTag[Attributed[T]]]

    override def unpickle(tag: String, reader: PReader): Any = {
      reader.hintTag(this.tag)
      reader.hintStaticallyElidedType()
      reader.pinHints()

      val r = reader.readField("data")
      val a = implicitly[Unpickler[T]].unpickleEntry(r).asInstanceOf[T]

      reader.unpinHints()
      Attributed(a)
    }
  }

  implicit def pickler[T: Pickler]: Pickler[Attributed[T]] = new Pickler[Attributed[T]] {

    override val tag = implicitly[FastTypeTag[Attributed[T]]]

    override def pickle(a: Attributed[T], builder: PBuilder): Unit = {
      builder.hintTag(tag)
      builder.hintStaticallyElidedType()
      builder.pinHints()

      builder.beginEntry(a)
      builder.putField("data", b ⇒ implicitly[Pickler[T]].pickle(a.data, b))
      builder.endEntry()

      builder.unpinHints()
    }
  }
}

And now I can't unpickle anymore (and I'm not sure if pickle is correct):

scala> att
res0: util.Attributed[java.io.File] = Attributed(/a/b/c)

scala> att.pickle
res1: pickling.json.pickleFormat.PickleType =
JSONPickle({
  "data": "file:\/a\/b\/c"
})

scala> res1.unpickle[Attributed[File]]
java.util.NoSuchElementException: key not found: java.io.File
jsuereth commented 9 years ago

Don't pin/unpin this hints. I don't think that's needed.... That's bascially saying you can't use any other hint, which is inaccurate. The underyling pickler should know and be able to hint its tag appropriately.

kiritsuku commented 9 years ago

When I don't pin/unpin, I get a NullPointerException on builder.putField

jsuereth commented 9 years ago

Right, so what you want is this:

builder.hintTag(tag)
builder.beginEntry(a)
builder.putField("data", { b =>
  val p = implicitly[Pickler[T]]
  b.hintTag(p.tag)
  b.hintStaticallyElidedType()
  p.pickle(a.data, b))
}
builder.endEntry()
kiritsuku commented 9 years ago

I corrected the pickling logic.

jsuereth commented 9 years ago

Sorry for takign so long to get back this. Your fixes look great. I need to document elided types and expectations in a doc, so we dont' mess it up, as I've confused myself over how they work.

kiritsuku commented 9 years ago

@dancingrobot84 added some cleanups and also removed the hintStaticallyElidedType

jsuereth commented 9 years ago

@sschaef This LGTM, but isn't merging. Could you rebase this on master and force push the change? If you need any help, I can tackle this.

kiritsuku commented 9 years ago

I rebased to master.

kiritsuku commented 9 years ago

I don't know if it is possible to configure, but it would be nice if the build bot would send a notification if the build was successful or not.

jsuereth commented 9 years ago

The .Travis.yml has the address to notify. If you figure out how to email the submitter of a commit, I'd turn it on. Otherwise it all just spams me