Permalink
Browse files

0.2-SNAPSHOT #5

  • Loading branch information...
1 parent 35cd794 commit 56c7bb9622072f1796645cc1fc322ac8db89ea6e @advorkovyy advorkovyy committed Jul 21, 2011
View
26 pom.xml
@@ -32,8 +32,9 @@
</developer>
</developers>
<properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <scala.version>2.9.0</scala.version>
+ <project.build.sourcEncoding>UTF-8</project.build.sourcEncoding>
+ <scala.version>2.9.0-1</scala.version>
+ <protostuff.version>1.0.0</protostuff.version>
</properties>
<build>
<sourceDirectory>src/main/scala</sourceDirectory>
@@ -76,7 +77,7 @@
</validHeaders>
<strictCheck>true</strictCheck>
<includes>
- <include>src/main/scala/**</include>
+ <include>src/main/scala/org/scalastuff/**</include>
</includes>
</configuration>
<executions>
@@ -125,7 +126,7 @@
<version>2.3</version>
<scope>compile</scope>
</dependency>
-
+
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
@@ -153,39 +154,32 @@
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-api</artifactId>
- <version>1.0.0</version>
+ <version>${protostuff.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
- <version>1.0.0</version>
+ <version>${protostuff.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-json</artifactId>
- <version>1.0.0</version>
+ <version>${protostuff.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-xml</artifactId>
- <version>1.0.0</version>
+ <version>${protostuff.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
- </dependencies>
- <repositories>
- <repository>
- <id>protostuff-repo</id>
- <name>protostuff-repo</name>
- <url>http://protostuff.googlecode.com/svn/repos/maven2</url>
- </repository>
- </repositories>
+ </dependencies>
<distributionManagement>
<repository>
<id>sonatype-nexus-staging</id>
@@ -17,39 +17,72 @@ package org.scalastuff.scalabeans.sig
import scala.collection.mutable.HashMap
import scala.collection.mutable.ArrayBuffer
-import UnPickler._
-import Mirror._
+
import scala.reflect.generic.Flags._
import com.google.common.collect.MapMaker
/**
* Extracts class and object declaration information from Scala signature.
*
+ * Only top-level classes and objects are parsed now. Declarations contain declared parents,
+ * property candidates (no strict filtering, actual properties are still resolved via Java reflection),
+ * type aliases. All returned objects are thread-safe.
+ *
+ * No types in other top-level entities are referenced directly, but via ExternalTermRef,
+ * ExternalModuleRef and ExternalTypeRef. Those must be resolved by extracting declarations
+ * from corresponding top-level entities.
+ *
* Uses output from UnPickler to get raw data structures in PickleFormat.
*/
object ClassDeclExtractor {
- def extract[T](implicit mf: Manifest[T]): Option[Seq[EntityDecl]] = extract(mf.erasure)
- def extract(clazz: String): Option[Seq[EntityDecl]] = extract(Class.forName(clazz))
+ def extract[T](implicit mf: Manifest[T]): Option[Seq[Mirror.EntityDecl]] = extract(mf.erasure)
+ def extract(clazz: String): Option[Seq[Mirror.EntityDecl]] = extract(Class.forName(clazz))
- private[this] val declarationsCache = new MapMaker().weakKeys().makeMap[Class[_], Option[Seq[EntityDecl]]]()
+ /**
+ * Declarations are grouped by the class where they appear in the Scala signature.
+ */
+ private[this] val declarationsCache = new MapMaker().weakKeys().makeMap[Class[_], Option[Seq[Mirror.EntityDecl]]]()
- def extract(clazz: Class[_]): Option[Seq[EntityDecl]] = {
+ def extract(clazz: Class[_]): Option[Seq[Mirror.EntityDecl]] = {
val cached = declarationsCache.get(clazz)
if (cached != null) return cached
val extracted =
- for (table <- read(clazz)) yield new ClassDeclExtractor().extract(table)
+ for (table <- UnPickler.read(clazz)) yield new ClassDeclExtractor().extract(table)
declarationsCache.putIfAbsent(clazz, extracted)
extracted
}
+
+ val mirror: scala.metaprogramming.Mirror = new scala.metaprogramming.Mirror {
+ val rootPackageDecl = new PackageDecl {
+ val name = "<root>"
+ val owner = this
+ }
+ }
+
+ type Type = mirror.Type
+ type EntityDecl = mirror.EntityDecl
+ case class ClassDecl
+ case class ValueDecl(name:String, owner: EntityDecl, visibility: Visibility, valueType: Type) extends mirror.ValueDecl with mirror.MemberDecl
+
+ type Visibility = mirror.Visibility
+ object Public extends mirror.Public
+
}
+/**
+ * This class is not thread-safe and must be not used directly. Use companion object API instead.
+ */
class ClassDeclExtractor {
+ import UnPickler._
+ import Mirror._
+
def extract(table: Array[Entry]): Seq[EntityDecl] = {
val children = HashMap[SymbolDeclEntry, ArrayBuffer[SymbolDeclEntry]]()
val topLevelEntries = ArrayBuffer[SymbolDeclEntry]()
+ // collect symbol children
for (i <- 0 until table.length) table(i) match {
case symbolEntry: SymbolDeclEntry =>
symbolEntry.owner match {
@@ -62,17 +95,18 @@ class ClassDeclExtractor {
case _ =>
}
+ // parse top-level entities
for (symDeclEntry <- topLevelEntries)
yield symDeclEntry match {
case cs: ClassSym => parseClassSymbol(cs, children.getOrElse(cs, Seq.empty[SymbolDeclEntry]))
case ms: ModuleSym => parseModuleSymbol(ms, children.getOrElse(ms, Seq.empty[SymbolDeclEntry]))
}
}
- private[this] def extractValues(_owner: EntityDecl, children: Seq[SymbolDeclEntry]): Seq[ValueDecl with MemberDecl] = children collect {
- case vs: ValSym if !(vs.name.endsWith(" ")) && !(vs.name.contains("$"))
+ private[this] def extractValues(_owner: EntityDecl, children: Seq[SymbolDeclEntry]): Seq[ValueDecl with MemberDecl] = children collect {
+ case vs: ValSym if !(vs.name.endsWith(" "))
&& (vs.typeEntry.isValueType)
- && (vs.flags & FINAL) == 0 =>
+ && (vs.flags & (FINAL | SYNTHETIC)) == 0 =>
new ValueDecl with MemberDecl {
val name = vs.name
val owner = _owner
@@ -81,6 +115,24 @@ class ClassDeclExtractor {
}
}
+// private[this] def extractMembers(_owner: EntityDecl, children: Seq[SymbolDeclEntry]): Seq[ValueDecl with MemberDecl] = {
+// val vals = new ArrayBuffer[ValueDecl with MemberDecl]()
+// val methods = new ArrayBuffer[ValueDecl with MemberDecl]()
+// for (member <- children) member match {
+// case vs: ValSym if !(vs.name.endsWith(" "))
+// && (vs.typeEntry.isValueType)
+// && (vs.flags & (FINAL | SYNTHETIC)) == 0 =>
+// new ValueDecl with MemberDecl {
+// val name = vs.name
+// val owner = _owner
+// val visibility = Public // TODO
+// val valueType = parseType(vs.typeEntry)
+// }
+// }
+//
+// vals
+// }
+
def parseClassSymbol(classSym: ClassSym, children: Seq[SymbolDeclEntry]) = {
new ClassDecl { self =>
val name = classSym.name
@@ -13,32 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/**
+ * Original work published by Gilles Dubochet on 2010-06-30 under BSD license.
+ *
+ * https://github.com/dubochet/scala-reflection/commit/53b4c0ff812468620ac816f1b24c27baf522f4d0
+ * https://github.com/dubochet/scala-reflection/blob/master/frontend/src/scala/metaprogramming/Mirror.scala
+ */
package org.scalastuff.scalabeans.sig
import collection._
-object Mirror extends Mirror
-
/** A mirror is the entry point of Scala's meta-programming infrastructure: it reflects program entities such as
* instances, classes, etc. Every program entity is reflected as a unique `Reflection` instance in this mirror.
*
* A mirror only reflects program entities that are within its field of view, which interpretation is left to
* subclasses (usually a given virtual machine and class loader, or a compiler instance).
- *
- * Note that the `Reflection` class and its subclasses are path-dependent to the mirror that owns them. */
-trait Mirror { mirror =>
-
- case class ExternalTermRef(name: String, owner: Declaration) extends TermDecl
- case class ExternalModuleRef(name: String, owner: Declaration) extends TermDecl
- case class ExternalTypeRef(name: String, owner: Declaration) extends TypeDecl {
- val typeParameters: TypeParameters = Nil // real type parameters have to be resolved from actual declaration
- override def toString = owner.qualifiedName + "." + name
- }
-// case class ExternalAliasTypeRef(name: String, owner: Declaration) extends TypeDecl {
-// val typeParameters: TypeParameters = Nil // real type parameters have to be resolved from actual declaration
-// override def toString = owner.qualifiedName + "#" + name
-// }
-
+ */
+object Mirror extends Mirror
+trait Mirror {
type Name = String
/** A reflection represents a program entity such as an instance, class, etc. reflected in the mirror owning it. */
@@ -69,10 +61,9 @@ trait Mirror { mirror =>
override def toString = parent match {
case st: SingletonType =>
st.path match {
- case mp: MemberPath =>
- if (mp.value.isInstanceOf[ExternalModuleRef]) mp.toString + "#" + member.toString
- else member.toString
- case _ => parent.toString + "#" + member.toString
+ case EmptyPath => member.toString
+ case mp: MemberPath if !mp.value.isInstanceOf[ExternalModuleRef] => member.toString
+ case _ => parent.toString + "#" + member.name // type alias actually
}
case _ => parent.toString + "#" + member.toString
}
@@ -304,6 +295,15 @@ trait Mirror { mirror =>
val name = "<root>"
val owner = this
}
+
+ /* ========== References ========== */
+
+ case class ExternalTermRef(name: String, owner: Declaration) extends TermDecl
+ case class ExternalModuleRef(name: String, owner: Declaration) extends TermDecl
+ case class ExternalTypeRef(name: String, owner: Declaration) extends TypeDecl {
+ val typeParameters: TypeParameters = Nil // real type parameters have to be resolved from actual declaration
+ override def toString = owner.qualifiedName + "." + name
+ }
/* ========== SCOPES ========== */
@@ -63,6 +63,7 @@ object UnPickler extends Application {
lazy val typeEntry: TypeEntry = table(symbolInfo.infoRef) match {
case te: TypeEntry => te
case x @ _ =>
+ // TODO: is this hack correct?
val typeRef = symbolInfo.privateWithinRef getOrElse (throw new RuntimeException("unexpected entry " + x))
table(typeRef).asInstanceOf[TypeEntry]
}
@@ -95,7 +96,7 @@ object UnPickler extends Application {
}
trait CompoundTypeEntryRef extends TypeEntryRef {
def typeRef: Int
- lazy val typeEntry = table(typeRef).asInstanceOf[TypeEntry]
+ lazy val typeEntry = table(typeRef).asInstanceOf[TypeEntry] // TODO: sometimes other Entry type
}
type SymbolInfo = PickleBuffer#SymbolInfo
@@ -75,6 +75,7 @@ object AnyRefType {
trait OptionType extends AnyRefType with SingleArgument
object OptionType {
+ def apply(arg: ScalaType): OptionType = new Impl(classOf[Option[_]], arg) with OptionType
def unapply(t: OptionType) = Some(t.argument)
}
@@ -180,8 +181,6 @@ trait CollectionType extends AnyRefType with SingleArgument {
None
}
}
-
- //def newBuilder = companion map (_.newBuilder)
}
object CollectionType {
@@ -215,6 +214,7 @@ object IterableType {
trait SeqType extends IterableType
object SeqType {
+ def apply(arg: ScalaType): SeqType = new Impl(classOf[scala.collection.Seq[_]], arg) with SeqType
def unapply(t: SeqType) = Some(t.argument)
}
@@ -281,6 +281,7 @@ object MutableLinearSeqType {
trait ListType extends ImmutableLinearSeqType
object ListType {
+ def apply(arg: ScalaType): ListType = new Impl(classOf[scala.collection.immutable.List[_]], arg) with ListType
def unapply(t: ListType) = Some(t.argument)
}
@@ -369,8 +370,9 @@ object LinkedHashSetType {
}
trait MapType extends IterableType {
+ override def toString() = erasure.getSimpleName + "[" + keyType.toString + "," + valueType + "]"
+
def keyType = argument.arguments(0)
-
def valueType = argument.arguments(1)
}
@@ -289,7 +289,7 @@ trait Mirror { mirror =>
}
/** */
- trait PackageDecl extends ModuleDecl with MemberDecl {
+ trait PackageDecl extends TermDecl {
def owner: PackageDecl
override def toString =
"package " + name
@@ -17,11 +17,11 @@ class ClassDeclExtractorTest {
assertEquals(7, classDecl.values.size)
checkProp(classDecl.values(0), "ai", "scala.Array[scala.Int]")
checkProp(classDecl.values(1), "aoi", "scala.Array[scala.Option[scala.Int]]")
- checkProp(classDecl.values(2), "aoli", "scala.Array[scala.Option[scala.package#scala.package.List[scala.Int]]]")
+ checkProp(classDecl.values(2), "aoli", "scala.Array[scala.Option[scala.package.type#List[scala.Int]]]")
checkProp(classDecl.values(3), "opt", "scala.Option[scala.Int]")
- checkProp(classDecl.values(4), "listopt", "scala.package#scala.package.List[scala.Option[scala.Int]]")
- checkProp(classDecl.values(5), "map", "scala.Predef#scala.Predef.Map[scala.Option[scala.Predef#scala.Predef.String], scala.package#scala.package.List[scala.Option[scala.Float]]]")
- checkProp(classDecl.values(6), "priv", "scala.package#scala.package.Seq[scala.Boolean]")
+ checkProp(classDecl.values(4), "listopt", "scala.package.type#List[scala.Option[scala.Int]]")
+ checkProp(classDecl.values(5), "map", "scala.Predef.type#Map[scala.Option[scala.Predef.type#String], scala.package.type#List[scala.Option[scala.Float]]]")
+ checkProp(classDecl.values(6), "priv", "scala.package.type#Seq[scala.Boolean]")
}
def checkProp(valDecl: ValueDecl, name: String, typeStr: String) {
@@ -52,5 +52,5 @@ package testbeans {
def funct(x: Int, y: Option[Int]): Int = x
private[this] val priv: Seq[Boolean] = Seq.empty
- }
+ }
}

0 comments on commit 56c7bb9

Please sign in to comment.