Skip to content

Commit

Permalink
Fix parsing of primitive generic type information
Browse files Browse the repository at this point in the history
  • Loading branch information
Joni Freeman committed May 28, 2011
1 parent 0388577 commit 7a986ee
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 12 deletions.
2 changes: 1 addition & 1 deletion core/json/src/main/scala/net/liftweb/json/JsonParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ object JsonParser {
}
}

def near = new String(segment, (cur-20) max 0, (cur+20) min offset)
def near = new String(segment, (cur-20) max 0, 40 min (offset - cur + 20))

def release = segments.foreach(Segments.release)

Expand Down
12 changes: 6 additions & 6 deletions core/json/src/main/scala/net/liftweb/json/Meta.scala
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ private[json] object Meta {
val typeArgs = x.getActualTypeArguments.toList.zipWithIndex
.map { case (t, idx) =>
if (t == classOf[java.lang.Object])
ScalaSigReader.readConstructor(context.argName, context.containingClass, context.allArgs.map(_._1))
ScalaSigReader.readConstructor(context.argName, context.containingClass, idx, context.allArgs.map(_._1))
else t
}
Some(mkParameterizedType(x.getRawType, typeArgs))
Expand Down Expand Up @@ -231,13 +231,13 @@ private[json] object Meta {
}
try {
val names = nameReader.lookupParameterNames(c).map(clean)
val types = c.getGenericParameterTypes.toList map {
case v: TypeVariable[_] =>
val types = c.getGenericParameterTypes.toList.zipWithIndex map {
case (v: TypeVariable[_], idx) =>
val arg = typeArgs.getOrElse(v, v)
if (arg == classOf[java.lang.Object])
context.map(ctx => ScalaSigReader.readConstructor(ctx.argName, ctx.containingClass, ctx.allArgs.map(_._1))).getOrElse(arg)
context.map(ctx => ScalaSigReader.readConstructor(ctx.argName, ctx.containingClass, idx, ctx.allArgs.map(_._1))).getOrElse(arg)
else arg
case x => x
case (x, _) => x
}
names.toList.zip(types)
} catch {
Expand Down Expand Up @@ -266,7 +266,7 @@ private[json] object Meta {
case ptype: ParameterizedType => ptype.getActualTypeArguments()(i) match {
case c: Class[_] =>
if (c == classOf[java.lang.Object])
ScalaSigReader.readConstructor(context.argName, context.containingClass, context.allArgs.map(_._1))
ScalaSigReader.readConstructor(context.argName, context.containingClass, i, context.allArgs.map(_._1))
else c
case p: ParameterizedType => p.getRawType.asInstanceOf[Class[_]]
case x => fail("do not know how to get type parameter from " + x)
Expand Down
17 changes: 12 additions & 5 deletions core/json/src/main/scala/net/liftweb/json/ScalaSig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ package json
import scala.tools.scalap.scalax.rules.scalasig._

private[json] object ScalaSigReader {
def readConstructor(argName: String, clazz: Class[_], argNames: List[String]): Class[_] = {
def readConstructor(argName: String, clazz: Class[_], typeArgIndex: Int, argNames: List[String]): Class[_] = {
val cl = findClass(clazz)
val cstr = findConstructor(cl, argNames).getOrElse(Meta.fail("Can't find constructor " + clazz))
findArgType(cstr, argNames.indexOf(argName))
findArgType(cstr, argNames.indexOf(argName), typeArgIndex)
}

def readField(name: String, clazz: Class[_], typeArgIndex: Int): Class[_] = {
Expand Down Expand Up @@ -60,17 +60,22 @@ private[json] object ScalaSigReader {
private def findField(c: ClassSymbol, name: String): Option[MethodSymbol] =
(c.children collect { case m: MethodSymbol if m.name == name => m }).headOption

private def findArgType(s: MethodSymbol, argIdx: Int): Class[_] = {
private def findArgType(s: MethodSymbol, argIdx: Int, typeArgIndex: Int): Class[_] = {
def findPrimitive(t: Type): Symbol = t match {
case TypeRefType(ThisType(_), symbol, _) if isPrimitive(symbol) => symbol
case TypeRefType(_, _, TypeRefType(ThisType(_), symbol, _) :: xs) => symbol
case TypeRefType(_, _, (ref @ TypeRefType(_, _, _)) :: xs) => findPrimitive(ref)
case TypeRefType(_, _, args) =>
args(typeArgIndex) match {
case ref @ TypeRefType(_, _, _) => findPrimitive(ref)
case x => Meta.fail("Unexpected type info " + x)
}
case x => Meta.fail("Unexpected type info " + x)
}
toClass(findPrimitive(s.children(argIdx).asInstanceOf[SymbolInfoSymbol].infoType))
}

private def findArgTypeF(s: MethodSymbol, typeArgIdx: Int): Class[_] = {
// FIXME can be removed when 2.8 no loner needs to supported.
// FIXME can be removed when 2.8 no longer needs to be supported.
// 2.8 does not have NullaryMethodType, work around that.
/*
val t = s.infoType match {
Expand Down Expand Up @@ -99,6 +104,8 @@ private[json] object ScalaSigReader {
case _ => classOf[AnyRef]
}

private def isPrimitive(s: Symbol) = toClass(s) != classOf[AnyRef]

private def findScalaSig(clazz: Class[_]): Option[ScalaSig] =
ScalaSigParser.parse(clazz).orElse(findScalaSig(clazz.getDeclaringClass))
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,17 @@ object SerializationBugs extends Specification {
val ser = Serialization.write(o)
ser mustEqual """{"x":{"some":"data"}}"""
}

"Map with Map value" in {
val a = Map("a" -> Map("a" -> 5))
val b = Map("b" -> 1)
val str = Serialization.write(MapWithMap(a, b))
read[MapWithMap](str) mustEqual MapWithMap(a, b)
}
}

case class MapWithMap(a: Map[String, Map[String, Int]], b: Map[String, Int])

case class LongList(xs: List[Num])
case class Num(x: Int)

Expand Down

0 comments on commit 7a986ee

Please sign in to comment.