summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
authorSean McDirmid <sean.mcdirmid@gmail.com>2008-01-27 13:11:26 +0000
committerSean McDirmid <sean.mcdirmid@gmail.com>2008-01-27 13:11:26 +0000
commit322c980230109582751836d1caf05836353e9cd8 (patch)
tree8cf5f6cfa8346139a530557044666cde6fa8318a /src/compiler/scala
parent2fd65e0fd34d13c355deeea982f30dce714b6528 (diff)
downloadscala-322c980230109582751836d1caf05836353e9cd8.tar.gz
scala-322c980230109582751836d1caf05836353e9cd8.tar.bz2
scala-322c980230109582751836d1caf05836353e9cd8.zip
Another massive IDE checkin.
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala24
-rw-r--r--src/compiler/scala/tools/nsc/IdeSupport.scala34
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala27
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/NewScanners.scala12
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala58
-rw-r--r--src/compiler/scala/tools/nsc/doc/ModelToXML.scala15
-rw-r--r--src/compiler/scala/tools/nsc/symtab/IdeSupport.scala590
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Scopes.scala24
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala46
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolWalker.scala221
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala38
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala19
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala31
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala337
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala49
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala63
-rw-r--r--src/compiler/scala/tools/nsc/util/Position.scala5
-rw-r--r--src/compiler/scala/tools/nsc/util/SourceFile.scala2
23 files changed, 1463 insertions, 174 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 99884f746b..4111845794 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -452,8 +452,9 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
var uncheckedWarnings: Boolean = false
private var p: Phase = firstPhase
+ protected def stopPhase(name : String) = settings.stop.contains(name)
- for (pd <- phaseDescriptors.takeWhile(pd => !(settings.stop contains pd.phaseName)))
+ for (pd <- phaseDescriptors.takeWhile(pd => !(stopPhase(pd.phaseName))))
if (!(settings.skip contains pd.phaseName)) p = pd.newPhase(p)
def cancel { reporter.cancelled = true }
@@ -495,10 +496,13 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
private var unitbuf = new ListBuffer[CompilationUnit]
private var fileset = new HashSet[AbstractFile]
- val terminalPhase : Phase =
- if (onlyPresentation) typerPhase.next.next
- else new TerminalPhase(p)
-
+ lazy val terminalPhase : Phase = {
+ //var q : Phase = firstPhase
+ //while (q != null && !stopPhase(q.name)) q = q.next
+ //if (q == null)
+ new TerminalPhase(p)
+ //else q
+ }
private def addUnit(unit: CompilationUnit) {
unitbuf += unit
fileset += unit.source.file
@@ -694,15 +698,9 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
def forCLDC: Boolean = settings.target.value == "cldc"
def forJVM : Boolean = settings.target.value startsWith "jvm"
def forMSIL: Boolean = settings.target.value == "msil"
- def onlyPresentation = settings.doc.value
-
- override def inIDE = false
+ def onlyPresentation = inIDE || settings.doc.value
private val unpickleIDEHook0 : (( => Type) => Type) = f => f
def unpickleIDEHook : (( => Type) => Type) = unpickleIDEHook0
+
def doPickleHash = false
- /* hook for IDE to detect source from class dependencies */
- def attachSourceToClass(clazz : Symbol, tpe : LazyType, sourceFile : AbstractFile) = clazz match {
- case clazz : ClassSymbol => clazz.sourceFile = sourceFile
- case _ =>
- }
}
diff --git a/src/compiler/scala/tools/nsc/IdeSupport.scala b/src/compiler/scala/tools/nsc/IdeSupport.scala
new file mode 100644
index 0000000000..deac9ffbdc
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/IdeSupport.scala
@@ -0,0 +1,34 @@
+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 = throw new Error
+ override def compileLate(file : AbstractFile) = {
+ // don't bother with any of the phase crap since adapt isn't supported
+ 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) = {
+ val run = new IdeRun
+ reloadSource(file)
+ val source = getSourceFile(file)
+ normalCompile(run.compileSources(source :: Nil))
+ run.units.find(unit => unit.source == source)
+ }
+ object loaders1 extends scala.tools.nsc.symtab.SymbolLoaders {
+ lazy val global : IdeSupport.this.type = IdeSupport.this
+ import global._
+ protected override def completeClassfile(root : global.Symbol, loader : ClassfileLoader)(f : => Unit) : Unit =
+ global.normalCompile(f)
+ }
+ override lazy val loaders = loaders1
+}
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 61b73a0d45..0ad3a5bc8a 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -177,11 +177,14 @@ trait Trees {
i += 1
}
}
- g(this.asInstanceOf[Product])
+ this match {
+ case p : Product => g(p)
+ case _ =>
+ }
hc
}
-
- def equalsStructure(that: Tree): Boolean = {
+ def equalsStructure(that : Tree) = equalsStructure0(that){case (t0,t1) => false}
+ def equalsStructure0(that: Tree)(f : (Tree,Tree) => Boolean): Boolean = {
if (this == that) return true
if (this.getClass != that.getClass) return false
val this0 = this.asInstanceOf[Product]
@@ -189,7 +192,7 @@ trait Trees {
assert(this0.productArity == that0.productArity)
def equals0(thiz: Any, that: Any): Boolean = thiz match {
case thiz: Tree =>
- thiz.equalsStructure(that.asInstanceOf[Tree])
+ f(thiz,that.asInstanceOf[Tree]) || thiz.equalsStructure0(that.asInstanceOf[Tree])(f)
case thiz: List[_] =>
val that0 = that.asInstanceOf[List[Any]]
if (thiz.length != that0.length) false
@@ -800,7 +803,7 @@ trait Trees {
extends TypTree
trait StubTree extends Tree {
- override def equalsStructure(that: Tree): Boolean = this eq that
+ override def equalsStructure0(that: Tree)(f : (Tree,Tree) => Boolean): Boolean = this eq that
}
/* A standard pattern match
case EmptyTree =>
@@ -1368,7 +1371,10 @@ trait Trees {
copy.TypeBoundsTree(tree, transform(lo), transform(hi))
case ExistentialTypeTree(tpt, whereClauses) =>
copy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses))
- case tree : StubTree => tree.duplicate
+ case tree : StubTree =>
+ tree.symbol = NoSymbol
+ tree.tpe = null
+ tree
}
def transformTrees(trees: List[Tree]): List[Tree] =
@@ -1669,5 +1675,14 @@ trait Trees {
super.traverse(tree)
}
}
+ /* hook to memoize trees in IDE */
+ trait TreeKind {
+ def isType : Boolean
+ def isTerm : Boolean
+ def isDef : Boolean
+ def hasSymbol : Boolean
+ def isTop : Boolean
+ }
+
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/NewScanners.scala b/src/compiler/scala/tools/nsc/ast/parser/NewScanners.scala
index 1afd477db3..a7c830a7b4 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/NewScanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/NewScanners.scala
@@ -130,11 +130,13 @@ trait NewScanners {
case code => code
}
// push on braces
- val pushOn = current.code match {
+ val pushOn = (current.code) match {
case LBRACE => RBRACE
case LPAREN => RPAREN
case LBRACKET => RBRACKET
- case CASE => ARROW
+ case CASE =>
+ assert(true)
+ ARROW
case RBRACE =>
while (!sepRegions.isEmpty && sepRegions.head != RBRACE)
sepRegions = sepRegions.tail
@@ -144,6 +146,9 @@ trait NewScanners {
case code @ (ARROW) if (!sepRegions.isEmpty && sepRegions.head == code) =>
sepRegions = sepRegions.tail
EMPTY
+ case ARROW =>
+ assert(true)
+ EMPTY
case code @ (RPAREN|RBRACKET) =>
if (!sepRegions.isEmpty && sepRegions.head == code)
sepRegions = sepRegions.tail
@@ -183,6 +188,7 @@ trait NewScanners {
if (headIsRBRACE && ((inLastOfStat(lastCode) && inFirstOfStat(next.code))
/* This need to be commented out, otherwise line
continuation in the interpreter will not work
+ XXX: not sure how the IDE reacts with this commented out.
|| next.code == EOF */ )) {
//if (hasNewline) current.code = NEWLINES
} else {
@@ -878,7 +884,7 @@ trait NewScanners {
}
class UnitScanner(unit: CompilationUnit) extends ParserScanner {
implicit val in =
- new DefaultInput(new NewCharArrayReader(unit.source.asInstanceOf[BatchSourceFile].content, !settings.nouescape.value, error)) {
+ new DefaultInput(new NewCharArrayReader(unit.source.content, !settings.nouescape.value, error)) {
override def error(offset : Int, msg : String) : Unit = UnitScanner.this.error(offset, msg)
override def incompleteError(offset : Int, msg : String) =
unit.incompleteInputError(new OffsetPosition(unit.source, offset), msg)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index e264b9a9cc..cd8c084f03 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1256,8 +1256,11 @@ trait Parsers extends NewScanners with MarkupParsers {
atPos(accept(CASE)) {
val pat = pattern()
val gd = guard()
- makeCaseDef(pat, gd, atPos(accept(ARROW))(block()))
+ makeCaseDef(pat, gd, caseBlock())
}
+ // IDE HOOK (so we can memoize case blocks)
+ def caseBlock(): Tree =
+ atPos(accept(ARROW))(block())
/** Guard ::= if PostfixExpr
*/
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index 7fed4c77c6..fae7800d0f 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -118,7 +118,7 @@ abstract class GenMSIL extends SubComponent {
val toDouble: MethodInfo = SystemConvert.GetMethod("ToDouble", objParam)
//val boxedUnit: FieldInfo = msilType(definitions.BoxedUnitModule.info).GetField("UNIT")
- val boxedUnit: FieldInfo = fields(definitions.BoxedUnit_UNIT)
+ val boxedUnit: FieldInfo = fields(definitions.BoxedUnit_UNIT.asInstanceOf[clrTypes.global.Symbol])
// Scala attributes
// symtab.Definitions -> object (singleton..)
@@ -438,7 +438,7 @@ abstract class GenMSIL extends SubComponent {
def writeAssembly() {
if (entryPoint != null) {
assert(entryPoint.enclClass.isModuleClass, "main-method not defined in a module")
- val mainMethod = methods(entryPoint)
+ val mainMethod = methods(entryPoint.asInstanceOf[clrTypes.global.Symbol])
val stringArrayTypes: Array[MsilType] = Array(MSTRING_ARRAY)
val globalMain = mmodule.DefineGlobalMethod(
"Main", MethodAttributes.Public | MethodAttributes.Static,
@@ -479,8 +479,8 @@ abstract class GenMSIL extends SubComponent {
private def createTypes() {
for (sym <- classes.keys) {
if (settings.debug.value)
- log("Calling CreatType for " + sym + ", " + types(sym))
- types(sym).asInstanceOf[TypeBuilder].CreateType()
+ log("Calling CreatType for " + sym + ", " + types(sym.asInstanceOf[clrTypes.global.Symbol]))
+ types(sym.asInstanceOf[clrTypes.global.Symbol]).asInstanceOf[TypeBuilder].CreateType()
}
}
@@ -560,9 +560,9 @@ abstract class GenMSIL extends SubComponent {
computeLocalVarsIndex(m)
if (m.symbol.isClassConstructor){
- mcode = constructors(m.symbol).asInstanceOf[ConstructorBuilder].GetILGenerator()
+ mcode = constructors(m.symbol.asInstanceOf[clrTypes.global.Symbol]).asInstanceOf[ConstructorBuilder].GetILGenerator()
} else {
- val mBuilder = methods(m.symbol).asInstanceOf[MethodBuilder]
+ val mBuilder = methods(m.symbol.asInstanceOf[clrTypes.global.Symbol]).asInstanceOf[MethodBuilder]
if (!mBuilder.IsAbstract())
try {
mcode = mBuilder.GetILGenerator()
@@ -1285,11 +1285,11 @@ abstract class GenMSIL extends SubComponent {
log("LOAD_FIELD with owner: " + field.owner +
" flags: " + Flags.flagsToString(field.owner.flags))
- var fieldInfo: FieldInfo = fields.get(field) match {
+ var fieldInfo: FieldInfo = fields.get(field.asInstanceOf[clrTypes.global.Symbol]) match {
case Some(fInfo) => fInfo
case None =>
val fInfo = getType(field.owner).GetField(msilName(field))
- fields(field) = fInfo
+ fields(field.asInstanceOf[clrTypes.global.Symbol]) = fInfo
fInfo
}
mcode.Emit(if (isStatic) OpCodes.Ldsfld else OpCodes.Ldfld, fieldInfo)
@@ -1348,11 +1348,11 @@ abstract class GenMSIL extends SubComponent {
mcode.Emit(OpCodes.Starg_S, 0)
case STORE_FIELD(field, isStatic) =>
- val fieldInfo: FieldInfo = fields.get(field) match {
+ val fieldInfo: FieldInfo = fields.get(field.asInstanceOf[clrTypes.global.Symbol]) match {
case Some(fInfo) => fInfo
case None =>
val fInfo = getType(field.owner).GetField(msilName(field))
- fields(field) = fInfo
+ fields(field.asInstanceOf[clrTypes.global.Symbol]) = fInfo
fInfo
}
mcode.Emit(if (isStatic) OpCodes.Stsfld else OpCodes.Stfld, fieldInfo)
@@ -1397,7 +1397,7 @@ abstract class GenMSIL extends SubComponent {
}
var doEmit: Boolean = true
- types.get(msym.owner) match {
+ types.get(msym.owner.asInstanceOf[clrTypes.global.Symbol]) match {
case Some(typ) if (typ.IsEnum) => {
def negBool = {
mcode.Emit(OpCodes.Ldc_I4_0)
@@ -1877,9 +1877,9 @@ abstract class GenMSIL extends SubComponent {
mf = mf | FieldAttributes.Static
else {
mf = mf | MethodAttributes.Virtual
- if (sym.isFinal && !types(sym.owner).IsInterface)
+ if (sym.isFinal && !types(sym.owner.asInstanceOf[clrTypes.global.Symbol]).IsInterface)
mf = mf | MethodAttributes.Final
- if (sym.hasFlag(Flags.DEFERRED) || types(sym.owner).IsInterface)
+ if (sym.hasFlag(Flags.DEFERRED) || types(sym.owner.asInstanceOf[clrTypes.global.Symbol]).IsInterface)
mf = mf | MethodAttributes.Abstract
}
}
@@ -1977,7 +1977,7 @@ abstract class GenMSIL extends SubComponent {
sym.tpe.paramTypes.map(msilType).toArray
}
- def getType(sym: Symbol): MsilType = types.get(sym) match {
+ def getType(sym: Symbol): MsilType = types.get(sym.asInstanceOf[clrTypes.global.Symbol]) match {
case Some(typ) => typ
case None =>
val name = if (sym.isModuleClass && !sym.isTrait) sym.fullNameString + "$"
@@ -1986,27 +1986,27 @@ abstract class GenMSIL extends SubComponent {
if (typ == null)
throw new Error(showsym(sym) + " with name " + name)
else {
- clrTypes.types(sym) = typ
+ clrTypes.types(sym.asInstanceOf[clrTypes.global.Symbol]) = typ
typ
}
}
def mapType(sym: Symbol, mType: MsilType) {
assert(mType != null, showsym(sym))
- types(sym) = mType
+ types(sym.asInstanceOf[clrTypes.global.Symbol]) = mType
}
def createTypeBuilder(iclass: IClass) {
def getMsilType(tpe: Type): MsilType = {
val sym = tpe.typeSymbol
- types.get(sym) match {
+ types.get(sym.asInstanceOf[clrTypes.global.Symbol]) match {
case Some(mtype) => mtype
- case None => createTypeBuilder(classes(sym)); types(sym)
+ case None => createTypeBuilder(classes(sym)); types(sym.asInstanceOf[clrTypes.global.Symbol])
}
}
val sym = iclass.symbol
- if (types contains sym) return
+ if (types contains sym.asInstanceOf[clrTypes.global.Symbol]) return
def isInterface(s: Symbol) = s.isTrait && !s.isImplClass
val parents: List[Type] =
@@ -2054,7 +2054,7 @@ abstract class GenMSIL extends SubComponent {
var attributes = msilFieldFlags(sym)
val fBuilder = mtype.DefineField(msilName(sym), msilType(sym.tpe), attributes)
- fields(sym) = fBuilder
+ fields(sym.asInstanceOf[clrTypes.global.Symbol]) = fBuilder
addAttributes(fBuilder, sym.attributes)
}
@@ -2085,7 +2085,7 @@ abstract class GenMSIL extends SubComponent {
for (i <- 0.until(paramTypes.length)){
method.DefineParameter(i, ParameterAttributes.None, msilName(m.params(i).sym))
}
- if (!methods.contains(sym))
+ if (!methods.contains(sym.asInstanceOf[clrTypes.global.Symbol]))
mapMethod(sym, method)
addAttributes(method, sym.attributes)
if (settings.debug.value)
@@ -2126,7 +2126,7 @@ abstract class GenMSIL extends SubComponent {
(FieldAttributes.Public |
//FieldAttributes.InitOnly |
FieldAttributes.Static).toShort)
- fields(sym) = fb
+ fields(sym.asInstanceOf[clrTypes.global.Symbol]) = fb
}
@@ -2141,14 +2141,14 @@ abstract class GenMSIL extends SubComponent {
// TODO: get module field for modules not defined in the
// source currently compiling (e.g. Console)
- fields get moduleClassSym match {
+ fields get moduleClassSym.asInstanceOf[clrTypes.global.Symbol] match {
case Some(sym) => sym
case None =>
//val mclass = types(moduleClassSym)
val mClass = clrTypes.getType(moduleClassSym.fullNameString + "$")
val mfield = mClass.GetField("MODULE$")
assert(mfield ne null, "module not found " + showsym(moduleClassSym))
- fields(moduleClassSym) = mfield
+ fields(moduleClassSym.asInstanceOf[clrTypes.global.Symbol]) = mfield
mfield
}
@@ -2165,7 +2165,7 @@ abstract class GenMSIL extends SubComponent {
val sicode = staticInit.GetILGenerator()
- val instanceConstructor = constructors(sym.primaryConstructor)
+ val instanceConstructor = constructors(sym.primaryConstructor.asInstanceOf[clrTypes.global.Symbol])
sicode.Emit(OpCodes.Newobj, instanceConstructor)
// the stsfld is done in the instance constructor, just after the super call.
@@ -2311,7 +2311,7 @@ abstract class GenMSIL extends SubComponent {
// #####################################################################
// get and create methods / constructors
- def getConstructor(sym: Symbol): ConstructorInfo = constructors.get(sym) match {
+ def getConstructor(sym: Symbol): ConstructorInfo = constructors.get(sym.asInstanceOf[clrTypes.global.Symbol]) match {
case Some(constr) => constr
case None =>
val mClass = getType(sym.owner)
@@ -2328,7 +2328,7 @@ abstract class GenMSIL extends SubComponent {
}
def mapConstructor(sym: Symbol, cInfo: ConstructorInfo) = {
- constructors(sym) = cInfo
+ constructors(sym.asInstanceOf[clrTypes.global.Symbol]) = cInfo
}
private def getMethod(sym: Symbol): MethodInfo = {
@@ -2343,7 +2343,7 @@ abstract class GenMSIL extends SubComponent {
// case SRToShort => toShort
// case _ =>
- methods.get(sym) match {
+ methods.get(sym.asInstanceOf[clrTypes.global.Symbol]) match {
case Some(method) => method
case None =>
val mClass = getType(sym.owner)
@@ -2374,7 +2374,7 @@ abstract class GenMSIL extends SubComponent {
*/
private def mapMethod(sym: Symbol, mInfo: MethodInfo) {
assert (mInfo != null, mInfo)
- methods(sym) = mInfo
+ methods(sym.asInstanceOf[clrTypes.global.Symbol]) = mInfo
}
/*
diff --git a/src/compiler/scala/tools/nsc/doc/ModelToXML.scala b/src/compiler/scala/tools/nsc/doc/ModelToXML.scala
index 8874a36b7a..d14a391069 100644
--- a/src/compiler/scala/tools/nsc/doc/ModelToXML.scala
+++ b/src/compiler/scala/tools/nsc/doc/ModelToXML.scala
@@ -73,6 +73,9 @@ trait ModelToXML extends ModelExtractor {
else parents;
parents1.mkXML(Text(""), <code> with </code>, Text(""))(link);
case _ =>
+ if (tpe.typeSymbol == NoSymbol) {
+ throw new Error(tpe + " has no type class " + tpe.getClass)
+ }
link(decode(tpe.typeSymbol))
}
}
@@ -81,7 +84,7 @@ trait ModelToXML extends ModelExtractor {
if (what.isEmpty) Text("")
else Text(before) ++ f(what.get) ++ Text(after)
- def bodyFor(entity: Entity)(implicit frame: Frame): NodeSeq = {
+ def bodyFor(entity: Entity)(implicit frame: Frame): NodeSeq = try {
var seq = {entity.typeParams.surround("[", "]")(e => {
Text(e.variance) ++ <em>{e.name}</em> ++
{printIf(e.hi, " <: ", "")(link)} ++
@@ -95,12 +98,18 @@ trait ModelToXML extends ModelExtractor {
if (str.length == 0) NodeSeq.Empty
else <code>{Text(str)} </code>
} ++
- <em>{arg.name}</em> ++
- Text(" : ") ++ link(arg.resultType.get)
+ <em>{arg.name}</em> ++ (try {
+
+ Text(" : ") ++ link(arg.resultType.get)
+ } catch {
+ case e : Throwable => System.err.println("ARG " + arg + " in " + entity); throw e
+ })
);
seq
})};
seq ++ {printIf(entity.resultType, " : ", "")(tpe => link(tpe))}
+ } catch {
+ case e => System.err.println("generating for " + entity); throw e
}
def extendsFor(entity: Entity)(implicit frame: Frame): NodeSeq = {
diff --git a/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala b/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala
new file mode 100644
index 0000000000..a9d4e90098
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala
@@ -0,0 +1,590 @@
+package scala.tools.nsc.symtab
+import scala.tools.nsc.util._
+import scala.collection.jcl._
+import scala.collection.jcl
+import scala.tools.nsc.io._
+
+trait IdeSupport extends SymbolTable { // added to global, not analyzers.
+ trait ScopeClient {
+ def changed : Unit = {}
+ def addTo(set : => LinkedHashSet[ScopeClient]) = 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
+ }
+
+ override def inIDE = true
+ 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 jcl.LinkedList[Symbol]
+ val reuseMap = new LinkedHashMap[PersistentScope,jcl.LinkedList[Symbol]] {
+ override def default(key : PersistentScope) = emptySet
+ }
+ def reuse(scope : PersistentScope, sym : Symbol) = {
+ var e = scope.lookupEntry(sym.name)
+ while (e != null && e.sym != sym) e = scope.lookupNextEntry(e)
+ if (e != null && e.sym == sym) {
+ assert(true)
+ val list = reuseMap.get(scope) match {
+ case Some(list) => list
+ case None =>
+ val list = new jcl.LinkedList[Symbol]
+ reuseMap(scope) = list; list
+ }
+ assert(!sym.isPackage)
+ import symtab.Flags._
+ if (sym.isClass && sym.hasFlag(CASE)) {
+ // grab the case factory
+ val name = sym.name.toTermName
+ e = scope.lookupEntry(name)
+ while (e != null && !e.sym.hasFlag(CASE)) e = scope.lookupNextEntry(e)
+ assert(e != null)
+ list += e.sym
+ scope unlink e.sym
+ //Console.println("RS-UNLINK: " + factory)
+ }
+ // 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 = scope lookupNextEntry e
+ if (e != null) {
+ val getter = e.sym
+ assert(getter.accessed == sym && !getter.isSetter)
+ 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) {
+ assert(getter.accessed == sym)
+ val setter = e.sym
+ list += setter
+ scope unlink setter
+ //Console.println("RS-UNLINK: " + setter)
+ }
+ }
+ }
+ //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 jcl.LinkedList[Symbol]
+ buf addAll scope.toList
+ buf.foreach(sym => assert(!sym.isPackage))
+ scope.clear
+ if (!buf.isEmpty) {
+ assert(true)
+ reuseMap(scope) = buf
+ }
+ scope
+ }
+
+ // TODO: implement a good compile late for the IDE.
+ def reloadSource(file : AbstractFile) = {
+ assert(true)
+ 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))
+ }
+ if (sym.isModuleClass) {
+ assert(sym.name.isTypeName)
+ if (sym.rawInfoSafe.isDefined)
+ if (sym.linkedModuleOfClass != NoSymbol) f(sym.linkedModuleOfClass)
+ } else {
+ assert(sym.name.isTypeName)
+ f(sym)
+ }
+ }
+ }
+ }
+ override def attachSource(clazz : ClassSymbol, file : io.AbstractFile) = {
+ topDefs(file) += clazz
+ super.attachSource(clazz, file)
+ }
+ def finishTyping = {
+ reuseMap.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.foreach{case (sym,oldType) =>
+ if (sym.rawInfo != NoType && !sym.rawInfo.isComplete) {
+ Console.println("XXX uncompleted: " + sym)
+ }
+ val resetType = sym.info == NoType || hasError(sym.info)
+ if (!resetType && !compareTypes(sym.info, oldType,Nil)(sym => tracedTypes.get(sym) match {
+ case None => sym.info
+ case Some(oldType) => oldType
+ })) (trackedTypes.removeKey(sym) match {
+ case Some(set) => set.foreach(_.changed)
+ case None =>
+ })
+ if (resetType) {
+ assert(true)
+ 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 addAll 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) || args.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 invalidate(name : Name) : Unit
+ }
+
+ trait ReallyHasClients extends HasClients {
+ private var clients : Map = 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)
+ })
+ override def invalidate(name : Name) : Unit = if (clients ne null) clients.removeKey(name.start) match {
+ case Some(clients) => clients.foreach(_.changed)
+ case None =>
+ }
+ }
+
+
+ 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(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) {
+ assert(true)
+ assert(true)
+ }
+ if (symbol.owner.isPackageClass && !symbol.isPackageClass && symbol.sourceFile != null) {
+ assert(true)
+ assert(true)
+ topDefs(symbol.sourceFile) += (symbol match {
+ case symbol : ClassSymbol => symbol
+ case symbol : ModuleSymbol => symbol.moduleClass.asInstanceOf[ClassSymbol]
+ })
+ }
+ super.enter(symbol)
+ }
+ def reuse(existing : Symbol) : Symbol = {
+ def record(existing : Symbol) = if (existing.rawInfoSafe.isDefined &&
+ existing.rawInfo.isComplete && existing.rawInfo != NoType && !hasError(existing.rawInfo)) {
+ tracedTypes(existing) = existing.info
+ }
+ def f(existing: Symbol, other : Symbol) : Unit = {
+ if (existing.isMonomorphicType) existing.resetFlag(Flags.MONOMORPHIC)
+ assert(!existing.isPackage)
+ existing.attributes = Nil // reset attributes, we don't look at these.
+ existing.setInfo(other.rawInfoSafe match {
+ case Some(info) =>
+ assert(true)
+ assert(true)
+ info
+ case _ => NoType
+ })
+ if (existing.isModule && existing.moduleClass != NoSymbol)
+ f(existing.moduleClass,symbol.moduleClass)
+ }
+ record(existing)
+ f(existing,symbol)
+ if (existing.pos == NoPosition) {
+ assert(true)
+ assert(true)
+ }
+
+ finish(existing)
+ }
+
+ assert(symbol != NoSymbol)
+ // catch double defs.
+ record(currentClient, symbol.name)
+ val i = reuseMap(this).elements
+ while (i.hasNext) {
+ var existing = i.next
+ if (existing == symbol) return {
+ assert(true)
+ i.remove
+ finish(existing)
+ }
+ else if ({
+ (symbol.pos,existing.pos) match {
+ case (apos : TrackedPosition, bpos : TrackedPosition) => apos == bpos
+ case (apos : OffsetPosition , bpos : OffsetPosition) => apos == bpos
+ case _ => existing.name == symbol.name
+ }
+ }) {
+ assert(existing != NoSymbol)
+ val oldName = existing.name
+ compatible(existing, symbol) match {
+ case NotCompatible =>
+ assert(true)
+ assert(true)
+ case code@GoResult(existing0) =>
+ i.remove
+ existing = existing0
+ if (code.isInstanceOf[Updated]) {
+ invalidate(oldName)
+ invalidate(existing.name)
+ }
+ return (reuse(existing))
+ }
+ }
+ }
+ if (true) {
+ assert(true)
+ //Console.println("NEW SYMBOL: " + symbol + ":" + symbol.id + " @ " + symbol.owner + " " + key);
+ }
+ 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.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|MONOMORPHIC|DEFERRED|ABSTRACT|PRIVATE|PROTECTED|FINAL|SEALED|CASE) !=
+ (symbol. flags|MONOMORPHIC|DEFERRED|ABSTRACT|PRIVATE|PROTECTED|FINAL|SEALED|CASE)) {
+ return NotCompatible
+ }
+ if (((existing.flags&(MONOMORPHIC|INTERFACE)) != 0) ||
+ ((symbol .flags&(MONOMORPHIC|INTERFACE)) != 0)) {
+ assert(true)
+ assert(true)
+ }
+ 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|MONOMORPHIC) != (symbol.flags|MONOMORPHIC)))) {
+ existing.name = (symbol.name)
+ // don't reset the monomorphic bit until we reset the type.
+ existing.flags = symbol.flags | (existing.flags&MONOMORPHIC)
+ 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)
+ assert(scope.key == kind)
+ 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) {
+ assert(true)
+ clazz
+ } else if (clazz.isModule && !clazz.isPackage) {
+ assert(true)
+ 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 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
+ case value => value
+ }))
+ }
+ // mostly intellisense hacks.
+ override def verifyAndPrioritize[T](verify : Symbol => Symbol)(pt : Type)(f : => T) : T = {
+ currentClient.verifyAndPrioritize(verify)(pt)(f)
+ }
+ 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)
+ 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 copy = 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(nme, _) => PackageDef(nme, 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)
+
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/symtab/Scopes.scala b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
index 817cebff77..afcb9ecfe0 100644
--- a/src/compiler/scala/tools/nsc/symtab/Scopes.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
@@ -42,10 +42,28 @@ trait Scopes {
*/
def newScope(initElems: ScopeEntry): Scope = new NormalScope(initElems)
final def newScope: Scope = newScope(null: ScopeEntry)
- def newClassScope(clazz : Symbol) = newScope // for use in ClassInfoType creation
def newTempScope = newScope(null : ScopeEntry)
- def scopeFor( tree : Tree) : Scope = newScope
- def scopeFor(old : Scope, tree : Tree) : Scope = newScope(old)
+ class ScopeKind(name : String) { override def toString = name }
+ def allocateScopeKind(name : String) = new ScopeKind(name)
+ lazy val Constructor0ScopeKind : ScopeKind = allocateScopeKind("constructors0")
+ lazy val Constructor1ScopeKind : ScopeKind = allocateScopeKind("constructors1")
+ lazy val InnerScopeKind : ScopeKind = allocateScopeKind("inner")
+ lazy val FinishWithScopeKind : ScopeKind = allocateScopeKind("finishWith")
+ lazy val TypeSigScopeKind : ScopeKind = allocateScopeKind("typeSig")
+ lazy val PolyTypeCompleterScopeKind : ScopeKind = allocateScopeKind("polyType")
+ lazy val CompoundTreeScopeKind : ScopeKind = allocateScopeKind("compoundTree")
+ lazy val FreshArgScopeKind : ScopeKind = allocateScopeKind("freshArgs")
+ lazy val LabelScopeKind : ScopeKind = allocateScopeKind("label")
+ lazy val TypedCasesScopeKind : ScopeKind = allocateScopeKind("typedCases")
+ lazy val TypedDefScopeKind : ScopeKind = allocateScopeKind("typedDef")
+ lazy val ParentTypesScopeKind : ScopeKind = allocateScopeKind("parentType")
+ lazy val TypedScopeKind : ScopeKind = allocateScopeKind("typed")
+ // have to sometimes use constructor depth unfortunately.
+ case class BlockScopeKind(depth : Int) extends ScopeKind("block") { override def toString = super.toString + "-" + depth }
+
+ def newClassScope(clazz : Symbol) = newScope // for use in ClassInfoType creation
+ def scopeFor( tree : Tree, kind : ScopeKind) : Scope = newScope
+ def scopeFor(old : Scope, tree : Tree, kind : ScopeKind) : Scope = newScope(old)
final def newScope(base: Scope) : Scope = newScope(base.elems)
final def newScope(decls: List[Symbol]) : Scope = {
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 80279b0c4c..116c2c3b24 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -47,7 +47,33 @@ abstract class SymbolLoaders {
def sourceFile: AbstractFile = null
protected def sourceString: String
- override def complete(root: Symbol) {
+ override def complete(root: Symbol) : Unit = {
+ if (inIDE && root.owner != NoSymbol) {
+ assert(root.rawInfo == this)
+ if (root.isModuleClass) {
+ val clazz = root.sourceModule.linkedClassOfModule
+ assert(root.rawInfo == this)
+ if (clazz != NoSymbol && !clazz.rawInfo.isInstanceOf[SymbolLoader]) {
+ // bail
+ assert(true)
+ root.setInfo(ErrorType)
+ Console.println("ditch " + root)
+ return
+ }
+ } else if (root.isClass) {
+ val module = root.linkedModuleOfClass
+ assert(root.rawInfo == this)
+ if (module != NoSymbol && !module.rawInfo.isInstanceOf[SymbolLoader]) {
+ assert(true)
+ root.setInfo(ErrorType)
+ Console.println("ditch " + root)
+ return
+ }
+ } else {
+ assert(root.isModule)
+ assert(true)
+ }
+ }
try {
val start = currentTime
val currentphase = phase
@@ -112,13 +138,13 @@ abstract class SymbolLoaders {
val owner = if (root.isRoot) definitions.EmptyPackageClass else root
val className = newTermName(name)
assert(owner.info.decls.lookup(name) == NoSymbol, owner.fullNameString + "." + name)
- val clazz = owner.newClass(NoPosition, name.toTypeName)
- val module = owner.newModule(NoPosition, name)
+ var clazz = owner.newClass(NoPosition, name.toTypeName)
+ var module = owner.newModule(NoPosition, name)
clazz setInfo completer
module setInfo completer
module.moduleClass setInfo moduleClassLoader
- owner.info.decls enter clazz
- owner.info.decls enter module
+ clazz = (owner.info.decls enter clazz).asInstanceOf[ClassSymbol]
+ module = (owner.info.decls enter module).asInstanceOf[ModuleSymbol]
assert(clazz.linkedModuleOfClass == module, module)
assert(module.linkedClassOfModule == clazz, clazz)
clazz
@@ -243,7 +269,7 @@ abstract class SymbolLoaders {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
}
protected def doComplete(root: Symbol) {
- typeParser.parse(typ, root) // don't check this
+ typeParser.parse(typ, root.asInstanceOf[typeParser.global.loaders.clrTypes.global.Symbol]) // don't check this
}
protected def kindString: String = typ.FullName
protected def sourceString = typ.Assembly.FullName
@@ -267,12 +293,16 @@ abstract class SymbolLoaders {
}
root match {
case clazz: ClassSymbol =>
- global.attachSourceToClass(clazz, this, if (sourceFile ne null) sourceFile else clazz.sourceFile)
+ if ((sourceFile ne null) && (clazz.sourceFile eq null))
+ clazz.sourceFile = sourceFile
case module: ModuleSymbol if module.moduleClass.isInstanceOf[ClassSymbol] =>
val clazz = module.moduleClass.asInstanceOf[ClassSymbol]
- global.attachSourceToClass(module, this, if (sourceFile ne null) sourceFile else clazz.sourceFile)
+ if ((sourceFile ne null) && (clazz.sourceFile eq null))
+ clazz.sourceFile = sourceFile
case _ =>
}
+ if (root.sourceFile ne null)
+ prepareReset(root, this)
}
protected def kindString: String = "class file"
protected def sourceString = classFile.toString()
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index 568938619c..1e3dd8aaa9 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -44,6 +44,12 @@ abstract class SymbolTable extends Names
}
def notifyImport(what : Name, container : Type, from : Name, to : Name) : Unit = {}
def sanitize(tree : Tree) : Tree = tree
+ def attachSource(symbol : ClassSymbol, file : io.AbstractFile) : Unit = {
+ assert(symbol != null)
+ }
+ def prepareReset(symbol : Symbol, tpe : LazyType) : Unit = {
+ assert(symbol != null)
+ }
/** A period is an ordinal number for a phase in a run.
* Phases in later runs have higher periods than phases in earlier runs.
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolWalker.scala b/src/compiler/scala/tools/nsc/symtab/SymbolWalker.scala
new file mode 100644
index 0000000000..e7cf3a20bd
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolWalker.scala
@@ -0,0 +1,221 @@
+package scala.tools.nsc.symtab
+
+trait SymbolWalker {
+ val global : Global
+ import scala.tools.nsc.util._
+ import global._
+ import scala.collection.jcl._
+ trait Visitor {
+ def update(pos : Position, sym : Symbol) : Unit
+ def contains(pos : Position) : Boolean
+ def apply(pos : Position) : Symbol
+ def putDef(sym : Symbol, pos : Position) : Unit = ()
+ }
+ import scala.collection.mutable.Map
+ /*
+ implicit def map2use(map : Map[Position,Symbol]) = new Visitor {
+ def update(pos : Position, sym : Symbol) : Unit = map.update(pos, sym)
+ def contains(pos : Position) : Boolean = map.contains(pos)
+ def apply(pos : Position) : Symbol = map.apply(pos)
+ }
+ */
+ def walk(tree: Tree, visitor : Visitor)(fid : (util.Position) => Option[String]) : Unit = {
+ val visited = new LinkedHashSet[Tree]
+ def f(t : Tree) : Unit = {
+ if (!visited.add(t)) return
+ def fs(l : List[Tree]) : Unit = {
+ val i = l.elements
+ while (i.hasNext) f(i.next)
+ }
+ def fss(l : List[List[Tree]]) : Unit = {
+ val i = l.elements
+ while (i.hasNext) fs(i.next)
+ }
+ if (t.isInstanceOf[StubTree]) return
+ def asTypeRef = t.tpe.asInstanceOf[TypeRef]
+ val sym = (t,t.tpe) match {
+ case (Super(_,_),SuperType(_,supertp)) if supertp.typeSymbol != NoSymbol && supertp.typeSymbol != null => supertp.typeSymbol
+ case _ if t.symbol != NoSymbol && t.symbol != null => t.symbol
+ case (t : TypeTree, tp) if tp != null && tp.typeSymbol != null && tp.typeSymbol != NoSymbol => tp.typeSymbol
+ case (t : TypeTree, tp) if tp != null && tp.resultType != null && tp.resultType.typeSymbol != null => tp.resultType.typeSymbol
+ case (t, tpe : Type) if tpe != null && (t.symbol eq NoSymbol) && t.isTerm && tpe.termSymbol != null =>
+ assert(true)
+ tpe.termSymbol
+ case (t, tpe : Type) if tpe != null && (t.symbol eq NoSymbol) && tpe.typeSymbol != null =>
+ if (t.tpe.isInstanceOf[TypeRef]) asTypeRef.sym // XXX: looks like a bug
+ else tpe.typeSymbol
+ case _ => NoSymbol
+ }
+ if (sym != null && sym != NoSymbol /* && !sym.hasFlag(SYNTHETIC) */) {
+ var id = fid(t.pos)
+ val doAdd = if (id.isDefined) {
+ if (id.get.charAt(0) == '`') id = Some(id.get.substring(1, id.get.length - 1))
+ val name = sym.name.decode.trim
+ if ((name startsWith id.get) || (id.get startsWith name)) true
+ else {
+ assert(true)
+ assert(true)
+ false
+ }
+ } else false
+ if (doAdd) {
+
+ if (!visitor.contains(t.pos)) {
+ visitor(t.pos) = sym
+ } else {
+ val existing = visitor(t.pos)
+ if (sym.sourceFile != existing.sourceFile || sym.pos != existing.pos) {
+ (sym,existing) match {
+ case (sym,existing) if sym.pos == existing.pos =>
+ case (sym : TypeSymbol ,_ : ClassSymbol) => visitor(t.pos) = sym
+ case (_ : ClassSymbol,_ : TypeSymbol) => // nothing
+ case _ if sym.isModule && existing.isValue => // nothing
+ case _ if sym.isClass && existing.isMethod => // nothing
+ case _ =>
+ assert(true)
+ }
+ }
+ }}
+ }
+ assert(true)
+ t match {
+ case t : DefTree if t.symbol != NoSymbol =>
+ if (t.pos != NoPosition)
+ visitor.putDef(t.symbol, t.pos)
+ if (t.symbol.isClass) {
+ val factory = NoSymbol // XXX: t.symbol.caseFactory
+ if (factory != NoSymbol) {
+ assert(true)
+ visitor.putDef(factory, t.pos)
+ }
+ }
+ case t : TypeBoundsTree => f(t.lo); f(t.hi)
+ case t : TypeTree if t.original != null =>
+ def h(original : Tree, tpe : Type): Unit = try {
+ if (original.tpe == null)
+ original.tpe = tpe
+ (original) match {
+ case (AppliedTypeTree(_,trees)) if tpe.isInstanceOf[TypeRef] =>
+ val types = tpe.asInstanceOf[TypeRef].args
+ trees.zip(types).foreach{
+ case (tree,tpe) => assert(tree != null && tpe != null); h(tree, tpe)
+ }
+ case _ =>
+ }
+ }
+ if (t.original.tpe == null) {
+ val dup = t.original.duplicate
+ h(dup,t.tpe)
+ f(dup)
+ } else f(t.original)
+ ()
+ case _ =>
+ }
+ (t) match {
+ case (t : MemberDef) if t.symbol != null && t.symbol != NoSymbol =>
+ val annotated = if (sym.isModule) sym.moduleClass else sym
+ val i = t.mods.annotations.elements
+ val j = annotated.attributes.elements
+ while (i.hasNext && j.hasNext) {
+ val tree = i.next.constr
+ val ainfo = j.next
+ val sym = ainfo.atp.typeSymbol
+ tree.setType(ainfo.atp)
+ tree.setSymbol(sym)
+ f(tree)
+ }
+
+ case _ =>
+ }
+ t match {
+ case tree: ImplDef =>
+ fs(tree.impl.parents); f(tree.impl.self); fs(tree.impl.body)
+ tree match {
+ case tree : ClassDef => fs(tree.tparams)
+ case _ =>
+ }
+ case tree: PackageDef => fs(tree.stats)
+ case tree: ValOrDefDef =>
+ f(tree.rhs);
+ if (tree.tpt != null) {
+ assert(true)
+ f(tree.tpt)
+ }
+ tree match {
+ case tree : DefDef => fs(tree.tparams); fss(tree.vparamss)
+ case _ =>
+ }
+ case tree: Function => fs(tree.vparams); f(tree.body)
+ case tree : Bind => f(tree.body)
+ case tree : Select =>
+ val qualifier = if (tree.tpe != null && tree.qualifier.tpe == null) {
+ val pre = tree.tpe.prefix
+ val qualifier = tree.qualifier.duplicate
+ qualifier.tpe = pre
+ qualifier
+ } else tree.qualifier
+
+ f(qualifier)
+ case tree : Annotation => f(tree.constr)
+ case tree : Annotated => f(tree.annot); f(tree.arg)
+ case tree : GenericApply => f(tree.fun); fs(tree.args)
+ case tree : UnApply => f(tree.fun); fs(tree.args)
+ case tree : AppliedTypeTree =>
+ if (tree.tpe != null) {
+ val i = tree.tpe.typeArgs.elements
+ val j = tree.args.elements
+ while (i.hasNext && j.hasNext) {
+ val tpe = i.next
+ val arg = j.next
+ if (arg.tpe == null) {
+ arg.tpe = tpe
+ }
+ }
+ }
+ f(tree.tpt); fs(tree.args)
+ case tree : SingletonTypeTree =>
+ if (tree.ref.tpe == null) {
+ val dup = tree.ref.duplicate
+ dup.tpe = tree.tpe
+ f(dup)
+ } else f(tree.ref)
+ case tree : CompoundTypeTree => f(tree.templ)
+ case tree : Template => fs(tree.parents); f(tree.self); fs(tree.body)
+ case tree : SelectFromTypeTree => {
+ if (tree.qualifier.tpe == null) tree.tpe match {
+ case tpe : TypeRef =>
+ // give it a type!
+ tree.qualifier.tpe = tpe.prefix
+ case _ =>
+ // tree.tpe.pre
+ }
+ f(tree.qualifier)
+ }
+ case tree : Literal =>
+ if (tree.tpe != null && tree.tpe.typeSymbol == definitions.ClassClass) {
+ // nothing we can do without original tree.
+ }
+
+ case tree : Typed => f(tree.expr); f(tree.tpt)
+ case tree : Block => fs(tree.stats); f(tree.expr)
+ case tree: CaseDef => f(tree.pat);f(tree.guard);f(tree.body)
+ case tree : Sequence => fs(tree.trees);
+ case tree : Assign => f(tree.lhs); f(tree.rhs);
+ case tree : If => f(tree.cond); f(tree.thenp); f(tree.elsep);
+ case tree : New => f(tree.tpt);
+ case tree : Match => f(tree.selector); fs(tree.cases);
+ case tree : Return => f(tree.expr);
+ case tree : LabelDef => f(tree.rhs);
+ case tree : Throw => f(tree.expr);
+ case tree : Try => f(tree.block); fs(tree.catches); f(tree.finalizer);
+ case tree : Alternative => fs(tree.trees);
+ case tree : TypeDef => f(tree.rhs); fs(tree.tparams)
+ case tree : DocDef => f(tree.definition);
+ case tree: Import => f(tree.expr)
+ case _ =>
+ }
+ }
+ f(tree)
+ }
+
+}
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 35440ec24a..2083eccc0a 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -479,7 +479,10 @@ trait Symbols {
cnt += 1
// allow for two completions:
// one: sourceCompleter to LazyType, two: LazyType to completed type
- if (cnt == 3) throw new Error("no progress in completing " + this + ":" + tp)
+ if (cnt == 3) {
+ assert(true)
+ throw new Error("no progress in completing " + this + ":" + tp)
+ }
}
val result = rawInfo
result
@@ -488,6 +491,10 @@ trait Symbols {
/** Set initial info. */
def setInfo(info: Type): this.type = {
assert(info ne null)
+ if (name.toString == "Either") {
+ assert(true)
+ assert(true)
+ }
infos = TypeHistory(currentPeriod, info, null)
if (info.isComplete) {
rawflags = rawflags & ~LOCKED
@@ -701,7 +708,7 @@ trait Symbols {
if (inIDE && (this eq result) && result != NoSymbol && (result hasFlag OVERLOADED)) {
return result
}
- assert(!(result hasFlag OVERLOADED), result.alternatives)
+ if (!inIDE) assert(!(result hasFlag OVERLOADED), result.alternatives)
result
}
@@ -1085,6 +1092,9 @@ trait Symbols {
final def fullNameString: String = fullNameString('.')
+
+
+
/** If settings.uniqid is set, the symbol's id, else "" */
final def idString: String =
if (settings.uniqid.value) "#"+id else ""
@@ -1110,7 +1120,9 @@ trait Symbols {
" in " + owner else ""
/** String representation of symbol's definition following its name */
- final def infoString(tp: Type): String = {
+ final def infoString(tp: Option[Type]): String = tp match {
+ case None => "<_>"
+ case Some(tp) =>
def typeParamsString: String = tp match {
case PolyType(tparams, _) if (tparams.length != 0) =>
(tparams map (_.defString)).mkString("[", ",", "]")
@@ -1132,13 +1144,13 @@ trait Symbols {
}
}
else if (isModule)
- moduleClass.infoString(tp)
+ moduleClass.infoString(Some(tp))
else
tp match {
case PolyType(tparams, res) =>
- typeParamsString + infoString(res)
+ typeParamsString + infoString(Some(res))
case MethodType(pts, res) =>
- pts.mkString("(", ",", ")") + infoString(res)
+ pts.mkString("(", ",", ")") + infoString(Some(res))
case _ =>
": " + tp
}
@@ -1157,7 +1169,7 @@ trait Symbols {
val f = if (settings.debug.value) flags
else if (owner.isRefinementClass) flags & ExplicitFlags & ~OVERRIDE
else flags & ExplicitFlags
- compose(List(flagsToString(f), keyString, varianceString + nameString + infoString(rawInfo)))
+ compose(List(flagsToString(f), keyString, varianceString + nameString + infoString(rawInfoSafe)))
}
/** Concatenate strings separated by spaces */
@@ -1305,9 +1317,12 @@ trait Symbols {
override def setInfo(tp: Type): this.type = {
tpePeriod = NoPeriod
tyconCache = null
- if (tp.isComplete)
+ if (tp.isComplete && tp != NoType)
if (tp.isInstanceOf[PolyType]) resetFlag(MONOMORPHIC)
- else if (!tp.isInstanceOf[AnnotatedType]) setFlag(MONOMORPHIC)
+ else if (!tp.isInstanceOf[AnnotatedType]) {
+ assert(true)
+ setFlag(MONOMORPHIC)
+ }
super.setInfo(tp)
this
}
@@ -1360,6 +1375,7 @@ trait Symbols {
if (owner.isPackageClass) source else super.sourceFile
override def sourceFile_=(f: AbstractFile) {
//System.err.println("set source file of " + this + ": " + f);
+ attachSource(this, f)
source = f
}
override def isFromClassFile = {
@@ -1484,6 +1500,10 @@ trait Symbols {
def cloneSymbols(syms: List[Symbol]): List[Symbol] = {
val syms1 = syms map (_.cloneSymbol)
for (sym1 <- syms1) sym1.setInfo(sym1.info.substSym(syms, syms1))
+ if (inIDE) {
+ assert(true)
+ assert(true)
+ }
syms1
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 1886c40af1..460a7a1f46 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -423,7 +423,6 @@ trait Types {
case tp =>
// if (sym.name.toString == "c") print(this + ".memberType(" + sym +":" + sym.tpe +")" + sym.ownerChain);//debug
val res = tp.asSeenFrom(this, sym.owner)
-// if (sym.name.toString == "c") println(" = "+res)
res
}
}
@@ -437,8 +436,8 @@ trait Types {
/** Substitute symbols `to' for occurrences of symbols
* `from' in this type.
*/
- def substSym(from: List[Symbol], to: List[Symbol]): Type =
- new SubstSymMap(from, to) apply this
+ def substSym(from: List[Symbol], to: List[Symbol]): Type = if (from eq to) this
+ else new SubstSymMap(from, to) apply this
/** Substitute all occurrences of `ThisType(from)' in this type
* by `to'.
@@ -3510,7 +3509,10 @@ A type's typeSymbol should never be inspected directly.
case (SingleType(_, _), ThisType(_)) => tp1 =:= tp2
case (SingleType(_, _), SingleType(_, _)) => tp1 =:= tp2
case (ConstantType(_), ConstantType(_)) => tp1 =:= tp2
-
+ case (TypeRef(pre1, sym1:TypeSkolem, args1), TypeRef(pre2, sym2:TypeSkolem, args2)) if {
+ inIDE && args1 == args2 && pre1 == pre2 &&
+ sym1.deSkolemize == sym2.deSkolemize
+ } => true
case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2))
if !(tp1.isHigherKinded || tp2.isHigherKinded) =>
//Console.println("isSubType " + tp1 + " " + tp2);//DEBUG
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 53ffc61361..5bff9d070f 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -329,7 +329,11 @@ abstract class ClassfileParser {
val c = pool.getClassSymbol(in.nextChar)
if (c != clazz) {
assert(true)
- if (inIDE) {
+ if ((clazz eq NoSymbol) && (c ne NoSymbol)) { // XXX: needed for build compiler, so can't protect with inIDE
+ assert(true)
+ clazz = c
+ } else if (inIDE) {
+ assert(true)
Console.println("WRONG CLASS: expected: " + clazz + " found " + c)
} else throw new IOException("class file '" + in.file + "' contains wrong " + c)
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index 5fdd2ac7a2..a607408720 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -76,10 +76,16 @@ abstract class UnPickler {
}
/** The `decls' scope associated with given symbol */
- private def symScope(sym: Symbol)(f : => Scope) = symScopes.get(sym) match {
- case None => val s = f; symScopes(sym) = s; s
+ private def symScope(sym: Symbol, isTemp : Boolean) = symScopes.get(sym) match {
+ case None =>
+ val s = if (isTemp) newTempScope
+ else if (sym.isClass || sym.isModuleClass || sym.isModule) newClassScope(sym);
+ else newScope
+
+ symScopes(sym) = s; s
case Some(s) => s
}
+ private def symScope(sym : Symbol) : Scope = symScope(sym, false)
/** Does entry represent an (internal) symbol */
private def isSymbolEntry(i: Int): Boolean = {
@@ -223,7 +229,7 @@ abstract class UnPickler {
else new LazyTypeRef(inforef))
if (sym.owner.isClass && sym != classRoot && sym != moduleRoot &&
!sym.isModuleClass && !sym.isRefinementClass && !sym.isTypeParameter)
- symScope(sym.owner)(newScope) enter sym
+ symScope(sym.owner) enter sym
}
sym
}
@@ -254,12 +260,12 @@ abstract class UnPickler {
val dcls = symScope(clazz)
new RefinedType(ps, dcls) { override def symbol = clazz }
*/
- new RefinedType(until(end, readTypeRef), symScope(clazz)(newTempScope)) {
+ new RefinedType(until(end, readTypeRef), symScope(clazz, true)) {
override def typeSymbol = clazz
}
case CLASSINFOtpe =>
val clazz = readSymbolRef()
- ClassInfoType(until(end, readTypeRef), symScope(clazz)(newClassScope(clazz)), clazz)
+ ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz)
case METHODtpe =>
val restpe = readTypeRef()
MethodType(until(end, readTypeRef), restpe)
@@ -761,7 +767,8 @@ abstract class UnPickler {
private val definedAtRunId = currentRunId
// In IDE, captures class files dependencies so they can be reloaded when their dependencies change.
private val ideHook = unpickleIDEHook
- override def complete(sym: Symbol) {
+ override def complete(sym: Symbol) : Unit = {
+ if (sym.rawInfo != this && inIDE) return
val tp = ideHook(at(i, readType))
sym setInfo tp
if (!inIDE && currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index c80c9ecf82..82cbbb30ab 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -84,9 +84,6 @@ trait Contexts { self: Analyzer =>
sc = sc.outer
}
}
- // IDE hooks
- protected def sanitize(tree: Tree): Tree = tree
- protected def scopeFor(old: Scope, tree: Tree): Scope = newScope(old)
class Context private[typechecker] {
var unit: CompilationUnit = _
var tree: Tree = _ // Tree associated with this context
@@ -193,7 +190,7 @@ trait Contexts { self: Analyzer =>
}
if (ret) {
if (!a17) {
- assert(this.implicitsCache == null || that.implicitsCache == null)
+ //assert(this.implicitsCache == null || that.implicitsCache == null)
}
}
ret
@@ -279,8 +276,10 @@ trait Contexts { self: Analyzer =>
make(unit, tree, owner, scope, imports)
}
- def makeNewScope(tree: Tree, owner: Symbol): Context =
- make(tree, owner, scopeFor(scope, tree))
+
+ def makeNewScope(tree: Tree, owner: Symbol)(implicit kind : ScopeKind): Context =
+ make(tree, owner, scopeFor(scope, tree, kind))
+ // IDE stuff: distinguish between scopes created for typing and scopes created for naming.
def make(tree: Tree, owner: Symbol): Context =
make0(tree, owner, scope)
@@ -306,7 +305,7 @@ trait Contexts { self: Analyzer =>
//todo: find out why we need next line
while (baseContext.tree.isInstanceOf[Template])
baseContext = baseContext.outer
- val argContext = baseContext.makeNewScope(tree, owner)
+ val argContext = baseContext.makeNewScope(tree, owner)(Constructor0ScopeKind)
argContext.reportGeneralErrors = this.reportGeneralErrors
argContext.reportAmbiguousErrors = this.reportAmbiguousErrors
def enterElems(c: Context) {
@@ -521,6 +520,7 @@ trait Contexts { self: Analyzer =>
if (outer.tree.isInstanceOf[Template]) outer.outer.outer
else outer.outer
} else outer
+ // can we can do something smarter to bring back the implicit cache?
if (implicitsRunId != currentRunId) {
implicitsRunId = currentRunId
implicitsCache = List()
@@ -569,7 +569,6 @@ trait Contexts { self: Analyzer =>
}
}
- def notifyImport(what : Name, container : Type, from : Name, to : Name) : Unit = {}
class ImportInfo(val tree: Import, val depth: Int) {
/** The prefix expression */
def qual: Tree = tree.symbol.info match {
@@ -634,22 +633,6 @@ trait Contexts { self: Analyzer =>
}
override def hashCode = if (inIDE) expr.hashCodeStructure else expr.hashCode
}
-
- /* APIs for interning contexts */
- import scala.collection.jcl
- import scala.ref
protected def intern(txt : Context) = txt
- class ContextInternMap extends jcl.WeakHashMap[Context,ref.WeakReference[Context]] {
- var last : Context = _
- override def default(txt : Context) : ref.WeakReference[Context] = {
- if (txt eq NoContext) new ref.WeakReference(NoContext)
- val txt0 = txt.intern0
- last = txt0 // to prevent collection
- val ret = new ref.WeakReference(txt0)
- this(txt0) = ret
- ret
- }
- def intern(txt : Context) = this(txt).get.get
- }
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
index 28d33ad2e7..7b705036ac 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -40,21 +40,18 @@ trait EtaExpansion { self: Analyzer =>
var cnt = 0 // for NoPosition
def freshName(pos : util.Position, n : Int) = {
cnt += 1
- if (pos == util.NoPosition) {
- if (inIDE) newTermName( ("eta$" + symbolHash + (cnt - 1)))
- else newTermName(unit.fresh.newName("eta$" + symbolHash + (cnt - 1)))
-/*
- } else if (n == 0) {
- newTermName(unit.fresh.newName(pos, "etaC$" + symbolHash))
-*/
- } else {
+ if (!inIDE) {
+ newTermName(unit.fresh.newName(pos, "eta$" + (cnt - 1) + "$"))
+ } else if (pos == util.NoPosition) {
+ // nothing we can do, hope for no conflict!
+ newTermName(("eta$" + symbolHash + (cnt - 1)))
+ } else
newTermName(unit.fresh.newName(pos, "eta$" + symbolHash + (cnt - 1) + "$"))
// Martin to Sean: I removed the
// else if (n == 0) branch and changed `n' in the line above to `(cnt - 1)'
// this was necessary because otherwise curried eta-expansions would get the same
// symbol. An example which failes test/files/run/Course-2002-02.scala
// todo: review and get rid of the `n' argument (which is unused right now).
- }
}
// { cnt = cnt + 1; newTermName("eta$" + cnt) }
val defs = new ListBuffer[Tree]
diff --git a/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala b/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala
new file mode 100644
index 0000000000..c2e0bd3b67
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala
@@ -0,0 +1,337 @@
+package scala.tools.nsc.typechecker;
+import scala.collection.jcl.WeakHashMap
+trait IdeSupport extends Analyzer {
+ val global : Global with symtab.IdeSupport
+ import global._
+
+ private class ContextInternMap extends WeakHashMap[Context,ref.WeakReference[Context]] {
+ var last : Context = _
+ override def default(txt : Context) : ref.WeakReference[Context] = {
+ if (txt eq NoContext) new ref.WeakReference(NoContext)
+ val txt0 = txt.intern0
+ last = 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.rawInfoSafe.isDefined || sym.rawInfo == NoType) // type information has already been reset.
+ if (currentClient.makeNoChanges) {
+ sym.setInfo(tpe)
+ sym.info // force completion.
+ return sym
+ }
+ object tpe0 extends LazyType with SimpleTypeProxy {
+ override def underlying = tpe
+ override def complete(sym0 : Symbol) : Unit = {
+ assert(sym eq sym0)
+ toComplete -= sym
+ val pos = sym.pos match {
+ case pos : TrackedPosition => pos
+ }
+ val oldType = oldTypeFor(sym0)
+ oldType match {
+ case PolyType(xxx,_) =>
+ val i = xxx.elements
+ var pause = false
+ while (i.hasNext) {
+ if (i.next.pos == util.NoPosition) pause = true
+ }
+ if (pause) {
+ assert(true)
+ assert(true)
+ }
+ case _=>
+ }
+ assert(sym.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 => sym + ":" + sym.pos).mkString("",",",""))
+ Console.println(" new=" + newc.map(sym => sym + ":" + sym.pos).mkString("",",",""))
+ case _ =>
+ }
+
+ if (!hadTypeErrors && pos.owner != null && pos.owner.hasTypeErrors) pos.owner.dirtyTyped
+ if (pos.owner != null && pos.owner.hasTypeErrors) {
+ // 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) {
+ override def qualifyingClassContext(tree: Tree, qual: Name): Context = {
+ if (qual.isEmpty) super.qualifyingClassContext(tree, qual)
+ 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 => super.typed1(tree, mode, pt)
+ }
+ }
+ private val toComplete = new scala.collection.jcl.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) {
+ assert(true)
+ assert(true)
+ Console.println("SCREWED: " + sym + " vs. " + tree.symbol)
+ }
+ import symtab.Flags._
+ val set = reuseMap.get(namer.context.scope.asInstanceOf[PersistentScope])
+ if (set.isDefined && sym.isClass && sym.hasFlag(CASE)) {
+ val name = sym.name.toTermName
+ val factory = set.get.find(_.name == name).get
+ val sym0 = namer.enterInScope(factory)
+ assert(sym0 == factory)
+ }
+ // 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(sym => sym.name == nme.getterName(sym.name) && sym.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)
+ }
+ }
+ }
+ case _ =>
+ }; if (trees.isEmpty) NoSymbol else trees.last.symbol }
+
+ 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 =>
+ if (tree.isInstanceOf[DefTree]) {
+ assert(true)
+ //Console.println("RENAME: " + tree)
+ }
+ namer.enterSym(tree)
+ }
+ } catch {
+ case te : TypeError => typeError(te.getMessage)
+ })
+ 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
+ }
+ use.last.symbol
+ }
+ def doTyper = if (typerTxt ne NoContext) updateTyper(newTyper(typerTxt), mode, pt)
+ def updateTyper(typer : Typer, mode : Int, pt : Type) : Type = {
+ assert(true)
+
+ 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) {
+ assert(true)
+ assert(true)
+ 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)
+ 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
+ }
+ }) {
+ assert(true)
+ 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 = 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
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 4f6d1682ad..0bb30f7b3e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -92,7 +92,7 @@ trait Namers { self: Analyzer =>
private var innerNamerCache: Namer = null
protected def makeConstructorScope(classContext : Context) : Context = {
val outerContext = classContext.outer.outer
- outerContext.makeNewScope(outerContext.tree, outerContext.owner)
+ outerContext.makeNewScope(outerContext.tree, outerContext.owner)(Constructor1ScopeKind)
}
def namerOf(sym: Symbol): Namer = {
@@ -101,7 +101,7 @@ trait Namers { self: Analyzer =>
if (innerNamerCache eq null)
innerNamerCache =
if (!isTemplateContext(context)) this
- else newNamer(context.make(context.tree, context.owner, scopeFor(context.tree)))
+ else newNamer(context.make(context.tree, context.owner, scopeFor(context.tree, InnerScopeKind)))
innerNamerCache
}
@@ -145,11 +145,32 @@ trait Namers { self: Analyzer =>
def enterInScope(sym: Symbol): Symbol = {
// allow for overloaded methods
if (!(sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass)) {
- val prev = context.scope.lookupEntry(sym.name);
- if ((prev ne null) && prev.owner == context.scope && conflict(sym, prev.sym)) {
+ var prev = context.scope.lookupEntry(sym.name);
+ if ((prev ne null) && inIDE) {
+ var guess = prev
+ while ((guess ne null) && (guess.sym ne sym)) guess = context.scope.lookupNextEntry(guess)
+ if (guess != null) prev = guess
+ while (prev != null && (prev.sym.rawInfoSafe.isEmpty || !prev.sym.rawInfo.isComplete ||
+ (prev.sym.sourceFile == null && sym.getClass == prev.sym.getClass))) {
+ if (prev.sym.rawInfo.isComplete) {
+ Console.println("DITCHING: " + prev.sym)
+ }
+ context.scope unlink prev.sym
+ prev = context.scope.lookupNextEntry(prev)
+ }
+ val sym0 = context.scope enter sym
+ if (sym0 ne sym) {
+ assert(true)
+ Console.println("WEIRD: " + sym0)
+ }
+ if (prev != null && (sym0 ne prev.sym) && conflict(sym0,prev.sym)) {
+ doubleDefError(sym0.pos, prev.sym)
+ }
+ sym0
+ } else if ((prev ne null) && prev.owner == context.scope && conflict(sym, prev.sym)) {
doubleDefError(sym.pos, prev.sym)
- if (!inIDE) sym setInfo ErrorType // don't do this in IDE for stability
- if (!inIDE) context.scope unlink prev.sym // let them co-exist...
+ sym setInfo ErrorType // don't do this in IDE for stability
+ context.scope unlink prev.sym // let them co-exist...
context.scope enter sym
} else context.scope enter sym
} else context.scope enter sym
@@ -258,12 +279,7 @@ trait Namers { self: Analyzer =>
else applicableTypeParams(owner.owner) ::: owner.typeParams
def deSkolemize: TypeMap = new DeSkolemizeMap(applicableTypeParams(context.owner))
-
- def reuse[T <: Tree](tree: T) = if (!inIDE) tree else {
- val tree0 = tree.duplicate
- //tree0.symbol = tree.symbol
- tree0
- }
+ // should be special path for IDE but maybe not....
def enterSym(tree: Tree): Context = {
@@ -276,7 +292,7 @@ trait Namers { self: Analyzer =>
//@M e.g., in [A[x <: B], B], A and B are entered first as both are in scope in the definition of x
//@M x is only in scope in `A[x <: B]'
if(!sym.isAbstractType) //@M TODO: change to isTypeMember ?
- newNamer(context.makeNewScope(tree, sym)).enterSyms(tparams)
+ newNamer(context.makeNewScope(tree, sym)(FinishWithScopeKind)).enterSyms(tparams)
ltype = new PolyTypeCompleter(tparams, ltype, tree, sym, context) //@M
if (sym.isTerm) skolemize(tparams)
}
@@ -304,9 +320,7 @@ trait Namers { self: Analyzer =>
}
case tree @ ModuleDef(mods, name, _) =>
tree.symbol = enterModuleSymbol(tree)
- // IDE: do not use the setInfo call for the module class as it is initialized
- // through module symbol
- tree.symbol.moduleClass.setInfo(namerOf(tree.symbol).moduleClassTypeCompleter(reuse(tree)))
+ tree.symbol.moduleClass.setInfo(namerOf(tree.symbol).moduleClassTypeCompleter((tree)))
finish
case ValDef(mods, name, tp, rhs) =>
@@ -781,6 +795,7 @@ trait Namers { self: Analyzer =>
}
case _ =>
}
+ implicit val scopeKind = TypeSigScopeKind
val result =
try {
tree match {
@@ -979,7 +994,7 @@ trait Namers { self: Analyzer =>
override val tree = restp.tree
override def complete(sym: Symbol) {
if(ownerSym.isAbstractType) //@M an abstract type's type parameters are entered -- TODO: change to isTypeMember ?
- newNamer(ctx.makeNewScope(owner, ownerSym)).enterSyms(tparams) //@M
+ newNamer(ctx.makeNewScope(owner, ownerSym)(PolyTypeCompleterScopeKind)).enterSyms(tparams) //@M
restp.complete(sym)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 240bc297cb..dfafb8abe0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -58,16 +58,7 @@ trait Typers { self: Analyzer =>
// IDE hooks
def newTyper(context: Context): Typer = new NormalTyper(context)
private class NormalTyper(context : Context) extends Typer(context)
- def scopeFor(tree : Tree) : Scope = newScope
- def newLocalDummy(clazz : Symbol, pos : Position) = clazz.newLocalDummy(pos)
- def recycle(sym : Symbol) : Symbol = sym
// hooks for auto completion
- def compare(sym : Symbol, name : Name) = sym.name == name
- def verifyAndPrioritize[T](g : Symbol => Symbol)(pt : Type)(f : => T) = f
- def trackSetInfo[T <: Symbol](sym : T)(info : Type) : T = {
- sym.setInfo(info)
- sym
- }
/** when in 1.4 mode the compiler accepts and ignores useless
* type parameters of Java generics
@@ -425,17 +416,14 @@ trait Typers { self: Analyzer =>
}
}
- def reenterValueParams(vparamss: List[List[ValDef]]) {
- for (vparams <- vparamss; vparam <- vparams)
- context.scope enter vparam.symbol
+ def reenterValueParams(vparamss: List[List[ValDef]]): Unit = {
+ for (vparams <- vparamss) for (vparam <- vparams)
+ vparam.symbol = context.scope enter vparam.symbol
}
def reenterTypeParams(tparams: List[TypeDef]): List[Symbol] =
for (tparam <- tparams) yield {
- val rawInfo = tparam.symbol.rawInfo
tparam.symbol = context.scope enter tparam.symbol
- // hack, because the skolems are reused.
- if (inIDE) tparam.symbol.setInfo(rawInfo)
tparam.symbol.deSkolemize
}
@@ -469,7 +457,7 @@ trait Typers { self: Analyzer =>
*/
def labelTyper(ldef: LabelDef): Typer =
if (ldef.symbol == NoSymbol) { // labeldef is part of template
- val typer1 = newTyper(context.makeNewScope(ldef, context.owner))
+ val typer1 = newTyper(context.makeNewScope(ldef, context.owner)(LabelScopeKind))
typer1.enterLabelDef(ldef)
typer1
} else this
@@ -902,8 +890,8 @@ trait Typers { self: Analyzer =>
}
val outercontext = context.outer
- val cbody2 =
- newTyper(outercontext.makeNewScope(constr, outercontext.owner))
+ val cbody2 = // called both during completion AND typing.
+ newTyper(outercontext.makeNewScope(constr, outercontext.owner)(ParentTypesScopeKind))
.typePrimaryConstrBody(clazz,
cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (_.map(_.duplicate)))
@@ -1024,7 +1012,7 @@ trait Typers { self: Analyzer =>
assert(clazz != NoSymbol)
reenterTypeParams(cdef.tparams)
val tparams1 = List.mapConserve(cdef.tparams)(typedTypeDef)
- val impl1 = newTyper(context.make(cdef.impl, clazz, scopeFor(cdef.impl)))
+ val impl1 = newTyper(context.make(cdef.impl, clazz, scopeFor(cdef.impl, TypedDefScopeKind)))
.typedTemplate(cdef.impl, parentTypes(cdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
if ((clazz != ClassfileAnnotationClass) &&
@@ -1048,7 +1036,7 @@ trait Typers { self: Analyzer =>
val clazz = mdef.symbol.moduleClass
if (inIDE && clazz == NoSymbol) throw new TypeError("bad signature")
assert(clazz != NoSymbol)
- val impl1 = newTyper(context.make(mdef.impl, clazz, scopeFor(mdef.impl)))
+ val impl1 = newTyper(context.make(mdef.impl, clazz, scopeFor(mdef.impl, TypedDefScopeKind)))
.typedTemplate(mdef.impl, parentTypes(mdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
@@ -1143,9 +1131,7 @@ trait Typers { self: Analyzer =>
else clazz.typeOfThis
// the following is necessary for templates generated later
assert(clazz.info.decls != EmptyScope)
- // XXX: let namer in typeSig be definitive, duplicate to ensure typer context doesn't stick.
- val templBody = if (inIDE) templ.body.map(_.duplicate : Tree) else templ.body
- enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templBody)
+ enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templ.body)
validateParentClasses(parents1, selfType)
if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members
checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType])
@@ -1367,6 +1353,10 @@ trait Typers { self: Analyzer =>
block.stats foreach enterLabelDef
val stats1 = typedStats(block.stats, context.owner)
val expr1 = typed(block.expr, mode & ~(FUNmode | QUALmode), pt)
+ if (expr1.tpe == null) {
+ assert(true)
+ assert(true)
+ }
val block1 = copy.Block(block, stats1, expr1)
.setType(if (treeInfo.isPureExpr(block)) expr1.tpe else expr1.tpe.deconst)
//checkNoEscaping.locals(context.scope, pt, block1)
@@ -1402,7 +1392,7 @@ trait Typers { self: Analyzer =>
def typedCases(tree: Tree, cases: List[CaseDef], pattp0: Type, pt: Type): List[CaseDef] = {
var pattp = pattp0
List.mapConserve(cases) ( cdef =>
- newTyper(context.makeNewScope(cdef, context.owner)).typedCase(cdef, pattp, pt))
+ newTyper(context.makeNewScope(cdef, context.owner)(TypedCasesScopeKind)).typedCase(cdef, pattp, pt))
/* not yet!
cdef.pat match {
case Literal(Constant(null)) =>
@@ -1457,7 +1447,7 @@ trait Typers { self: Analyzer =>
if (context.retyping) context.scope enter vparam.symbol
vparam.symbol
}
- // XXX: here to for IDE hooks.
+
val vparams = List.mapConserve(fun.vparams)(typedValDef)
// for (val vparam <- vparams) {
// checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); ()
@@ -1687,9 +1677,8 @@ trait Typers { self: Analyzer =>
else {
if (settings.debug.value) log("infer method inst "+fun+", tparams = "+tparams+", args = "+args2.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info));//debug
val undetparams = inferMethodInstance(fun, tparams, args2, pt)
- val result = if (!inIDE) doTypedApply(tree, fun, args2, mode, pt)
- else doTypedApply(tree.duplicate,fun.duplicate,args2.map(_.duplicate),mode,pt)
- context.undetparams = undetparams
+ val result = doTypedApply(tree, fun, args2, mode, pt)
+ context.undetparams = undetparams
result
}
}
@@ -1728,7 +1717,7 @@ trait Typers { self: Analyzer =>
(ErrorType, List())
}
val (unappFormal, freeVars) = freshArgType(unappType)
- val context1 = context.makeNewScope(context.tree, context.owner)
+ val context1 = context.makeNewScope(context.tree, context.owner)(FreshArgScopeKind)
freeVars foreach(sym => context1.scope.enter(sym))
val typer1 = newTyper(context1)
arg.tpe = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
@@ -1872,7 +1861,7 @@ trait Typers { self: Analyzer =>
def annotArg(tree: Tree): AnnotationArgument = {
val arg = new AnnotationArgument(tree)
- if(needsConstant && !arg.isConstant)
+ if(needsConstant && !arg.isConstant && !inIDE)
needConst(tree)
arg
}
@@ -2836,7 +2825,7 @@ trait Typers { self: Analyzer =>
val parents1 = List.mapConserve(templ.parents)(typedType)
if (parents1 exists (_.tpe.isError)) tree setType ErrorType
else {
- val decls = scopeFor(tree)
+ val decls = scopeFor(tree, CompoundTreeScopeKind)
val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls)
newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ.body)
tree setType self
@@ -2889,6 +2878,7 @@ trait Typers { self: Analyzer =>
}
// begin typed1
+ implicit val scopeKind = TypedScopeKind
val sym: Symbol = tree.symbol
if (sym ne null) sym.initialize
//if (settings.debug.value && tree.isDef) log("typing definition of "+sym);//DEBUG
@@ -2932,7 +2922,7 @@ trait Typers { self: Analyzer =>
typedAnnotated(annot, typed(arg, mode, pt))
case tree @ Block(_, _) =>
- newTyper(context.makeNewScope(tree, context.owner))
+ newTyper(context.makeNewScope(tree, context.owner)(BlockScopeKind(context.depth)))
.typedBlock(tree, mode, pt)
case Sequence(elems) =>
@@ -3129,7 +3119,6 @@ trait Typers { self: Analyzer =>
val lo1 = typedType(lo)
val hi1 = typedType(hi)
copy.TypeBoundsTree(tree, lo1, hi1) setType mkTypeBounds(lo1.tpe, hi1.tpe)
-
case etpt @ ExistentialTypeTree(_, _) =>
newTyper(context.makeNewScope(tree, context.owner)).typedExistentialTypeTree(etpt)
@@ -3176,7 +3165,7 @@ trait Typers { self: Analyzer =>
tree1.tpe = addAnnotations(tree1, tree1.tpe)
- val result = if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt)
+ val result = if (tree1.isEmpty || (inIDE && tree1.tpe == null)) tree1 else adapt(tree1, mode, pt)
// Console.println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams);//DEBUG
// if ((mode & TYPEmode) != 0) println("type: "+tree1+" has type "+tree1.tpe)
result
@@ -3442,11 +3431,11 @@ trait Typers { self: Analyzer =>
}
def implicitsOfType(tp: Type): List[List[ImplicitInfo]] = {
- def getParts(tp: Type, s: Set[Type]) {
+ def getParts(tp: Type, s: collection.jcl.Set[Type]) {
tp match {
case TypeRef(pre, sym, args) if (!sym.isPackageClass) =>
for (bc <- sym.info.baseClasses)
- if (sym.isClass) s.addEntry(tp.baseType(bc))
+ if (sym.isClass) s add (tp.baseType(bc))
getParts(pre, s)
for (arg <- args) getParts(arg, s)
case ThisType(_) =>
@@ -3460,7 +3449,7 @@ trait Typers { self: Analyzer =>
case _ =>
}
}
- val tps = new HashSet[Type]
+ val tps = new collection.jcl.LinkedHashSet[Type]
getParts(tp, tps)
tps.elements.map(implicitsOfClass).toList
}
diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala
index 4c58ef00a2..2978f44a14 100644
--- a/src/compiler/scala/tools/nsc/util/Position.scala
+++ b/src/compiler/scala/tools/nsc/util/Position.scala
@@ -84,4 +84,9 @@ case class LinePosition(source0: SourceFile, line0: Int) extends Position {
case class OffsetPosition(source0: SourceFile, offset0: Int) extends Position {
override def source = Some(source0)
override def offset = Some(offset0)
+ override def equals(that : Any) = that match {
+ case that : OffsetPosition => offset0 == that.offset0 && source0.file == that.source0.file
+ case that => false
+ }
+ override def hashCode = offset0 + source0.file.hashCode
}
diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala
index 07cc6de0f0..2f07b79d1e 100644
--- a/src/compiler/scala/tools/nsc/util/SourceFile.scala
+++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala
@@ -21,7 +21,7 @@ object SourceFile {
/** abstract base class of a source file used in the compiler */
abstract class SourceFile {
import SourceFile._
- //def content : Seq[Char] // normalized, must end in SU
+ def content : RandomAccessSeq[Char] // normalized, must end in SU
def file : AbstractFile
def isLineBreak(idx : Int) : Boolean
def length : Int