summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-08-18 09:29:44 -0700
committerPaul Phillips <paulp@improving.org>2013-08-18 13:23:21 -0700
commit6d77da374e94ea8b80fc0bf9e544e11f4e9d5cc8 (patch)
tree672e9dfa0343526c77f68d45c7a4698a9dc832dc /src/reflect
parenta905d0e7e49bf92f119b2fdcd2b9d15b71d64ca2 (diff)
downloadscala-6d77da374e94ea8b80fc0bf9e544e11f4e9d5cc8.tar.gz
scala-6d77da374e94ea8b80fc0bf9e544e11f4e9d5cc8.tar.bz2
scala-6d77da374e94ea8b80fc0bf9e544e11f4e9d5cc8.zip
Refined name-based patmat methods.
This fleshes out some of the slightly unfinished corners of the adventure, especially for unapplySeq. There's still an unhealthy amount of duplication and a paucity of specification, but I think it's in eminently good shape for a milestone.
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala79
1 files changed, 51 insertions, 28 deletions
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index f1480c6cbd..19458361e1 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -681,41 +681,23 @@ trait Definitions extends api.StandardDefinitions {
def isExactProductType(tp: Type): Boolean = isProductNSymbol(tp.typeSymbol)
/** if tpe <: ProductN[T1,...,TN], returns List(T1,...,TN) else Nil */
- def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNSymbol match {
+ @deprecated("No longer used", "2.11.0") def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNSymbol match {
case Some(x) => tpe.baseType(x).typeArgs
case _ => Nil
}
- def getNameBasedProductSelectors(tpe: Type): List[Symbol] = {
- def loop(n: Int): List[Symbol] = tpe member TermName("_" + n) match {
- case NoSymbol => Nil
- case m if m.paramss.nonEmpty => Nil
- case m => m :: loop(n + 1)
- }
- loop(1)
- }
- def getNameBasedProductSelectorTypes(tpe: Type): List[Type] = getProductArgs(tpe) match {
- case xs if xs.nonEmpty => xs
- case _ => getterMemberTypes(tpe, getNameBasedProductSelectors(tpe))
+
+ @deprecated("No longer used", "2.11.0") def unapplyUnwrap(tpe:Type) = tpe.finalResultType.dealiasWiden match {
+ case RefinedType(p :: _, _) => p.dealiasWiden
+ case tp => tp
}
def getterMemberTypes(tpe: Type, getters: List[Symbol]): List[Type] =
getters map (m => dropNullaryMethod(tpe memberType m))
- def getNameBasedProductSeqElementType(tpe: Type) = getNameBasedProductSelectorTypes(tpe) match {
- case _ :+ elem => unapplySeqElementType(elem)
- case _ => NoType
- }
-
def dropNullaryMethod(tp: Type) = tp match {
case NullaryMethodType(restpe) => restpe
case _ => tp
}
-
- def unapplyUnwrap(tpe:Type) = tpe.finalResultType.dealiasWiden match {
- case RefinedType(p :: _, _) => p.dealiasWiden
- case tp => tp
- }
-
def abstractFunctionForFunctionType(tp: Type) = {
assert(isFunctionType(tp), tp)
abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last)
@@ -738,13 +720,54 @@ trait Definitions extends api.StandardDefinitions {
def scalaRepeatedType(arg: Type) = appliedType(RepeatedParamClass, arg)
def seqType(arg: Type) = appliedType(SeqClass, arg)
- def typeOfMemberNamedGet(tp: Type) = resultOfMatchingMethod(tp, nme.get)()
-
- def unapplySeqElementType(seqType: Type) = (
- resultOfMatchingMethod(seqType, nme.apply)(IntTpe)
- orElse resultOfMatchingMethod(seqType, nme.head)()
+ // FYI the long clunky name is because it's really hard to put "get" into the
+ // name of a method without it sounding like the method "get"s something, whereas
+ // this method is about a type member which just happens to be named get.
+ def typeOfMemberNamedGet(tp: Type) = resultOfMatchingMethod(tp, nme.get)()
+ def typeOfMemberNamedHead(tp: Type) = resultOfMatchingMethod(tp, nme.head)()
+ def typeOfMemberNamedApply(tp: Type) = resultOfMatchingMethod(tp, nme.apply)()
+ def typeOfMemberNamedGetOrSelf(tp: Type) = typeOfMemberNamedGet(tp) orElse tp
+ def typesOfSelectors(tp: Type) = getterMemberTypes(tp, productSelectors(tp))
+ def typesOfCaseAccessors(tp: Type) = getterMemberTypes(tp, tp.typeSymbol.caseFieldAccessors)
+
+ /** If this is a case class, the case field accessors (which may be an empty list.)
+ * Otherwise, if there are any product selectors, that list.
+ * Otherwise, a list containing only the type itself.
+ */
+ def typesOfSelectorsOrSelf(tp: Type): List[Type] = (
+ if (tp.typeSymbol.isCase)
+ typesOfCaseAccessors(tp)
+ else typesOfSelectors(tp) match {
+ case Nil => tp :: Nil
+ case tps => tps
+ }
)
+ /** If the given type has one or more product selectors, the type of the last one.
+ * Otherwise, the type itself.
+ */
+ def typeOfLastSelectorOrSelf(tp: Type) = typesOfSelectorsOrSelf(tp).last
+
+ def elementTypeOfLastSelectorOrSelf(tp: Type) = {
+ val last = typeOfLastSelectorOrSelf(tp)
+ ( typeOfMemberNamedHead(last)
+ orElse typeOfMemberNamedApply(last)
+ orElse elementType(ArrayClass, last)
+ )
+ }
+
+ /** Returns the method symbols for members _1, _2, ..., _N
+ * which exist in the given type.
+ */
+ def productSelectors(tpe: Type): List[Symbol] = {
+ def loop(n: Int): List[Symbol] = tpe member TermName("_" + n) match {
+ case NoSymbol => Nil
+ case m if m.paramss.nonEmpty => Nil
+ case m => m :: loop(n + 1)
+ }
+ loop(1)
+ }
+
/** If `tp` has a term member `name`, the first parameter list of which
* matches `paramTypes`, and which either has no further parameter
* lists or only an implicit one, then the result type of the matching