summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-07-31 11:33:16 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-08-02 15:50:52 +0200
commit027b00171c0d92ec669deaa471966e6468c6b8cf (patch)
tree63808014ea752c49ae39e0b731f0d15bc6edeb28
parentb578059b43a4caaadee2cb20f74cd9a7c876c8ef (diff)
downloadscala-027b00171c0d92ec669deaa471966e6468c6b8cf.tar.gz
scala-027b00171c0d92ec669deaa471966e6468c6b8cf.tar.bz2
scala-027b00171c0d92ec669deaa471966e6468c6b8cf.zip
more refinements of reflection API
Added a bunch of test methods to symbols to cover public flags: (e.g. isPrivate, isFinal, isOverride, isImplicit, etc). I'd argue that the API duplication w.r.t flag sets is trumped by unified interface to tests and better encapsulation. Also updated the API to be easier to understand after prior exposure to Java or .NET reflection APIs: 1) Added typeParams to TypeSymbol and ClassSymbol. 2) Renamed MethodSymbol.resultType to returnType. 3) Removed the distinction between MethodSymbol.params vs MethodSymbol.allParams now we just have MethodSymbol.params: List[List[Symbol]].
-rw-r--r--src/library/scala/reflect/base/Symbols.scala16
-rw-r--r--src/reflect/scala/reflect/api/FlagSets.scala4
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala155
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala12
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala17
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala6
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala5
-rw-r--r--test/files/run/reflection-methodsymbol-allparams.check8
-rw-r--r--test/files/run/reflection-methodsymbol-allparams.scala24
-rw-r--r--test/files/run/reflection-methodsymbol-params.check12
-rw-r--r--test/files/run/reflection-methodsymbol-resulttype.scala24
-rw-r--r--test/files/run/reflection-methodsymbol-returntype.check (renamed from test/files/run/reflection-methodsymbol-resulttype.check)0
-rw-r--r--test/files/run/reflection-methodsymbol-returntype.scala24
13 files changed, 159 insertions, 148 deletions
diff --git a/src/library/scala/reflect/base/Symbols.scala b/src/library/scala/reflect/base/Symbols.scala
index 052571dbcb..45f7c0c1bd 100644
--- a/src/library/scala/reflect/base/Symbols.scala
+++ b/src/library/scala/reflect/base/Symbols.scala
@@ -80,10 +80,6 @@ trait Symbols { self: Universe =>
/** The base API that all symbols support */
trait SymbolBase { this: Symbol =>
- /** An id number which is unique for all symbols in this universe */
- // [Eugene++ to Martin] do we leave this here?
- def id: Int
-
/** The owner of this symbol. This is the symbol
* that directly contains the current symbol's definition.
* The `NoSymbol` symbol does not have an owner, and calling this method
@@ -112,18 +108,6 @@ trait Symbols { self: Universe =>
*/
def fullName: String
- /** If this symbol is a class, this symbol; otherwise the next enclosing
- * class, or `NoSymbol` if none exists.
- */
- def enclosingClass: Symbol =
- if (isClass || this == NoSymbol) this else owner.enclosingClass
-
- /** If this symbol is a method, this symbol; otherwise the next enclosing
- * method, or `NoSymbol` if none exists.
- */
- def enclosingMethod: Symbol =
- if (isMethod || this == NoSymbol) this else owner.enclosingMethod
-
/** Does this symbol represent the definition of a type?
* Note that every symbol is either a term or a type.
* So for every symbol `sym`, either `sym.isTerm` is true
diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala
index c56de49962..6d105c9d20 100644
--- a/src/reflect/scala/reflect/api/FlagSets.scala
+++ b/src/reflect/scala/reflect/api/FlagSets.scala
@@ -97,9 +97,5 @@ trait FlagSets { self: Universe =>
/** Flag indicating that parameter has a default value */
val DEFAULTPARAM: FlagSet
-
- /** Flag indicating that trait has neither method implementations nor fields.
- * This means the trait can be represented as a Java interface. */
- val INTERFACE: FlagSet
}
}
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index e55c1ea11a..13f5f743f1 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -43,6 +43,53 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def hasAnnotation(sym: Symbol): Boolean
+ /** For a class: the module or case class factory with the same name in the same package.
+ * For a module: the class with the same name in the same package.
+ * For all others: NoSymbol
+ */
+ def companionSymbol: Symbol
+
+ /** The type signature of this symbol seen as a member of given type `site`.
+ */
+ def typeSignatureIn(site: Type): Type
+
+ /** The type signature of this symbol.
+ * Note if the symbol is a member of a class, one almost always is interested
+ * in `typeSignatureIn` with a site type instead.
+ */
+ def typeSignature: Type
+
+ /******************* tests *******************/
+
+ /** Does this symbol represent a synthetic (i.e. a compiler-generated) entity?
+ * Examples of synthetic entities are accessors for vals and vars
+ * or mixin constructors in trait implementation classes.
+ */
+ def isSynthetic: Boolean
+
+ /** Does this symbol represent a local declaration or definition?
+ *
+ * If yes, either `isPrivate` or `isProtected` are guaranteed to be true.
+ * Local symbols can only be accessed from the same object instance.
+ *
+ * If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ */
+ def isLocal: Boolean
+
+ /** Does this symbol represent a private declaration or definition?
+ * If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ */
+ def isPrivate: Boolean
+
+ /** Does this symbol represent a protected declaration or definition?
+ * If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ */
+ def isProtected: Boolean
+
+ /** Does this symbol represent a public declaration or definition?
+ */
+ def isPublic: Boolean
+
/**
* Set when symbol has a modifier of the form private[X], NoSymbol otherwise.
*
@@ -70,24 +117,6 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def privateWithin: Symbol
- /** For a class: the module or case class factory with the same name in the same package.
- * For a module: the class with the same name in the same package.
- * For all others: NoSymbol
- */
- def companionSymbol: Symbol
-
- /** The type signature of this symbol seen as a member of given type `site`.
- */
- def typeSignatureIn(site: Type): Type
-
- /** The type signature of this symbol.
- * Note if the symbol is a member of a class, one almost always is interested
- * in `typeSignatureIn` with a site type instead.
- */
- def typeSignature: Type
-
- /******************* tests *******************/
-
/** Does this symbol represent the definition of a package?
* If yes, `isTerm` is also guaranteed to be true.
*/
@@ -121,6 +150,18 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def isStatic: Boolean
+ /** Is this symbol final?
+ */
+ def isFinal: Boolean
+
+ /** Is this symbol overriding something?
+ */
+ def isOverride: Boolean
+
+ /** Is this symbol a macro?
+ */
+ def isMacro: Boolean
+
/******************* helpers *******************/
/** ...
@@ -177,6 +218,14 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def isOverloaded : Boolean
+ /** Does this symbol represent an implicit value, definition or parameter?
+ */
+ def isImplicit: Boolean
+
+ /** Does this symbol represent a lazy value?
+ */
+ def isLazy: Boolean
+
/** The overloaded alternatives of this symbol */
def alternatives: List[Symbol]
@@ -208,23 +257,6 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def isSkolem : Boolean
- /** Does this symbol represent the definition of a primitive class?
- * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
- * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
- */
- def isPrimitiveValueClass: Boolean
-
- /** Does this symbol represent the definition of a numeric value class?
- * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
- * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
- */
- def isNumericValueClass: Boolean
-
- /** Does this symbol represent the definition of a custom value class?
- * Namely, is AnyVal among its parent classes?
- */
- def isDerivedValueClass: Boolean
-
/** Does this symbol represent the definition of a type alias?
*/
def isAliasType : Boolean
@@ -236,6 +268,9 @@ trait Symbols extends base.Symbols { self: Universe =>
/** Does this symbol represent an existentially bound type?
*/
def isExistential : Boolean
+
+ /** For a polymorphic type, its type parameters, the empty list for all other types */
+ def typeParams: List[Symbol]
}
/** The API of method symbols */
@@ -243,24 +278,16 @@ trait Symbols extends base.Symbols { self: Universe =>
/** For a polymorphic method, its type parameters, the empty list for all other methods */
def typeParams: List[Symbol]
- /** The first parameter list of the method.
- *
- * For a nullary method, returns the empty list.
- * For a method with an empty parameter list, returns the empty list.
- * To distinguish between those, use `allParams`.
- */
- def params: List[Symbol]
-
/** All parameter lists of the method.
*
* Can be used to distinguish nullary methods and methods with empty parameter lists.
* For a nullary method, returns the empty list (i.e. `List()`).
* For a method with an empty parameter list, returns a list that contains the empty list (i.e. `List(List())`).
*/
- def allParams: List[List[Symbol]]
+ def params: List[List[Symbol]]
- /** The result type of the method */
- def resultType: Type
+ /** The return type of the method */
+ def returnType: Type
}
/** The API of module symbols */
@@ -269,6 +296,39 @@ trait Symbols extends base.Symbols { self: Universe =>
/** The API of class symbols */
trait ClassSymbolApi extends TypeSymbolApi with ClassSymbolBase { this: ClassSymbol =>
+ /** Does this symbol represent the definition of a primitive class?
+ * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
+ * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
+ */
+ def isPrimitive: Boolean
+
+ /** Does this symbol represent the definition of a numeric value class?
+ * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
+ * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
+ */
+ def isNumeric: Boolean
+
+ /** Does this symbol represent the definition of a custom value class?
+ * Namely, is AnyVal among its parent classes?
+ */
+ def isDerivedValueClass: Boolean
+
+ /** Does this symbol represent a trait?
+ */
+ def isTrait: Boolean
+
+ /** Does this symbol represent an abstract class?
+ */
+ def isAbstractClass: Boolean
+
+ /** Does this symbol represent a case class?
+ */
+ def isCaseClass: Boolean
+
+ /** Does this symbol represent a sealed class?
+ */
+ def isSealed: Boolean
+
/** If this symbol is a class or trait, its self type, otherwise the type
* of the symbol itself.
*/
@@ -276,6 +336,9 @@ trait Symbols extends base.Symbols { self: Universe =>
/** The type `C.this`, where `C` is the current class */
def thisPrefix: Type
+
+ /** For a polymorphic class/trait, its type parameters, the empty list for all other classes/trait */
+ def typeParams: List[Symbol]
}
/** The API of free term symbols */
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index 28dd764c70..8165f599b2 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -640,8 +640,16 @@ trait Trees extends base.Trees { self: Universe =>
abstract class Transformer {
val treeCopy: TreeCopier = newLazyTreeCopier
protected[scala] var currentOwner: Symbol = rootMirror.RootClass
- protected def currentMethod = currentOwner.enclosingMethod
- protected def currentClass = currentOwner.enclosingClass
+ protected def currentMethod = {
+ def enclosingMethod(sym: Symbol): Symbol =
+ if (sym.isMethod || sym == NoSymbol) sym else enclosingMethod(sym.owner)
+ enclosingMethod(currentOwner)
+ }
+ protected def currentClass = {
+ def enclosingClass(sym: Symbol): Symbol =
+ if (sym.isClass || sym == NoSymbol) sym else enclosingClass(sym.owner)
+ enclosingClass(currentOwner)
+ }
// protected def currentPackage = currentOwner.enclosingTopLevelClass.owner
def transform(tree: Tree): Tree = itransform(this, tree)
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 372520e48f..304caa74d4 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -456,6 +456,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isAliasType = false
def isAbstractType = false
def isSkolem = false
+ def isMacro = this hasFlag MACRO
/** A Type, but not a Class. */
def isNonClassType = false
@@ -2487,19 +2488,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
res
}
- override def allParams: List[List[Symbol]] = paramss
+ override def params: List[List[Symbol]] = paramss
- override def params: List[Symbol] = {
- def loop(tpe: Type): List[Symbol] =
- tpe match {
- case NullaryMethodType(_) => Nil
- case MethodType(params, _) => params
- case PolyType(_, tpe) => loop(tpe)
- }
- loop(info)
- }
-
- override def resultType: Type = {
+ override def returnType: Type = {
def loop(tpe: Type): Type =
tpe match {
case NullaryMethodType(ret) => loop(ret)
@@ -2772,8 +2763,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def isJavaInterface = hasAllFlags(JAVA | TRAIT)
override def isNestedClass = !owner.isPackageClass
override def isNumericValueClass = definitions.isNumericValueClass(this)
+ override def isNumeric = isNumericValueClass
override def isPackageObjectClass = isModuleClass && (name == tpnme.PACKAGE)
override def isPrimitiveValueClass = definitions.isPrimitiveValueClass(this)
+ override def isPrimitive = isPrimitiveValueClass
// The corresponding interface is the last parent by convention.
private def lastParent = if (tpe.parents.isEmpty) NoSymbol else tpe.parents.last.typeSymbol
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index b11eda9b7b..64c47a5502 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -216,7 +216,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
def showTparams(tparams: List[Symbol]) = "[" + (tparams map showTparam mkString ", ") + "]"
sig += showTparams(symbol.typeParams)
}
- if (symbol.allParams.nonEmpty) {
+ if (symbol.params.nonEmpty) {
def showParam(param: Symbol) = s"${param.name}: ${param.typeSignature}"
def showParams(params: List[Symbol]) = {
val s_mods = if (params.nonEmpty && params(0).hasFlag(IMPLICIT)) "implicit " else ""
@@ -224,9 +224,9 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
"(" + s_mods + s_params + ")"
}
def showParamss(paramss: List[List[Symbol]]) = paramss map showParams mkString ""
- sig += showParamss(symbol.allParams)
+ sig += showParamss(symbol.params)
}
- sig += s": ${symbol.resultType}"
+ sig += s": ${symbol.returnType}"
sig
}
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
index 525673fe6d..c65357b652 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
@@ -110,9 +110,8 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable =>
trait SynchronizedMethodSymbol extends MethodSymbol with SynchronizedTermSymbol {
override def typeAsMemberOf(pre: Type): Type = synchronized { super.typeAsMemberOf(pre) }
- override def allParams: List[List[Symbol]] = synchronized { super.allParams }
- override def params: List[Symbol] = synchronized { super.params }
- override def resultType: Type = synchronized { super.resultType }
+ override def params: List[List[Symbol]] = synchronized { super.params }
+ override def returnType: Type = synchronized { super.returnType }
}
trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol {
diff --git a/test/files/run/reflection-methodsymbol-allparams.check b/test/files/run/reflection-methodsymbol-allparams.check
deleted file mode 100644
index 11f349d52b..0000000000
--- a/test/files/run/reflection-methodsymbol-allparams.check
+++ /dev/null
@@ -1,8 +0,0 @@
-List()
-List(List())
-List(List(value x))
-List(List(value x), List(value y))
-List()
-List(List())
-List(List(value x))
-List(List(value x), List(value y))
diff --git a/test/files/run/reflection-methodsymbol-allparams.scala b/test/files/run/reflection-methodsymbol-allparams.scala
deleted file mode 100644
index d7c1c281b0..0000000000
--- a/test/files/run/reflection-methodsymbol-allparams.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-import scala.reflect.runtime.universe._
-
-class C {
- def x1: Int = ???
- def x2(): Int = ???
- def x3(x: Int): Int = ???
- def x4(x: Int)(y: Int): Int = ???
-
- def y1[T]: Int = ???
- def y2[T](): Int = ???
- def y3[T](x: Int): Int = ???
- def y4[T](x: Int)(y: Int): Int = ???
-}
-
-object Test extends App {
- println(typeOf[C].member(newTermName("x1")).asMethod.allParams)
- println(typeOf[C].member(newTermName("x2")).asMethod.allParams)
- println(typeOf[C].member(newTermName("x3")).asMethod.allParams)
- println(typeOf[C].member(newTermName("x4")).asMethod.allParams)
- println(typeOf[C].member(newTermName("y1")).asMethod.allParams)
- println(typeOf[C].member(newTermName("y2")).asMethod.allParams)
- println(typeOf[C].member(newTermName("y3")).asMethod.allParams)
- println(typeOf[C].member(newTermName("y4")).asMethod.allParams)
-} \ No newline at end of file
diff --git a/test/files/run/reflection-methodsymbol-params.check b/test/files/run/reflection-methodsymbol-params.check
index 899ae15a0c..11f349d52b 100644
--- a/test/files/run/reflection-methodsymbol-params.check
+++ b/test/files/run/reflection-methodsymbol-params.check
@@ -1,8 +1,8 @@
List()
+List(List())
+List(List(value x))
+List(List(value x), List(value y))
List()
-List(value x)
-List(value x)
-List()
-List()
-List(value x)
-List(value x)
+List(List())
+List(List(value x))
+List(List(value x), List(value y))
diff --git a/test/files/run/reflection-methodsymbol-resulttype.scala b/test/files/run/reflection-methodsymbol-resulttype.scala
deleted file mode 100644
index 0e3de26b9f..0000000000
--- a/test/files/run/reflection-methodsymbol-resulttype.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-import scala.reflect.runtime.universe._
-
-class C {
- def x1: Int = ???
- def x2(): Int = ???
- def x3(x: Int): Int = ???
- def x4(x: Int)(y: Int): Int = ???
-
- def y1[T]: Int = ???
- def y2[T](): Int = ???
- def y3[T](x: Int): Int = ???
- def y4[T](x: Int)(y: Int): Int = ???
-}
-
-object Test extends App {
- println(typeOf[C].member(newTermName("x1")).asMethod.resultType)
- println(typeOf[C].member(newTermName("x2")).asMethod.resultType)
- println(typeOf[C].member(newTermName("x3")).asMethod.resultType)
- println(typeOf[C].member(newTermName("x4")).asMethod.resultType)
- println(typeOf[C].member(newTermName("y1")).asMethod.resultType)
- println(typeOf[C].member(newTermName("y2")).asMethod.resultType)
- println(typeOf[C].member(newTermName("y3")).asMethod.resultType)
- println(typeOf[C].member(newTermName("y4")).asMethod.resultType)
-} \ No newline at end of file
diff --git a/test/files/run/reflection-methodsymbol-resulttype.check b/test/files/run/reflection-methodsymbol-returntype.check
index 0f30d1beaf..0f30d1beaf 100644
--- a/test/files/run/reflection-methodsymbol-resulttype.check
+++ b/test/files/run/reflection-methodsymbol-returntype.check
diff --git a/test/files/run/reflection-methodsymbol-returntype.scala b/test/files/run/reflection-methodsymbol-returntype.scala
new file mode 100644
index 0000000000..392754dbe4
--- /dev/null
+++ b/test/files/run/reflection-methodsymbol-returntype.scala
@@ -0,0 +1,24 @@
+import scala.reflect.runtime.universe._
+
+class C {
+ def x1: Int = ???
+ def x2(): Int = ???
+ def x3(x: Int): Int = ???
+ def x4(x: Int)(y: Int): Int = ???
+
+ def y1[T]: Int = ???
+ def y2[T](): Int = ???
+ def y3[T](x: Int): Int = ???
+ def y4[T](x: Int)(y: Int): Int = ???
+}
+
+object Test extends App {
+ println(typeOf[C].member(newTermName("x1")).asMethod.returnType)
+ println(typeOf[C].member(newTermName("x2")).asMethod.returnType)
+ println(typeOf[C].member(newTermName("x3")).asMethod.returnType)
+ println(typeOf[C].member(newTermName("x4")).asMethod.returnType)
+ println(typeOf[C].member(newTermName("y1")).asMethod.returnType)
+ println(typeOf[C].member(newTermName("y2")).asMethod.returnType)
+ println(typeOf[C].member(newTermName("y3")).asMethod.returnType)
+ println(typeOf[C].member(newTermName("y4")).asMethod.returnType)
+} \ No newline at end of file