Skip to content
This repository has been archived by the owner on Feb 20, 2019. It is now read-only.

Commit

Permalink
stop compiling when pickler fields are empty. Fixes #60, #263
Browse files Browse the repository at this point in the history
Current implementation uses reflectivelyWithoutGetter to try accessing
primary constructor params by name, and is allowed to fail silently.
This ends up generating empty objects for Java classes like
java.lang.Byte.

- This does not attempt reflection unless we have a known param.
- When the list of fields are non-empty, but the pickler generates zero
fields, it will raise exception to fail the macro.
  • Loading branch information
eed3si9n committed Feb 10, 2015
1 parent 4562538 commit 189ca9e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
15 changes: 12 additions & 3 deletions core/src/main/scala/pickling/Macros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import ir._
trait TypeAnalysis extends Macro {
import c.universe._

def isStaticOnly: Boolean =
c.inferImplicitValue(typeOf[IsStaticOnly]) != EmptyTree

def isCaseClass(sym: TypeSymbol): Boolean =
sym.isClass && sym.asClass.isCaseClass

Expand Down Expand Up @@ -188,7 +191,8 @@ trait PicklerMacros extends Macro with PickleMacros with FastTypeTagMacros {
scala.pickling.PickleOps(out).pickleInto(b)
)
""")
} else (nonLoopyFields ++ loopyFields).flatMap(fir => {
}
else (nonLoopyFields ++ loopyFields).flatMap(fir => {
// for each field, compute a tree for pickling it
// (or empty list, if impossible)

Expand Down Expand Up @@ -225,11 +229,16 @@ trait PicklerMacros extends Macro with PickleMacros with FastTypeTagMacros {
else reflectively("picklee", fir)(fm => putField(q"$fm.get.asInstanceOf[${fir.tpe}]"))
} else if (fir.javaSetter.isDefined) {
List(putField(getField(fir)))
} else {
} else if (fir.isParam) {
reflectivelyWithoutGetter("picklee", fir)(fvalue =>
tryPutField(q"$fvalue.asInstanceOf[scala.util.Try[${fir.tpe}]]"))
} else {
Nil
}
})
if (cir.fields.nonEmpty && putFields.isEmpty) {
throw PicklingException("No fields are captured. You need a custom pickler to handle this.")
}
val endEntry = q"builder.endEntry()"
if (shouldBotherAboutSharing(tpe)) {
q"""
Expand Down Expand Up @@ -298,7 +307,7 @@ trait PicklerMacros extends Macro with PickleMacros with FastTypeTagMacros {

case tpe1 if sym.isClass =>
def pickleAfterDispatch(excludeSelf: Boolean) = {
val dispatchTree = if (c.inferImplicitValue(typeOf[IsStaticOnly]) != EmptyTree) { // StaticOnly *imported*
val dispatchTree = if (isStaticOnly) { // StaticOnly *imported*
val notClosedReasons = whyNotClosed(sym.asType)
if (notClosedReasons.nonEmpty)
c.abort(c.enclosingPosition, s"cannot generate fully static pickler because: ${notClosedReasons.mkString(", ")}")
Expand Down
20 changes: 20 additions & 0 deletions core/src/test/scala/pickling/neg/java-field-fail.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package scala.pickling.javafieldfail

import scala.pickling._
import NegativeCompilation._
import org.scalatest.FunSuite

class JavaFieldFailTest extends FunSuite {
test("main") {
expectError("Cannot generate") {
"""import _root_.scala.pickling._
|import _root_.scala.pickling.Defaults._
|import _root_.scala.pickling.json._
|import _root_.scala.pickling.static._
|
|val x: java.lang.Byte = 10.toByte
|
|val p = x.pickle""".stripMargin
}
}
}

0 comments on commit 189ca9e

Please sign in to comment.