├── .gitignore ├── README.markdown ├── project ├── build.properties ├── build │ └── project.scala └── plugins │ ├── Plugins.scala │ └── project │ └── build.properties └── src ├── main └── scala │ └── scalaj │ └── reflect │ ├── AutographBook.scala │ ├── Collatable.scala │ ├── ForwardPipe.scala │ ├── Mirrors.scala │ ├── NameHelpers.scala │ ├── SymbolTreePrinter.scala │ ├── TypeMirrors.scala │ └── TypeWrangler.scala └── test └── scala └── scalaj └── reflect ├── AutographBookSpec.scala ├── CollatableSpec.scala ├── ExpectedPrintTrees.scala ├── MirrorsSpec.scala ├── SymbolTreePrinterSpec.scala ├── TypeWranglerSpec.scala └── targets ├── BasicSample.scala ├── NestedPolymorphicSample.scala ├── PolymorphicSample.scala ├── TweedleDee.scala ├── TweedleDo.scala └── TweedleDum.scala /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | .classpath 4 | .project 5 | .scala_dependencies 6 | */log/ 7 | */tmp/ 8 | *~ 9 | .#* 10 | CVS/ 11 | .svn/ 12 | .hg/ 13 | target/ 14 | lib_managed/ 15 | src_managed/ 16 | project/boot/ 17 | project/build/target/ 18 | project/plugins/target/ 19 | project/plugins/project/ 20 | project/plugins/lib_managed/ 21 | project/plugins/src_managed/ 22 | .cvsignore 23 | .hgignore 24 | *.iml 25 | *.iws 26 | *.ipr 27 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # scalaj-reflect 2 | 3 | A reflection library based on the Scala Signature logic from scalap 4 | 5 | ## Usage 6 | 7 | TBD 8 | 9 | ## Requirements 10 | 11 | scalaj-reflect requires Scala 2.8.1+ 12 | 13 | ## Installation 14 | 15 | ### sbt 16 | 17 | If you're using simple-build-tool, simply add the following line to your project file: 18 | 19 | val scalaj_spring = "org.scalaj" %% "scalaj-reflect" % "0.1-SNAPSHOT" 20 | 21 | ### Maven 22 | 23 | If you're using Maven, add the following to your pom.xml: 24 | 25 | 26 | org.scalaj 27 | scalaj-reflect_${scala.version} 28 | 0.1-SNAPSHOT 29 | 30 | 31 | ### JARs 32 | 33 | Soon to be released at [scala-tools.org](http://www.scala-tools.org/repo-releases/org/scalaj/scalaj-reflect_2.8.1/0.1-SNAPSHOT/) 34 | 35 | ### From source 36 | 37 | Clone the repository from Github: 38 | 39 | git clone git://github.com/scalaj/scalaj-reflect.git 40 | 41 | Build the project and create the JAR (requires [sbt](http://code.google.com/p/simple-build-tool/) version 0.7.4 or greater): 42 | 43 | cd scalaj-reflect 44 | sbt package 45 | 46 | ## Documentation 47 | 48 | TBD -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | #Project properties 2 | #Sun Nov 22 18:53:20 PST 2009 3 | project.organization=org.scalaj 4 | project.name=scalaj-reflect 5 | sbt.version=0.7.7 6 | project.version=0.1-SNAPSHOT 7 | def.scala.version=2.7.7 8 | build.scala.versions=2.9.0 9 | project.initialize=false 10 | -------------------------------------------------------------------------------- /project/build/project.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | import de.element34.sbteclipsify._ 3 | 4 | 5 | class ScalajProject(info: ProjectInfo) extends DefaultProject(info) 6 | with IdeaProject 7 | with Eclipsify 8 | with posterous.Publish { 9 | override def compileOptions = Seq(Deprecation, Unchecked) 10 | 11 | //Dependencies 12 | val scalap = "org.scala-lang" % "scalap" % "2.8.1" withSources() 13 | val specs = "org.scala-tools.testing" %% "specs" % "1.6.6" 14 | val unit = "junit" % "junit" % "4.8.2" % "test" 15 | //val logback = "ch.qos.logback" % "logback-classic" % "0.9.25" 16 | //val grizzledSlf4j = "org.clapper" %% "grizzled-slf4j" % "0.3.2" 17 | 18 | // Publishing 19 | override def managedStyle = ManagedStyle.Maven 20 | val publishTo = "Scala Tools Nexus" at "http://nexus.scala-tools.org/content/repositories/snapshots/" 21 | Credentials(Path.userHome / ".ivy2" / ".credentials", log) 22 | override def publishAction = super.publishAction && publishCurrentNotes 23 | override def extraTags = "scalaj" :: super.extraTags 24 | 25 | } 26 | -------------------------------------------------------------------------------- /project/plugins/Plugins.scala: -------------------------------------------------------------------------------- 1 | import sbt._ 2 | class Plugins(info: ProjectInfo) extends PluginDefinition(info) { 3 | 4 | val edinboroughUniRepo = "www2.ph.ed.ac.uk-releases" at "http://www2.ph.ed.ac.uk/maven2/" 5 | val sbtIdeaRepo = "sbt-idea-repo" at "http://mpeltonen.github.com/maven/" 6 | val thuntRepo = "t_repo" at "http://tristanhunt.com:8081/content/groups/public/" 7 | val sbtIdea = "com.github.mpeltonen" % "sbt-idea-plugin" % "0.4.0" 8 | val posterous = "net.databinder" % "posterous-sbt" % "0.1.6" 9 | val eclipse = "de.element34" % "sbt-eclipsify" % "0.7.0" 10 | } 11 | -------------------------------------------------------------------------------- /project/plugins/project/build.properties: -------------------------------------------------------------------------------- 1 | #Project properties 2 | #Tue Jan 04 07:41:40 GMT 2011 3 | plugin.uptodate=true 4 | -------------------------------------------------------------------------------- /src/main/scala/scalaj/reflect/AutographBook.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | import tools.scalap.scalax.rules.scalasig._ 4 | import reflect.ScalaSignature 5 | import scala.reflect.generic.ByteCodecs 6 | 7 | object AutographBook { 8 | 9 | def decodeSigBytes(bytes: Array[Byte]): Array[Byte] = { 10 | val length = ByteCodecs.decode(bytes) 11 | bytes.take(length) 12 | } 13 | 14 | def sigBytesFromAnnotation(sig: ScalaSignature) = decodeSigBytes(sig.bytes.getBytes) 15 | 16 | def sigBytesFromType(tpe: Class[_]) = { 17 | tpe.getAnnotations.view collect { case x: ScalaSignature => x } map {sigBytesFromAnnotation} headOption 18 | } 19 | 20 | def sigFromBytes(bytes: Array[Byte]) = ScalaSigAttributeParsers.parse(ByteCode(bytes)) 21 | 22 | def sigFromType(tpe: Class[_]) = sigBytesFromType(tpe) map (sigFromBytes) 23 | 24 | def topLevelSymsFromSig(s: ScalaSig) = s.topLevelClasses ++ s.topLevelObjects 25 | 26 | def decompile(s: ScalaSig) = 27 | tools.scalap.Main.parseScalaSignature(s, false) 28 | 29 | def safeGetClass(name: String): Option[Class[_]] = { 30 | try Some(Class forName name) catch { case e: Exception => None } 31 | } 32 | 33 | /** 34 | * Given a string, will return a `Class[_] -> String` representing the longest possible 35 | * match that's a valid class name, paired with the remainder of the string. 36 | */ 37 | 38 | def resolveClassAndRemainder(path: String) = { 39 | val splitPoints = path.zipWithIndex collect {case ('.',i) => i} 40 | val splits = (path->"") +: (splitPoints.reverse map {path.splitAt} map { case (a,b) => (a,b.tail)}) 41 | splits.view flatMap { case (l,r) => safeGetClass(l) map (_ -> r) } headOption 42 | } 43 | 44 | def resolveExternal(path: String) = { 45 | resolveClassAndRemainder(path) map { resolv => 46 | val (cls, remainder) = resolv 47 | val subparts = remainder split '.' 48 | val sig = sigFromType(cls) 49 | val syms = sig.toSeq flatMap { _.symbols } collect { 50 | case sym: AliasSymbol if sym.name == remainder => sym 51 | } 52 | syms 53 | } 54 | } 55 | 56 | def deAlias(sym: AliasSymbol) = { 57 | sym.infoType 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/scala/scalaj/reflect/Collatable.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | import collection.generic.CanBuildFrom 4 | 5 | /** 6 | * Adds the `collate` method to traversable collections. 7 | * 8 | * This is a cross between collect and partition, comparing elements against a partial function 9 | * and extracting matches into a collection of the same type as the PF's return (as `collect` does). 10 | * But also returning non-matches in a collection with the same type as the input (as `partition` does). 11 | * 12 | */ 13 | import collection.generic.CanBuildFrom 14 | 15 | class Collatable[Repr <% Traversable[T], T] { 16 | //class Collatable[Repr, T](xs: Repr)(implicit bf: CanBuildFrom[Repr, T, Repr], ev: Repr => Traversable[T]) { 17 | def of(xs: Repr)(implicit rbf: CanBuildFrom[Repr, T, Repr]) = new Of(xs) 18 | class Of(xs: Repr)(implicit rbf: CanBuildFrom[Repr, T, Repr]) { 19 | trait Results { 20 | def remainder: Repr 21 | 22 | type Append[That] <: Results 23 | def append[That](tup: (That, Repr)): Append[That] 24 | 25 | def andThen[R, That](pf: PartialFunction[T, R])(implicit mbf: CanBuildFrom[Repr, R, That]) = { 26 | val more = of(remainder).collateOne[R,That](pf) 27 | append(more) 28 | } 29 | } 30 | 31 | case class Results9[M1,M2,M3,M4,M5,M6,M7,M8,M9]( 32 | m1: M1, m2: M2, m3: M3, m4: M4, m5: M5, m6: M6, m7: M7, m8: M8, m9: M9, remainder: Repr) 33 | extends Results { 34 | implicit def toTuple = (m1, m2, m3, m4, m5, m6, m7, m8, m9, remainder) 35 | def append[That](tup: (That, Repr)) = error("can't collate beyond 9 elements") 36 | } 37 | 38 | case class Results8[M1,M2,M3,M4,M5,M6,M7,M8]( 39 | m1: M1, m2: M2, m3: M3, m4: M4, m5: M5, m6: M6, m7: M7, m8: M8, remainder: Repr) 40 | extends Results { 41 | implicit def toTuple = (m1, m2, m3, m4, m5, m6, m7, m8, remainder) 42 | type Append[That] = Results9[M1,M2,M3,M4,M5,M6,M7,M8,That] 43 | def append[That](tup: (That, Repr)) = Results9(m1, m2, m3, m4, m5, m6, m7, m8, tup._1, tup._2) 44 | } 45 | 46 | case class Results7[M1,M2,M3,M4,M5,M6,M7]( 47 | m1: M1, m2: M2, m3: M3, m4: M4, m5: M5, m6: M6, m7: M7, remainder: Repr) 48 | extends Results { 49 | implicit def toTuple = (m1, m2, m3, m4, m5, m6, m7, remainder) 50 | type Append[That] = Results8[M1,M2,M3,M4,M5,M6,M7,That] 51 | def append[That](tup: (That, Repr)) = Results8(m1, m2, m3, m4, m5, m6, m7, tup._1, tup._2) 52 | } 53 | 54 | case class Results6[M1,M2,M3,M4,M5,M6]( 55 | m1: M1, m2: M2, m3: M3, m4: M4, m5: M5, m6: M6, remainder: Repr) 56 | extends Results { 57 | implicit def toTuple = (m1, m2, m3, m4, m5, m6, remainder) 58 | type Append[That] = Results7[M1,M2,M3,M4,M5,M6,That] 59 | def append[That](tup: (That, Repr)) = Results7(m1, m2, m3, m4, m5, m6, tup._1, tup._2) 60 | } 61 | 62 | case class Results5[M1,M2,M3,M4,M5]( 63 | m1: M1, m2: M2, m3: M3, m4: M4, m5: M5, remainder: Repr) 64 | extends Results { 65 | implicit def toTuple = (m1, m2, m3, m4, m5, remainder) 66 | type Append[That] = Results6[M1,M2,M3,M4,M5,That] 67 | def append[That](tup: (That, Repr)) = Results6(m1, m2, m3, m4, m5, tup._1, tup._2) 68 | } 69 | 70 | case class Results4[M1,M2,M3,M4]( 71 | m1: M1, m2: M2, m3: M3, m4: M4, remainder: Repr) 72 | extends Results { 73 | implicit def toTuple = (m1, m2, m3, m4, remainder) 74 | type Append[That] = Results5[M1,M2,M3,M4,That] 75 | def append[That](tup: (That, Repr)) = Results5(m1, m2, m3, m4, tup._1, tup._2) 76 | } 77 | 78 | case class Results3[M1,M2,M3]( 79 | m1: M1, m2: M2, m3: M3, remainder: Repr) 80 | extends Results { 81 | implicit def toTuple = (m1, m2, m3, remainder) 82 | type Append[That] = Results4[M1,M2,M3,That] 83 | def append[That](tup: (That, Repr)) = Results4(m1, m2, m3, tup._1, tup._2) 84 | } 85 | 86 | case class Results2[M1,M2]( 87 | m1: M1, m2: M2, remainder: Repr) 88 | extends Results { 89 | implicit def toTuple = (m1, m2, remainder) 90 | type Append[That] = Results3[M1,M2,That] 91 | def append[That](tup: (That, Repr)) = Results3(m1, m2, tup._1, tup._2) 92 | } 93 | 94 | case class Results1[M1](matches: M1, remainder: Repr) extends Results { 95 | implicit def toTuple = (matches, remainder) 96 | 97 | type Append[That] = Results2[M1, That] 98 | def append[That](tup: (That, Repr)) = Results2(matches, tup._1, tup._2) 99 | } 100 | 101 | def collateOne[R, That](pf: PartialFunction[T, R])(implicit mbf: CanBuildFrom[Repr, R, That]) = { 102 | val matches = mbf(xs) 103 | val remainder = rbf(xs) 104 | for (x <- xs) if (pf.isDefinedAt(x)) matches += pf(x) else remainder += x 105 | (matches.result, remainder.result) 106 | } 107 | 108 | def collate[R, That](pf: PartialFunction[T, R])(implicit mbf: CanBuildFrom[Repr, R, That]): Results1[That] = { 109 | val tup = collateOne[R,That](pf) 110 | Results1(tup._1, tup._2) 111 | } 112 | } 113 | } 114 | 115 | object Collatable { 116 | implicit def traversableIsCollatable[CC[X] <: Traversable[X], T] 117 | (xs: CC[T])(implicit rbf: CanBuildFrom[CC[T], T, CC[T]]) = new Collatable[CC[T], T] of xs 118 | 119 | implicit def stringIsCollatable(xs: String) = new Collatable[String, Char] of xs 120 | } 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/main/scala/scalaj/reflect/ForwardPipe.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | 4 | class ForwardPipe[A](value: A) { 5 | def |>[B](f: A => B): B = f(value) 6 | } 7 | 8 | object ForwardPipe { 9 | implicit def apply[A](a: => A) = new ForwardPipe(a) 10 | } 11 | -------------------------------------------------------------------------------- /src/main/scala/scalaj/reflect/Mirrors.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | import tools.scalap.scalax.rules.scalasig.{Type => SymType, _} 4 | import java.lang.Class 5 | import java.lang.reflect.{Type => JType} 6 | 7 | import Collatable._ 8 | import reflect.{Manifest, NoManifest} 9 | 10 | /** 11 | * Mirrors symbols; anything with a name that can be referenced elsewhere 12 | */ 13 | object Mirror { 14 | import NameHelpers._ 15 | val cache = collection.mutable.Map.empty[Symbol, Mirror] 16 | 17 | private def generateFor(sym: Symbol): Mirror = sym match { 18 | case o: ObjectSymbol => ObjectMirror(o) 19 | case c: ClassSymbol if !isRefinementClass(c) && !c.isModule => ClassMirror(c) 20 | case m: MethodSymbol => MethodMirror(m) 21 | // case t: TypeSymbol if !t.isParam && !t.name.matches("_\\$\\d+")=> error("not implemented") 22 | case x => RawSymbolMirror(x) 23 | } 24 | 25 | def ofSymbol(sym: Symbol): Mirror = cache.getOrElseUpdate(sym, generateFor(sym)) 26 | 27 | def ofClass[T: ClassManifest]: Option[ClassMirror] = { 28 | val tpe = classManifest[T].erasure 29 | val sig = AutographBook.sigFromType(tpe) 30 | 31 | val classes = sig map { _.topLevelClasses } 32 | val sym = classes flatMap { _ find (_.name == tpe.getSimpleName) } 33 | sym map {Mirror ofSymbol} collect { case cm: ClassMirror => cm} 34 | } 35 | 36 | def ofClass[T](clazz: Class[T]): Option[ClassMirror] = { 37 | val sig = AutographBook.sigFromType(clazz) 38 | 39 | val classes = sig map { _.topLevelClasses } 40 | val sym = classes flatMap { _ find (_.name == clazz.getSimpleName) } 41 | sym map {Mirror ofSymbol} collect { case cm: ClassMirror => cm} 42 | } 43 | 44 | def ofObject[T <: AnyRef with Singleton](obj: T): Option[ObjectMirror] = { 45 | val tpe = obj.getClass 46 | val sig = AutographBook.sigFromType(tpe) 47 | 48 | val objects = sig map { _.topLevelObjects } 49 | val sym = objects flatMap { _ find (_.name == tpe.getName) } 50 | sym map {Mirror ofSymbol} collect { case cm: ObjectMirror => cm} 51 | } 52 | 53 | } 54 | 55 | sealed trait Mirror 56 | sealed trait NamedMirror extends Mirror { def name: String } 57 | 58 | 59 | //////////////////////// 60 | // TYPE MIRRORS 61 | // 62 | 63 | object TypeMirror { 64 | def apply(tpe: SymType) = tpe match { 65 | // case mt: MethodType => MethodMirror(mt) 66 | case trt: TypeRefType => TypeRefMirror(trt) 67 | case st: SingleType => SingleTypeMirror(st) 68 | case pt: PolyType => PolyTypeMirror(pt) 69 | case x => RawTypeMirror(x) 70 | } 71 | } 72 | 73 | sealed trait TypeMirror extends Mirror { 74 | def tpe: SymType 75 | def toManifest[T <: AnyRef]: Manifest[T] 76 | override def toString = "<>" 77 | } 78 | 79 | case class RawTypeMirror(tpe: SymType) extends TypeMirror { 80 | def toManifest[T <: AnyRef]: Manifest[T] = tpe match { 81 | case ThisType(symbol) => error("todo - ThisType manifest") 82 | case SingleType(typeRef, symbol) => error("todo - SingleType manifest") 83 | case ConstantType(constant) => error("todo - ConstantType manifest") 84 | //case TypeRefType(prefix, symbol, typeArgs) => ... 85 | case TypeBoundsType(lower, upper) => 86 | val lbound = TypeMirror(lower).toManifest 87 | val ubound = TypeMirror(upper).toManifest 88 | Manifest.wildcardType(lbound, ubound) 89 | case RefinedType(classSym, typeRefs) => error("todo - RefinedType manifest") 90 | case ClassInfoType(symbol, typeRefs) => 91 | //todo: check for poly 92 | Manifest.classType(Class.forName(symbol.path)) 93 | //error("todo - ClassInfoType manifest") 94 | case ClassInfoTypeWithCons(symbol, typeRefs, cons) => error("todo - ClassInfoTypeWithCons manifest") 95 | case MethodType(resultType, paramSymbols) => error("todo - MethodType manifest") 96 | //case PolyType(typeRef, symbols) => error("todo") 97 | case PolyTypeWithCons(typeRef, symbols, cons) => error("todo - PolyTypeWithCons manifest") 98 | case ImplicitMethodType(resultType, paramSymbols) => error("todo - ImplicitMethodType manifest") 99 | case AnnotatedType(typeRef, attribTreeRefs) => error("todo - AnnotatedType manifest") 100 | case AnnotatedWithSelfType(typeRef, symbol, attribTreeRefs) => error("todo - AnnotatedWithSelfType manifest") 101 | case DeBruijnIndexType(typeLevel, typeIndex) => error("todo - DeBruijnIndexType manifest") 102 | case ExistentialType(typeRef, symbols) => error("todo - ExistentialType manifest") 103 | } 104 | } 105 | 106 | case class SingleTypeMirror(tpe: SingleType) extends TypeMirror with NamedMirror { 107 | // println("SingleTypeMirror for type " + tpe + " with symbol " + tpe.symbol + " of class " + tpe.symbol.getClass) 108 | val name = tpe.symbol.name 109 | val path = tpe.symbol.path 110 | override def toString = name 111 | def toManifest[T <: AnyRef]: Manifest[T] = { 112 | println("fetching Manifest for: " + path) 113 | Manifest.classType(Class.forName(path)) 114 | } 115 | } 116 | 117 | case class TypeRefMirror(tpe: TypeRefType) extends TypeMirror with NamedMirror { 118 | val name = tpe.symbol.name 119 | val path = tpe.symbol.path 120 | override def toString = name 121 | def toManifest[T <: AnyRef]: Manifest[T] = { 122 | println("fetching Java type for: " + path) 123 | path match { 124 | case "scala.Nothing" => Manifest.Nothing.asInstanceOf[Manifest[T]] 125 | case "scala.Any" => Manifest.Any.asInstanceOf[Manifest[T]] 126 | case _ => Manifest.classType(Class.forName(path)) 127 | } 128 | } 129 | 130 | } 131 | 132 | case class PolyTypeMirror(tpe: PolyType) extends TypeMirror { 133 | val typeRef = TypeMirror(tpe.typeRef) 134 | val rawSymbols = tpe.symbols 135 | val symbols = rawSymbols map { SymbolMirror(_) } 136 | override def toString = symbols.mkString("[", ", ", "]") + typeRef.toString 137 | def toManifest[T <: AnyRef]: Manifest[T] = { 138 | val symbolTypes = symbols collect { 139 | case sym: TypedSymbolMirror => sym.symType 140 | } 141 | if (symbolTypes.size < symbols.size) { 142 | println("untyped symbol in PolyType signature") 143 | } 144 | 145 | val symbolManifests = symbolTypes map {_.toManifest} 146 | 147 | val rawClass = tpe.typeRef match { 148 | case cit: ClassInfoType => 149 | Class.forName(cit.symbol.path).asInstanceOf[Class[T]] 150 | case _ => error("can only extract a manifest from a PolyType wrapping a ClassInfoType, found " + tpe.typeRef) 151 | } 152 | Manifest.classType(rawClass, symbolManifests.head, symbolManifests.tail: _*) 153 | } 154 | } 155 | 156 | case class RefinedTypeMirror(underlying: TypeMirror, refinedTypes: List[Manifest]) extends TypeMirror { 157 | def tpe = underlying.tpe 158 | def toManifest[T <: AnyRef]: Manifest[T] = 159 | Manifest.classType(underlying.toManifest.erasure, refinedTypes.head, refinedTypes.tail) 160 | 161 | } 162 | 163 | //////////////////////// 164 | // SYMBOL MIRRORS 165 | // 166 | 167 | sealed trait MemberMirror extends NamedMirror { def isPrivate: Boolean } 168 | 169 | /** 170 | * A symbol is ANY atomic entity with a name, such as: 171 | * * T 172 | * * Int 173 | * * someProperty 174 | * * aMethod 175 | * * MyClass 176 | * * ... 177 | */ 178 | object SymbolMirror { 179 | def apply(sym: Symbol): NamedMirror = sym match { 180 | case m: MethodSymbol => MethodMirror(m) 181 | case t: TypeSymbol => TypeSymbolMirror(t) 182 | case x => RawSymbolMirror(x) 183 | } 184 | } 185 | 186 | sealed trait SymbolMirror extends NamedMirror { 187 | def sym: Symbol 188 | def name = sym.name 189 | override def toString = "<>" 190 | } 191 | 192 | sealed trait TypedSymbolMirror extends SymbolMirror { 193 | def sym: SymbolInfoSymbol 194 | def symType = TypeMirror(sym.infoType) 195 | def manifest[T <: AnyRef] = symType.toManifest[T] 196 | def typeParams: Seq[Manifest[_]] = manifest.typeArguments 197 | } 198 | 199 | sealed trait Reifiable[Repr <: Reifiable[_]] { 200 | self: TypedSymbolMirror => 201 | def reify(reifiedParams: Manifest[_]*) : Repr 202 | } 203 | 204 | case class RawSymbolMirror(sym: Symbol) extends SymbolMirror 205 | 206 | case class TypeSymbolMirror(sym: TypeSymbol) extends TypedSymbolMirror { 207 | override def toString = name 208 | } 209 | 210 | /** 211 | * Anything that can hold *publicly visible* members. 212 | * "members" being classes, defs, vals, etc. 213 | */ 214 | abstract class MemberContainerMirror extends SymbolMirror { 215 | def memberSymbols: Seq[Symbol] 216 | 217 | lazy val typeAliases = memberSymbols collect { case als: AliasSymbol => RawSymbolMirror(als) } 218 | 219 | lazy val allMethodSymbols = memberSymbols collect { case ms @ MethodSymbol(_,_) => ms } 220 | lazy val reallyTrulyAllMethods = allMethodSymbols map { MethodMirror(_) } 221 | lazy val allNaturalMethods = reallyTrulyAllMethods filterNot { m => m.isSynthetic || m.isLocal } 222 | lazy val allSyntheticMethods = reallyTrulyAllMethods filter { m => m.isSynthetic || m.isLocal } 223 | 224 | lazy val allDefs = allNaturalMethods filterNot { m => m.isAccessor || m.isConstructor } 225 | lazy val publicDefs = allDefs filterNot { _.isPrivate } 226 | lazy val privateDefs = allDefs filter { _.isPrivate } 227 | 228 | lazy val allAccessors = allNaturalMethods filter { _.isAccessor } collect { 229 | case m if !(m.name endsWith "_$eq") => 230 | val setter = allNaturalMethods find (_.name == m.name + "_$eq") 231 | setter map {VarMirror(m,_)} getOrElse ValMirror(m) 232 | } 233 | 234 | lazy val publicAccessors = allAccessors filterNot (_.isPrivate) 235 | 236 | lazy val vals = allAccessors collect {case v: ValMirror => v} 237 | lazy val vars = allAccessors collect {case v: VarMirror => v} 238 | 239 | //lazy val publicMembers: Seq[NamedMirror] = 240 | } 241 | 242 | case class ClassMirror(sym: ClassSymbol) extends MemberContainerMirror with TypedSymbolMirror with Reifiable[ClassMirror] { 243 | val memberSymbols = sym.children 244 | 245 | val parent = sym.parent 246 | val qualifiedName = (parent map {_.path + "."} getOrElse "") + sym.name 247 | lazy val javaClass = Class.forName(qualifiedName) 248 | 249 | def reify(reifiedParams: Manifest[_]*) : ClassMirror = error("not impl") 250 | 251 | lazy val constructors = allNaturalMethods filter {_.isConstructor} map {ConstructorMirror(this,_)} 252 | 253 | override def toString = "class " + name 254 | //def methods: Seq[MethodMirror] = 255 | } 256 | 257 | case class ObjectMirror(sym: ObjectSymbol) extends MemberContainerMirror { 258 | val TypeRefType(prefix, classSymbol: ClassSymbol, typeArgs) = sym.infoType 259 | val memberSymbols = classSymbol.children 260 | override def toString = "object " + name 261 | } 262 | 263 | /** 264 | * Anything that takes parameters: Constructors, Setters and Methods 265 | */ 266 | case class MethodMirror(val sym: MethodSymbol) extends SymbolMirror with MemberMirror { 267 | val isSynthetic = sym.isSynthetic 268 | val isAccessor = sym.isAccessor 269 | val isLocal = sym.isLocal 270 | val isPrivate = sym.isPrivate 271 | val isConstructor = name == NameHelpers.CONSTRUCTOR_NAME 272 | 273 | val rawType = sym.infoType 274 | val (refType, typeParamSymbols) = rawType match { 275 | case PolyType(refType, typeParamSymbols) => (refType, typeParamSymbols) 276 | case x => (x, Seq.empty[TypeSymbol]) 277 | } 278 | 279 | val typeParams = typeParamSymbols map TypeSymbolMirror.apply 280 | 281 | private[this] val returnChain = Iterator.iterate(Some(refType): Option[SymType]){ 282 | case Some(MethodType(rt, _)) => Some(rt) 283 | case Some(ImplicitMethodType(rt, _)) => Some(rt) 284 | case _ => None 285 | } takeWhile (None !=) map (_.get) map { 286 | case mt: MethodType => ExplicitParamBlockMirror(mt) 287 | case imt: ImplicitMethodType => ImplicitParamBlockMirror(imt) 288 | case x => TypeMirror(x) 289 | } toList 290 | 291 | val paramBlocks = returnChain collect { case pbm: ParamBlockMirror => pbm } 292 | val returnType = returnChain.last 293 | 294 | def flatParams = paramBlocks flatMap (_.params) 295 | 296 | override def toString = { 297 | val prefix = ( 298 | Some("SYN").filter(_ => isSynthetic) :: 299 | Some("ACC").filter(_ => isAccessor) :: 300 | Some("CTOR").filter(_ => isConstructor) :: 301 | Some("LCL").filter(_ => isLocal) :: 302 | Nil).flatten mkString " " 303 | 304 | val typeParamsStr = if (typeParams.isEmpty) "" else typeParams.mkString("[",", ","]") 305 | val paramBlocksStr = paramBlocks mkString "" 306 | prefix + "method " + name + typeParamsStr + paramBlocks.mkString("") + ": " + returnType.toString 307 | } 308 | // TODO: def invoke(args: Object*) 309 | } 310 | 311 | //TODO: DefMirror?, ConstructorMirror? 312 | /** 313 | * A val or a var, also (potentially) bean properties 314 | */ 315 | 316 | sealed trait PropertyMirror extends MemberMirror { 317 | def isGettable: Boolean 318 | def isSettable: Boolean 319 | } 320 | 321 | case class ValMirror(getter: MethodMirror) extends PropertyMirror { 322 | val name = getter.name 323 | def isPrivate = getter.isPrivate 324 | val isGettable = true 325 | val isSettable = false 326 | } 327 | 328 | case class VarMirror(getter: MethodMirror, setter: MethodMirror) extends PropertyMirror { 329 | val name = getter.name 330 | def isPrivate = getter.isPrivate 331 | val isGettable = true 332 | val isSettable = true 333 | } 334 | 335 | case class ConstructorMirror(clazz: ClassMirror, method: MethodMirror) extends MemberMirror { 336 | def isPrivate = method.isPrivate 337 | def name = "this" 338 | method.flatParams map (_.name) 339 | //def toJavaConstructor = clazz.javaClass.getConstructor() 340 | } 341 | 342 | abstract class ParamBlockMirror(paramSymbols: Seq[Symbol]) extends Mirror { 343 | val params = paramSymbols map { 344 | case ms: MethodSymbol => ParamMirror(ms) 345 | case x => error("Don't know what to do with a param that isn't a MethodSymbol!") 346 | } 347 | } 348 | 349 | case class ExplicitParamBlockMirror(val tpe: MethodType) extends ParamBlockMirror(tpe.paramSymbols) { 350 | override def toString = params.mkString("(", ", ", ")") 351 | } 352 | case class ImplicitParamBlockMirror(val tpe: ImplicitMethodType) extends ParamBlockMirror(tpe.paramSymbols) { 353 | override def toString = params.mkString("(implicit ", ", ", ")") 354 | } 355 | 356 | case class ParamMirror(sym: MethodSymbol) extends TypedSymbolMirror { 357 | override def toString = name + ": " + symType.toString 358 | } 359 | 360 | 361 | 362 | 363 | /** 364 | * Anything that takes a type. Some classes, methods and aliases 365 | */ 366 | trait TypeParamaterizedMirror extends Mirror { 367 | def typeParams: Seq[Object] 368 | } 369 | 370 | 371 | 372 | 373 | /** 374 | * Anything that has a constructor. 375 | * Basically just classes at the moment. 376 | * (maybe traits in the future, who knows?) 377 | */ 378 | //trait ConstructableMirror extends Mirror { 379 | // def primaryConstructor: MethodMirror 380 | // def secondaryConstructors: Seq[MethodMirror] 381 | // def allConstructors = primaryConstructor +: secondaryConstructors 382 | //} 383 | 384 | 385 | 386 | 387 | 388 | -------------------------------------------------------------------------------- /src/main/scala/scalaj/reflect/NameHelpers.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | import java.util.regex.Pattern 4 | import tools.scalap.scalax.rules.scalasig._ 5 | 6 | object NameHelpers { 7 | val CONSTRUCTOR_NAME = "" 8 | 9 | val _syms = Map( 10 | "\\$bar" -> "|", 11 | "\\$tilde" -> "~", 12 | "\\$bang" -> "!", 13 | "\\$up" -> "^", 14 | "\\$plus" -> "+", 15 | "\\$minus" -> "-", 16 | "\\$eq" -> "=", 17 | "\\$less" -> "<", 18 | "\\$times" -> "*", 19 | "\\$div" -> "/", 20 | "\\$bslash" -> "\\\\", 21 | "\\$greater" -> ">", 22 | "\\$qmark" -> "?", 23 | "\\$percent" -> "%", 24 | "\\$amp" -> "&", 25 | "\\$colon" -> ":", 26 | "\\$u2192" -> "?", 27 | "\\$hash" -> "#") 28 | val pattern = Pattern.compile(_syms.keys.mkString("", "|", "")) 29 | val placeholderPattern = "_\\$(\\d)+" 30 | 31 | private def stripPrivatePrefix(name: String) = { 32 | val i = name.lastIndexOf("$$") 33 | if (i > 0) name.substring(i + 2) else name 34 | } 35 | 36 | def processName(name: String) = { 37 | val stripped = stripPrivatePrefix(name) 38 | val m = pattern.matcher(stripped) 39 | var temp = stripped 40 | while (m.find) { 41 | val key = m.group 42 | val re = "\\" + key 43 | temp = temp.replaceAll(re, _syms(re)) 44 | } 45 | val result = temp.replaceAll(placeholderPattern, "_") 46 | scala.reflect.NameTransformer.decode(result) 47 | } 48 | 49 | def isRefinementClass(c: ClassSymbol) = c.name == "" 50 | 51 | def isConstructor(c: Symbol) = 52 | c.isInstanceOf[MethodSymbol] && c.name == "" 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/scala/scalaj/reflect/SymbolTreePrinter.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | import tools.scalap.scalax.rules.scalasig.{Type => SymType, _} 3 | 4 | object SymbolTreePrinter extends SymbolTreePrinter { 5 | def withoutOwners = new SymbolTreePrinter { 6 | override def mkTree[T](input: T) = (new Run).mkTree(input)(Context(false, true)) 7 | } 8 | } 9 | 10 | class SymbolTreePrinter { 11 | def quote(s: String) = "\"" + s + "\"" 12 | 13 | def mkTree[T](input: T) = 14 | (new Run).mkTree(input) 15 | 16 | case class Context(skipChildren: Boolean = false, skipOwner: Boolean = false) { 17 | def withoutChildren: Context = this.copy(skipChildren=true) 18 | def withoutOwner: Context = this.copy(skipOwner=true) 19 | } 20 | 21 | class Run { 22 | var symbolsSeen: Set[Symbol] = Set.empty 23 | var typesSeen: Set[SymType] = Set.empty 24 | 25 | def mkTree[T](input: T)(implicit ctx: Context = new Context): String = input match { 26 | case sm: SymbolMirror => mkTree(sm.sym) 27 | case sym: Symbol => symbolsSeen += sym; mkSymbolTree(sym) 28 | case tpe: SymType => typesSeen += tpe; mkTypeTree(tpe) 29 | case i: Int => i.toString 30 | case s: String => s 31 | case e: ScalaSig#Entry => e.toString 32 | case _ => "oops @ " + input.toString + ": " + input.asInstanceOf[AnyRef].getClass 33 | } 34 | 35 | private def optNest[T](input: (String, Option[T]))(implicit ctx: Context = new Context) = input match { 36 | case (name, Some(value)) => nest(name->value) 37 | case _ => "" 38 | } 39 | 40 | private def nestAll[T](input: (String, Seq[T]))(implicit ctx: Context = new Context) = input match { 41 | case (name, values) => values.zipWithIndex map { case (v,i) => 42 | val indexedName = "%s %d/%d".format(name, i+1, values.size) 43 | nest(indexedName->v) 44 | } mkString "" 45 | } 46 | 47 | private def nest[T](input: (String, T))(implicit ctx: Context = new Context) = { 48 | val (name, x) = input 49 | val nested = x match { 50 | case s: ScalaSigSymbol if symbolsSeen contains s => s.path + " (already seen at #" + s.entry.index + ")" 51 | case s: Symbol if symbolsSeen contains s => s.path + " (already seen)" 52 | case t: SymType if typesSeen contains t => typeName(t) + "(type already seen)" 53 | case null => "" 54 | case _ => mkTree(x) 55 | } 56 | (name + " = " + nested).lines map {"| " + _} mkString("\n","\n","") 57 | } 58 | 59 | def mkTypeTree(tpe: SymType)(implicit ctx: Context = new Context): String = tpe match { 60 | case NoType => "NoType" 61 | case NoPrefixType => "NoPrefixType" 62 | case ThisType(symbol) => 63 | "ThisType" + 64 | nest("symbol"->symbol) 65 | case SingleType(typeRef, symbol) => 66 | "SingleType" + 67 | nest("typeRef"->typeRef) + 68 | nest("symbol"->symbol) 69 | case ConstantType(constant) => 70 | "ConstantType" + 71 | nest("constant"->constant) 72 | case TypeRefType(prefix, symbol, typeArgs) => 73 | "TypeRefType" + 74 | nest("prefix"->prefix) + 75 | nest("symbol"->symbol) + 76 | nestAll("typeArg"->typeArgs) 77 | case TypeBoundsType(lower, upper) => 78 | "TypeBoundsType" + 79 | nest("lower"->lower) + 80 | nest("upper"->upper) 81 | case RefinedType(classSym, typeRefs) => 82 | "RefinedType" + 83 | nest("classSym"->classSym) + 84 | nest("typeRefs"->typeRefs) 85 | case ClassInfoType(symbol, typeRefs) => 86 | "ClassInfoType" + 87 | nest("symbol"->symbol) + 88 | nestAll("typeRef"->typeRefs) 89 | case ClassInfoTypeWithCons(symbol, typeRefs, cons) => 90 | "ClassInfoTypeWithCons" + 91 | nest("symbol"->symbol) + 92 | nestAll("typeRef"->typeRefs) + 93 | nest("cons"->cons) 94 | case MethodType(resultType, paramSymbols) => 95 | "MethodType" + 96 | nest("resultType"->resultType) + 97 | nestAll("paramSymbol"->paramSymbols) 98 | case PolyType(typeRef, symbols) => 99 | "PolyType" + 100 | nest("typeRef"->typeRef) + 101 | nestAll("symbol"->symbols) 102 | case PolyTypeWithCons(typeRef, symbols, cons) => 103 | "PolyTypeWithCons" + 104 | nest("typeRef"->typeRef) + 105 | nestAll("symbol"->symbols) + 106 | nest("cons"->cons) 107 | case ImplicitMethodType(resultType, paramSymbols) => 108 | "ImplicitMethodType" + 109 | nest("resultType"->resultType) + 110 | nestAll("paramSymbol"->paramSymbols) 111 | case AnnotatedType(typeRef, attribTreeRefs) => 112 | "AnnotatedType" + 113 | nest("typeRef"->typeRef) + 114 | nestAll("attribTreeRef"->attribTreeRefs) 115 | case AnnotatedWithSelfType(typeRef, symbol, attribTreeRefs) => 116 | "AnnotatedWithSelfType" + 117 | nest("typeRef"->typeRef) + 118 | nest("symbol"->symbol) + 119 | nestAll("attribTreeRef"->attribTreeRefs) 120 | case DeBruijnIndexType(typeLevel, typeIndex) => 121 | "DeBruijnIndexType" + 122 | nest("typeLevel"->typeLevel) + 123 | nest("typeIndex"->typeIndex) 124 | case ExistentialType(typeRef, symbols) => 125 | "ExistentialType" + 126 | nest("typeRef"->typeRef) + 127 | nestAll("symbol"->symbols) 128 | } 129 | 130 | def mkSymbolTree(sym: Symbol)(implicit ctx: Context = new Context): String = sym match { 131 | case NoSymbol => "NoSymbol" 132 | case ExternalSymbol(name, parent, entry) => 133 | quote(sym.path) + 134 | " (external #" + entry.index + " type = " + entryTypeName(entry.entryType) + ")" + 135 | optNest("parent"->parent)(ctx.withoutChildren) 136 | //(if(!ctx.skipChildren) nestAll("child"->sym.children) else "") 137 | 138 | case sym @ TypeSymbol(_) => "TypeSymbol" + addSymbolInfo(sym) 139 | case sym @ AliasSymbol(_) => "AliasSymbol" + addSymbolInfo(sym) 140 | case sym @ ClassSymbol(_, thisTypeRef) => "ClassSymbol" + addSymbolInfo(sym) + 141 | optNest("thisTypeRef"->thisTypeRef) 142 | case sym @ ObjectSymbol(_) => "ObjectSymbol" + addSymbolInfo(sym) 143 | case sym @ MethodSymbol(_, aliasRef) => "MethodSymbol" + addSymbolInfo(sym) + 144 | optNest("aliasRef"->aliasRef) 145 | } 146 | 147 | def addSymbolInfo(sym: SymbolInfoSymbol)(implicit ctx: Context = new Context): String = { 148 | val SymbolInfo(name, owner, flags, privateWithin, info, entry) = sym.symbolInfo 149 | " name = " + quote(name) + " (entry #" + entry.index + ")" + 150 | nest("path"->quote(sym.path)) + 151 | { if (ctx.skipOwner) "" else nest("owner"->owner)(ctx.withoutChildren) } + 152 | nest("flags/info"->(flags.toString + " / " + info.toString)) + 153 | optNest("privateWithin"->privateWithin) + 154 | nest("infoType"->sym.infoType) + 155 | nestAll("child"->sym.children) 156 | } 157 | } 158 | 159 | def typeName(tpe: SymType): String = tpe match { 160 | case NoType => "NoType" 161 | case NoPrefixType => "NoPrefixType" 162 | case ThisType(symbol) => symbol.path 163 | case SingleType(_, symbol) => symbol.path 164 | case ConstantType(constant) => constant.toString 165 | case TypeRefType(prefix, symbol, typeArgs) => symbol.path 166 | case TypeBoundsType(lower, upper) => typeName(lower) + " <: " + typeName(upper) 167 | case RefinedType(classSym, typeRefs) => classSym.path 168 | case ClassInfoType(symbol, typeRefs) => symbol.path 169 | case ClassInfoTypeWithCons(symbol, typeRefs, cons) => symbol.path 170 | case MethodType(resultType, paramSymbols) => "MethodType" 171 | case PolyType(typeRef, symbols) => "PolyType" 172 | case PolyTypeWithCons(typeRef, symbols, cons) => "PolyTypeWithCons" 173 | case ImplicitMethodType(resultType, paramSymbols) => "ImplicitMethodType" 174 | case AnnotatedType(typeRef, attribTreeRefs) => "AnnotatedType" 175 | case AnnotatedWithSelfType(typeRef, symbol, attribTreeRefs) => symbol.path 176 | case DeBruijnIndexType(typeLevel, typeIndex) => "DeBruijnIndexType" 177 | case ExistentialType(typeRef, symbols) => "ExistentialType" 178 | } 179 | 180 | val entryTypeName = Map( 181 | 1->"TERMNAME", 182 | 2->"TYPENAME", 183 | 3->"NONEsym", 184 | 4->"TYPEsym", 185 | 5->"ALIASsym", 186 | 6->"CLASSsym", 187 | 7->"MODULEsym", 188 | 8->"VALsym", 189 | 9->"EXTref", 190 | 10->"EXTMODCLASSref", 191 | 11->"NOtpe", 192 | 12->"NOPREFIXtpe", 193 | 13->"THIStpe", 194 | 14->"SINGLEtpe", 195 | 15->"CONSTANTtpe", 196 | 16->"TYPEREFtpe", 197 | 17->"TYPEBOUNDStpe", 198 | 18->"REFINEDtpe", 199 | 19->"CLASSINFOtpe", 200 | 20->"METHODtpe", 201 | 21->"POLYTtpe", 202 | 22->"IMPLICITMETHODtpe", 203 | 52->"SUPERtpe", 204 | 24->"LITERALunit", 205 | 25->"LITERALboolean", 206 | 26->"LITERALbyte", 207 | 27->"LITERALshort", 208 | 28->"LITERALchar", 209 | 29->"LITERALint", 210 | 30->"LITERALlong", 211 | 31->"LITERALfloat", 212 | 32->"LITERALdouble", 213 | 33->"LITERALstring", 214 | 34->"LITERALnull", 215 | 35->"LITERALclass", 216 | 36->"LITERALenum", 217 | 40->"SYMANNOT", 218 | 41->"CHILDREN", 219 | 42->"ANNOTATEDtpe", 220 | 43->"ANNOTINFO", 221 | 44->"ANNOTARGARRAY", 222 | 47->"DEBRUIJNINDEXtpe", 223 | 48->"EXISTENTIALtpe") map {case (a,b) => a -> "%s[%s]".format(b,a)} 224 | 225 | } 226 | -------------------------------------------------------------------------------- /src/main/scala/scalaj/reflect/TypeMirrors.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | import tools.scalap.scalax.rules.scalasig.{Type => SymType, _} 4 | import tools.scalap.scalax.util.StringUtil 5 | 6 | //object TypeMirror { 7 | // def of(symType: SymType): TypeMirror = symType match { 8 | // case trt: TypeRefType => RefTypeMirror(trt) 9 | // case pt: PolyType => PolyTypeMirror(pt) 10 | // case mt: MethodType => MethodTypeMirror(mt) 11 | // case mt: ImplicitMethodType => MethodTypeMirror(mt) 12 | // case x => UnknownTypeMirror(x) 13 | // } 14 | //} 15 | 16 | //sealed abstract trait TypeMirror { 17 | // val symType: SymType 18 | //} 19 | // 20 | //case class PolyTypeMirror(symType: PolyType) extends TypeMirror { 21 | // val innerSymMirror = TypeMirror.of(symType.typeRef) 22 | // val typeSymbols = symType.symbols map Mirror.of 23 | // def typesStr = typeSymbols map {_.toString} mkString "," 24 | // override def toString = "" + innerSymMirror.toString 25 | //} 26 | // 27 | //case class SimpleTypeMirror(symType: SymType) extends TypeMirror { 28 | // import NameHelpers._ 29 | // 30 | // def innerToString(t: SymType, sep: String) = symType match { 31 | // case ThisType(symbol) => sep + processName(symbol.path) + ".type" 32 | // case SingleType(typeRef, symbol) => sep + processName(symbol.path) + ".type" 33 | // case ConstantType(constant) => sep + (constant match { 34 | // case null => "Null" 35 | // case _: Unit => "Unit" 36 | // case _: Boolean => "Boolean" 37 | // case _: Byte => "Byte" 38 | // case _: Char => "Char" 39 | // case _: Short => "Short" 40 | // case _: Int => "Int" 41 | // case _: Long => "Long" 42 | // case _: Float => "Float" 43 | // case _: Double => "Double" 44 | // case _: String => "String" 45 | // case c: Class[_] => "Class[" + c.getComponentType.getCanonicalName.replace("$", ".") + "]" 46 | // }) 47 | //// case TypeRefType(prefix, symbol, typeArgs) => sep + (symbol.path match { 48 | //// case "scala." => flags match { 49 | //// case TypeFlags(true) => toString(typeArgs.head) + "*" 50 | //// case _ => "scala.Seq" + typeArgString(typeArgs) 51 | //// } 52 | //// case "scala." => "=> " + toString(typeArgs.head) 53 | //// case _ => { 54 | //// val path = StringUtil.cutSubstring(symbol.path)(".package") //remove package object reference 55 | //// StringUtil.trimStart(processName(path) + typeArgString(typeArgs), ".") 56 | //// } 57 | //// }) 58 | //// case TypeBoundsType(lower, upper) => { 59 | //// val lb = toString(lower) 60 | //// val ub = toString(upper) 61 | //// val lbs = if (!lb.equals("scala.Nothing")) " >: " + lb else "" 62 | //// val ubs = if (!ub.equals("scala.Any")) " <: " + ub else "" 63 | //// lbs + ubs 64 | //// } 65 | //// case RefinedType(classSym, typeRefs) => sep + typeRefs.map(toString).mkString("", " with ", "") 66 | //// case ClassInfoType(symbol, typeRefs) => sep + typeRefs.map(toString).mkString(" extends ", " with ", "") 67 | //// case ClassInfoTypeWithCons(symbol, typeRefs, cons) => sep + typeRefs.map(toString). 68 | //// mkString(cons + " extends ", " with ", "") 69 | //// 70 | //// case ImplicitMethodType(resultType, _) => toString(resultType, sep) 71 | //// case MethodType(resultType, _) => toString(resultType, sep) 72 | //// 73 | //// case PolyType(typeRef, symbols) => typeParamString(symbols) + toString(typeRef, sep) 74 | //// case PolyTypeWithCons(typeRef, symbols, cons) => typeParamString(symbols) + processName(cons) + toString(typeRef, sep) 75 | //// case AnnotatedType(typeRef, attribTreeRefs) => { 76 | //// toString(typeRef, sep) 77 | //// } 78 | //// case AnnotatedWithSelfType(typeRef, symbol, attribTreeRefs) => toString(typeRef, sep) 79 | //// //case DeBruijnIndexType(typeLevel, typeIndex) => 80 | //// case ExistentialType(typeRef, symbols) => { 81 | //// val refs = symbols.map(toString _).filter(!_.startsWith("_")).map("type " + _) 82 | //// toString(typeRef, sep) + (if (refs.size > 0) refs.mkString(" forSome {", "; ", "}") else "") 83 | //// } 84 | // case _ => sep + "" + t.toString 85 | // } 86 | // 87 | // override def toString = innerToString(symType, "") 88 | //} 89 | // 90 | //case class RefTypeMirror(symType: TypeRefType) extends TypeMirror { 91 | // val targetSymbol = Mirror.of(symType.symbol) 92 | // override def toString = "" + targetSymbol.toString 93 | //} 94 | // 95 | //case class UnknownTypeMirror(symType: SymType) extends TypeMirror { 96 | // override def toString = "" + symType.toString 97 | //} 98 | // 99 | //case class MethodTypeMirror(symType: SymType) extends TypeMirror { 100 | // 101 | // val typeParams: Seq[TypeParamMirror] = symType match { 102 | // //multiple param blocks 103 | // case pt@PolyType(mt, typeParams) => typeParams map { TypeParamMirror.apply } 104 | // case _ => Seq.empty 105 | // } 106 | // 107 | // val isImplicit = symType.isInstanceOf[ImplicitMethodType] 108 | // 109 | // val resultType: TypeMirror = symType match { 110 | // case MethodType(rt, _) => MethodTypeMirror(rt) 111 | // case ImplicitMethodType(rt, _) => MethodTypeMirror(rt) 112 | // case rt @ TypeRefType(_, _, _) => RefTypeMirror(rt) 113 | // case x => SimpleTypeMirror(x) 114 | // } 115 | // 116 | // def paramToMirror(param: Symbol) = param match { 117 | // case ms: MethodSymbol => ParamMirror(ms) 118 | // case _ => UnknownMirror(param) 119 | // } 120 | // 121 | // val paramSymbols = symType match { 122 | // case MethodType(_, ps) => ps map {paramToMirror} 123 | // case ImplicitMethodType(_, ps) => ps map {paramToMirror} 124 | // case x => Seq.empty 125 | // } 126 | // 127 | // def resultToString = resultType match { 128 | // case MethodTypeMirror(_) => resultType.toString 129 | // case _ => ": " + resultType.toString 130 | // } 131 | // 132 | // override def toString = { 133 | // "" + (if (paramSymbols.isEmpty) { 134 | // "" 135 | // } else { 136 | // paramSymbols.map{_.toString}.mkString( 137 | // if(isImplicit) "(implicit " else "(", 138 | // ",", 139 | // ")" 140 | // ) 141 | // }) + resultToString 142 | // } 143 | //} 144 | // 145 | //trait ParamBlockTypeMirror { 146 | // def resultType: SymType 147 | // def paramSymbols: Seq[Symbol] 148 | // 149 | // def params: Seq[ParamMirror] = paramSymbols map { 150 | // case ms: MethodSymbol => ParamMirror(ms) 151 | // case ps => error(ps.toString) 152 | // } 153 | //} 154 | // 155 | //case class SimpleParamBlockTypeMirror(symType: MethodType) extends ParamBlockTypeMirror { 156 | // val resultType = symType.resultType 157 | // val paramSymbols = symType.paramSymbols 158 | //} 159 | // 160 | //case class ImplicitParamBlockTypeMirror(symType: ImplicitMethodType) extends ParamBlockTypeMirror { 161 | // val resultType = symType.resultType 162 | // val paramSymbols = symType.paramSymbols 163 | //} 164 | -------------------------------------------------------------------------------- /src/main/scala/scalaj/reflect/TypeWrangler.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | import java.{lang => jl} 4 | import java.lang.reflect.{ Type => JType, Array => _, _ } 5 | import scala.reflect.Manifest 6 | import scala.reflect.Manifest.{ classType, intersectionType, arrayType, wildcardType } 7 | 8 | 9 | /** 10 | * Negotiates between Spring's TypeDescriptor and Scala's Manifest mechanisms 11 | */ 12 | 13 | object TypeWrangler { 14 | 15 | val ByteClass = classOf[scala.Byte] 16 | val ShortClass = classOf[scala.Short] 17 | val CharClass = classOf[scala.Char] 18 | val IntClass = classOf[scala.Int] 19 | val LongClass = classOf[scala.Long] 20 | val FloatClass = classOf[scala.Float] 21 | val DoubleClass = classOf[scala.Double] 22 | val BooleanClass = classOf[scala.Boolean] 23 | val NullClass = classOf[scala.Null] 24 | val UnitClass = classOf[scala.Unit] 25 | 26 | val JByteClass = classOf[jl.Byte] 27 | val JShortClass = classOf[jl.Short] 28 | val JCharClass = classOf[jl.Character] 29 | val JIntClass = classOf[jl.Integer] 30 | val JLongClass = classOf[jl.Long] 31 | val JFloatClass = classOf[jl.Float] 32 | val JDoubleClass = classOf[jl.Double] 33 | val JBooleanClass = classOf[jl.Boolean] 34 | 35 | 36 | // Manifest.classType(x) will return a Manifest 37 | def manifestOf(c : Class[_]) = c match { 38 | case JByteClass | jl.Byte.TYPE | ByteClass => Manifest.Byte 39 | case JShortClass | jl.Short.TYPE | ShortClass => Manifest.Short 40 | case JCharClass | jl.Character.TYPE | CharClass => Manifest.Char 41 | case JIntClass | jl.Integer.TYPE | IntClass => Manifest.Int 42 | case JLongClass | jl.Long.TYPE | LongClass => Manifest.Long 43 | case JFloatClass | jl.Float.TYPE | FloatClass => Manifest.Float 44 | case JDoubleClass | jl.Double.TYPE | DoubleClass => Manifest.Double 45 | case JBooleanClass | jl.Boolean.TYPE | BooleanClass => Manifest.Boolean 46 | case jl.Void.TYPE | UnitClass => Manifest.Unit 47 | case null | NullClass => Manifest.Null 48 | case x => classType(x) 49 | } 50 | 51 | def intersect(tps: JType*): Manifest[_] = intersectionType(tps map javaType: _*) 52 | 53 | def javaType(tp: JType): Manifest[_] = tp match { 54 | case null => Manifest.Null 55 | case x: Class[_] => manifestOf(x) 56 | case x: ParameterizedType => 57 | val owner = x.getOwnerType 58 | val raw = x.getRawType() match { case clazz: Class[_] => clazz } 59 | val targs = x.getActualTypeArguments() map javaType 60 | 61 | (owner == null, targs.isEmpty) match { 62 | case (true, true) => javaType(raw) 63 | case (true, false) => classType(raw, targs.head, targs.tail: _*) 64 | case (false, _) => classType(javaType(owner), raw, targs: _*) 65 | } 66 | case x: GenericArrayType => arrayType(javaType(x.getGenericComponentType)) 67 | case x: WildcardType => wildcardType(intersect(x.getLowerBounds: _*), intersect(x.getUpperBounds: _*)) 68 | case x: TypeVariable[_] => intersect(x.getBounds(): _*) 69 | } 70 | 71 | 72 | } -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/AutographBookSpec.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | //give the wrangler a short name, don't import methods as we want full control without using them as implicits 4 | import scalaj.reflect.{TypeWrangler => wrangler} 5 | import org.specs.SpecificationWithJUnit 6 | 7 | import AutographBook._ 8 | import tools.scalap.scalax.rules.scalasig._ 9 | 10 | class AutographBookSpec extends SpecificationWithJUnit { 11 | 12 | 13 | "the AutographBook" should { 14 | "correctly resolve the mirror of a class" in { 15 | val tpe = classOf[targets.BasicSample] 16 | val sig = sigFromType(tpe) 17 | 18 | // val decompiledText = sig map decompile getOrElse("couldn't decompile") 19 | // println(decompiledText) 20 | // println("=====") 21 | 22 | val syms = sig map (topLevelSymsFromSig) getOrElse Nil 23 | 24 | val mirrors = syms map (Mirror.ofSymbol) 25 | // mirrors collect { case mcm: MemberContainerMirror => mcm } foreach { mcm => 26 | // println(mcm.toString) 27 | // mcm.allNaturalMethods map (_.toString) foreach {println} 28 | // mcm.allSyntheticMethods map (_.toString) foreach {println} 29 | // } 30 | val tgtMirror = (mirrors collect { case m: ClassMirror => m }).head 31 | tgtMirror.qualifiedName mustEqual "scalaj.reflect.targets.BasicSample" 32 | 33 | } 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/CollatableSpec.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | import org.specs.SpecificationWithJUnit 4 | import Collatable._ 5 | 6 | class CollatableSpec extends SpecificationWithJUnit { 7 | "Collatable" should { 8 | "collate a List[Int]" in { 9 | val ints = List(0,9,4,5,-3,-5,6,5,-2,1,0,6,-3,-2) 10 | val results = ints collate { 11 | case i: Int if(i < 0) => i.floatValue 12 | } andThen { 13 | case i: Int if(i > 5) => i.toString 14 | } andThen { 15 | case i: Int if(i == 0) => i 16 | } toTuple 17 | val expected = (List(-3.0, -5.0, -2.0, -3.0, -2.0), List("9", "6", "6"), List(0, 0), List(4, 5, 5, 1)) 18 | results mustEqual expected 19 | } 20 | 21 | "collate a String" in { 22 | val input = "129sdS DDFJ37$%$w__9 7sSF:::#\t tWE" 23 | val results = input collate { 24 | case c: Char if(c.isDigit) => c 25 | } andThen { 26 | case c: Char if(c.isUpper) => c 27 | } andThen { 28 | case c: Char if(c.isLower) => c 29 | } andThen { 30 | case c: Char if(c.isWhitespace) => c 31 | } toTuple 32 | val expected = ("1293797","SDDFJSFWE","sdwst"," \t ","$%$__:::#") 33 | results mustEqual expected 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/ExpectedPrintTrees.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | object ExpectedPrintTrees { 3 | val simpleVarGetter = 4 | """>MethodSymbol name = "simpleVar" (entry #74) 5 | >| path = "scalaj.reflect.targets.BasicSample.simpleVar" 6 | >| flags/info = 134218240 / 76 7 | >| infoType = PolyType 8 | >| | typeRef = TypeRefType 9 | >| | | prefix = ThisType 10 | >| | | | symbol = "scala" (external #20 type = EXTMODCLASSref[10]) 11 | >| | | symbol = "scala.Int" (external #36 type = EXTref[9]) 12 | >| | | | parent = scala (already seen at #20)""".stripMargin('>') 13 | 14 | val simpleVarSetter = 15 | """>MethodSymbol name = "simpleVar_$eq" (entry #77) 16 | >| path = "scalaj.reflect.targets.BasicSample.simpleVar_$eq" 17 | >| flags/info = 134218240 / 79 18 | >| infoType = MethodType 19 | >| | resultType = TypeRefType 20 | >| | | prefix = ThisType 21 | >| | | | symbol = "scala" (external #20 type = EXTMODCLASSref[10]) 22 | >| | | symbol = "scala.Unit" (external #81 type = EXTref[9]) 23 | >| | | | parent = scala (already seen at #20) 24 | >| | paramSymbol 1/1 = MethodSymbol name = "x$1" (entry #83) 25 | >| | | path = "scalaj.reflect.targets.BasicSample.simpleVar_$eq.x$1" 26 | >| | | flags/info = 2105344 / 35 27 | >| | | infoType = TypeRefType 28 | >| | | | prefix = scala(type already seen) 29 | >| | | | symbol = "scala.Int" (external #36 type = EXTref[9]) 30 | >| | | | | parent = scala (already seen at #20) 31 | >| child 1/1 = scalaj.reflect.targets.BasicSample.simpleVar_$eq.x$1 (already seen at #83)""".stripMargin('>') 32 | 33 | val simpleMethodArg = 34 | """>MethodSymbol name = "arg" (entry #90) 35 | >| path = "scalaj.reflect.targets.BasicSample.simpleMethod.arg" 36 | >| flags/info = 8192 / 26 37 | >| infoType = TypeRefType 38 | >| | prefix = SingleType 39 | >| | | typeRef = ThisType 40 | >| | | | symbol = "scala" (external #20 type = EXTMODCLASSref[10]) 41 | >| | | symbol = "scala.Predef" (external #28 type = EXTref[9]) 42 | >| | | | parent = scala (already seen at #20) 43 | >| | symbol = "scala.Predef.String" (external #30 type = EXTref[9]) 44 | >| | | parent = "scala.Predef" (external #32 type = EXTMODCLASSref[10]) 45 | >| | | | parent = scala (already seen at #20)""".stripMargin('>') 46 | 47 | val genericMethodArg = 48 | """>MethodSymbol name = "arg" (entry #117) 49 | >| path = "scalaj.reflect.targets.BasicSample.genericMethod.arg" 50 | >| flags/info = 8192 / 118 51 | >| infoType = TypeRefType 52 | >| | prefix = NoPrefixType 53 | >| | symbol = TypeSymbol name = "T" (entry #120) 54 | >| | | path = "T" 55 | >| | | flags/info = 1073750272 / 122 56 | >| | | infoType = TypeBoundsType 57 | >| | | | lower = TypeRefType 58 | >| | | | | prefix = ThisType 59 | >| | | | | | symbol = "scala" (external #20 type = EXTMODCLASSref[10]) 60 | >| | | | | symbol = "scala.Nothing" (external #124 type = EXTref[9]) 61 | >| | | | | | parent = scala (already seen at #20) 62 | >| | | | upper = TypeRefType 63 | >| | | | | prefix = scala(type already seen) 64 | >| | | | | symbol = "scala.Any" (external #127 type = EXTref[9]) 65 | >| | | | | | parent = scala (already seen at #20)""".stripMargin('>').replace("\\r","") 66 | 67 | 68 | val basicSampleClass = 69 | """>ClassSymbol name = "BasicSample" (entry #0) 70 | >| path = "scalaj.reflect.targets.BasicSample" 71 | >| owner = "scalaj.reflect.targets" (external #2 type = EXTMODCLASSref[10]) 72 | >| | parent = "scalaj.reflect" (external #4 type = EXTMODCLASSref[10]) 73 | >| | | parent = "scalaj" (external #6 type = EXTMODCLASSref[10]) 74 | >| flags/info = 1073741824 / 9 75 | >| infoType = ClassInfoType 76 | >| | symbol = scalaj.reflect.targets.BasicSample (already seen at #0) 77 | >| | typeRef 1/2 = TypeRefType 78 | >| | | prefix = ThisType 79 | >| | | | symbol = "java.lang" (external #12 type = EXTMODCLASSref[10]) 80 | >| | | | | parent = "java" (external #14 type = EXTMODCLASSref[10]) 81 | >| | | symbol = "java.lang.Object" (external #16 type = EXTref[9]) 82 | >| | | | parent = java.lang (already seen at #12) 83 | >| | typeRef 2/2 = TypeRefType 84 | >| | | prefix = ThisType 85 | >| | | | symbol = "scala" (external #20 type = EXTMODCLASSref[10]) 86 | >| | | symbol = "scala.ScalaObject" (external #22 type = EXTref[9]) 87 | >| | | | parent = scala (already seen at #20) 88 | >| child 1/19 = MethodSymbol name = "param1" (entry #24) 89 | >| | path = "scalaj.reflect.targets.BasicSample.param1" 90 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 91 | >| | flags/info = 537395204 / 26 92 | >| | infoType = TypeRefType 93 | >| | | prefix = SingleType 94 | >| | | | typeRef = scala(type already seen) 95 | >| | | | symbol = "scala.Predef" (external #28 type = EXTref[9]) 96 | >| | | | | parent = scala (already seen at #20) 97 | >| | | symbol = "scala.Predef.String" (external #30 type = EXTref[9]) 98 | >| | | | parent = "scala.Predef" (external #32 type = EXTMODCLASSref[10]) 99 | >| | | | | parent = scala (already seen at #20) 100 | >| child 2/19 = MethodSymbol name = "param2" (entry #33) 101 | >| | path = "scalaj.reflect.targets.BasicSample.param2" 102 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 103 | >| | flags/info = 537395204 / 35 104 | >| | infoType = TypeRefType 105 | >| | | prefix = scala(type already seen) 106 | >| | | symbol = "scala.Int" (external #36 type = EXTref[9]) 107 | >| | | | parent = scala (already seen at #20) 108 | >| child 3/19 = MethodSymbol name = "" (entry #38) 109 | >| | path = "scalaj.reflect.targets.BasicSample." 110 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 111 | >| | flags/info = 512 / 40 112 | >| | infoType = MethodType 113 | >| | | resultType = TypeRefType 114 | >| | | | prefix = ThisType 115 | >| | | | | symbol = scalaj.reflect.targets (already seen at #2) 116 | >| | | | symbol = scalaj.reflect.targets.BasicSample (already seen at #0) 117 | >| | | paramSymbol 1/2 = MethodSymbol name = "param1" (entry #43) 118 | >| | | | path = "scalaj.reflect.targets.BasicSample..param1" 119 | >| | | | owner = scalaj.reflect.targets.BasicSample. (already seen at #38) 120 | >| | | | flags/info = 8192 / 26 121 | >| | | | infoType = scala.Predef.String(type already seen) 122 | >| | | paramSymbol 2/2 = MethodSymbol name = "param2" (entry #44) 123 | >| | | | path = "scalaj.reflect.targets.BasicSample..param2" 124 | >| | | | owner = scalaj.reflect.targets.BasicSample. (already seen at #38) 125 | >| | | | flags/info = 8192 / 35 126 | >| | | | infoType = scala.Int(type already seen) 127 | >| | child 1/2 = scalaj.reflect.targets.BasicSample..param1 (already seen at #43) 128 | >| | child 2/2 = scalaj.reflect.targets.BasicSample..param2 (already seen at #44) 129 | >| child 4/19 = MethodSymbol name = "" (entry #45) 130 | >| | path = "scalaj.reflect.targets.BasicSample." 131 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 132 | >| | flags/info = 512 / 46 133 | >| | infoType = MethodType 134 | >| | | resultType = scalaj.reflect.targets.BasicSample(type already seen) 135 | >| | | paramSymbol 1/1 = MethodSymbol name = "param2a" (entry #47) 136 | >| | | | path = "scalaj.reflect.targets.BasicSample..param2a" 137 | >| | | | owner = scalaj.reflect.targets.BasicSample. (already seen at #45) 138 | >| | | | flags/info = 8192 / 49 139 | >| | | | infoType = TypeRefType 140 | >| | | | | prefix = scala(type already seen) 141 | >| | | | | symbol = "scala.Float" (external #50 type = EXTref[9]) 142 | >| | | | | | parent = scala (already seen at #20) 143 | >| | child 1/1 = scalaj.reflect.targets.BasicSample..param2a (already seen at #47) 144 | >| child 5/19 = AliasSymbol name = "StringAlias" (entry #52) 145 | >| | path = "StringAlias" 146 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 147 | >| | flags/info = 1073741824 / 26 148 | >| | infoType = scala.Predef.String(type already seen) 149 | >| child 6/19 = ClassSymbol name = "Foo" (entry #54) 150 | >| | path = "scalaj.reflect.targets.BasicSample.Foo" 151 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 152 | >| | flags/info = 1073741824 / 56 153 | >| | infoType = ClassInfoType 154 | >| | | symbol = scalaj.reflect.targets.BasicSample.Foo (already seen at #54) 155 | >| | | typeRef 1/2 = java.lang.Object(type already seen) 156 | >| | | typeRef 2/2 = scala.ScalaObject(type already seen) 157 | >| | child 1/3 = MethodSymbol name = "param" (entry #57) 158 | >| | | path = "scalaj.reflect.targets.BasicSample.Foo.param" 159 | >| | | owner = scalaj.reflect.targets.BasicSample.Foo (already seen at #54) 160 | >| | | flags/info = 675283456 / 59 161 | >| | | infoType = PolyType 162 | >| | | | typeRef = scala.Predef.String(type already seen) 163 | >| | child 2/3 = MethodSymbol name = "param " (entry #60) 164 | >| | | path = "scalaj.reflect.targets.BasicSample.Foo.param " 165 | >| | | owner = scalaj.reflect.targets.BasicSample.Foo (already seen at #54) 166 | >| | | flags/info = 537395204 / 26 167 | >| | | infoType = scala.Predef.String(type already seen) 168 | >| | child 3/3 = MethodSymbol name = "" (entry #62) 169 | >| | | path = "scalaj.reflect.targets.BasicSample.Foo." 170 | >| | | owner = scalaj.reflect.targets.BasicSample.Foo (already seen at #54) 171 | >| | | flags/info = 512 / 63 172 | >| | | infoType = MethodType 173 | >| | | | resultType = TypeRefType 174 | >| | | | | prefix = ThisType 175 | >| | | | | | symbol = scalaj.reflect.targets.BasicSample (already seen at #0) 176 | >| | | | | symbol = scalaj.reflect.targets.BasicSample.Foo (already seen at #54) 177 | >| | | | paramSymbol 1/1 = MethodSymbol name = "param" (entry #66) 178 | >| | | | | path = "scalaj.reflect.targets.BasicSample.Foo..param" 179 | >| | | | | owner = scalaj.reflect.targets.BasicSample.Foo. (already seen at #62) 180 | >| | | | | flags/info = 8192 / 26 181 | >| | | | | infoType = scala.Predef.String(type already seen) 182 | >| | | child 1/1 = scalaj.reflect.targets.BasicSample.Foo..param (already seen at #66) 183 | >| child 7/19 = MethodSymbol name = "implicitString" (entry #67) 184 | >| | path = "scalaj.reflect.targets.BasicSample.implicitString" 185 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 186 | >| | flags/info = 138412545 / 69 187 | >| | infoType = PolyType 188 | >| | | typeRef = TypeRefType 189 | >| | | | prefix = java.lang(type already seen) 190 | >| | | | symbol = "java.lang.String" (external #71 type = EXTref[9]) 191 | >| | | | | parent = java.lang (already seen at #12) 192 | >| child 8/19 = MethodSymbol name = "implicitString " (entry #72) 193 | >| | path = "scalaj.reflect.targets.BasicSample.implicitString " 194 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 195 | >| | flags/info = 524292 / 70 196 | >| | infoType = java.lang.String(type already seen) 197 | >| child 9/19 = MethodSymbol name = "simpleVar" (entry #74) 198 | >| | path = "scalaj.reflect.targets.BasicSample.simpleVar" 199 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 200 | >| | flags/info = 134218240 / 76 201 | >| | infoType = PolyType 202 | >| | | typeRef = scala.Int(type already seen) 203 | >| child 10/19 = MethodSymbol name = "simpleVar_$eq" (entry #77) 204 | >| | path = "scalaj.reflect.targets.BasicSample.simpleVar_$eq" 205 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 206 | >| | flags/info = 134218240 / 79 207 | >| | infoType = MethodType 208 | >| | | resultType = TypeRefType 209 | >| | | | prefix = scala(type already seen) 210 | >| | | | symbol = "scala.Unit" (external #81 type = EXTref[9]) 211 | >| | | | | parent = scala (already seen at #20) 212 | >| | | paramSymbol 1/1 = MethodSymbol name = "x$1" (entry #83) 213 | >| | | | path = "scalaj.reflect.targets.BasicSample.simpleVar_$eq.x$1" 214 | >| | | | owner = scalaj.reflect.targets.BasicSample.simpleVar_$eq (already seen at #77) 215 | >| | | | flags/info = 2105344 / 35 216 | >| | | | infoType = scala.Int(type already seen) 217 | >| | child 1/1 = scalaj.reflect.targets.BasicSample.simpleVar_$eq.x$1 (already seen at #83) 218 | >| child 11/19 = MethodSymbol name = "simpleVar " (entry #85) 219 | >| | path = "scalaj.reflect.targets.BasicSample.simpleVar " 220 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 221 | >| | flags/info = 528388 / 35 222 | >| | infoType = scala.Int(type already seen) 223 | >| child 12/19 = MethodSymbol name = "simpleMethod" (entry #87) 224 | >| | path = "scalaj.reflect.targets.BasicSample.simpleMethod" 225 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 226 | >| | flags/info = 512 / 89 227 | >| | infoType = MethodType 228 | >| | | resultType = java.lang.String(type already seen) 229 | >| | | paramSymbol 1/1 = MethodSymbol name = "arg" (entry #90) 230 | >| | | | path = "scalaj.reflect.targets.BasicSample.simpleMethod.arg" 231 | >| | | | owner = scalaj.reflect.targets.BasicSample.simpleMethod (already seen at #87) 232 | >| | | | flags/info = 8192 / 26 233 | >| | | | infoType = scala.Predef.String(type already seen) 234 | >| | child 1/1 = scalaj.reflect.targets.BasicSample.simpleMethod.arg (already seen at #90) 235 | >| child 13/19 = MethodSymbol name = "defaultArgMethod" (entry #92) 236 | >| | path = "scalaj.reflect.targets.BasicSample.defaultArgMethod" 237 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 238 | >| | flags/info = 512 / 94 239 | >| | infoType = MethodType 240 | >| | | resultType = java.lang.String(type already seen) 241 | >| | | paramSymbol 1/1 = MethodSymbol name = "arg" (entry #95) 242 | >| | | | path = "scalaj.reflect.targets.BasicSample.defaultArgMethod.arg" 243 | >| | | | owner = scalaj.reflect.targets.BasicSample.defaultArgMethod (already seen at #92) 244 | >| | | | flags/info = 33562624 / 26 245 | >| | | | infoType = scala.Predef.String(type already seen) 246 | >| | child 1/1 = scalaj.reflect.targets.BasicSample.defaultArgMethod.arg (already seen at #95) 247 | >| child 14/19 = MethodSymbol name = "implicitArgMethod" (entry #96) 248 | >| | path = "scalaj.reflect.targets.BasicSample.implicitArgMethod" 249 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 250 | >| | flags/info = 512 / 98 251 | >| | infoType = ImplicitMethodType 252 | >| | | resultType = java.lang.String(type already seen) 253 | >| | | paramSymbol 1/1 = MethodSymbol name = "arg" (entry #99) 254 | >| | | | path = "scalaj.reflect.targets.BasicSample.implicitArgMethod.arg" 255 | >| | | | owner = scalaj.reflect.targets.BasicSample.implicitArgMethod (already seen at #96) 256 | >| | | | flags/info = 8193 / 26 257 | >| | | | infoType = scala.Predef.String(type already seen) 258 | >| | child 1/1 = scalaj.reflect.targets.BasicSample.implicitArgMethod.arg (already seen at #99) 259 | >| child 15/19 = MethodSymbol name = "multiArgMethod" (entry #100) 260 | >| | path = "scalaj.reflect.targets.BasicSample.multiArgMethod" 261 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 262 | >| | flags/info = 512 / 102 263 | >| | infoType = MethodType 264 | >| | | resultType = java.lang.String(type already seen) 265 | >| | | paramSymbol 1/2 = MethodSymbol name = "arg1" (entry #103) 266 | >| | | | path = "scalaj.reflect.targets.BasicSample.multiArgMethod.arg1" 267 | >| | | | owner = scalaj.reflect.targets.BasicSample.multiArgMethod (already seen at #100) 268 | >| | | | flags/info = 8192 / 26 269 | >| | | | infoType = scala.Predef.String(type already seen) 270 | >| | | paramSymbol 2/2 = MethodSymbol name = "arg2" (entry #105) 271 | >| | | | path = "scalaj.reflect.targets.BasicSample.multiArgMethod.arg2" 272 | >| | | | owner = scalaj.reflect.targets.BasicSample.multiArgMethod (already seen at #100) 273 | >| | | | flags/info = 8192 / 26 274 | >| | | | infoType = scala.Predef.String(type already seen) 275 | >| | child 1/2 = scalaj.reflect.targets.BasicSample.multiArgMethod.arg1 (already seen at #103) 276 | >| | child 2/2 = scalaj.reflect.targets.BasicSample.multiArgMethod.arg2 (already seen at #105) 277 | >| child 16/19 = MethodSymbol name = "multiBlockMethod" (entry #107) 278 | >| | path = "scalaj.reflect.targets.BasicSample.multiBlockMethod" 279 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 280 | >| | flags/info = 512 / 109 281 | >| | infoType = MethodType 282 | >| | | resultType = MethodType 283 | >| | | | resultType = java.lang.String(type already seen) 284 | >| | | | paramSymbol 1/1 = MethodSymbol name = "arg2" (entry #111) 285 | >| | | | | path = "scalaj.reflect.targets.BasicSample.multiBlockMethod.arg2" 286 | >| | | | | owner = scalaj.reflect.targets.BasicSample.multiBlockMethod (already seen at #107) 287 | >| | | | | flags/info = 8192 / 26 288 | >| | | | | infoType = scala.Predef.String(type already seen) 289 | >| | | paramSymbol 1/1 = MethodSymbol name = "arg1" (entry #112) 290 | >| | | | path = "scalaj.reflect.targets.BasicSample.multiBlockMethod.arg1" 291 | >| | | | owner = scalaj.reflect.targets.BasicSample.multiBlockMethod (already seen at #107) 292 | >| | | | flags/info = 8192 / 26 293 | >| | | | infoType = scala.Predef.String(type already seen) 294 | >| | child 1/2 = scalaj.reflect.targets.BasicSample.multiBlockMethod.arg2 (already seen at #111) 295 | >| | child 2/2 = scalaj.reflect.targets.BasicSample.multiBlockMethod.arg1 (already seen at #112) 296 | >| child 17/19 = MethodSymbol name = "genericMethod" (entry #113) 297 | >| | path = "scalaj.reflect.targets.BasicSample.genericMethod" 298 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 299 | >| | flags/info = 512 / 115 300 | >| | infoType = PolyType 301 | >| | | typeRef = MethodType 302 | >| | | | resultType = java.lang.String(type already seen) 303 | >| | | | paramSymbol 1/1 = MethodSymbol name = "arg" (entry #117) 304 | >| | | | | path = "scalaj.reflect.targets.BasicSample.genericMethod.arg" 305 | >| | | | | owner = scalaj.reflect.targets.BasicSample.genericMethod (already seen at #113) 306 | >| | | | | flags/info = 8192 / 118 307 | >| | | | | infoType = TypeRefType 308 | >| | | | | | prefix = NoPrefixType 309 | >| | | | | | symbol = TypeSymbol name = "T" (entry #120) 310 | >| | | | | | | path = "T" 311 | >| | | | | | | owner = scalaj.reflect.targets.BasicSample.genericMethod (already seen at #113) 312 | >| | | | | | | flags/info = 1073750272 / 122 313 | >| | | | | | | infoType = TypeBoundsType 314 | >| | | | | | | | lower = TypeRefType 315 | >| | | | | | | | | prefix = scala(type already seen) 316 | >| | | | | | | | | symbol = "scala.Nothing" (external #124 type = EXTref[9]) 317 | >| | | | | | | | | | parent = scala (already seen at #20) 318 | >| | | | | | | | upper = TypeRefType 319 | >| | | | | | | | | prefix = scala(type already seen) 320 | >| | | | | | | | | symbol = "scala.Any" (external #127 type = EXTref[9]) 321 | >| | | | | | | | | | parent = scala (already seen at #20) 322 | >| | | symbol 1/1 = T (already seen at #120) 323 | >| | child 1/2 = scalaj.reflect.targets.BasicSample.genericMethod.arg (already seen at #117) 324 | >| | child 2/2 = T (already seen at #120) 325 | >| child 18/19 = MethodSymbol name = "viewBoundMethod" (entry #129) 326 | >| | path = "scalaj.reflect.targets.BasicSample.viewBoundMethod" 327 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 328 | >| | flags/info = 512 / 131 329 | >| | infoType = PolyType 330 | >| | | typeRef = MethodType 331 | >| | | | resultType = ImplicitMethodType 332 | >| | | | | resultType = java.lang.String(type already seen) 333 | >| | | | | paramSymbol 1/1 = MethodSymbol name = "evidence$1" (entry #134) 334 | >| | | | | | path = "scalaj.reflect.targets.BasicSample.viewBoundMethod.evidence$1" 335 | >| | | | | | owner = scalaj.reflect.targets.BasicSample.viewBoundMethod (already seen at #129) 336 | >| | | | | | flags/info = 8193 / 136 337 | >| | | | | | infoType = TypeRefType 338 | >| | | | | | | prefix = scala(type already seen) 339 | >| | | | | | | symbol = "scala.Function1" (external #137 type = EXTref[9]) 340 | >| | | | | | | | parent = scala (already seen at #20) 341 | >| | | | | | | typeArg 1/2 = TypeRefType 342 | >| | | | | | | | prefix = NoPrefixType(type already seen) 343 | >| | | | | | | | symbol = TypeSymbol name = "T" (entry #140) 344 | >| | | | | | | | | path = "T" 345 | >| | | | | | | | | owner = scalaj.reflect.targets.BasicSample.viewBoundMethod (already seen at #129) 346 | >| | | | | | | | | flags/info = 1073750272 / 122 347 | >| | | | | | | | | infoType = scala.Nothing <: scala.Any(type already seen) 348 | >| | | | | | | typeArg 2/2 = TypeRefType 349 | >| | | | | | | | prefix = SingleType 350 | >| | | | | | | | | typeRef = SingleType 351 | >| | | | | | | | | | typeRef = ThisType 352 | >| | | | | | | | | | | symbol = "." (external #145 type = EXTMODCLASSref[10]) 353 | >| | | | | | | | | | | | parent = NoSymbol 354 | >| | | | | | | | | | symbol = "scala" (external #147 type = EXTref[9]) 355 | >| | | | | | | | | symbol = "scala.package" (external #148 type = EXTref[9]) 356 | >| | | | | | | | | | parent = scala (already seen at #20) 357 | >| | | | | | | | symbol = "scala.package.Ordered" (external #150 type = EXTref[9]) 358 | >| | | | | | | | | parent = "scala.package" (external #152 type = EXTMODCLASSref[10]) 359 | >| | | | | | | | | | parent = scala (already seen at #20) 360 | >| | | | | | | | typeArg 1/1 = T(type already seen) 361 | >| | | | paramSymbol 1/1 = MethodSymbol name = "arg" (entry #153) 362 | >| | | | | path = "scalaj.reflect.targets.BasicSample.viewBoundMethod.arg" 363 | >| | | | | owner = scalaj.reflect.targets.BasicSample.viewBoundMethod (already seen at #129) 364 | >| | | | | flags/info = 8192 / 139 365 | >| | | | | infoType = T(type already seen) 366 | >| | | symbol 1/1 = T (already seen at #140) 367 | >| | child 1/3 = scalaj.reflect.targets.BasicSample.viewBoundMethod.evidence$1 (already seen at #134) 368 | >| | child 2/3 = T (already seen at #140) 369 | >| | child 3/3 = scalaj.reflect.targets.BasicSample.viewBoundMethod.arg (already seen at #153) 370 | >| child 19/19 = MethodSymbol name = "defaultArgMethod$default$1" (entry #154) 371 | >| | path = "scalaj.reflect.targets.BasicSample.defaultArgMethod$default$1" 372 | >| | owner = scalaj.reflect.targets.BasicSample (already seen at #0) 373 | >| | flags/info = 35652096 / 156 374 | >| | infoType = PolyType 375 | >| | | typeRef = AnnotatedType 376 | >| | | | typeRef = scala.Predef.String(type already seen) 377 | >| | | | attribTreeRef 1/1 = 158""".stripMargin('>') 378 | 379 | val polymorphicSampleClass = 380 | """>ClassSymbol name = "PolymorphicSample" (entry #0) 381 | >| path = "scalaj.reflect.targets.PolymorphicSample" 382 | >| owner = "scalaj.reflect.targets" (external #2 type = EXTMODCLASSref[10]) 383 | >| | parent = "scalaj.reflect" (external #4 type = EXTMODCLASSref[10]) 384 | >| | | parent = "scalaj" (external #6 type = EXTMODCLASSref[10]) 385 | >| flags/info = 128 / 9 386 | >| infoType = PolyType 387 | >| | typeRef = ClassInfoType 388 | >| | | symbol = scalaj.reflect.targets.PolymorphicSample (already seen at #0) 389 | >| | | typeRef 1/2 = TypeRefType 390 | >| | | | prefix = ThisType 391 | >| | | | | symbol = "java.lang" (external #13 type = EXTMODCLASSref[10]) 392 | >| | | | | | parent = "java" (external #15 type = EXTMODCLASSref[10]) 393 | >| | | | symbol = "java.lang.Object" (external #17 type = EXTref[9]) 394 | >| | | | | parent = java.lang (already seen at #13) 395 | >| | | typeRef 2/2 = TypeRefType 396 | >| | | | prefix = ThisType 397 | >| | | | | symbol = "scala" (external #21 type = EXTMODCLASSref[10]) 398 | >| | | | symbol = "scala.ScalaObject" (external #23 type = EXTref[9]) 399 | >| | | | | parent = scala (already seen at #21) 400 | >| | symbol 1/1 = TypeSymbol name = "T" (entry #32) 401 | >| | | path = "T" 402 | >| | | owner = scalaj.reflect.targets.PolymorphicSample (already seen at #0) 403 | >| | | flags/info = 1073750272 / 34 404 | >| | | infoType = TypeBoundsType 405 | >| | | | lower = TypeRefType 406 | >| | | | | prefix = scala(type already seen) 407 | >| | | | | symbol = "scala.Nothing" (external #36 type = EXTref[9]) 408 | >| | | | | | parent = scala (already seen at #21) 409 | >| | | | upper = TypeRefType 410 | >| | | | | prefix = scala(type already seen) 411 | >| | | | | symbol = "scala.Any" (external #39 type = EXTref[9]) 412 | >| | | | | | parent = scala (already seen at #21) 413 | >| child 1/4 = MethodSymbol name = "" (entry #25) 414 | >| | path = "scalaj.reflect.targets.PolymorphicSample." 415 | >| | owner = scalaj.reflect.targets.PolymorphicSample (already seen at #0) 416 | >| | flags/info = 512 / 27 417 | >| | infoType = MethodType 418 | >| | | resultType = TypeRefType 419 | >| | | | prefix = ThisType 420 | >| | | | | symbol = scalaj.reflect.targets (already seen at #2) 421 | >| | | | symbol = scalaj.reflect.targets.PolymorphicSample (already seen at #0) 422 | >| | | | typeArg 1/1 = TypeRefType 423 | >| | | | | prefix = NoPrefixType 424 | >| | | | | symbol = T (already seen at #32) 425 | >| child 2/4 = T (already seen at #32) 426 | >| child 3/4 = MethodSymbol name = "sampleVal" (entry #41) 427 | >| | path = "scalaj.reflect.targets.PolymorphicSample.sampleVal" 428 | >| | owner = scalaj.reflect.targets.PolymorphicSample (already seen at #0) 429 | >| | flags/info = 768 / 43 430 | >| | infoType = PolyType 431 | >| | | typeRef = T(type already seen) 432 | >| child 4/4 = MethodSymbol name = "method" (entry #44) 433 | >| | path = "scalaj.reflect.targets.PolymorphicSample.method" 434 | >| | owner = scalaj.reflect.targets.PolymorphicSample (already seen at #0) 435 | >| | flags/info = 512 / 46 436 | >| | infoType = PolyType 437 | >| | | typeRef = MethodType 438 | >| | | | resultType = TypeRefType 439 | >| | | | | prefix = NoPrefixType(type already seen) 440 | >| | | | | symbol = TypeSymbol name = "T" (entry #49) 441 | >| | | | | | path = "T" 442 | >| | | | | | owner = scalaj.reflect.targets.PolymorphicSample.method (already seen at #44) 443 | >| | | | | | flags/info = 1073750272 / 34 444 | >| | | | | | infoType = scala.Nothing <: scala.Any(type already seen) 445 | >| | | | paramSymbol 1/1 = MethodSymbol name = "x" (entry #50) 446 | >| | | | | path = "scalaj.reflect.targets.PolymorphicSample.method.x" 447 | >| | | | | owner = scalaj.reflect.targets.PolymorphicSample.method (already seen at #44) 448 | >| | | | | flags/info = 8192 / 48 449 | >| | | | | infoType = T(type already seen) 450 | >| | | symbol 1/1 = T (already seen at #49) 451 | >| | child 1/2 = T (already seen at #49) 452 | >| | child 2/2 = scalaj.reflect.targets.PolymorphicSample.method.x (already seen at #50)""".stripMargin('>') 453 | 454 | } 455 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/MirrorsSpec.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | 4 | import scalaj.reflect.{TypeWrangler => wrangler} 5 | import org.specs.SpecificationWithJUnit 6 | import reflect.Manifest 7 | 8 | class MirrorsSpec extends SpecificationWithJUnit { 9 | val tgtMirror = Mirror.ofClass[targets.BasicSample].get 10 | 11 | "a class mirror" should { 12 | "reflect a dynamically sourced Class[_] instance" in { 13 | val dynMirror = Mirror.ofClass(Class.forName("scalaj.reflect.targets.BasicSample")) 14 | dynMirror map { m => m.name mustEqual "BasicSample" } 15 | } 16 | 17 | "locate all defs" in { 18 | 19 | val defs = tgtMirror.allDefs map (_.name) 20 | // println("defs = " + (defs mkString ", ")) 21 | defs mustEqual Seq( 22 | "simpleMethod", 23 | "defaultArgMethod", 24 | "implicitArgMethod", 25 | "multiArgMethod", 26 | "multiBlockMethod", 27 | "genericMethod", 28 | "viewBoundMethod") 29 | } 30 | 31 | "locate all constructors" in { 32 | val constructors = tgtMirror.constructors 33 | // println("constructors = " + (constructors.map(_.method) mkString ", ")) 34 | constructors.size mustEqual 2 35 | 36 | val Seq(ctor1,ctor2) = constructors 37 | } 38 | 39 | "locate all accessors" in { 40 | val accessors = tgtMirror.allAccessors map (_.name) 41 | // println("accessors = " + (accessors mkString ", ")) 42 | accessors mustEqual Seq("implicitString", "simpleVar") 43 | } 44 | 45 | "locate all vals" in { 46 | val vals = tgtMirror.vals map (_.name) 47 | // println("vals = " + (vals mkString ", ")) 48 | vals mustEqual Seq("implicitString") 49 | } 50 | 51 | "locate all vars" in { 52 | val vars = tgtMirror.vars map (_.name) 53 | // println("vars = " + (vars mkString ", ")) 54 | vars mustEqual Seq("simpleVar") 55 | } 56 | 57 | "locate all type aliases" in { 58 | val typeAliases = tgtMirror.typeAliases map (_.name) 59 | // println("typeAliases = " + (typeAliases mkString ", ")) 60 | typeAliases mustEqual Seq("StringAlias") 61 | } 62 | 63 | "correctly display the name of the mirrored class" in { 64 | // symNames mustEqual Seq("class SampleTarget", "object SampleTarget") 65 | tgtMirror.toString mustEqual "class BasicSample" 66 | 67 | tgtMirror.name mustEqual "BasicSample" 68 | tgtMirror.qualifiedName mustEqual "scalaj.reflect.targets.BasicSample" 69 | } 70 | 71 | "locate default type params for a generic polymorphic mirrored class" in { 72 | val mirror = Mirror.ofClass[targets.PolymorphicSample[_]].get 73 | val actual = mirror.typeParams 74 | val expected = Seq(Manifest.wildcardType(Manifest.Nothing, Manifest.Any)) 75 | actual mustEqual expected 76 | } 77 | 78 | "generate a manifest for a simple (monomorphic) mirrored class" in { 79 | val mani = tgtMirror.manifest 80 | mani mustEqual manifest[targets.BasicSample] 81 | } 82 | 83 | "generate a manifest for a wildcard polymorphic mirrored class" in { 84 | val mirror = Mirror.ofClass[targets.PolymorphicSample[_]].get 85 | val actual = mirror.manifest 86 | val expected = manifest[targets.PolymorphicSample[_]] 87 | actual mustEqual expected 88 | } 89 | 90 | "directly refine a generic polymorphic mirrored class" in { 91 | val mirror = Mirror.ofClass[targets.PolymorphicSample[_]].get 92 | val refined = mirror.reify(manifest[Int]) 93 | val actual = refined.manifest 94 | val expected = manifest[targets.PolymorphicSample[Int]] 95 | actual mustEqual expected 96 | } 97 | 98 | "generate a manifest for a refined polymorphic mirrored class" in { 99 | val mirror = Mirror.ofClass[targets.PolymorphicSample[Int]].get 100 | val actual = mirror.manifest 101 | val expected = manifest[targets.PolymorphicSample[Int]] 102 | actual mustEqual expected 103 | } 104 | 105 | // "generate a manifest for a nested polymorphic mirrored class" in { 106 | // val mirror = Mirror.ofClass[targets.NestedPolymorphicSample[Int]#Inner].get 107 | // val actual = mirror.manifest 108 | // val expected = manifest[targets.NestedPolymorphicSample[Int]#Inner] 109 | // actual mustEqual expected 110 | // } 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/SymbolTreePrinterSpec.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect 2 | 3 | import org.specs.SpecificationWithJUnit 4 | 5 | class SymbolTreePrinterSpec extends SpecificationWithJUnit { 6 | "a symbol tree printer" should { 7 | "print tree of primitive var" in { 8 | val classMirror = Mirror.ofClass[targets.BasicSample].get 9 | 10 | val varMirror = classMirror.vars.find(_.name=="simpleVar").get 11 | 12 | val getterTree = SymbolTreePrinter.withoutOwners mkTree varMirror.getter 13 | compareLines(getterTree, ExpectedPrintTrees.simpleVarGetter) 14 | 15 | val setterTree = SymbolTreePrinter.withoutOwners mkTree varMirror.setter 16 | compareLines(setterTree, ExpectedPrintTrees.simpleVarSetter) 17 | } 18 | 19 | "print tree of simple method param" in { 20 | val classMirror = Mirror.ofClass[targets.BasicSample].get 21 | 22 | val method = classMirror.allDefs.find(_.name=="simpleMethod").get 23 | val params = method.flatParams 24 | val paramStrings = params map {p => p.name + ": " + p.symType.toString} 25 | val actualTree = SymbolTreePrinter.withoutOwners mkTree params.head 26 | compareLines(actualTree, ExpectedPrintTrees.simpleMethodArg) 27 | } 28 | 29 | "print tree of generic method param" in { 30 | val classMirror = Mirror.ofClass[targets.BasicSample].get 31 | 32 | val method = classMirror.allDefs.find(_.name=="genericMethod").get 33 | val params = method.flatParams 34 | val paramStrings = params map {p => p.name + ": " + p.symType.toString} 35 | val actualTree = SymbolTreePrinter.withoutOwners mkTree params.head 36 | compareLines(actualTree, ExpectedPrintTrees.genericMethodArg) 37 | } 38 | 39 | "print tree of a simple class" in { 40 | val classMirror = Mirror.ofClass[targets.BasicSample].get 41 | val actualTree = SymbolTreePrinter mkTree classMirror 42 | compareLines(actualTree, ExpectedPrintTrees.basicSampleClass) 43 | } 44 | 45 | "print tree of a polymorphic class" in { 46 | val classMirror = Mirror.ofClass[targets.PolymorphicSample[_]].get 47 | val actualTree = SymbolTreePrinter mkTree classMirror 48 | compareLines(actualTree, ExpectedPrintTrees.polymorphicSampleClass) 49 | } 50 | 51 | // "print tree with nested class" in { 52 | // val classMirror = Mirror.ofClass[targets.TweedleDee] 53 | // try { 54 | // println (classMirror map {SymbolTreePrinter.withoutOwners.mkTree} ) 55 | // } catch { 56 | // case e: Exception => 57 | // println(e.getMessage) 58 | // e.printStackTrace 59 | // } 60 | // } 61 | // 62 | // "print tree with path-dependent alias" in { 63 | // val classMirror = Mirror.ofClass[targets.TweedleDo] 64 | // try { 65 | // //val member = classMirror.allNaturalMethods.find(_.name=="member").get 66 | // println (classMirror map {SymbolTreePrinter.withoutOwners.mkTree}) 67 | // } catch { 68 | // case e: Exception => 69 | // println(e.getMessage) 70 | // e.printStackTrace 71 | // } 72 | // } 73 | def compareLines(actual: String, expected: String): Unit = 74 | (actual.lines zip expected.lines) foreach { 75 | case (l,r) => l.trim mustEqual r.trim 76 | } 77 | 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/TypeWranglerSpec.scala: -------------------------------------------------------------------------------- 1 | package scalaj.spring 2 | 3 | //give the wrangler a short name, don't import methods as we want full control without using them as implicits 4 | import scalaj.reflect.{TypeWrangler => wrangler} 5 | import org.specs.SpecificationWithJUnit 6 | 7 | 8 | class TypeWranglerSpec extends SpecificationWithJUnit { 9 | "the TypeWrangler" should { 10 | "dynamically lookup a Seq[String] manifest" in { 11 | val actual : Manifest[_] = wrangler.manifestOf(classOf[Seq[String]]) 12 | val expected : Manifest[_] = manifest[Seq[String]] 13 | 14 | 1 mustEqual 1 15 | //actual.toString mustEqual expected.toString 16 | //actual mustEqual expected 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/targets/BasicSample.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect.targets 2 | 3 | class BasicSample(param1: String, param2: Int) { 4 | 5 | def this(param2a: Float) = this("float", param2a.toInt) 6 | 7 | type StringAlias = String 8 | 9 | class Foo(val param: String) 10 | 11 | // case class Bar(val param: String) 12 | 13 | implicit val implicitString = "xxx" 14 | 15 | var simpleVar = 42 16 | 17 | def simpleMethod(arg: String) = "xxx" 18 | def defaultArgMethod(arg: String = "default") = "xxx" 19 | def implicitArgMethod(implicit arg: String) = "xxx" 20 | 21 | def multiArgMethod(arg1: String, arg2: String) = "xxx" 22 | def multiBlockMethod(arg1: String)(arg2: String) = "xxx" 23 | 24 | def genericMethod[T](arg: T) = "xxx" 25 | def viewBoundMethod[T <% Ordered[T]](arg: T) = "xxx" 26 | 27 | } 28 | 29 | //object SampleTarget 30 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/targets/NestedPolymorphicSample.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect.targets 2 | 3 | abstract class NestedPolymorphicSample[T] { 4 | abstract class Inner { 5 | def sampleVal: T 6 | def method[T](x: T) = x 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/targets/PolymorphicSample.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect.targets 2 | 3 | abstract class PolymorphicSample[T] { 4 | def sampleVal: T 5 | def method[T](x: T) = x 6 | } 7 | 8 | class polymorphicSub extends PolymorphicSample[Int] { 9 | def sampleVal: Int = 42 10 | } 11 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/targets/TweedleDee.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect.targets 2 | 3 | class TweedleDee { 4 | class InnerDee { 5 | val member = (new TweedleDum).getInner 6 | } 7 | 8 | type InnerT = InnerDee 9 | def getInner: InnerT = new InnerDee 10 | } 11 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/targets/TweedleDo.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect.targets 2 | class TweedleDo { 3 | 4 | def a = (new TweedleDee) 5 | val b: TweedleDee#InnerT = a.getInner 6 | val c = b.member 7 | def d = c.member 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/test/scala/scalaj/reflect/targets/TweedleDum.scala: -------------------------------------------------------------------------------- 1 | package scalaj.reflect.targets; 2 | class TweedleDum { 3 | class InnerDum { 4 | val member = "XXX" 5 | } 6 | 7 | type InnerT = InnerDum 8 | def getInner: InnerT = new InnerDum 9 | } 10 | --------------------------------------------------------------------------------