summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2008-01-09 16:25:17 +0000
committerIulian Dragos <jaguarul@gmail.com>2008-01-09 16:25:17 +0000
commit779aec9f38b1ac5037141e4c4a77310f6953adf1 (patch)
treea7a742a5ae8c53327462eb33cf093d18926e6db5 /src
parent5b273b4327cdc8295bc547a4d9df238bce5ae794 (diff)
downloadscala-779aec9f38b1ac5037141e4c4a77310f6953adf1.tar.gz
scala-779aec9f38b1ac5037141e4c4a77310f6953adf1.tar.bz2
scala-779aec9f38b1ac5037141e4c4a77310f6953adf1.zip
Merged patch from Ross Judson (bean info class ...
Merged patch from Ross Judson (bean info class generation).
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala82
-rw-r--r--src/library/scala/reflect/BeanDescription.scala20
-rw-r--r--src/library/scala/reflect/BeanDisplayName.scala19
-rw-r--r--src/library/scala/reflect/BeanInfo.scala22
-rw-r--r--src/library/scala/reflect/BeanInfoSkip.scala19
-rw-r--r--src/library/scala/reflect/ScalaBeanInfo.scala47
6 files changed, 209 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 4172398f58..77286d5ddc 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -73,6 +73,10 @@ abstract class GenJVM extends SubComponent {
val VolatileAttr = definitions.getClass("scala.volatile")
val RemoteAttr = definitions.getClass("scala.remote")
val ThrowsAttr = definitions.getClass("scala.throws")
+ val BeanInfoAttr = definitions.getClass("scala.reflect.BeanInfo")
+ val BeanInfoSkipAttr = definitions.getClass("scala.reflect.BeanInfoSkip")
+ val BeanDisplayNameAttr = definitions.getClass("scala.reflect.BeanDisplayName")
+ val BeanDescriptionAttr = definitions.getClass("scala.reflect.BeanDescription")
lazy val CloneableClass = definitions.getClass("java.lang.Cloneable")
lazy val RemoteInterface = definitions.getClass("java.rmi.Remote")
@@ -194,6 +198,84 @@ abstract class GenJVM extends SubComponent {
addAnnotations(jclass, c.symbol.attributes)
emitClass(jclass, c.symbol)
+
+ if (c.symbol.attributes.exists(_.atp.typeSymbol == BeanInfoAttr))
+ genBeanInfoClass(c)
+ }
+
+ /**
+ * Generate a bean info class that describes the given class.
+ *
+ * @author Ross Judson (ross.judson@soletta.com)
+ */
+ def genBeanInfoClass(c: IClass) {
+ val description = c.symbol.attributes.find(_.atp.typeSymbol == BeanDescriptionAttr)
+ // informProgress(description.toString())
+
+ val beanInfoClass = fjbgContext.JClass(javaFlags(c.symbol),
+ javaName(c.symbol) + "BeanInfo",
+ "scala/reflect/ScalaBeanInfo",
+ JClass.NO_INTERFACES,
+ c.cunit.source.toString)
+
+ var fieldList = List[String]()
+ for (f <- clasz.fields if f.symbol.hasGetter;
+ val g = f.symbol.getter(c.symbol);
+ val s = f.symbol.setter(c.symbol);
+ if g.isPublic)
+ fieldList = javaName(f.symbol) :: javaName(g) :: (if (s != NoSymbol) javaName(s) else null) :: fieldList
+ val methodList =
+ for (m <- clasz.methods
+ if !m.symbol.isConstructor &&
+ m.symbol.isPublic &&
+ !(m.symbol.name startsWith "$") &&
+ !m.symbol.isGetter &&
+ !m.symbol.isSetter) yield javaName(m.symbol)
+
+ val constructor = beanInfoClass.addNewMethod(JAccessFlags.ACC_PUBLIC, "<init>", JType.VOID, javaTypes(Nil), javaNames(Nil))
+ jcode = constructor.getCode().asInstanceOf[JExtendedCode]
+ val strKind = new JObjectType(javaName(definitions.StringClass))
+ val stringArrayKind = new JArrayType(strKind)
+ val conType = new JMethodType(JType.VOID, Array(javaType(definitions.ClassClass), stringArrayKind, stringArrayKind))
+
+ def push(lst:Seq[String]) {
+ var fi = 0
+ for (f <- lst) {
+ jcode.emitDUP()
+ jcode.emitPUSH(fi)
+ if (f != null)
+ jcode.emitPUSH(f)
+ else
+ jcode.emitACONST_NULL()
+ jcode.emitASTORE(strKind)
+ fi = fi + 1
+ }
+ }
+
+ jcode.emitALOAD_0()
+ // push the class
+ jcode.emitPUSH(javaType(c.symbol).asInstanceOf[JReferenceType])
+
+ // push the the string array of field information
+ jcode.emitPUSH(fieldList.length)
+ jcode.emitANEWARRAY(strKind)
+ push(fieldList)
+
+ // push the string array of method information
+ jcode.emitPUSH(methodList.length)
+ jcode.emitANEWARRAY(strKind)
+ push(methodList)
+
+ // invoke the superclass constructor, which will do the
+ // necessary java reflection and create Method objects.
+ jcode.emitINVOKESPECIAL("scala/reflect/ScalaBeanInfo", "<init>", conType)
+ jcode.emitRETURN()
+
+ // write the bean information class file.
+ val outfile = getFile(beanInfoClass, ".class")
+ beanInfoClass.writeTo(outfile)
+ val file = scala.tools.nsc.io.AbstractFile.getFile(outfile)
+ informProgress("wrote BeanInfo " + outfile)
}
def addExceptionsAttribute(sym: Symbol): Unit = {
diff --git a/src/library/scala/reflect/BeanDescription.scala b/src/library/scala/reflect/BeanDescription.scala
new file mode 100644
index 0000000000..491db4d630
--- /dev/null
+++ b/src/library/scala/reflect/BeanDescription.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.reflect
+
+/** Provides a short description that will be included when generating
+ * bean information. This annotation can be attached to the bean itself,
+ * or to any member.
+ *
+ * @author Ross Judson (rjudson@managedobjects.com)
+ */
+class BeanDescription(val description: String) extends Annotation
+
diff --git a/src/library/scala/reflect/BeanDisplayName.scala b/src/library/scala/reflect/BeanDisplayName.scala
new file mode 100644
index 0000000000..7cd6e94e18
--- /dev/null
+++ b/src/library/scala/reflect/BeanDisplayName.scala
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.reflect
+
+/** Provides a display name when generating bean information. This
+ * annotation can be attached to the bean itself, or to any member.
+ *
+ * @author Ross Judson (rjudson@managedobjects.com)
+ */
+class BeanDisplayName(val name: String) extends Annotation
+
diff --git a/src/library/scala/reflect/BeanInfo.scala b/src/library/scala/reflect/BeanInfo.scala
new file mode 100644
index 0000000000..a5ea0fb975
--- /dev/null
+++ b/src/library/scala/reflect/BeanInfo.scala
@@ -0,0 +1,22 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.reflect
+
+/** <p>
+ * This attribute indicates that a JavaBean-compliant BeanInfo
+ * class should be generated for this attributed Scala class.
+ * A val becomes a read-only property. A var becomes a read-write
+ * property. A def becomes a method.
+ * </p>
+ *
+ * @author Ross Judson (rjudson@managedobjects.com)
+ */
+class BeanInfo extends Annotation
diff --git a/src/library/scala/reflect/BeanInfoSkip.scala b/src/library/scala/reflect/BeanInfoSkip.scala
new file mode 100644
index 0000000000..5cf5ae3264
--- /dev/null
+++ b/src/library/scala/reflect/BeanInfoSkip.scala
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.reflect
+
+/** This attribute indicates that bean information should
+ * <strong>not</strong> be generated for the val, var, or def that it is
+ * attached to.
+ *
+ * @author Ross Judson (rjudson@managedobjects.com)
+ */
+class BeanInfoSkip extends Annotation
diff --git a/src/library/scala/reflect/ScalaBeanInfo.scala b/src/library/scala/reflect/ScalaBeanInfo.scala
new file mode 100644
index 0000000000..f8ea948818
--- /dev/null
+++ b/src/library/scala/reflect/ScalaBeanInfo.scala
@@ -0,0 +1,47 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// $Id$
+
+package scala.reflect
+
+/** Provides some simple runtime processing necessary to create
+ * JavaBean descriptors for Scala entities. The compiler creates
+ * subclasses of this class automatically when the BeanInfo annotation is
+ * attached to a class.
+ *
+ * @author Ross Judson (rjudson@managedobjects.com)
+ */
+abstract class ScalaBeanInfo(clazz: java.lang.Class[_],
+ props: Array[String],
+ methods: Array[String]) extends java.beans.SimpleBeanInfo {
+
+ import java.beans._
+
+ private val pd = new Array[PropertyDescriptor](props.length / 3)
+ private val md =
+ for (m <- clazz.getMethods if methods.exists(_ == m.getName))
+ yield new MethodDescriptor(m)
+
+ init
+
+ override def getPropertyDescriptors() = pd
+ override def getMethodDescriptors() = md
+
+ // override def getAdditionalBeanInfo() = Array(Introspector getBeanInfo clazz.getSuperclass)
+
+ private def init {
+ var i = 0;
+ while (i < props.length) {
+ pd(i/3) = new PropertyDescriptor(props(i), clazz, props(i+1), props(i+2))
+ i = i + 3;
+ }
+ }
+
+}
+