summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/Scopes.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-07-30 13:17:17 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-08-02 15:36:55 +0200
commita727c6fc198d33842ff85d8a16d48143a6757d51 (patch)
tree3b995ade8066488c3ac42d7b65e0bb02b976cabc /src/reflect/scala/reflect/internal/Scopes.scala
parent937da62be2834a646a31dbfb01527a82672f111e (diff)
downloadscala-a727c6fc198d33842ff85d8a16d48143a6757d51.tar.gz
scala-a727c6fc198d33842ff85d8a16d48143a6757d51.tar.bz2
scala-a727c6fc198d33842ff85d8a16d48143a6757d51.zip
SI-5732 members and derivatives now return Scope
Firstly this unifies the reflection API - now both decls and members return Scope (not Scope and List[Symbol] as it were before). Secondly this fixes SI-5732 without having to sort the result of members. Type.members now returns Scope, a distinguished type, which has the `sorted` method, which does the required sorting if necessary. Also removes nonPrivateMembers and nonPrivateDeclarations to keep the API minimalistic (as can be seen from their implementation in internal.Types they are just members and decls with bridges and private members removed).
Diffstat (limited to 'src/reflect/scala/reflect/internal/Scopes.scala')
-rw-r--r--src/reflect/scala/reflect/internal/Scopes.scala50
1 files changed, 43 insertions, 7 deletions
diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala
index 89e3c52de6..ed390b5a3b 100644
--- a/src/reflect/scala/reflect/internal/Scopes.scala
+++ b/src/reflect/scala/reflect/internal/Scopes.scala
@@ -41,9 +41,9 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
* This is necessary because when run from reflection every scope needs to have a
* SynchronizedScope as mixin.
*/
- class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends Iterable[Symbol] {
-
- /** A bitset containing the last 6 bits of the start value of every name
+ class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends ScopeBase with MemberScopeBase {
+
+ /** A bitset containing the last 6 bits of the start value of every name
* stored in this scope.
*/
var fingerPrints: Long = initFingerPrints
@@ -118,10 +118,10 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
*
* @param sym ...
*/
- def enter[T <: Symbol](sym: T): T = {
+ def enter[T <: Symbol](sym: T): T = {
fingerPrints |= sym.name.fingerPrint
- enterEntry(newScopeEntry(sym, this))
- sym
+ enterEntry(newScopeEntry(sym, this))
+ sym
}
/** enter a symbol, asserting that no symbol with same name exists in scope
@@ -282,6 +282,10 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
elemsCache
}
+ /** Vanilla scope - symbols are stored in declaration order.
+ */
+ def sorted: List[Symbol] = toList
+
/** Return the nesting level of this scope, i.e. the number of times this scope
* was nested in another */
def nestingLevel = nestinglevel
@@ -324,14 +328,46 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
toList.map(_.defString).mkString(start, sep, end)
override def toString(): String = mkString("Scope{\n ", ";\n ", "\n}")
-
}
implicit val ScopeTag = ClassTag[Scope](classOf[Scope])
+ type MemberScope = Scope
+
+ implicit val MemberScopeTag = ClassTag[MemberScope](classOf[MemberScope])
+
/** Create a new scope */
def newScope: Scope = new Scope()
+ /** Create a new scope to be used in `findMembers`.
+ *
+ * But why do we need a special scope for `findMembers`?
+ * Let me tell you a story.
+ *
+ * `findMembers` creates a synthetic scope and then iterates over
+ * base classes in linearization order, and for every scrutinized class
+ * iterates over `decls`, the collection of symbols declared in that class.
+ * Declarations that fit the filter get appended to the created scope.
+ *
+ * The problem is that `decls` returns a Scope, and to iterate a scope performantly
+ * one needs to go from its end to its beginning.
+ *
+ * Hence the `findMembers` scope is populated in a wicked order:
+ * symbols that belong to the same declaring class come in reverse order of their declaration,
+ * however, the scope itself is ordered w.r.t the linearization of the target type.
+ *
+ * Once `members` became a public API, this has been confusing countless numbers of users.
+ * Therefore we introduce a special flavor of scopes to accommodate this quirk of `findMembers`
+ */
+ private[scala] def newFindMemberScope: Scope = new Scope() {
+ override def sorted = {
+ val members = toList
+ val owners = members.map(_.owner).distinct
+ val grouped = members groupBy (_.owner)
+ owners.flatMap(owner => grouped(owner).reverse)
+ }
+ }
+
/** Create a new scope nested in another one with which it shares its elements */
def newNestedScope(outer: Scope): Scope = new Scope(outer)