Skip to content

Commit 854de25

Browse files
committed
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.
1 parent 82ffae1 commit 854de25

File tree

2 files changed

+71
-49
lines changed

2 files changed

+71
-49
lines changed

src/compiler/scala/tools/nsc/interactive/CompilerControl.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,14 +217,17 @@ trait CompilerControl { self: Global =>
217217
val sym: Symbol
218218
val tpe: Type
219219
val accessible: Boolean
220+
def implicitlyAdded = false
220221
}
221222

222223
case class TypeMember(
223224
sym: Symbol,
224225
tpe: Type,
225226
accessible: Boolean,
226227
inherited: Boolean,
227-
viaView: Symbol) extends Member
228+
viaView: Symbol) extends Member {
229+
override def implicitlyAdded = viaView != NoSymbol
230+
}
228231

229232
case class ScopeMember(
230233
sym: Symbol,

src/compiler/scala/tools/nsc/interactive/Global.scala

Lines changed: 67 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import scala.tools.nsc.ast._
1616
import scala.tools.nsc.io.Pickler._
1717
import scala.tools.nsc.typechecker.DivergentImplicit
1818
import scala.annotation.tailrec
19-
import scala.reflect.generic.Flags.LOCKED
19+
import scala.reflect.generic.Flags.{ACCESSOR, PARAMACCESSOR}
2020

2121
/** The main class of the presentation compiler in an interactive environment such as an IDE
2222
*/
@@ -45,7 +45,7 @@ self =>
4545
else NullLogger
4646

4747
import log.logreplay
48-
debugLog("interactive compiler from 3 Feb")
48+
debugLog("interactive compiler from 9 Feb")
4949
debugLog("logger: " + log.getClass + " writing to " + (new java.io.File(logName)).getAbsolutePath)
5050
debugLog("classpath: "+classPath)
5151

@@ -270,9 +270,9 @@ self =>
270270
case _ =>
271271
}
272272

273-
lastWasReload = false
273+
lastWasReload = false
274274

275-
logreplay("workitem", scheduler.nextWorkItem()) match {
275+
logreplay("workitem", scheduler.nextWorkItem()) match {
276276
case Some(action) =>
277277
try {
278278
debugLog("picked up work item at "+pos+": "+action)
@@ -619,22 +619,49 @@ self =>
619619

620620
val Dollar = newTermName("$")
621621

622+
class Members[M <: Member] extends LinkedHashMap[Name, Set[M]] {
623+
override def default(key: Name) = Set()
624+
625+
private def matching(sym: Symbol, symtpe: Type, ms: Set[M]): Option[M] = ms.find { m =>
626+
(m.sym.name == sym.name) && (m.sym.isType || (m.tpe matches symtpe))
627+
}
628+
629+
private def keepSecond(m: M, sym: Symbol, implicitlyAdded: Boolean): Boolean =
630+
m.sym.hasFlag(ACCESSOR | PARAMACCESSOR) &&
631+
!sym.hasFlag(ACCESSOR | PARAMACCESSOR) &&
632+
(!implicitlyAdded || m.implicitlyAdded)
633+
634+
def add(sym: Symbol, pre: Type, implicitlyAdded: Boolean)(toMember: (Symbol, Type) => M) {
635+
if ((sym.isGetter || sym.isSetter) && sym.accessed != NoSymbol) {
636+
add(sym.accessed, pre, implicitlyAdded)(toMember)
637+
} else if (!sym.name.decode.containsName(Dollar) && !sym.isSynthetic && sym.hasRawInfo) {
638+
val symtpe = pre.memberType(sym) onTypeError ErrorType
639+
matching(sym, symtpe, this(sym.name)) match {
640+
case Some(m) =>
641+
if (keepSecond(m, sym, implicitlyAdded)) {
642+
//print(" -+ "+sym.name)
643+
this(sym.name) = this(sym.name) - m + toMember(sym, symtpe)
644+
}
645+
case None =>
646+
//print(" + "+sym.name)
647+
this(sym.name) = this(sym.name) + toMember(sym, symtpe)
648+
}
649+
}
650+
}
651+
652+
def allMembers: List[M] = values.toList.flatten
653+
}
654+
622655
/** Return all members visible without prefix in context enclosing `pos`. */
623656
def scopeMembers(pos: Position): List[ScopeMember] = {
624657
typedTreeAt(pos) // to make sure context is entered
625658
val context = doLocateContext(pos)
626-
val locals = new LinkedHashMap[Name, ScopeMember]
659+
val locals = new Members[ScopeMember]
627660
def addScopeMember(sym: Symbol, pre: Type, viaImport: Tree) =
628-
if (!sym.name.decode.containsName(Dollar) &&
629-
!sym.isSynthetic &&
630-
sym.hasRawInfo &&
631-
!locals.contains(sym.name)) {
632-
locals(sym.name) = new ScopeMember(
633-
sym,
634-
pre.memberType(sym) onTypeError ErrorType,
635-
context.isAccessible(sym, pre, false),
636-
viaImport)
661+
locals.add(sym, pre, false) { (s, st) =>
662+
new ScopeMember(s, st, context.isAccessible(s, pre, false), viaImport)
637663
}
664+
//print("add scope members")
638665
var cx = context
639666
while (cx != NoContext) {
640667
for (sym <- cx.scope)
@@ -646,14 +673,15 @@ self =>
646673
}
647674
cx = cx.outer
648675
}
649-
676+
//print("\nadd imported members")
650677
for (imp <- context.imports) {
651678
val pre = imp.qual.tpe
652679
for (sym <- imp.allImportedSymbols) {
653680
addScopeMember(sym, pre, imp.qual)
654681
}
655682
}
656-
val result = locals.values.toList
683+
// println()
684+
val result = locals.allMembers
657685
// if (debugIDE) for (m <- result) println(m)
658686
result
659687
}
@@ -683,17 +711,13 @@ self =>
683711
debugLog("typeMembers at "+tree+" "+tree.tpe)
684712

685713
val superAccess = tree.isInstanceOf[Super]
686-
val scope = new Scope
687-
val members = new LinkedHashMap[Symbol, TypeMember]
688-
689-
def addTypeMember(sym: Symbol, pre: Type, inherited: Boolean, viaView: Symbol) {
690-
val symtpe = pre.memberType(sym) onTypeError ErrorType
691-
if (scope.lookupAll(sym.name) forall (sym => !(members(sym).tpe matches symtpe))) {
692-
scope enter sym
693-
members(sym) = new TypeMember(
694-
sym,
695-
symtpe,
696-
context.isAccessible(sym, pre, superAccess && (viaView == NoSymbol)),
714+
val members = new Members[TypeMember]
715+
716+
def addTypeMember(sym: Symbol, pre: Type, inherited: Boolean, viaView: Symbol) = {
717+
val implicitlyAdded = viaView != NoSymbol
718+
members.add(sym, pre, implicitlyAdded) { (s, st) =>
719+
new TypeMember(s, st,
720+
context.isAccessible(s, pre, superAccess && !implicitlyAdded),
697721
inherited,
698722
viaView)
699723
}
@@ -708,37 +732,32 @@ self =>
708732
.onTypeError(EmptyTree)
709733
}
710734

711-
/** Names containing $ are not valid completions. */
712-
def shouldDisplay(sym: Symbol): Boolean =
713-
!sym.name.toString.contains("$")
714-
715735
val pre = stabilizedType(tree)
716736
val ownerTpe = tree.tpe match {
717737
case analyzer.ImportType(expr) => expr.tpe
718738
case null => pre
719739
case _ => tree.tpe
720740
}
721741

722-
for (sym <- ownerTpe.decls if shouldDisplay(sym))
742+
//print("add members")
743+
for (sym <- ownerTpe.members)
723744
addTypeMember(sym, pre, false, NoSymbol)
724-
members.values.toList #:: {
725-
for (sym <- ownerTpe.members if shouldDisplay(sym))
726-
addTypeMember(sym, pre, true, NoSymbol)
727-
members.values.toList #:: {
728-
val applicableViews: List[SearchResult] =
729-
if (ownerTpe.isErroneous) List()
730-
else new ImplicitSearch(
731-
tree, functionType(List(ownerTpe), AnyClass.tpe), isView = true,
732-
context.makeImplicit(reportAmbiguousErrors = false)).allImplicits
733-
for (view <- applicableViews) {
734-
val vtree = viewApply(view)
735-
val vpre = stabilizedType(vtree)
736-
for (sym <- vtree.tpe.members) {
737-
addTypeMember(sym, vpre, false, view.tree.symbol)
738-
}
745+
members.allMembers #:: {
746+
//print("\nadd pimped")
747+
val applicableViews: List[SearchResult] =
748+
if (ownerTpe.isErroneous) List()
749+
else new ImplicitSearch(
750+
tree, functionType(List(ownerTpe), AnyClass.tpe), isView = true,
751+
context.makeImplicit(reportAmbiguousErrors = false)).allImplicits
752+
for (view <- applicableViews) {
753+
val vtree = viewApply(view)
754+
val vpre = stabilizedType(vtree)
755+
for (sym <- vtree.tpe.members) {
756+
addTypeMember(sym, vpre, false, view.tree.symbol)
739757
}
740-
Stream(members.values.toList)
741758
}
759+
//println()
760+
Stream(members.allMembers)
742761
}
743762
}
744763

0 commit comments

Comments
 (0)