summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-02-09 17:46:55 +0000
committerMartin Odersky <odersky@gmail.com>2011-02-09 17:46:55 +0000
commit854de25ee63e85c3bda6f0205f25b341458dd5f1 (patch)
tree7a9fffc22e7cbc2b9d6661f21a39203beb464cb1
parent82ffae1693e1c8a665a08ac555ded165dab24b3f (diff)
downloadscala-854de25ee63e85c3bda6f0205f25b341458dd5f1.tar.gz
scala-854de25ee63e85c3bda6f0205f25b341458dd5f1.tar.bz2
scala-854de25ee63e85c3bda6f0205f25b341458dd5f1.zip
Filter completion proposals so that SDT need no...
Filter completion proposals so that SDT need not do it. Should solve the completion problems we were seeing.
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala5
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala115
2 files changed, 71 insertions, 49 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index e26822afeb..aefdece905 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -217,6 +217,7 @@ trait CompilerControl { self: Global =>
val sym: Symbol
val tpe: Type
val accessible: Boolean
+ def implicitlyAdded = false
}
case class TypeMember(
@@ -224,7 +225,9 @@ trait CompilerControl { self: Global =>
tpe: Type,
accessible: Boolean,
inherited: Boolean,
- viaView: Symbol) extends Member
+ viaView: Symbol) extends Member {
+ override def implicitlyAdded = viaView != NoSymbol
+ }
case class ScopeMember(
sym: Symbol,
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 88e47d9cb8..260b54d601 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -16,7 +16,7 @@ import scala.tools.nsc.ast._
import scala.tools.nsc.io.Pickler._
import scala.tools.nsc.typechecker.DivergentImplicit
import scala.annotation.tailrec
-import scala.reflect.generic.Flags.LOCKED
+import scala.reflect.generic.Flags.{ACCESSOR, PARAMACCESSOR}
/** The main class of the presentation compiler in an interactive environment such as an IDE
*/
@@ -45,7 +45,7 @@ self =>
else NullLogger
import log.logreplay
- debugLog("interactive compiler from 3 Feb")
+ debugLog("interactive compiler from 9 Feb")
debugLog("logger: " + log.getClass + " writing to " + (new java.io.File(logName)).getAbsolutePath)
debugLog("classpath: "+classPath)
@@ -270,9 +270,9 @@ self =>
case _ =>
}
- lastWasReload = false
+ lastWasReload = false
- logreplay("workitem", scheduler.nextWorkItem()) match {
+ logreplay("workitem", scheduler.nextWorkItem()) match {
case Some(action) =>
try {
debugLog("picked up work item at "+pos+": "+action)
@@ -619,22 +619,49 @@ self =>
val Dollar = newTermName("$")
+ class Members[M <: Member] extends LinkedHashMap[Name, Set[M]] {
+ override def default(key: Name) = Set()
+
+ private def matching(sym: Symbol, symtpe: Type, ms: Set[M]): Option[M] = ms.find { m =>
+ (m.sym.name == sym.name) && (m.sym.isType || (m.tpe matches symtpe))
+ }
+
+ private def keepSecond(m: M, sym: Symbol, implicitlyAdded: Boolean): Boolean =
+ m.sym.hasFlag(ACCESSOR | PARAMACCESSOR) &&
+ !sym.hasFlag(ACCESSOR | PARAMACCESSOR) &&
+ (!implicitlyAdded || m.implicitlyAdded)
+
+ def add(sym: Symbol, pre: Type, implicitlyAdded: Boolean)(toMember: (Symbol, Type) => M) {
+ if ((sym.isGetter || sym.isSetter) && sym.accessed != NoSymbol) {
+ add(sym.accessed, pre, implicitlyAdded)(toMember)
+ } else if (!sym.name.decode.containsName(Dollar) && !sym.isSynthetic && sym.hasRawInfo) {
+ val symtpe = pre.memberType(sym) onTypeError ErrorType
+ matching(sym, symtpe, this(sym.name)) match {
+ case Some(m) =>
+ if (keepSecond(m, sym, implicitlyAdded)) {
+ //print(" -+ "+sym.name)
+ this(sym.name) = this(sym.name) - m + toMember(sym, symtpe)
+ }
+ case None =>
+ //print(" + "+sym.name)
+ this(sym.name) = this(sym.name) + toMember(sym, symtpe)
+ }
+ }
+ }
+
+ def allMembers: List[M] = values.toList.flatten
+ }
+
/** Return all members visible without prefix in context enclosing `pos`. */
def scopeMembers(pos: Position): List[ScopeMember] = {
typedTreeAt(pos) // to make sure context is entered
val context = doLocateContext(pos)
- val locals = new LinkedHashMap[Name, ScopeMember]
+ val locals = new Members[ScopeMember]
def addScopeMember(sym: Symbol, pre: Type, viaImport: Tree) =
- if (!sym.name.decode.containsName(Dollar) &&
- !sym.isSynthetic &&
- sym.hasRawInfo &&
- !locals.contains(sym.name)) {
- locals(sym.name) = new ScopeMember(
- sym,
- pre.memberType(sym) onTypeError ErrorType,
- context.isAccessible(sym, pre, false),
- viaImport)
+ locals.add(sym, pre, false) { (s, st) =>
+ new ScopeMember(s, st, context.isAccessible(s, pre, false), viaImport)
}
+ //print("add scope members")
var cx = context
while (cx != NoContext) {
for (sym <- cx.scope)
@@ -646,14 +673,15 @@ self =>
}
cx = cx.outer
}
-
+ //print("\nadd imported members")
for (imp <- context.imports) {
val pre = imp.qual.tpe
for (sym <- imp.allImportedSymbols) {
addScopeMember(sym, pre, imp.qual)
}
}
- val result = locals.values.toList
+ // println()
+ val result = locals.allMembers
// if (debugIDE) for (m <- result) println(m)
result
}
@@ -683,17 +711,13 @@ self =>
debugLog("typeMembers at "+tree+" "+tree.tpe)
val superAccess = tree.isInstanceOf[Super]
- val scope = new Scope
- val members = new LinkedHashMap[Symbol, TypeMember]
-
- def addTypeMember(sym: Symbol, pre: Type, inherited: Boolean, viaView: Symbol) {
- val symtpe = pre.memberType(sym) onTypeError ErrorType
- if (scope.lookupAll(sym.name) forall (sym => !(members(sym).tpe matches symtpe))) {
- scope enter sym
- members(sym) = new TypeMember(
- sym,
- symtpe,
- context.isAccessible(sym, pre, superAccess && (viaView == NoSymbol)),
+ val members = new Members[TypeMember]
+
+ def addTypeMember(sym: Symbol, pre: Type, inherited: Boolean, viaView: Symbol) = {
+ val implicitlyAdded = viaView != NoSymbol
+ members.add(sym, pre, implicitlyAdded) { (s, st) =>
+ new TypeMember(s, st,
+ context.isAccessible(s, pre, superAccess && !implicitlyAdded),
inherited,
viaView)
}
@@ -708,10 +732,6 @@ self =>
.onTypeError(EmptyTree)
}
- /** Names containing $ are not valid completions. */
- def shouldDisplay(sym: Symbol): Boolean =
- !sym.name.toString.contains("$")
-
val pre = stabilizedType(tree)
val ownerTpe = tree.tpe match {
case analyzer.ImportType(expr) => expr.tpe
@@ -719,26 +739,25 @@ self =>
case _ => tree.tpe
}
- for (sym <- ownerTpe.decls if shouldDisplay(sym))
+ //print("add members")
+ for (sym <- ownerTpe.members)
addTypeMember(sym, pre, false, NoSymbol)
- members.values.toList #:: {
- for (sym <- ownerTpe.members if shouldDisplay(sym))
- addTypeMember(sym, pre, true, NoSymbol)
- members.values.toList #:: {
- val applicableViews: List[SearchResult] =
- if (ownerTpe.isErroneous) List()
- else new ImplicitSearch(
- tree, functionType(List(ownerTpe), AnyClass.tpe), isView = true,
- context.makeImplicit(reportAmbiguousErrors = false)).allImplicits
- for (view <- applicableViews) {
- val vtree = viewApply(view)
- val vpre = stabilizedType(vtree)
- for (sym <- vtree.tpe.members) {
- addTypeMember(sym, vpre, false, view.tree.symbol)
- }
+ members.allMembers #:: {
+ //print("\nadd pimped")
+ val applicableViews: List[SearchResult] =
+ if (ownerTpe.isErroneous) List()
+ else new ImplicitSearch(
+ tree, functionType(List(ownerTpe), AnyClass.tpe), isView = true,
+ context.makeImplicit(reportAmbiguousErrors = false)).allImplicits
+ for (view <- applicableViews) {
+ val vtree = viewApply(view)
+ val vpre = stabilizedType(vtree)
+ for (sym <- vtree.tpe.members) {
+ addTypeMember(sym, vpre, false, view.tree.symbol)
}
- Stream(members.values.toList)
}
+ //println()
+ Stream(members.allMembers)
}
}