summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-08-02 18:22:20 +0000
committerMartin Odersky <odersky@gmail.com>2009-08-02 18:22:20 +0000
commitf9c2bc54ff2e047b9c2ebc9bcae4a4d1b87be0c2 (patch)
tree1261c27f53e4f57620f3d316cf8c4828e83e4b9f /src/compiler/scala
parentd339959ff129d9c3ccabad25d924618d21b7a471 (diff)
downloadscala-f9c2bc54ff2e047b9c2ebc9bcae4a4d1b87be0c2.tar.gz
scala-f9c2bc54ff2e047b9c2ebc9bcae4a4d1b87be0c2.tar.bz2
scala-f9c2bc54ff2e047b9c2ebc9bcae4a4d1b87be0c2.zip
Deleted IDeSupport.
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/tools/nsc/IdeSupport.scala54
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala11
-rwxr-xr-xsrc/compiler/scala/tools/nsc/interactive/ContextTrees.scala1
-rwxr-xr-xsrc/compiler/scala/tools/nsc/interactive/Global.scala124
-rw-r--r--src/compiler/scala/tools/nsc/symtab/IdeSupport.scala664
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Scopes.scala84
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala378
9 files changed, 148 insertions, 1186 deletions
diff --git a/src/compiler/scala/tools/nsc/IdeSupport.scala b/src/compiler/scala/tools/nsc/IdeSupport.scala
deleted file mode 100644
index ab1580e124..0000000000
--- a/src/compiler/scala/tools/nsc/IdeSupport.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2009 LAMP/EPFL
- * @author Martin Odersky
- */
-// $Id$
-
-package scala.tools.nsc
-
-import scala.tools.nsc.io._
-
-trait IdeSupport extends Global with symtab.IdeSupport {
- /** to do no dependency tracking */
- protected def normalCompile[T](f: => T): T = f
- override def unpickleIDEHook: (( => Type) => Type) = f => normalCompile(f)
-
- class IdeRun extends Run {
- override def compiles(sym: Symbol): Boolean = false // throw new Error
- override def compileLate(file: AbstractFile) = {
- reloadSource(file)
- normalCompile(super.compileLate(file))
- }
- override def stopPhase(name : String) =
- name == "superaccessors" || super.stopPhase(name)
- }
-
- // load a source file without us caring about adapt.
- def loadSource(file: AbstractFile): Option[CompilationUnit] = {
- val run = new IdeRun
- reloadSource(file)
- val source = getSourceFile(file)
- try {
- normalCompile(run.compileSources(source :: Nil))
- run.units.find(_.source == source)
- } catch {
- case e =>
- logError("error in presentation normal compile ", e)
- None
- }
- }
-
- object loaders1 extends {
- val global: IdeSupport.this.type = IdeSupport.this
- } with scala.tools.nsc.symtab.SymbolLoaders {
- import global._
- protected override def completeClassfile(root: global.Symbol, loader: ClassfileLoader)(f: => Unit) {
- global.normalCompile(f)
- }
- override def computeDepends(from: PackageLoader): global.PackageScopeDependMap =
- IdeSupport.this.computeDepends(from.asInstanceOf[IdeSupport.this.loaders.PackageLoader])
- }
-
- def computeDepends(from: loaders.PackageLoader): PackageScopeDependMap = null
- override lazy val loaders = loaders1
-}
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index b22cc9098d..069516bbf4 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -20,10 +20,13 @@ trait CompilerControl { self: Global =>
/** Info given for every member found by completion
*/
- case class Member(val sym: Symbol, val tpe: Type, val accessible: Boolean, val inherited: Boolean, val viaView: Symbol) {
- def shadows(other: Member) =
- sym.name == other.sym.name && (sym.tpe matches other.sym.tpe)
- }
+ case class Member(val sym: Symbol, val tpe: Type, val accessible: Boolean)
+
+ class TypeMember(sym: Symbol, tpe: Type, accessible: Boolean, val inherited: Boolean, val viaView: Symbol = NoSymbol)
+ extends Member(sym, tpe, accessible)
+
+ class ScopeMember(sym: Symbol, tpe: Type, accessible: Boolean, val viaImport: Tree = EmptyTree)
+ extends Member(sym, tpe, accessible)
/** The scheduler by which client and compiler communicate
* Must be initialized before starting compilerRunner
diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
index aea858c68b..e78a4cc19f 100755
--- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
+++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
@@ -7,6 +7,7 @@ import util.Position
trait ContextTrees { self: Global =>
type Context = analyzer.Context
+ val NoContext = analyzer.NoContext
type Contexts = ArrayBuffer[ContextTree]
/** A context tree contains contexts that are indexed by positions.
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 4ca2203bb2..d055e5ec41 100755
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -24,6 +24,8 @@ self =>
import definitions._
+ final val debugIDE = false
+
override def onlyPresentation = true
/** A list indicating in which order some units should be typechecked.
@@ -120,14 +122,14 @@ self =>
case Some(action) =>
try {
acting = true
- //println("picked up work item: "+action)
+ if (debugIDE) println("picked up work item: "+action)
action()
- //println("done with work item: "+action)
+ if (debugIDE) println("done with work item: "+action)
} catch {
case ex: CancelActionReq =>
- //println("cancelled work item: "+action)
+ if (debugIDE) println("cancelled work item: "+action)
} finally {
- //println("quitting work item: "+action)
+ if (debugIDE) println("quitting work item: "+action)
acting = false
}
case None =>
@@ -209,13 +211,13 @@ self =>
/** Compile all given units
*/
private def backgroundCompile() {
- //inform("Starting new presentation compiler type checking pass")
+ if (debugIDE) inform("Starting new presentation compiler type checking pass")
reporter.reset
firsts = firsts filter (s => unitOfFile contains (s.file))
val prefix = firsts map unitOf
val units = prefix ::: (unitOfFile.values.toList diff prefix) filter (!_.isUpToDate)
recompile(units)
- //inform("Everything is now up to date")
+ if (debugIDE) inform("Everything is now up to date")
}
/** Reset unit to just-parsed state */
@@ -244,11 +246,11 @@ self =>
def recompile(units: List[RichCompilationUnit]) {
for (unit <- units) {
reset(unit)
- //inform("parsing: "+unit)
+ if (debugIDE) inform("parsing: "+unit)
parse(unit)
}
for (unit <- units) {
- //inform("type checking: "+unit)
+ if (debugIDE) inform("type checking: "+unit)
activeLocks = 0
currentTyperRun.typeCheck(unit)
unit.status = currentRunId
@@ -329,59 +331,85 @@ self =>
respond(result) { scopeMembers(pos) }
}
- def scopeMembers(pos: Position): List[Member] = {
+ /** 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)
- List() // to be completed
+ val locals = new LinkedHashMap[Name, ScopeMember]
+ def addScopeMember(sym: Symbol, pre: Type, viaImport: Tree) =
+ if (!(locals contains sym.name)) {
+ locals(sym.name) = new ScopeMember(
+ sym,
+ pre.memberType(sym),
+ context.isAccessible(sym, pre, false),
+ viaImport)
+ }
+ var cx = context
+ while (cx != NoContext) {
+ for (sym <- cx.scope)
+ addScopeMember(sym, NoPrefix, EmptyTree)
+ cx = cx.enclClass
+ val pre = cx.prefix
+ for (sym <- pre.members)
+ addScopeMember(sym, pre, EmptyTree)
+ cx = cx.outer
+ }
+ for (imp <- context.imports) {
+ val pre = imp.qual.tpe
+ for (sym <- imp.allImportedSymbols) {
+ addScopeMember(sym, pre, imp.qual)
+ }
+ }
+ locals.valuesIterator.toList
}
def getTypeCompletion(pos: Position, result: Response[List[Member]]) {
respond(result) { typeMembers(pos) }
}
- def typeMembers(pos: Position): List[Member] = {
+ def typeMembers(pos: Position): List[TypeMember] = {
val tree = typedTreeAt(pos)
+ println("typeMembers at "+tree+" "+tree.tpe)
val context = doLocateContext(pos)
val superAccess = tree.isInstanceOf[Super]
+ val scope = newScope
+ val members = new LinkedHashMap[Symbol, TypeMember]
+ def addTypeMember(sym: Symbol, pre: Type, inherited: Boolean, viaView: Symbol) {
+ val symtpe = pre.memberType(sym)
+ 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)),
+ inherited,
+ viaView)
+ }
+ }
+ def viewApply(view: SearchResult): Tree = {
+ assert(view.tree != EmptyTree)
+ try {
+ analyzer.newTyper(context.makeImplicit(false)).typed(Apply(view.tree, List(tree)) setPos tree.pos)
+ } catch {
+ case ex: TypeError => EmptyTree
+ }
+ }
val pre = stabilizedType(tree)
- def member(sym: Symbol, inherited: Boolean) = new Member(
- sym,
- pre memberType sym,
- context.isAccessible(sym, pre, superAccess),
- inherited,
- NoSymbol
- )
- def implicitMembers(s: SearchResult): List[Member] = {
- val vtree = viewApply(s, tree, context)
+ for (sym <- tree.tpe.decls)
+ addTypeMember(sym, pre, false, NoSymbol)
+ for (sym <- tree.tpe.members)
+ addTypeMember(sym, pre, true, NoSymbol)
+ val applicableViews: List[SearchResult] =
+ new ImplicitSearch(tree, functionType(List(tree.tpe), AnyClass.tpe), true, context.makeImplicit(false))
+ .allImplicits
+ for (view <- applicableViews) {
+ val vtree = viewApply(view)
val vpre = stabilizedType(vtree)
- vtree.tpe.members map { sym => new Member(
- sym,
- vpre memberType sym,
- context.isAccessible(sym, vpre, false),
- false,
- s.tree.symbol
- )}
- }
- println("typeMembers at "+tree+" "+tree.tpe)
- val decls = tree.tpe.decls.toList map (member(_, false))
- val inherited = tree.tpe.members.toList diff decls map (member(_, true))
- val implicits = applicableViews(tree, context) flatMap implicitMembers
- def isVisible(m: Member) =
- !(decls exists (_.shadows(m))) && !(inherited exists (_.shadows(m)))
- val allMembers = decls ::: inherited ::: (implicits filter isVisible)
- allMembers // filter (_.sym.name.startsWith(prefix))
- }
-
- def applicableViews(tree: Tree, context: Context): List[SearchResult] =
- new ImplicitSearch(tree, functionType(List(tree.tpe), AnyClass.tpe), true, context.makeImplicit(false))
- .allImplicits
-
- def viewApply(view: SearchResult, tree: Tree, context: Context): Tree = {
- assert(view.tree != EmptyTree)
- try {
- analyzer.newTyper(context.makeImplicit(false)).typed(Apply(view.tree, List(tree)) setPos tree.pos)
- } catch {
- case ex: TypeError => EmptyTree
+ for (sym <- vtree.tpe.members) {
+ addTypeMember(sym, vpre, false, view.tree.symbol)
+ }
}
+ members.valuesIterator.toList
}
// ---------------- Helper classes ---------------------------
diff --git a/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala b/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala
deleted file mode 100644
index 3a61095430..0000000000
--- a/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala
+++ /dev/null
@@ -1,664 +0,0 @@
-package scala.tools.nsc
-package symtab
-import scala.tools.nsc.util._
-import scala.collection.mutable._
-import scala.tools.nsc.io._
-
-trait IdeSupport extends SymbolTable { // added to global, not analyzers.
- trait ScopeClient {
- def changed : Unit = {}
- def addTo(set : => LinkedHashSet[ScopeClient]): Unit = set += this
- def notify(name : Name, scope : HookedScope) : Boolean = false
- def notify(name : Name, sym : Symbol) : Unit = {}
- def verifyAndPrioritize[T](verify : Symbol => Symbol)(pt : Type)(f : => T) : T = f
- def makeNoChanges : Boolean = false
- }
- def check(condition : Boolean, msg : => String) = {
- assert(condition)
- condition
- }
-
- import CompatibleResult._
- trait TrackedPosition extends Position with ReallyHasClients {
- // symbols without scopes!
- def asOffset : Option[(Int,AbstractFile)]
- private var recycled : List[Symbol] = Nil
- def recycle(sym : Symbol) : Symbol = {
- recycled.foreach{existing => compatible(existing,sym) match {
- case NotCompatible => false
- case GoResult(existing) => return existing
- }}
- recycled = sym :: recycled; sym
- }
- private var scopes : List[((ScopeKind,AnyRef),PersistentScope)] = Nil
- def scopeFor(key : (ScopeKind,AnyRef)) : PersistentScope =
- scopes.find{
- case (key0,scope) if key == key0 => true
- case _ => false
- } match {
- case Some((_,scope)) => reuse(scope)
- case None =>
- val scope = new PersistentScope(key,this)
- scopes = (key,scope) :: scopes
- scope
- }
- }
- // dynamic context
- private object NullClient extends ScopeClient {
- override def addTo(clients : => LinkedHashSet[ScopeClient]) = {}
- }
-
- def currentClient : ScopeClient = NullClient
- abstract class HookedScope(entry : ScopeEntry) extends Scope(entry) {
- def record(client : ScopeClient, name : Name) = {}
- override def lookupEntry(name : Name) = {
- val client = currentClient
- if (client.notify(name, this)) null // not found
- else {
- record(client, name)
- super.lookupEntry(name)
- }
- }
- }
- private val topDefs = new LinkedHashMap[AbstractFile,LinkedHashSet[ClassSymbol]] {
- override def default(what : AbstractFile) = {
- val set = new LinkedHashSet[ClassSymbol]
- this(what) = set; set
- }
- }
- private val emptySet = new ListBuffer[Symbol]
- val reuseMap = new LinkedHashMap[PersistentScope,ListBuffer[Symbol]] {
- override def default(key : PersistentScope) = emptySet
- }
- def reuse(scope : PersistentScope, sym : Symbol) = {
- var e = scope.lookupEntry(sym.name)
- var delete = List[Symbol]()
- while (e != null && e.sym != sym) {
- if (false && !e.sym.rawInfo.isComplete) {
-
- delete = e.sym :: delete
- }
- e = scope.lookupNextEntry(e)
- }
- delete.foreach(scope.unlink)
- if (e != null && e.sym == sym) {
-
- val list = reuseMap.get(scope) match {
- case Some(list) => list
- case None =>
- val list = new ListBuffer[Symbol]
- reuseMap(scope) = list; list
- }
- check(!sym.isPackage, "" +sym)
- import symtab.Flags._
- // if def is abstract, will only unlink its name
- if (sym.isGetter) {
- val setter = scope lookup nme.getterToSetter(sym.name)
- if (setter != NoSymbol && setter.isSetter) {
- list += setter
- scope unlink setter
- //Console.println("RS-UNLINK: " + setter)
- }
- } else if (sym.hasGetter) {
- e = scope lookupEntry nme.getterName(sym.name)
- while (e != null && !e.sym.isGetter && (!e.sym.hasFlag(ACCESSOR) || e.sym.accessed != sym)) {
- e = scope lookupNextEntry e
- }
- if (e != null && check(e.sym.accessed == sym, "accessed" + e.sym.accessed +" vs. " + sym) && check(!e.sym.isSetter, "setter: " + e.sym)) {
- val getter = e.sym
- check(e.sym.accessed == sym && !e.sym.isSetter, e.sym.toString)
- list += getter
- scope unlink getter
- //Console.println("RS-UNLINK: " + getter)
- e = scope lookupEntry nme.getterToSetter(getter.name)
- while (e != null && !e.sym.isSetter) e = scope lookupNextEntry e
- if (e != null) {
- check(getter.accessed == sym, "" + getter + " vs. " + sym)
- val setter = e.sym
- list += setter
- scope unlink setter
- //Console.println("RS-UNLINK: " + setter)
- }
- }
- } else if (sym.hasFlag(Flags.LAZY)) {
- val getter = sym.lazyAccessor
- if (getter != NoSymbol) {
- list += getter
- scope unlink getter
- }
- }
- //Console.println("RS-UNLINK: " + sym)
- list += sym
- scope unlink sym // clear from scope.
- }
- }
- private def reuse(scope : PersistentScope) : PersistentScope = {
- if (currentClient.makeNoChanges) return scope
- val buf = new ListBuffer[Symbol]
- scope.toList.foreach{sym =>
- if (false && sym.hasFlag(Flags.CASE) && sym.hasFlag(Flags.SYNTHETIC)) {
- check(sym != null, "")
- } else {
- buf += sym
- scope unlink sym
- }
- }
- if (!buf.isEmpty) {
-
- reuseMap.get(scope) match {
- case Some(buf0) => buf.foreach(buf0.+=)
- case None => reuseMap(scope) = buf
- }
- }
- scope
- }
-
- def reloadSource(file : AbstractFile) = {
- if (!currentClient.makeNoChanges)
- topDefs removeKey file match {
- case None => ;
- case Some(symbols) =>
- symbols.foreach{
- sym =>
- def f(sym : Symbol) = sym.owner.info.decls match {
- case scope : PersistentScope => reuse(scope, (sym))
- case scope =>
- check(false, scope + " is not persistent")
- }
- if (sym.isModuleClass) {
- if (check(sym.name.isTypeName,"") && sym.hasRawInfo)
- if (sym.linkedModuleOfClass != NoSymbol) f(sym.linkedModuleOfClass)
- } else {
- if (check(sym.name.isTypeName, ""))
- f(sym)
- }
- }
- }
- }
-
- override def attachSource(clazz : ClassSymbol, file : io.AbstractFile) = {
- topDefs(file) += clazz
- super.attachSource(clazz, file)
- }
- def finishTyping = {
- val clear = reuseMap.toList
- reuseMap.clear
- clear.foreach{
- case (scope,old) => old.foreach{
- case NoSymbol =>
- case sym =>
- // note that we didn't unlink them
- val scope0 = scope
- Console.println("RECYCLE: " + sym + ":" + sym.id + " in " + sym.owner); // + " " + scope0 + " " + scope0.key);
- scope0.invalidate(sym.name)
- }}
- reuseMap.clear
- tracedTypes.toList.foreach{case (sym,oldType) =>
- if (sym.rawInfo != NoType && !sym.rawInfo.isComplete) {
- Console.println("XXX uncompleted: " + sym)
- }
- val syminfo = try {
- sym.info
- } catch {
- case e => check(false, ""+e); NoType
- }
-
- val resetType = syminfo == NoType || hasError(syminfo)
- if (!resetType && !compareTypes(syminfo, oldType,Nil)(sym => tracedTypes.get(sym) match {
- case None => syminfo
- case Some(oldType) => oldType
- })) (trackedTypes.removeKey(sym) match {
- case Some(set) => set.foreach(_.changed)
- case None =>
- })
- if (resetType) {
-
- sym.setInfo(oldType) // restore old good type.
- }
- }
- tracedTypes.clear
- }
- def oldTypeFor(sym : Symbol) = tracedTypes.get(sym) match {
- case Some(tpe) => tpe
- case None => NoType
- }
-
- private def compare0(newP : Any, oldP : Any, syms : List[Symbol])(implicit oldType : Symbol => Type) : Boolean = ((newP,oldP) match {
- case (newP:AnyRef,oldP:AnyRef) if newP eq oldP => true
- case (newP:Type,oldP:Type) => compareTypes(newP,oldP, syms)
- case (newS:Symbol,oldS:Symbol) if compareSyms(newS,oldS,syms) => true
- case (newL:List[a],oldL:List[b]) =>
- var va = newL; var vb = oldL
- while (!va.isEmpty && !vb.isEmpty) {
- if (!compare0(va.head,vb.head,syms)) return false
- va = va.tail; vb = vb.tail
- }
- va.isEmpty && vb.isEmpty
- case (newS:Scope,oldS:Scope) =>
- val set = new LinkedHashSet[Symbol]
- set ++= newS.toList
- oldS.toList.forall{oldS => if (!set.remove(oldS)) {
- var other = newS.lookupEntry(oldS.name)
- while (other != null && !compareTypes(other.sym.info,oldType(oldS), syms))
- other = newS.lookupNextEntry(other)
- other != null
- } else true}
- case (newP,oldP) => newP == oldP
- })
- private def compareSyms(newS : Symbol, oldS : Symbol, syms : List[Symbol])(implicit oldType : Symbol => Type) =
- if (oldS eq newS) {
- if (syms.contains(oldS)) true
- else {
- compareTypes(newS.info, oldType(oldS), newS :: syms)
- }
- } else {
- if (syms.contains(oldS) && syms.contains(newS)) true
- else newS.name == oldS.name && newS.owner == oldS.owner && newS.flags == oldS.flags &&
- compareTypes(newS.info,oldType(oldS), newS :: oldS :: syms)
- }
-
- def hasError(infoA : Type) : Boolean = {
- if (infoA == ErrorType) return true
- infoA match {
- case MethodType(args,ret) => hasError(ret) || infoA.paramTypes.exists(hasError)
- case PolyType(params,ret) => hasError(ret)
- case TypeBounds(lo,hi) => hasError(lo) || hasError(hi)
- case TypeRef(pre,_,args) => hasError(pre) || args.exists(hasError)
- case _ => false
- }
- }
- def compareTypes(newInfo : Type, oldInfo : Type, syms : List[Symbol])(implicit oldType : Symbol => Type) : Boolean = (newInfo eq oldInfo) || (newInfo.getClass == oldInfo.getClass && ((newInfo,oldInfo) match {
- case (newInfo:ThisType,oldInfo:ThisType) if compare0(newInfo.typeSymbol,oldInfo.typeSymbol,syms) => true
- case (newInfo:Product, oldInfo:Product) =>
- (0 until newInfo.productArity).forall(i =>
- compare0(newInfo.productElement(i), oldInfo.productElement(i),syms))
- }))
-
- trait HasClients {
- def record(client : ScopeClient, name : Name) : Unit
- def record(client : Function1[PersistentScope,Unit]) : Unit
- def invalidate(from : PersistentScope, name : Name) : Unit
- }
-
- trait ReallyHasClients extends HasClients {
- private var clients : Map = null
- private var anyClients : LinkedHashSet[Function1[PersistentScope,Unit]] = null
- private class Map extends LinkedHashMap[Int,LinkedHashSet[ScopeClient]] {
- override def default(hash : Int) = {
- val set = new LinkedHashSet[ScopeClient]
- this(hash) = set; set
- }
- }
- def record(client : ScopeClient, name : Name) : Unit =
- client.addTo({
- if (clients eq null) clients = new Map
- clients(name.start)
- })
- def record(client : Function1[PersistentScope,Unit]) = {
- if (anyClients == null) anyClients = new LinkedHashSet[Function1[PersistentScope,Unit]]
- anyClients += client
- }
-
- override def invalidate(from : PersistentScope, name : Name) : Unit = {
- if (clients ne null) clients.removeKey(name.start) match {
- case Some(clients) => clients.foreach(_.changed)
- case None =>
- }
- if (anyClients != null) {
- var c = anyClients
- anyClients = null
- c.foreach(_.apply(from))
- }
- }
- }
-
-
- class PersistentScope(val key : AnyRef, val owner : HasClients) extends HookedScope(null) {
- override def record(client : ScopeClient, name : Name) =
- owner.record(client, name)
- override def invalidate(name : Name) : Unit = owner.invalidate(this,name)
- override def enter(symbol : Symbol) : Symbol = {
- if (currentClient.makeNoChanges) { // might have unpickles.
- return if (lookupEntry(symbol.name) == null)
- super.enter(symbol)
- else symbol
- }
- def finish(symbol : Symbol) = {
- if (symbol.isTypeSkolem) {
-
- }
- if (symbol.owner.isPackageClass && !symbol.isPackageClass && symbol.sourceFile != null) {
-
- topDefs(symbol.sourceFile) += (symbol match {
- case symbol : ClassSymbol => symbol
- case symbol : ModuleSymbol => symbol.moduleClass.asInstanceOf[ClassSymbol]
- })
- }
- super.enter(symbol)
- }
- def nuke(existing: Symbol) : Unit = {
- if (existing.isMonomorphicType) existing.resetFlag(Flags.MONOMORPHIC)
- assert(!existing.isPackage)
- existing.setAnnotations(Nil) // reset annotations, we don't look at these.
- if (existing.isModuleClass) {
- //Console.println("NUKE_N: " + existing + " " + existing.id)
- } else {
- existing.setInfo(if (symbol.hasRawInfo) symbol.rawInfo else NoType)
- }
- if (existing.isModule && existing.moduleClass != NoSymbol){
- //Console.println("NUKE_0: " + existing + " " + existing.id)
- //Console.println("NUKE_1: " + existing.moduleClass + " " + existing.moduleClass.id)
- existing.moduleClass.setInfo(if (symbol.moduleClass.hasRawInfo) symbol.moduleClass.rawInfo else NoType)
- }
- }
-
- def reuse(existing : Symbol) : Symbol = {
- def record(existing : Symbol) = if (existing.hasRawInfo &&
- existing.rawInfo.isComplete && existing.rawInfo != NoType && !hasError(existing.rawInfo)) {
- tracedTypes(existing) = existing.info
- }
- record(existing)
- nuke(existing)
- if (existing.pos == NoPosition) {
-
- }
-
- finish(existing)
- }
- val symX = lookup(symbol.name)
- if (symX != NoSymbol) {
- if (symX == symbol) return (symX)
- if (!symbol.hasRawInfo && symX.hasRawInfo && symX.rawInfo.isComplete &&
- symbol.pos.isInstanceOf[TrackedPosition] && symX.pos.isInstanceOf[TrackedPosition] &&
- symbol.pos == symX.pos) compatible(symX, symbol) match {
- case NotCompatible => // do nothing
- case code@GoResult(existing0) =>
- val existing = existing0
- if (code.isInstanceOf[Updated]) {
- invalidate(existing.name)
- }
- nuke(existing)
- return (existing)
- }
- }
- if (symbol == NoSymbol) return symbol
- // catch double defs.
- record(currentClient, symbol.name)
-
- // Martin: I changed rest of methods to avoid Iterator.remove
- val buf = reuseMap(this)
- if (buf contains symbol) {
- buf -= symbol
- finish(symbol)
- } else buf find { existing =>
- if (existing.hasFlag(symtab.Flags.SYNTHETIC) && existing.name == symbol.name) true
- else (symbol.pos,existing.pos) match {
- case (apos : TrackedPosition, bpos : TrackedPosition) => apos == bpos
- case (apos : OffsetPosition , bpos : OffsetPosition) => apos == bpos
- case _ => existing.name == symbol.name
- }
- } match {
- case Some(existing) =>
- if (check(existing != NoSymbol,"")) {
- val oldName = existing.name
- compatible(existing, symbol) match {
- case NotCompatible =>
-
- case code@GoResult(existing0) =>
- buf -= existing
- if (code.isInstanceOf[Updated]) {
- invalidate(oldName)
- invalidate(existing0.name)
- }
- return (reuse(existing0))
- }
- }
- case None =>
- }
- invalidate(symbol.name)
- return finish(symbol)
- }
- }
- private val tops = new LinkedHashMap[OffsetPosition,Symbol]
-
- protected def compatible(existing : Symbol, symbol : Symbol) : Result = {
- import scala.tools.nsc.symtab.Flags._
- if (existing.hasRawInfo && symbol.hasRawInfo) {
-
-
- }
-
-
- if (existing.getClass != symbol.getClass) (existing,symbol) match {
- case (existing:TypeSkolem,symbol:TypeSymbol) =>
- val other = existing.deSkolemize
- return if (!other.isSkolem)
- compatible(other,symbol)
- else NotCompatible
- case _ => return NotCompatible
- }
- if (existing.isGetter != symbol.isGetter) return NotCompatible
- if (existing.isSetter != symbol.isSetter) return NotCompatible
- if (existing.owner != symbol.owner) return NotCompatible
- if (existing.name != symbol.name || existing.name.length != symbol.name.length) {
- val ret = (!existing.name.toString.contains('$') &&
- !symbol.name.toString.contains('$') &&
- !(existing hasFlag SYNTHETIC) && !(symbol hasFlag SYNTHETIC) && {
- existing.name.isTypeName == symbol.name.isTypeName &&
- nme.isSetterName(existing.name) == nme.isSetterName(symbol.name) &&
- nme.isLocalName(existing.name) == nme.isLocalName(symbol.name)
- })
- if (!ret) return NotCompatible
- }
- // because module var shares space with monomorphic.
- if (existing.isModuleVar != symbol.isModuleVar) return NotCompatible
- if ((existing.flags|LOCKED|INTERFACE|MONOMORPHIC|DEFERRED|ABSTRACT|PRIVATE|PROTECTED|FINAL|SEALED|CASE|SYNTHETIC) !=
- (symbol. flags|LOCKED|INTERFACE|MONOMORPHIC|DEFERRED|ABSTRACT|PRIVATE|PROTECTED|FINAL|SEALED|CASE|SYNTHETIC)) {
- return NotCompatible
- }
- if (((existing.flags&(MONOMORPHIC|INTERFACE)) != 0) ||
- ((symbol .flags&(MONOMORPHIC|INTERFACE)) != 0)) {
-
- }
- val ret = (existing.owner == symbol.owner || {
- existing.owner.name == symbol.owner.name && // why????
- (existing.owner.name == nme.ANON_FUN_NAME||symbol.owner.name == nme.ANON_FUN_NAME) &&
- existing.owner.pos == symbol.owner.pos
- })
- if (!ret) return NotCompatible
- existing.setPos(symbol.pos) // not significant for updating purposes.
- if ((existing.privateWithin != symbol.privateWithin ||
- existing.name != symbol.name || ((existing.flags|LOCKED|MONOMORPHIC|INTERFACE) != (symbol.flags|LOCKED|MONOMORPHIC|INTERFACE)))) {
- existing.name = (symbol.name)
- // don't reset the monomorphic bit until we reset the type.
- existing.flags = symbol.flags
- existing.privateWithin = symbol.privateWithin
- return new Updated(existing)
- }
- return new Compatible(existing)
- }
- protected object CompatibleResult {
- abstract class Result {
- def map(symbol : Symbol) : Result = this
- }
- case object NotCompatible extends Result
- case class GoResult(val symbol : Symbol) extends Result {
- }
- class Compatible(override val symbol : Symbol) extends GoResult(symbol) {
- override def map(symbol : Symbol) = new Compatible(symbol)
- }
- class Updated(override val symbol : Symbol) extends GoResult(symbol) {
- override def map(symbol : Symbol) = new Updated(symbol)
- }
- }
-
- private class DefInfo extends ReallyHasClients {
- var ref : scala.ref.WeakReference[Symbol] = _
- var scopes : List[(PersistentScope)] = Nil
- def scope(kind : ScopeKind) = scopes.find(_.key == kind) match {
- case Some(scope) => scope
- case None =>
- val scope = new PersistentScope(kind,this)
- check(scope.key == kind, ""+scope.key + " " + scope.toString)
- scopes = (scope) :: scopes
- scope
- }
- }
-
- private val defMap = new WeakHashMap[Symbol,DefInfo] {
- override def default(clazz : Symbol) = {
- val ref = new scala.ref.WeakReference(clazz)
- val info = new DefInfo
- this(clazz) = info
- info.ref = ref
- info
- }
- }
- override def newClassScope(clazz : Symbol) = {
- newDefScope0({
- if (clazz.isModuleClass && !clazz.isPackageClass) {
-
- clazz
- } else if (clazz.isModule && !clazz.isPackage) {
-
- clazz.moduleClass
- } else clazz
- }, ClassKind)
- }
- private lazy val ClassKind = allocateScopeKind("class")
- private def newDefScope0(sym : Symbol, key : ScopeKind) = reuse(defMap(sym).scope(key))
-
- override def recycle(sym : Symbol) = sym.pos match {
- case pos : TrackedPosition => pos.recycle(sym)
- case _ => super.recycle(sym)
- }
- override def newLocalDummy(clazz : Symbol, pos : util.Position) =
- recycle(super.newLocalDummy(clazz,pos)).asInstanceOf[TermSymbol]
-
- def newScope(pos : Position, key : (ScopeKind,AnyRef), old : Option[Scope]) : Scope = pos match {
- case pos : TrackedPosition => pos.scopeFor(key)
- case _ if old.isEmpty => newScope(null : ScopeEntry)
- case _ => super.scopeFor(old.get, null,key._1)
- }
-
- private def scopeFor00(tree : Tree, old : Option[Scope], kind : ScopeKind) = (tree,tree.symbol) match {
- case (_,null|NoSymbol) => newScope(tree.pos, (kind,tree.getClass), (old))
- case (tree : DefTree, sym) => newDefScope0((sym),kind) // indexed by symbol
- case _ => newScope(tree.pos, (kind,tree.getClass), old)
- }
-
- override def scopeFor(old : Scope, tree : Tree, kind : ScopeKind) = scopeFor00(tree, Some(old), kind)
- override def scopeFor(tree : Tree, kind : ScopeKind) = scopeFor00(tree, None, kind)
- override def newScope(initElements : ScopeEntry) : Scope = {
- object owner extends ReallyHasClients
- new PersistentScope(null, owner)
- }
- override def newPackageScope(depends0 : PackageScopeDependMap) : PackageScope = {
- object owner extends ReallyHasClients
- object myPackageScope extends PersistentScope(null, owner) with PackageScope {
- val depends = depends0
- }
- myPackageScope
- }
-
-
- override def newTempScope : Scope = new TemporaryScope
- private class TemporaryScope extends HookedScope(null) {
- override def hashCode = toList.map(_.hashCode).foldLeft(0)(_ + _)
- override def equals(that : Any) = that match {
- case that : TemporaryScope if this eq that => true
- case that : TemporaryScope => // do a brute force comparison
- val l0 = this.toList
- val l1 = that.toList
- l0.size == l1.size && l0.forall(l1.contains)
- case _ => false
- }
- }
- private class ThrowAwayScope(decls : List[Symbol]) extends HookedScope(null:ScopeEntry) {
- decls.foreach(d => enter(d))
- }
- override def newThrowAwayScope(decls : List[Symbol]) : Scope= new ThrowAwayScope(decls)
-
- private val trackedTypes = new LinkedHashMap[Symbol,LinkedHashSet[ScopeClient]] {
- override def default(sym : Symbol) = {
- val set = new LinkedHashSet[ScopeClient]
- this(sym) = set; set
- }
- }
- // trace symbols whose types are watched!
- private val tracedTypes = new LinkedHashMap[Symbol,Type]
-
- override def trackTypeIDE(sym : Symbol): Boolean = if (sym != NoSymbol && !sym.isPackageClass && !sym.isPackage) {
- // will wind up watching a lot of stuff!
- currentClient.addTo(trackedTypes(sym))
- super.trackTypeIDE(sym)
- } else super.trackTypeIDE(sym)
- override def mkConstantType(value: Constant): ConstantType = {
- super.mkConstantType(Constant(value.value match {
- case _ : Int => 0 : Int
- case _ : Long => 0 : Long
- case _ : Byte => 0 : Byte
- case _ : Char => 0 : Char
- case _ : Short => 0 : Short
- case _ : Float => 0 : Float
- case _ : Double => 0 : Double
- case _ : String => "string"
- case _ : scala.Symbol => Symbol("symbol")
- case value => value
- }))
- }
- // mostly intellisense hacks.
- override def verifyAndPrioritize[T](verify : Symbol => Symbol)(pt : Type)(f : => T) : T = {
- try {
- currentClient.verifyAndPrioritize(verify)(pt)(f)
- } catch {case e : Error=>
- throw e
- }
- }
- override def compare(sym : Symbol, name : Name) = {
- val client = currentClient
- sym.info.decls match {
- case scope : HookedScope =>
- scope.record(client, name)
- case _ =>
- }
- client.notify(name, sym)
- super.compare(sym, name)
- }
- override def notifyImport(what : Name, container : Type, from : Name, to : Name) : Unit = {
- super.notifyImport(what, container, from, to)
- // sanity checking.
- if ((container eq null) ||
- (what eq null) ||
- (from eq null) ||
- (currentClient eq null)) return
- val from0 = if (what.isTypeName) from.toTypeName else from.toTermName
- val result = container.member(from0)
- if (result != NoSymbol)
- currentClient.notify(what, result)
- }
-
- object lightDuplicator extends Transformer {
- override val treeCopy = new StrictTreeCopier
- }
- // make the trees less detailed.
- override def sanitize(tree : Tree) : Tree = lightDuplicator.transform(tree match {
- case Template(_,vdef,_) => Template(Nil, sanitize(vdef).asInstanceOf[ValDef], Nil)
- case PackageDef(pid, _) => PackageDef(pid, Nil)
- case DefDef(mods, _, _, _, _:TypeTree, _) => DefDef(NoMods, nme.ERROR, Nil, Nil, TypeTree(), Literal(()))
- case DefDef(mods, _, _, _, restpt, _) => DefDef(NoMods, nme.ERROR, Nil, Nil, sanitize(restpt), Literal(()))
- case ValDef(_, _, _ : TypeTree, _) => ValDef(NoMods, nme.ERROR, TypeTree(), EmptyTree)
- case ValDef(_, _, restpt, _) => ValDef(NoMods, nme.ERROR, sanitize(restpt), EmptyTree)
- case ModuleDef(_, _, impl) =>
- ModuleDef(NoMods, nme.ERROR, sanitize(impl).asInstanceOf[Template])
- case ClassDef(_, _, tparams, impl) =>
- ClassDef(NoMods, nme.ERROR.toTypeName, Nil, sanitize(impl).asInstanceOf[Template])
- case DocDef(_, definition) => sanitize(definition)
- case CaseDef(x, y, z) => CaseDef(Literal(()), EmptyTree, Literal(()))
- case Block(_, _) => Block(Nil, Literal(()))
- case Function(vparams,body) =>
- Function(vparams.map(sanitize).asInstanceOf[List[ValDef]],Literal(()))
- case _ => tree
- }).setPos(tree.pos)
-
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/Scopes.scala b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
index 6170964a22..8a09d361cb 100644
--- a/src/compiler/scala/tools/nsc/symtab/Scopes.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
@@ -7,15 +7,21 @@
package scala.tools.nsc
package symtab
+// Martin: I am about 1/4 way on a cleanup of scopes.
+// The most important change is that scopes are now Iterables.
+// This removed the need for the various iterators on ScopeEntries.
+// ScopeEntries are conceptually an internal representation detail,
+// so it's better not to return them in public iterators.
+// It's true that other code also references ScopeEntries but that's
+// done for performance (and could be reviewed).
+// Another addition is a lookupAll method that returns all symbols with
+// a name in a scopein an iterator.
+// I still have to remove all the cruft about PackageScope's and the like
+// that's a leftover from the old Eclipse plugin days.
+//
trait Scopes {
self: SymbolTable =>
- def entryIterator(e: ScopeEntry): Iterator[ScopeEntry] =
- if (e == null) Iterator.empty else e.entryIterator
-
- def bucketIterator(e: ScopeEntry): Iterator[ScopeEntry] =
- if (e == null) Iterator.empty else e.bucketIterator
-
class ScopeEntry(val sym: Symbol, val owner: Scope) {
/** the next entry in the hash bucket
*/
@@ -25,19 +31,6 @@ trait Scopes {
*/
var next: ScopeEntry = null
- class ScopeEntryIterator(f: ScopeEntry => ScopeEntry) extends Iterator[ScopeEntry] {
- private var buf: ScopeEntry = ScopeEntry.this
- def hasNext = buf != null
- def next = {
- val res = buf
- buf = f(buf)
- res
- }
- }
-
- def bucketIterator: Iterator[ScopeEntry] = new ScopeEntryIterator(_.tail)
- def entryIterator: Iterator[ScopeEntry] = new ScopeEntryIterator(_.next)
-
override def hashCode(): Int = sym.name.start
override def toString(): String = sym.toString()
}
@@ -54,7 +47,11 @@ trait Scopes {
e
}
- object NoScopeEntry extends ScopeEntry(NoSymbol, null)
+ // Martin: This code contains a lot of stuff for the old Eclipse plugin.
+ // Now it's just needless complexity, which should be eleminated.
+ // We should make the elems list doubly-linked,
+ // and have scopes inherit from LinearSequence,
+ // that way, we need to do way fewer toList than before.
/**
* @param initElems ...
@@ -128,7 +125,7 @@ trait Scopes {
}
}
- abstract class Scope(initElems: ScopeEntry) {
+ abstract class Scope(initElems: ScopeEntry) extends Iterable[Symbol] {
var elems: ScopeEntry = initElems
@@ -139,9 +136,6 @@ trait Scopes {
/** the hash table
*/
private var hashtable: Array[ScopeEntry] = null
- private def hashtableIterator(index: Int): Iterator[ScopeEntry] =
- if (hashtable == null) Iterator.empty
- else bucketIterator(hashtable(index))
/** a cache for all elements, to be used by symbol iterator.
*/
@@ -186,10 +180,18 @@ trait Scopes {
/** is the scope empty? */
- def isEmpty: Boolean = elems eq null
+ override def isEmpty: Boolean = elems eq null
/** the number of entries in this scope */
- def size: Int = entryIterator(elems).length
+ override def size: Int = {
+ var s = 0
+ var e = elems
+ while (e ne null) {
+ s += 1
+ e = e.next
+ }
+ s
+ }
/** enter a scope entry
*
@@ -303,6 +305,15 @@ trait Scopes {
val e = lookupEntry(name)
if (e eq null) NoSymbol else e.sym
}
+
+ /** Returns an iterator eidling every symbol with given name in this scope.
+ */
+ def lookupAll(name: Name): Iterator[Symbol] = new Iterator[Symbol] {
+ var e = lookupEntry(name)
+ def hasNext: Boolean = e ne null
+ def next: Symbol = { val r = e.sym; e = lookupNextEntry(e); r }
+ }
+
/** Can lookup symbols and trace who the client is.
*/
def lookupEntryWithContext(name : Name)(from : Symbol) : ScopeEntry = lookupEntry(name)
@@ -345,7 +356,7 @@ trait Scopes {
/** Return all symbols as a list in the order they were entered in this scope.
*/
- def toList: List[Symbol] = {
+ override def toList: List[Symbol] = {
if (elemsCache eq null) {
elemsCache = Nil
var e = elems
@@ -361,12 +372,12 @@ trait Scopes {
*/
def iterator: Iterator[Symbol] = toList.iterator
- @deprecated("use `iterator'") def elements = iterator
+ override def foreach[U](p: Symbol => U): Unit = toList foreach p
- def filter(p: Symbol => Boolean): Scope =
+ override def filter(p: Symbol => Boolean): Scope =
if (!(toList forall p)) newScope(toList filter p) else this
- def mkString(start: String, sep: String, end: String) =
+ override def mkString(start: String, sep: String, end: String) =
toList.map(_.defString).mkString(start, sep, end)
override def toString(): String = mkString("{\n ", ";\n ", "\n}")
@@ -389,16 +400,21 @@ trait Scopes {
/** The error scope.
*/
class ErrorScope(owner: Symbol) extends Scope(null: ScopeEntry) {
+ /* The following method was intended to be here,
+ * but it was written (in two different iterations!) so that
+ * it was actually a no-op. That's why I am leaving it comment-out
+ * for now.
override def lookupEntry(name: Name): ScopeEntry = {
- def errorScope =
+ def errorSym =
if (name.isTermName) owner newErrorValue name
else owner newErrorClass name
- super.lookupEntry(name) match {
- case NoScopeEntry => enter(errorScope) ; super.lookupEntry(name)
- case e => e
+ super.lookupEntry(name) match {
+ case null => enter(errorSym); lookupEntry(name)
+ case e => e
}
}
+ */
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 42a8f3848a..8636866c52 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -65,10 +65,8 @@ abstract class ExplicitOuter extends InfoTransform
def outerAccessor(clazz: Symbol): Symbol = {
val firstTry = clazz.info.decl(clazz expandedName nme.OUTER)
if (firstTry != NoSymbol && firstTry.outerSource == clazz) firstTry
- else
- entryIterator(clazz.info.decls.elems) .
- find (_.sym.outerSource == clazz) map (_.sym) getOrElse (NoSymbol)
- }
+ else clazz.info.decls find (_.outerSource == clazz) getOrElse NoSymbol
+ }
/** <p>
* The type transformation method:
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 78b2e29048..fcb4833df7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -575,6 +575,18 @@ trait Contexts { self: Analyzer =>
result
}
+ def allImportedSymbols: List[Symbol] =
+ qual.tpe.members flatMap (transformImport(tree.selectors, _))
+
+ private def transformImport(selectors: List[(Name, Name)], sym: Symbol): List[Symbol] = selectors match {
+ case List() => List()
+ case List((nme.WILDCARD, _)) => List(sym)
+ case (from, to) :: _ if (from == sym.name) =>
+ if (to == nme.WILDCARD) List()
+ else { val sym1 = sym.cloneSymbol; sym1.name = to; List(sym1) }
+ case _ :: rest => transformImport(rest, sym)
+ }
+
override def toString() = tree.toString()
override def hashCode = tree.hashCodeStructure + depth
diff --git a/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala b/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala
deleted file mode 100644
index db48683213..0000000000
--- a/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala
+++ /dev/null
@@ -1,378 +0,0 @@
-package scala.tools.nsc
-package typechecker;
-import scala.collection.mutable.{WeakHashMap, LinkedHashSet}
-trait IdeSupport extends Analyzer {
- val global : Global with symtab.IdeSupport
- import global._
-
- private class ContextInternMap extends WeakHashMap[Context,ref.WeakReference[Context]] {
- var lastContext : Context = _
- override def default(txt : Context) : ref.WeakReference[Context] = {
- if (txt eq NoContext) new ref.WeakReference(NoContext)
- val txt0 = txt.intern0
- lastContext = txt0 // to prevent collection
- val ret = new ref.WeakReference(txt0)
- this(txt0) = ret
- ret
- }
- def intern(txt : Context) = this(txt).get.get
- }
- private val internMap = new ContextInternMap
- override def intern(txt : Context) =
- if (false) super.intern(txt)
- else if (txt.outer eq txt) txt
- else internMap.intern(txt)
-
- override def newNamer(context : Context) : Namer = new Namer(context)
- class Namer(context: Context) extends super.Namer(context) {
- override protected def setInfo[Sym <: Symbol](sym : Sym)(tpe : LazyType) : Sym = {
- assert(!sym.hasRawInfo || sym.rawInfo == NoType) // type information has already been reset.
- if (currentClient.makeNoChanges) {
- sym.setInfo(tpe)
- try {
- sym.info // force completion.
- } catch {
- case e =>
- }
- return sym
- }
- object tpe0 extends LazyType with SimpleTypeProxy {
- override def underlying = tpe
- override def complete(sym0 : Symbol) : Unit = {
- if (sym ne sym0) {
- logError("DUPLICATE: " + sym.fullNameString + " "+sym.id + " vs. " + sym0.id, null)
- toComplete -= sym0
- }
- toComplete -= sym
- val pos = sym0.pos match {
- case pos : TrackedPosition => pos
- }
- val oldType = oldTypeFor(sym0)
- oldType match {
- case PolyType(xxx,_) =>
- val i = xxx.iterator
- var pause = false
- while (i.hasNext) {
- if (i.next.pos == util.NoPosition) pause = true
- }
- if (pause) {
- assert(true)
- }
- case _=>
- }
- assert(sym0.rawInfo == this)
- val hadTypeErrors = pos.owner != null && pos.owner.hasTypeErrors
- if (pos.owner == null) underlying.complete(sym0) else pos.owner.activate(try {
- underlying.complete(sym0)
- } catch {
- case te : TypeError =>
- pos.owner.typeError(te.getMessage)
- sym0.setInfo(ErrorType)
- })
- (oldType,sym0.info) match {
- case (PolyType(xxx,_),PolyType(yyy,_)) if xxx != yyy =>
- val oldc = xxx
- val newc = yyy
- Console.print("DIFF old=" + oldc.map(sym => sym0 + ":" + sym0.pos).mkString("",",",""))
- Console.println(" new=" + newc.map(sym => sym0+ ":" + sym0.pos).mkString("",",",""))
- case _ =>
- }
-
- //if (!hadTypeErrors && pos.owner != null && pos.owner.hasTypeErrors) pos.owner.dirtyTyped
- if (pos.owner != null && pos.owner.hasTypeErrors && (!sym0.rawInfo.isComplete || sym0.info == NoType || sym0.info == ErrorType)) {
- // go back to original type.
- val oldType = oldTypeFor(sym0)
- if (oldType != NoType)
- sym0.setInfo(oldType)
- }
- }
- }
- toComplete += sym
- super.setInfo(sym)(tpe0)
- }
- override def enterSym(tree : Tree) : Context = tree match {
- case tree : StubTree =>
- if (tree.symbol == NoSymbol) // reset stub symbol on refresh.
- tree.symbol = tree.underlying.updateNamer(this)
- context
- case tree => super.enterSym(tree)
- }
- }
- override def newTyper(txt : Context) : Typer = new Typer(txt)
- class Typer(context : Context) extends super.Typer(context) {
- /* !!! Miles, do we need still this? It's broken as it is because we have to return a Symbol not a Context
- override def qualifyingClassContext(tree: Tree, qual: Name, packageOK: Boolean): Context = {
- if (qual.isEmpty) super.qualifyingClassContext(tree, qual, packageOK)
- else {
- var c = context.enclClass
- val client = currentClient
- while (c != NoContext && {
- // register dependency.
- client.notify(qual, c.owner)
- c.owner.owner.info.decls match {
- case scope : HookedScope => scope.record(client, qual)
- case _ =>
- }
- true
- } && c.owner.name != qual) c = c.outer.enclClass
- c
- }
- }
- */
- // no adapting.
- override protected def adapt(tree: Tree, mode: Int, pt: Type): Tree = super.adapt(tree,mode,pt)
- override def typed1(tree: Tree, mode: Int, pt: Type): Tree = tree match {
- case tree : StubTree =>
- if (tree.tpe == null)
- tree.tpe = tree.underlying.updateTyper(this, mode, pt)
- tree
- case tree =>
- try {
- super.typed1(tree, mode, pt)
- } catch {
- case e : TypeError => throw e
- case e : Error => global.check(false, "tree: " + tree + " " + e); throw e
- }
- }
- }
- private val toComplete = new LinkedHashSet[Symbol]
- def finishTyping = while (!toComplete.isEmpty) {
- toComplete.toList.foreach(sym => if (sym.pos match {
- case pos : TrackedPosition if !pos.isValid => toComplete.remove(sym); false
- case _ => true
- }){
- if (sym.info.isComplete) toComplete.remove(sym)
- else {
- sym.info
- if (!sym.info.isComplete) {
- Console.println("not-completing: " + sym)
- toComplete remove sym
- }
- }
- })
- }
-
- trait TrackedPosition extends global.TrackedPosition {
- def owner : MemoizedTree
- def isValid : Boolean
- }
- trait MemoizedTree {
- def kind : TreeKind
- def pos : TrackedPosition
- def typeIsDirty : Boolean
- def dirtyTyped : Unit
- def useTrees : List[Tree]
- def setUseTrees(uses : List[Tree]) : Unit
- def lastTyped : List[Tree]
- def activate(f : => Unit) : Unit
- def typeError(msg : String) : Unit
- def hasTypeErrors : Boolean
- def shouldBeTyped : Boolean = true
- // probably invalidate parent if its not being validated now
- // most type changes detected via setType.
- protected def typeChanged : Unit
- protected def highlightChanged : Unit
- def lastSymbol = if (lastTyped.isEmpty) NoSymbol else lastTyped.last.symbol
- def lastType = if (lastTyped.isEmpty) null else lastTyped.last.tpe
- protected var namerTxt : Context = NoContext
- protected var typerTxt : Context = NoContext
- protected var mode : Int = 0
- protected var pt : Type = NoType
-
- def doNamer = if (namerTxt ne NoContext) updateNamer(newNamer(namerTxt))
- def updateNamer(namer : Namer) : Symbol = {
- val makeNoChanges = currentClient.makeNoChanges
- val namerTxt = intern(namer.context)
- if (!makeNoChanges && (this.namerTxt ne namerTxt)) {
- assert(namerTxt.scope ne EmptyScope)
- assert(namerTxt.owner ne NoSymbol)
- this.namerTxt = namerTxt
- dirtyTyped
- }
- val lastSymbol = this.lastSymbol
-
- def fakeUpdate(trees : List[Tree]) : Symbol = { trees.foreach{
- case tree : DefTree if (tree.symbol != NoSymbol && tree.symbol != null) =>
- // becareful, the symbol could have been rentered!
- var e = namer.context.scope.lookupEntry(tree.symbol.name)
- while (e != null && e.sym != tree.symbol) e = namer.context.scope.lookupNextEntry(e)
- if (e == null) {
- //Console.println("FK-ENTER: " + tree.symbol)
- val sym = namer.enterInScope(tree.symbol)
- if (sym != tree.symbol) {
- Console.println("BAD: " + sym + " " + sym.id + " vs. " + tree.symbol.id)
- }
- import symtab.Flags._
- val set = reuseMap.get(namer.context.scope.asInstanceOf[PersistentScope])
- // could be getter or local, then we need to re-add getter/setter
- if (sym.isGetter && set.isDefined)
- set.get.find(sym0 => sym0.name == nme.getterToSetter(sym.name) && sym0.isSetter) match {
- case None =>
- case Some(setter) =>
- val setter0 = namer.enterInScope(setter)
- assert(setter0 == setter)
- } else if (sym.hasGetter && set.isDefined)
- set.get.find(sym0 => {
- sym0.name == nme.getterName(sym.name) &&
- sym0.isGetter
- }) match {
- case None =>
- case Some(getter) =>
- val getter0 = namer.enterInScope(getter)
- assert(getter0 == getter)
- if (set.isDefined)
- set.get.find(sym => sym.name == nme.getterToSetter(getter.name) && sym.isSetter) match {
- case None =>
- case Some(setter) =>
- val setter0 = namer.enterInScope(setter)
- assert(setter0 == setter)
- }
- } else if (sym.hasFlag(symtab.Flags.LAZY) && sym.lazyAccessor != NoSymbol) {
- if (set.get.find(sym0 => sym0 == sym.lazyAccessor).isDefined) {
- namer.enterInScope(sym.lazyAccessor)
- }
- }
- }
- case _ =>
- }; if (trees.isEmpty) NoSymbol else trees.last.symbol }
- import symtab.Flags._
- if (!typeIsDirty) lastTyped.foreach{
- case tree :DefTree if tree.symbol != null && tree.symbol != NoSymbol && tree.symbol.isClass && tree.symbol.hasFlag(CASE) =>
- var e = namer.context.scope.lookupEntry(tree.symbol.name.toTermName)
- while (e != null && !e.sym.hasFlag(MODULE)) e = namer.context.scope.lookupNextEntry(e)
- Console.println("CHECKING: " + e + " " + (if (e != null) caseClassOfModuleClass.contains(e.sym.moduleClass)))
- if (e == null) dirtyTyped
- // we don't clear caseClassOfModuleClass unless we have to.
- else if (!caseClassOfModuleClass.contains(e.sym.moduleClass)) dirtyTyped
- case tree : DefTree if tree.symbol != null && tree.symbol != NoSymbol =>
- case _ =>
- }
-
- if (makeNoChanges) {}
- else if (!typeIsDirty && !lastTyped.isEmpty)
- return fakeUpdate(lastTyped)
- else if (namerTxt != NoContext && shouldBeTyped) {} else return fakeUpdate(lastTyped)
- val use = useTrees
- if (makeNoChanges) {}
- else if (use.isEmpty || use.last.symbol != NoSymbol) {
- return fakeUpdate(use) // already named
- }
-
- if (kind.isTop) namer.context.unit.source.file match {
- case file : io.PlainFile => reloadSource(file)
- case _ =>
- }
- // before we retype, unlink/recycle our previously defined symbols.
- if (!makeNoChanges) lastTyped.foreach{tree =>
- if (tree.symbol != NoSymbol && tree.symbol != null) (namer.context.scope,tree) match {
- case (scope : PersistentScope,tree : DefTree) => if (!tree.symbol.isPackage) reuse(scope, tree.symbol)
- case _ =>
- }
- }
- activate(try {
- use.foreach{tree =>
- namer.enterSym(tree)
- }
- } catch {
- case te : TypeError => typeError(te.getMessage)
- })
- if (!makeNoChanges) use.foreach{tree=>
- if (tree.symbol != null &&
- tree.symbol.isClass &&
- tree.symbol.hasFlag(symtab.Flags.CASE) &&
- tree.symbol.owner != null &&
- tree.symbol.owner.rawInfo.isComplete) {
- var e = tree.symbol.owner.info.decls.lookupEntry(tree.symbol.name.toTermName)
- if (e != null) e.sym.pos match { // retype the object if its in the scope.
- case pos : TrackedPosition if pos.owner != null && pos.owner != MemoizedTree.this =>
- pos.owner.dirtyTyped // hope this works!
- case _ =>
- }
- ()
- }
- }
- if (makeNoChanges) {}
- else if (hasTypeErrors && lastSymbol != null && lastSymbol != NoSymbol && use.last.symbol != lastSymbol) {
- if (use.last.symbol != null && use.last.symbol != NoSymbol) {
- namer.context.scope unlink use.last.symbol
- }
- Console.println("ER-LINK: " + lastSymbol)
- val sym = namer.enterInScope(lastSymbol)
- assert(sym == lastSymbol)
- use.last.symbol = lastSymbol
- }
- if (lastSymbol != NoSymbol && lastSymbol != use.last.symbol) {
- assert(true)
- }
- use.last.symbol
- }
- def doTyper = try {
- if (typerTxt ne NoContext) updateTyper(newTyper(typerTxt), mode, pt)
- } catch {
- case e => logError("doTyper crash", e)
- }
- def updateTyper(typer : Typer, mode : Int, pt : Type) : Type = {
- val typerTxt = intern(typer.context)
- val makeNoChanges = currentClient.makeNoChanges
- if (!makeNoChanges && ((this.typerTxt ne typerTxt) || (this.pt != pt) || (this.mode != mode))) {
- this.typerTxt = typerTxt
- this.pt = pt
- this.mode = mode
- dirtyTyped
- }
- val lastType = this.lastType
- if (makeNoChanges) {}
- else if (typeIsDirty && shouldBeTyped && typerTxt != NoContext) {
-
- } else if (lastType == null) {
- return NoType
- } else return lastType
- var use = useTrees
- if (use.isEmpty) return lastType;
- if ((use.last.tpe != null)) return use.last.tpe
- if (use.last.symbol == NoSymbol && namerTxt != NoContext)
- updateNamer(newNamer(namerTxt))
- if (makeNoChanges) {
- assert(true)
- }
- activate(try {
- setUseTrees{use = use.map{typer.typed(_,mode,pt)}; use}
- } catch {
- case te : TypeError => typeError(te.getMessage)
- })
- if (!makeNoChanges && hasTypeErrors && lastType != null) {
- use.last.tpe = lastType
- }
- if (!makeNoChanges && !hasTypeErrors && use.last.tpe != null && lastType != null &&
- !compareTypes(use.last.tpe, lastType,Nil)(_.info)) {
- // the type changed in a good way.
- typeChanged
- }
- if (!makeNoChanges && (use.length != lastTyped.length || !use.zip(lastTyped).forall{
- case (t0,t1) => t0.equalsStructure0(t1){
- case (t0:StubTree,t1:StubTree) if t0.underlying == t0.underlying || true => true
- case _ => false
- }
- })) {
- highlightChanged
- }
- if (use.last.tpe == null) ErrorType else use.last.tpe
- }
- }
- trait StubTree extends global.StubTree {
- def underlying : MemoizedTree
- override var symbol : Symbol = NoSymbol
- override def duplicate : this.type = this //throw new Error("not supported")
- override def isType = underlying.kind.isType
- override def isTerm = underlying.kind.isTerm
- override def isDef = underlying.kind.isDef
- override def hasSymbol = underlying.kind.hasSymbol
- override def hashCode = underlying.hashCode
- override def equals(that : Any) = that match {
- case that : StubTree => that.underlying == underlying
- case _ => false
- }
- override def toString = "st-" + underlying.toString
- override def pos = util.NoPosition
- }
-}