summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-07-30 21:14:42 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-08-02 15:36:58 +0200
commit367b82de04bdee24b0994e30c1464297eae16d74 (patch)
tree79480d2ac5adc812b0d50041ddeca5e910ffb46f
parent7112c66d6951ac83ae3591426291ec2797824258 (diff)
downloadscala-367b82de04bdee24b0994e30c1464297eae16d74.tar.gz
scala-367b82de04bdee24b0994e30c1464297eae16d74.tar.bz2
scala-367b82de04bdee24b0994e30c1464297eae16d74.zip
miscellaneous refinements of reflection API
1) Removed unnecessary (i.e. implementable with pattern matching) type APIs. 2) Renamed isHigherKinded to takesTypeArgs making it easier to understand. 2) typeParams and resultType have been moved from MethodType to MethodSymbol Strictly speaking they are superfluous, but they are used very often.
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala5
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala79
-rw-r--r--src/reflect/scala/reflect/api/Types.scala98
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala23
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala1
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala3
-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.check8
-rw-r--r--test/files/run/reflection-methodsymbol-params.scala24
-rw-r--r--test/files/run/reflection-methodsymbol-resulttype.check8
-rw-r--r--test/files/run/reflection-methodsymbol-resulttype.scala24
-rw-r--r--test/files/run/reflection-methodsymbol-typeparams.check8
-rw-r--r--test/files/run/reflection-methodsymbol-typeparams.scala24
15 files changed, 239 insertions, 101 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
index 56b9c7011c..202d5d3f82 100644
--- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
@@ -212,8 +212,7 @@ trait TypeStrings {
}
private def tparamString[T: ru.TypeTag] : String = {
- // [Eugene++ to Paul] needs review!!
- def typeArguments: List[ru.Type] = ru.typeOf[T].typeArguments
+ def typeArguments: List[ru.Type] = ru.typeOf[T] match { case ru.TypeRef(_, _, args) => args; case _ => Nil }
// [Eugene++] todo. need to use not the `rootMirror`, but a mirror with the REPL's classloader
// how do I get to it? acquiring context classloader seems unreliable because of multithreading
def typeVariables: List[java.lang.Class[_]] = typeArguments map (targ => ru.rootMirror.runtimeClass(targ))
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index 7bd5f4caeb..bd2808d049 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -70,11 +70,8 @@ trait MethodSynthesis {
// [Eugene++->Martin] now this compiles, will soon check it out
def newMethodType[F](owner: Symbol)(implicit t: TT[F]): Type = {
val fnSymbol = compilerSymbolFromTag(t)
- assert(fnSymbol isSubClass FunctionClass(t.tpe.typeArguments.size - 1), (owner, t))
- // [Eugene++ to Paul] needs review!!
- // val symbols = m.typeArguments map (m => manifestToSymbol(m))
- // val formals = symbols.init map (_.typeConstructor)
val formals = compilerTypeFromTag(t).typeArguments
+ assert(fnSymbol isSubClass FunctionClass(formals.size - 1), (owner, t))
val params = owner newSyntheticValueParams formals
MethodType(params, formals.last)
}
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index 7ca1d9c7c6..cd9044c934 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -43,23 +43,6 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def hasAnnotation(sym: Symbol): Boolean
- /** ...
- */
- def orElse(alt: => Symbol): Symbol
-
- /** ...
- */
- def filter(cond: Symbol => Boolean): Symbol
-
- /** If this is a NoSymbol, returns NoSymbol, otherwise
- * returns the result of applying `f` to this symbol.
- */
- def map(f: Symbol => Symbol): Symbol
-
- /** ...
- */
- def suchThat(cond: Symbol => Boolean): Symbol
-
/**
* Set when symbol has a modifier of the form private[X], NoSymbol otherwise.
*
@@ -93,15 +76,17 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def companionSymbol: Symbol
- /** If this symbol is a package class, this symbol; otherwise the next enclosing
- * package class, or `NoSymbol` if none exists.
+ /** The type signature of this symbol seen as a member of given type `site`.
*/
- def enclosingPackageClass: Symbol
+ def typeSignatureIn(site: Type): Type
- /** If this symbol is a top-level class, this symbol; otherwise the next enclosing
- * top-level class, or `NoSymbol` if none exists.
+ /** 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 enclosingTopLevelClass: Symbol
+ def typeSignature: Type
+
+ /******************* tests *******************/
/** Does this symbol represent the definition of a package?
* If yes, `isTerm` is also guaranteed to be true.
@@ -136,15 +121,24 @@ trait Symbols extends base.Symbols { self: Universe =>
*/
def isStatic: Boolean
- /** The type signature of this symbol seen as a member of given type `site`.
+ /******************* helpers *******************/
+
+ /** ...
*/
- def typeSignatureIn(site: Type): Type
+ def orElse(alt: => Symbol): Symbol
- /** 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
+ def filter(cond: Symbol => Boolean): Symbol
+
+ /** If this is a NoSymbol, returns NoSymbol, otherwise
+ * returns the result of applying `f` to this symbol.
+ */
+ def map(f: Symbol => Symbol): Symbol
+
+ /** ...
+ */
+ def suchThat(cond: Symbol => Boolean): Symbol
/** The string discriminator of this symbol; useful for debugging */
def kind: String
@@ -263,10 +257,33 @@ trait Symbols extends base.Symbols { self: Universe =>
}
/** The API of method symbols */
- type MethodSymbolApi = MethodSymbolBase
+ trait MethodSymbolApi extends TermSymbolApi with MethodSymbolBase { this: MethodSymbol =>
+ /** 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]]
+
+ /** The result type of the method */
+ def resultType: Type
+ }
/** The API of module symbols */
- type ModuleSymbolApi = ModuleSymbolBase
+ trait ModuleSymbolApi extends TermSymbolApi with ModuleSymbolBase { this: ModuleSymbol =>
+ }
/** The API of class symbols */
trait ClassSymbolApi extends TypeSymbolApi with ClassSymbolBase { this: ClassSymbol =>
diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala
index 33248fcbee..199cf9b9e5 100644
--- a/src/reflect/scala/reflect/api/Types.scala
+++ b/src/reflect/scala/reflect/api/Types.scala
@@ -45,45 +45,14 @@ trait Types extends base.Types { self: Universe =>
*/
def members: MemberScope
- /** Substitute symbols in `to` for corresponding occurrences of references to
- * symbols `from` in this type.
- */
- def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type
-
- /** Substitute types in `to` for corresponding occurrences of references to
- * symbols `from` in this type.
- */
- def substituteTypes(from: List[Symbol], to: List[Type]): Type
-
- /** If this is a parameterized types, the type arguments.
- * Otherwise the empty list
- */
- def typeArguments: List[Type]
-
- /** For a (potentially wrapped) poly type, its type parameters,
- * the empty list for all other types */
- def typeParams: List[Symbol]
-
- /** For a (nullary) method or poly type, its direct result type,
- * the type itself for all other types. */
- def resultType: Type
-
/** Is this type a type constructor that is missing its type arguments?
*/
- def isHigherKinded: Boolean // !!! This should be called "isTypeConstructor", no?
+ def takesTypeArgs: Boolean
/** Returns the corresponding type constructor (e.g. List for List[T] or List[String])
*/
def typeConstructor: Type
- /** Does this type refer to spliceable types or is a spliceable type?
- */
- def isConcrete: Boolean
-
- /** Is this type an abstract type that needs to be resolved?
- */
- def isSpliceable: Boolean
-
/**
* Expands type aliases and converts higher-kinded TypeRefs to PolyTypes.
* Functions on types are also implemented as PolyTypes.
@@ -92,7 +61,7 @@ trait Types extends base.Types { self: Universe =>
* TypeRef(pre, <List>, List()) is replaced by
* PolyType(X, TypeRef(pre, <List>, List(X)))
*/
- def normalize: Type // !!! Alternative name? "normalize" is used to mean too many things.
+ def normalize: Type
/** Does this type conform to given type argument `that`? */
def <:< (that: Type): Boolean
@@ -104,7 +73,7 @@ trait Types extends base.Types { self: Universe =>
* in reverse linearization order, starting with the class itself and ending
* in class Any.
*/
- def baseClasses: List[Symbol] // !!! Alternative name, perhaps linearization?
+ def baseClasses: List[Symbol]
/** The least type instance of given class which is a supertype
* of this type. Example:
@@ -134,36 +103,7 @@ trait Types extends base.Types { self: Universe =>
/** The erased type corresponding to this type after
* all transformations from Scala to Java have been performed.
*/
- def erasure: Type // !!! "erasedType", compare with "widen" (so "erase") or "underlying" (so "erased")
- // why not name it "erasure"?
-
- /** Apply `f` to each part of this type, returning
- * a new type. children get mapped before their parents */
- def map(f: Type => Type): Type
-
- /** Apply `f` to each part of this type, for side effects only */
- def foreach(f: Type => Unit)
-
- /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`,
- * or None if none exists.
- */
- def find(p: Type => Boolean): Option[Type]
-
- /** Is there part of this type which satisfies predicate `p`? */
- def exists(p: Type => Boolean): Boolean
-
- /** Does this type contain a reference to given symbol? */
- def contains(sym: Symbol): Boolean
-
- /** If this is a compound type, the list of its parent types;
- * otherwise the empty list
- */
- def parents: List[Type]
-
- /** If this is a singleton type, returns the type underlying it;
- * otherwise returns this type itself.
- */
- def underlying: Type
+ def erasure: Type
/** If this is a singleton type, widen it to its nearest underlying non-singleton
* base type by applying one or more `underlying` dereferences.
@@ -186,6 +126,36 @@ trait Types extends base.Types { self: Universe =>
*/
def narrow: Type
+ /******************* helpers *******************/
+
+ /** Substitute symbols in `to` for corresponding occurrences of references to
+ * symbols `from` in this type.
+ */
+ def substituteSymbols(from: List[Symbol], to: List[Symbol]): Type
+
+ /** Substitute types in `to` for corresponding occurrences of references to
+ * symbols `from` in this type.
+ */
+ def substituteTypes(from: List[Symbol], to: List[Type]): Type
+
+ /** Apply `f` to each part of this type, returning
+ * a new type. children get mapped before their parents */
+ def map(f: Type => Type): Type
+
+ /** Apply `f` to each part of this type, for side effects only */
+ def foreach(f: Type => Unit)
+
+ /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`,
+ * or None if none exists.
+ */
+ def find(p: Type => Boolean): Option[Type]
+
+ /** Is there part of this type which satisfies predicate `p`? */
+ def exists(p: Type => Boolean): Boolean
+
+ /** Does this type contain a reference to given symbol? */
+ def contains(sym: Symbol): Boolean
+
/** The string discriminator of this type; useful for debugging */
def kind: String
}
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 8cf20ba062..68144da2d7 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -2486,6 +2486,29 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
mtpeResult = res
res
}
+
+ override def allParams: 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 = {
+ def loop(tpe: Type): Type =
+ tpe match {
+ case NullaryMethodType(ret) => loop(ret)
+ case MethodType(_, ret) => loop(ret)
+ case PolyType(_, tpe) => loop(tpe)
+ case tpe => tpe
+ }
+ loop(info)
+ }
}
implicit val MethodSymbolTag = ClassTag[MethodSymbol](classOf[MethodSymbol])
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 1386cca42f..442a91774d 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -323,6 +323,7 @@ trait Types extends api.Types { self: SymbolTable =>
/** Is this type higher-kinded, i.e., is it a type constructor @M */
def isHigherKinded: Boolean = false
+ def takesTypeArgs: Boolean = this.isHigherKinded
/** Does this type denote a stable reference (i.e. singleton type)? */
def isStable: Boolean = false
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
index 6a3501b1dd..525673fe6d 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
@@ -110,6 +110,9 @@ 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 }
}
trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol {
diff --git a/test/files/run/reflection-methodsymbol-allparams.check b/test/files/run/reflection-methodsymbol-allparams.check
new file mode 100644
index 0000000000..11f349d52b
--- /dev/null
+++ b/test/files/run/reflection-methodsymbol-allparams.check
@@ -0,0 +1,8 @@
+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
new file mode 100644
index 0000000000..cfd14f56a5
--- /dev/null
+++ b/test/files/run/reflection-methodsymbol-allparams.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")).asMethodSymbol.allParams)
+ println(typeOf[C].member(newTermName("x2")).asMethodSymbol.allParams)
+ println(typeOf[C].member(newTermName("x3")).asMethodSymbol.allParams)
+ println(typeOf[C].member(newTermName("x4")).asMethodSymbol.allParams)
+ println(typeOf[C].member(newTermName("y1")).asMethodSymbol.allParams)
+ println(typeOf[C].member(newTermName("y2")).asMethodSymbol.allParams)
+ println(typeOf[C].member(newTermName("y3")).asMethodSymbol.allParams)
+ println(typeOf[C].member(newTermName("y4")).asMethodSymbol.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
new file mode 100644
index 0000000000..899ae15a0c
--- /dev/null
+++ b/test/files/run/reflection-methodsymbol-params.check
@@ -0,0 +1,8 @@
+List()
+List()
+List(value x)
+List(value x)
+List()
+List()
+List(value x)
+List(value x)
diff --git a/test/files/run/reflection-methodsymbol-params.scala b/test/files/run/reflection-methodsymbol-params.scala
new file mode 100644
index 0000000000..654a16b59d
--- /dev/null
+++ b/test/files/run/reflection-methodsymbol-params.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")).asMethodSymbol.params)
+ println(typeOf[C].member(newTermName("x2")).asMethodSymbol.params)
+ println(typeOf[C].member(newTermName("x3")).asMethodSymbol.params)
+ println(typeOf[C].member(newTermName("x4")).asMethodSymbol.params)
+ println(typeOf[C].member(newTermName("y1")).asMethodSymbol.params)
+ println(typeOf[C].member(newTermName("y2")).asMethodSymbol.params)
+ println(typeOf[C].member(newTermName("y3")).asMethodSymbol.params)
+ println(typeOf[C].member(newTermName("y4")).asMethodSymbol.params)
+} \ No newline at end of file
diff --git a/test/files/run/reflection-methodsymbol-resulttype.check b/test/files/run/reflection-methodsymbol-resulttype.check
new file mode 100644
index 0000000000..0f30d1beaf
--- /dev/null
+++ b/test/files/run/reflection-methodsymbol-resulttype.check
@@ -0,0 +1,8 @@
+Int
+Int
+Int
+Int
+Int
+Int
+Int
+Int
diff --git a/test/files/run/reflection-methodsymbol-resulttype.scala b/test/files/run/reflection-methodsymbol-resulttype.scala
new file mode 100644
index 0000000000..7a9f66dda8
--- /dev/null
+++ b/test/files/run/reflection-methodsymbol-resulttype.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")).asMethodSymbol.resultType)
+ println(typeOf[C].member(newTermName("x2")).asMethodSymbol.resultType)
+ println(typeOf[C].member(newTermName("x3")).asMethodSymbol.resultType)
+ println(typeOf[C].member(newTermName("x4")).asMethodSymbol.resultType)
+ println(typeOf[C].member(newTermName("y1")).asMethodSymbol.resultType)
+ println(typeOf[C].member(newTermName("y2")).asMethodSymbol.resultType)
+ println(typeOf[C].member(newTermName("y3")).asMethodSymbol.resultType)
+ println(typeOf[C].member(newTermName("y4")).asMethodSymbol.resultType)
+} \ No newline at end of file
diff --git a/test/files/run/reflection-methodsymbol-typeparams.check b/test/files/run/reflection-methodsymbol-typeparams.check
new file mode 100644
index 0000000000..c888e09a17
--- /dev/null
+++ b/test/files/run/reflection-methodsymbol-typeparams.check
@@ -0,0 +1,8 @@
+List()
+List()
+List()
+List()
+List(type T)
+List(type T)
+List(type T)
+List(type T)
diff --git a/test/files/run/reflection-methodsymbol-typeparams.scala b/test/files/run/reflection-methodsymbol-typeparams.scala
new file mode 100644
index 0000000000..28f1c8973d
--- /dev/null
+++ b/test/files/run/reflection-methodsymbol-typeparams.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")).asMethodSymbol.typeParams)
+ println(typeOf[C].member(newTermName("x2")).asMethodSymbol.typeParams)
+ println(typeOf[C].member(newTermName("x3")).asMethodSymbol.typeParams)
+ println(typeOf[C].member(newTermName("x4")).asMethodSymbol.typeParams)
+ println(typeOf[C].member(newTermName("y1")).asMethodSymbol.typeParams)
+ println(typeOf[C].member(newTermName("y2")).asMethodSymbol.typeParams)
+ println(typeOf[C].member(newTermName("y3")).asMethodSymbol.typeParams)
+ println(typeOf[C].member(newTermName("y4")).asMethodSymbol.typeParams)
+} \ No newline at end of file