diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala new file mode 100644 index 0000000000..91dee97277 --- /dev/null +++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala @@ -0,0 +1,78 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.nsc +package interpreter + +import java.lang.{ reflect => r } +import r.TypeVariable +import scala.reflect.NameTransformer + +/** Logic for turning a type into a String. The goal is to be + * able to take some arbitrary object 'x' and obtain the most precise + * String for which an injection of x.asInstanceOf[String] will + * be valid from both the JVM's and scala's perspectives. + * + * "definition" is when you want strings like + */ +trait TypeStrings { + private val ObjectClass = classOf[java.lang.Object] + private val primitives = Set[String]("byte", "char", "short", "int", "long", "float", "double", "boolean") + private def unbox(s: String): String = s.stripPrefix("java.lang.") match { + case "Integer" => "scala.Int" + case "Character" => "scala.Char" + case "Void" => "scala.Unit" + case x @ ("Byte" | "Short" | "Long" | "Float" | "Double" | "Boolean") => "scala." + x + case _ => NameTransformer.decode(s) + } + + def scalaName(s: String): String = { + if (s endsWith "$") (s dropRight 1) + ".type" + else if (primitives(s)) "scala." + s.capitalize + else if (s == "void") "scala.Unit" + else unbox(s) + } + def scalaName(clazz: JClass): String = scalaName(clazz.getName) + def scalaName(m: ClassManifest[_]): String = scalaName(m.erasure) + def anyClass(x: Any): JClass = if (x == null) null else x.asInstanceOf[AnyRef].getClass + + private def tvarString(tvar: TypeVariable[_]): String = tvarString(tvar.getBounds.toList) + private def tvarString(bounds: List[AnyRef]): String = { + val xs = bounds filterNot (_ == ObjectClass) collect { case x: Class[_] => x } + if (xs.isEmpty) "_" + else scalaName(xs.head) + } + private def tparamString(clazz: JClass): String = { + val tps = clazz.getTypeParameters.toList + if (tps.isEmpty) + return "" + + (tps map tvarString).mkString("[", ", ", "]") + } + private def tparamString[T: Manifest] : String = { + val tps = manifest[T].typeArguments + if (tps.isEmpty) + return "" + + tps.map(m => tvarString(List(m.erasure))).mkString("[", ", ", "]") + } + /** Going for an overabundance of caution right now. + */ + def fromTypedValue[T: Manifest](x: T): String = fromManifest[T] + def fromValue(value: Any): String = if (value == null) "Null" else fromClazz(anyClass(value)) + def fromClazz(clazz: JClass): String = scalaName(clazz) + tparamString(clazz) + def fromManifest[T: Manifest] : String = scalaName(manifest[T].erasure) + tparamString[T] + + /** Reducing fully qualified noise for some common packages. + */ + val typeTransforms = List( + "java.lang." -> "", + "scala.collection.immutable." -> "immutable.", + "scala.collection.mutable." -> "mutable.", + "scala.collection.generic." -> "generic." + ) +} + +object TypeStrings extends TypeStrings { }
\ No newline at end of file |