aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2016-09-21 17:23:14 -0700
committerJakob Odersky <jakob@odersky.com>2016-09-21 17:23:14 -0700
commit499131c281de4cdb4a53b4ae9e4bcb6ca399e738 (patch)
tree24f3e16f78c6784ab63830ccda38acb5ca07572a
parent8c3ee2bc42e6320b9341cebdba51a00162c897ea (diff)
downloadspark-499131c281de4cdb4a53b4ae9e4bcb6ca399e738.tar.gz
spark-499131c281de4cdb4a53b4ae9e4bcb6ca399e738.tar.bz2
spark-499131c281de4cdb4a53b4ae9e4bcb6ca399e738.zip
Move reflection functions to trait
-rw-r--r--sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/ScalaReflection.scala246
1 files changed, 127 insertions, 119 deletions
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/ScalaReflection.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/ScalaReflection.scala
index 7923cfce82..7800643429 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/ScalaReflection.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/ScalaReflection.scala
@@ -48,6 +48,133 @@ object ScalaReflection extends ScalaReflection {
import universe._
+ /**
+ * Returns the parameter names and types for the primary constructor of this class.
+ *
+ * Note that it only works for scala classes with primary constructor, and currently doesn't
+ * support inner class.
+ */
+ override def getConstructorParameters(cls: Class[_]): Seq[(String, Type)] = {
+ val m = runtimeMirror(cls.getClassLoader)
+ val classSymbol = m.staticClass(cls.getName)
+ val t = classSymbol.selfType
+ getConstructorParameters(t)
+ }
+
+ /**
+ * Returns the parameter names for the primary constructor of this class.
+ *
+ * Logically we should call `getConstructorParameters` and throw away the parameter types to get
+ * parameter names, however there are some weird scala reflection problems and this method is a
+ * workaround to avoid getting parameter types.
+ */
+ override def getConstructorParameterNames(cls: Class[_]): Seq[String] = {
+ val m = runtimeMirror(cls.getClassLoader)
+ val classSymbol = m.staticClass(cls.getName)
+ val t = classSymbol.selfType
+ constructParams(t).map(_.name.toString)
+ }
+
+ /*
+ * Retrieves the runtime class corresponding to the provided type.
+ */
+ override def getClassFromType(tpe: Type): Class[_] = mirror.runtimeClass(tpe.erasure.typeSymbol.asClass)
+
+}
+
+/**
+ * Support for generating catalyst schemas for scala objects. Note that unlike its companion
+ * object, this trait able to work in both the runtime and the compile time (macro) universe.
+ */
+trait ScalaReflection {
+ /** The universe we work in (runtime or macro) */
+ val universe: scala.reflect.api.Universe
+
+ /** The mirror used to access types in the universe */
+ def mirror: universe.Mirror
+
+ import universe._
+
+ // The Predef.Map is scala.collection.immutable.Map.
+ // Since the map values can be mutable, we explicitly import scala.collection.Map at here.
+ import scala.collection.Map
+
+ def getConstructorParameters(cls: Class[_]): Seq[(String, Type)] = ???
+
+ def getConstructorParameterNames(cls: Class[_]): Seq[String] = ???
+
+ def getClassFromType(tpe: Type): Class[_] = ???
+
+ /**
+ * Return the Scala Type for `T` in the current classloader mirror.
+ *
+ * Use this method instead of the convenience method `universe.typeOf`, which
+ * assumes that all types can be found in the classloader that loaded scala-reflect classes.
+ * That's not necessarily the case when running using Eclipse launchers or even
+ * Sbt console or test (without `fork := true`).
+ *
+ * @see SPARK-5281
+ */
+ // SPARK-13640: Synchronize this because TypeTag.tpe is not thread-safe in Scala 2.10.
+ def localTypeOf[T: TypeTag]: `Type` = ScalaReflectionLock.synchronized {
+ val tag = implicitly[TypeTag[T]]
+ tag.in(mirror).tpe.normalize
+ }
+
+ /**
+ * Returns the full class name for a type. The returned name is the canonical
+ * Scala name, where each component is separated by a period. It is NOT the
+ * Java-equivalent runtime name (no dollar signs).
+ *
+ * In simple cases, both the Scala and Java names are the same, however when Scala
+ * generates constructs that do not map to a Java equivalent, such as singleton objects
+ * or nested classes in package objects, it uses the dollar sign ($) to create
+ * synthetic classes, emulating behaviour in Java bytecode.
+ */
+ def getClassNameFromType(tpe: `Type`): String = {
+ tpe.erasure.typeSymbol.asClass.fullName
+ }
+
+ /**
+ * Returns classes of input parameters of scala function object.
+ */
+ def getParameterTypes(func: AnyRef): Seq[Class[_]] = {
+ val methods = func.getClass.getMethods.filter(m => m.getName == "apply" && !m.isBridge)
+ assert(methods.length == 1)
+ methods.head.getParameterTypes
+ }
+
+ /**
+ * Returns the parameter names and types for the primary constructor of this type.
+ *
+ * Note that it only works for scala classes with primary constructor, and currently doesn't
+ * support inner class.
+ */
+ def getConstructorParameters(tpe: Type): Seq[(String, Type)] = {
+ val formalTypeArgs = tpe.typeSymbol.asClass.typeParams
+ val TypeRef(_, _, actualTypeArgs) = tpe
+ constructParams(tpe).map { p =>
+ p.name.toString -> p.typeSignature.substituteTypes(formalTypeArgs, actualTypeArgs)
+ }
+ }
+
+ protected def constructParams(tpe: Type): Seq[Symbol] = {
+ val constructorSymbol = tpe.member(nme.CONSTRUCTOR)
+ val params = if (constructorSymbol.isMethod) {
+ constructorSymbol.asMethod.paramss
+ } else {
+ // Find the primary constructor, and use its parameter ordering.
+ val primaryConstructorSymbol: Option[Symbol] = constructorSymbol.asTerm.alternatives.find(
+ s => s.isMethod && s.asMethod.isPrimaryConstructor)
+ if (primaryConstructorSymbol.isEmpty) {
+ sys.error("Internal SQL error: Product object did not have a primary constructor.")
+ } else {
+ primaryConstructorSymbol.get.asMethod.paramss
+ }
+ }
+ params.flatten
+ }
+
// The Predef.Map is scala.collection.immutable.Map.
// Since the map values can be mutable, we explicitly import scala.collection.Map at here.
import scala.collection.Map
@@ -590,33 +717,6 @@ object ScalaReflection extends ScalaReflection {
}
/**
- * Returns the parameter names and types for the primary constructor of this class.
- *
- * Note that it only works for scala classes with primary constructor, and currently doesn't
- * support inner class.
- */
- def getConstructorParameters(cls: Class[_]): Seq[(String, Type)] = {
- val m = runtimeMirror(cls.getClassLoader)
- val classSymbol = m.staticClass(cls.getName)
- val t = classSymbol.selfType
- getConstructorParameters(t)
- }
-
- /**
- * Returns the parameter names for the primary constructor of this class.
- *
- * Logically we should call `getConstructorParameters` and throw away the parameter types to get
- * parameter names, however there are some weird scala reflection problems and this method is a
- * workaround to avoid getting parameter types.
- */
- def getConstructorParameterNames(cls: Class[_]): Seq[String] = {
- val m = runtimeMirror(cls.getClassLoader)
- val classSymbol = m.staticClass(cls.getName)
- val t = classSymbol.selfType
- constructParams(t).map(_.name.toString)
- }
-
- /**
* Returns the parameter values for the primary constructor of this class.
*/
def getConstructorParameterValues(obj: DefinedByConstructorParams): Seq[AnyRef] = {
@@ -625,10 +725,6 @@ object ScalaReflection extends ScalaReflection {
}
}
- /*
- * Retrieves the runtime class corresponding to the provided type.
- */
- def getClassFromType(tpe: Type): Class[_] = mirror.runtimeClass(tpe.erasure.typeSymbol.asClass)
case class Schema(dataType: DataType, nullable: Boolean)
@@ -718,93 +814,5 @@ object ScalaReflection extends ScalaReflection {
"interface", "long", "native", "new", "null", "package", "private", "protected", "public",
"return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw",
"throws", "transient", "true", "try", "void", "volatile", "while")
-}
-
-/**
- * Support for generating catalyst schemas for scala objects. Note that unlike its companion
- * object, this trait able to work in both the runtime and the compile time (macro) universe.
- */
-trait ScalaReflection {
- /** The universe we work in (runtime or macro) */
- val universe: scala.reflect.api.Universe
-
- /** The mirror used to access types in the universe */
- def mirror: universe.Mirror
-
- import universe._
-
- // The Predef.Map is scala.collection.immutable.Map.
- // Since the map values can be mutable, we explicitly import scala.collection.Map at here.
- import scala.collection.Map
-
- /**
- * Return the Scala Type for `T` in the current classloader mirror.
- *
- * Use this method instead of the convenience method `universe.typeOf`, which
- * assumes that all types can be found in the classloader that loaded scala-reflect classes.
- * That's not necessarily the case when running using Eclipse launchers or even
- * Sbt console or test (without `fork := true`).
- *
- * @see SPARK-5281
- */
- // SPARK-13640: Synchronize this because TypeTag.tpe is not thread-safe in Scala 2.10.
- def localTypeOf[T: TypeTag]: `Type` = ScalaReflectionLock.synchronized {
- val tag = implicitly[TypeTag[T]]
- tag.in(mirror).tpe.normalize
- }
-
- /**
- * Returns the full class name for a type. The returned name is the canonical
- * Scala name, where each component is separated by a period. It is NOT the
- * Java-equivalent runtime name (no dollar signs).
- *
- * In simple cases, both the Scala and Java names are the same, however when Scala
- * generates constructs that do not map to a Java equivalent, such as singleton objects
- * or nested classes in package objects, it uses the dollar sign ($) to create
- * synthetic classes, emulating behaviour in Java bytecode.
- */
- def getClassNameFromType(tpe: `Type`): String = {
- tpe.erasure.typeSymbol.asClass.fullName
- }
-
- /**
- * Returns classes of input parameters of scala function object.
- */
- def getParameterTypes(func: AnyRef): Seq[Class[_]] = {
- val methods = func.getClass.getMethods.filter(m => m.getName == "apply" && !m.isBridge)
- assert(methods.length == 1)
- methods.head.getParameterTypes
- }
-
- /**
- * Returns the parameter names and types for the primary constructor of this type.
- *
- * Note that it only works for scala classes with primary constructor, and currently doesn't
- * support inner class.
- */
- def getConstructorParameters(tpe: Type): Seq[(String, Type)] = {
- val formalTypeArgs = tpe.typeSymbol.asClass.typeParams
- val TypeRef(_, _, actualTypeArgs) = tpe
- constructParams(tpe).map { p =>
- p.name.toString -> p.typeSignature.substituteTypes(formalTypeArgs, actualTypeArgs)
- }
- }
-
- protected def constructParams(tpe: Type): Seq[Symbol] = {
- val constructorSymbol = tpe.member(nme.CONSTRUCTOR)
- val params = if (constructorSymbol.isMethod) {
- constructorSymbol.asMethod.paramss
- } else {
- // Find the primary constructor, and use its parameter ordering.
- val primaryConstructorSymbol: Option[Symbol] = constructorSymbol.asTerm.alternatives.find(
- s => s.isMethod && s.asMethod.isPrimaryConstructor)
- if (primaryConstructorSymbol.isEmpty) {
- sys.error("Internal SQL error: Product object did not have a primary constructor.")
- } else {
- primaryConstructorSymbol.get.asMethod.paramss
- }
- }
- params.flatten
- }
}