summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
diff options
context:
space:
mode:
authorSean McDirmid <sean.mcdirmid@gmail.com>2007-09-17 16:36:10 +0000
committerSean McDirmid <sean.mcdirmid@gmail.com>2007-09-17 16:36:10 +0000
commita205b6b06e705711308c9ad3abac74ba66b6266f (patch)
tree49aa189b4917b20d76c2da02cbf9475af5a49662 /src/compiler/scala/tools/nsc/typechecker
parent3f9b82c88d74c1b03daf5131b50c172213f40a63 (diff)
downloadscala-a205b6b06e705711308c9ad3abac74ba66b6266f.tar.gz
scala-a205b6b06e705711308c9ad3abac74ba66b6266f.tar.bz2
scala-a205b6b06e705711308c9ad3abac74ba66b6266f.zip
Massive check-in for IDE.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala217
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala26
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala276
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala49
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala256
8 files changed, 558 insertions, 281 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 6d95b1a762..1ec4da1a54 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -26,7 +26,7 @@ trait Analyzer extends AnyRef
val phaseName = "namer"
def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
def apply(unit: CompilationUnit): unit =
- new Namer(rootContext(unit)).enterSym(unit.body)
+ newNamer(rootContext(unit)).enterSym(unit.body)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 734c29e2cf..ee1637c65a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -86,9 +86,12 @@ trait Contexts { self: Analyzer =>
sc = sc.outer
}
}
- class Context {
+ // 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
+ var tree: Tree = _ // Tree associated with this context
var owner: Symbol = NoSymbol// The current owner
var scope: Scope = _ // The current scope
var outer: Context = _ // The next outer context
@@ -113,39 +116,88 @@ trait Contexts { self: Analyzer =>
var savedTypeBounds: List[(Symbol, Type)] = List()
- override def equals(that : Any) = that match {
- case that if (super.equals(that)) => true
- case NoContext => false
+
+ def intern0 : Context = {
+ if (this eq NoContext) return this
+ val txt = new Context
+ txt.unit = unit
+ txt.tree = tree
+ txt.owner = owner
+ txt.scope = scope
+ assert(outer ne this) // stupid
+ txt.outer = outer // already interned
+ def f(what : Context) =
+ if (what eq this) txt
+ else what
+ txt.enclClass = f(enclClass)
+ txt.enclMethod = f(enclMethod)
+ txt.implicitsEnabled = implicitsEnabled
+ txt.variance = variance
+ txt._undetparams = _undetparams
+ txt.depth = depth
+ txt.imports = imports
+ txt.prefix = prefix
+ txt.inConstructorSuffix = inConstructorSuffix
+ txt.returnsSeen = returnsSeen
+ txt.reportGeneralErrors = reportGeneralErrors
+ txt.checking = checking
+ txt.retyping = retyping
+ txt.savedTypeBounds = savedTypeBounds
+ txt
+ }
+ override def equals(that : Any) : Boolean = that match {
+ case that : AnyRef if (this eq that) => true
+ case that if !inIDE => super.equals(that)
+ //case NoContext => false
case that : Context =>
- val a0 = if (tree eq null) tree == that.tree else tree equalsStructure that.tree;
- val a1 = owner == that.owner
- val a2 = scope == that.scope
- val a3 = outer == that.outer
- val a4 = {
- if (enclClass eq this) {
- that.enclClass eq that;
- } else enclClass == that.enclClass;
+ if (that eq NoContext) return this eq NoContext
+ assert(that ne NoContext)
+ if (this eq NoContext) return false
+ assert(inIDE)
+ def eq[T](x : T, y : T) = x == y
+ val a0 = {
+ if (tree ne null) tree.setType(null)
+ if ((tree eq null) || (that.tree eq null)) tree == that.tree else
+ tree equalsStructure that.tree;
+ }
+ val a1 = eq(owner, that.owner)
+ val a2 = eq(scope, that.scope)
+ def f(txt0 : Context, txt1 : Context) =
+ ((this eq txt0) && (that eq txt1)) || (txt0 eq txt1)
+
+ val a3 = f(outer, that.outer)
+ val a4 = f(enclClass, that.enclClass)
+ val a5 = f(enclMethod, that.enclMethod)
+ val a6 = eq(variance, that.variance)
+ val a7 = eq(_undetparams, that._undetparams)
+ val a8 = eq(depth, that.depth)
+ val a9 = eq(imports, that.imports)
+
+ val a10 = eq(prefix, that.prefix)
+ val a11 = eq(inConstructorSuffix, that.inConstructorSuffix)
+ val a12 = eq(implicitsEnabled, that.implicitsEnabled)
+ val a13 = eq(checking, that.checking)
+ val a14 = eq(retyping, that.retyping)
+ val a15 = eq(savedTypeBounds, that.savedTypeBounds)
+ val a16 = eq(unit, that.unit)
+ val ret = a0 && a1 && a2 && a3 && a4 && a5 && a6 && a7 && a8 && a9 && a10 && a11 && a12 && a13 && a14 && a15 && a16
+ val a17 = {
+ if (implicitsRunId > that.implicitsRunId) {
+ that.implicitsRunId = NoRunId
+ that.implicitsCache = null
+ }
+ else if (that.implicitsRunId > implicitsRunId) {
+ implicitsRunId = NoRunId
+ implicitsCache = null
+ }
+ implicitsCache == that.implicitsCache
}
- val a5 = {
- if (enclMethod eq this)
- that.enclMethod eq that;
- else enclMethod == that.enclMethod;
+ if (ret) {
+ if (!a17) {
+ assert(this.implicitsCache == null || that.implicitsCache == null)
+ }
}
- val a6 = variance == that.variance;
- val a7 = _undetparams == that._undetparams;
- val a8 = depth == that.depth;
- val a9 = if (imports.length != that.imports.length) false else
- (for (x <- imports.zip(that.imports)) yield
- (x._1.tree equalsStructure x._2.tree) && x._1.depth == x._2.depth).
- foldLeft(true)((x,y) => x && y);
-
- val a10 = prefix == that.prefix
- val a11 = inConstructorSuffix == that.inConstructorSuffix
- val a12 = implicitsEnabled == that.implicitsEnabled
- val a13 = checking == that.checking
- val a14 = retyping == that.retyping
- val a15 = savedTypeBounds == that.savedTypeBounds
- a0 && a1 && a2 && a3 && a4 && a5 && a6 && a7 && a8 && a9 && a10 && a11 && a12 && a13 && a14 && a15
+ ret
case _ => false
}
@@ -168,16 +220,23 @@ trait Contexts { self: Analyzer =>
scope: Scope, imports: List[ImportInfo]): Context = {
val c = new Context
c.unit = unit
- c.tree = tree
+ c.tree = sanitize(tree)
c.owner = owner
c.scope = scope
+
+ c.outer = intern(this)
+ def internIf(txt : Context) = {
+ if (txt eq this) c.outer // already interned!
+ else txt
+ }
+
tree match {
case Template(_, _, _) | PackageDef(_, _) =>
c.enclClass = c
c.prefix = c.owner.thisType
c.inConstructorSuffix = false
case _ =>
- c.enclClass = this.enclClass
+ c.enclClass = internIf(this.enclClass)
c.prefix =
if (c.owner != this.owner && c.owner.isTerm) NoPrefix
else this.prefix
@@ -187,7 +246,7 @@ trait Contexts { self: Analyzer =>
case DefDef(_, _, _, _, _, _) =>
c.enclMethod = c
case _ =>
- c.enclMethod = this.enclMethod
+ c.enclMethod = internIf(this.enclMethod)
}
c.variance = this.variance
c.depth = if (scope == this.scope) this.depth else this.depth + 1
@@ -197,7 +256,6 @@ trait Contexts { self: Analyzer =>
c.implicitsEnabled = this.implicitsEnabled
c.checking = this.checking
c.retyping = this.retyping
- c.outer = this
c
}
@@ -212,14 +270,21 @@ trait Contexts { self: Analyzer =>
def makeNewImport(imp: Import): Context =
make(unit, imp, owner, scope, new ImportInfo(imp, depth) :: imports)
- def make(tree: Tree, owner: Symbol, scope: Scope): Context =
+
+
+ def make(tree: Tree, owner: Symbol, scope: Scope): Context = {
+ if (tree == this.tree && owner == this.owner && scope == this.scope) this
+ else make0(tree, owner, scope)
+ }
+ private def make0(tree : Tree, owner : Symbol, scope : Scope) : Context = {
make(unit, tree, owner, scope, imports)
+ }
def makeNewScope(tree: Tree, owner: Symbol): Context =
- make(tree, owner, newScope(scope))
+ make(tree, owner, scopeFor(scope, tree))
def make(tree: Tree, owner: Symbol): Context =
- make(tree, owner, scope)
+ make0(tree, owner, scope)
def make(tree: Tree): Context =
make(tree, owner)
@@ -242,7 +307,7 @@ trait Contexts { self: Analyzer =>
//todo: find out why we need next line
while (baseContext.tree.isInstanceOf[Template])
baseContext = baseContext.outer
- val argContext = Contexts.this.makeNewScope(baseContext, tree, owner)
+ val argContext = baseContext.makeNewScope(tree, owner)
argContext.reportGeneralErrors = this.reportGeneralErrors
argContext.reportAmbiguousErrors = this.reportAmbiguousErrors
def enterElems(c: Context) {
@@ -364,6 +429,8 @@ trait Contexts { self: Analyzer =>
def accessWithin(owner: Symbol): Boolean = {
var c = this
while (c != NoContext && c.owner != owner) {
+ if (false && inIDE) // XXX: we didn't get to update these syms....
+ assert(c.owner.fullNameString != owner.fullNameString)
if (c.outer eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug
if (c.outer.enclClass eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug
c = c.outer.enclClass
@@ -422,6 +489,11 @@ trait Contexts { self: Analyzer =>
private var implicitsCache: List[List[ImplicitInfo]] = null
private var implicitsRunId = NoRunId
+ def resetCache : Unit = {
+ implicitsRunId = NoRunId
+ implicitsCache = null
+ if (outer != null && outer != this) outer.resetCache
+ }
private def collectImplicits(syms: List[Symbol], pre: Type): List[ImplicitInfo] =
for (sym <- syms if sym.hasFlag(IMPLICIT) && isAccessible(sym, pre, false))
yield new ImplicitInfo(sym.name, pre, sym)
@@ -473,10 +545,33 @@ trait Contexts { self: Analyzer =>
}
implicitsCache
}
- }
+ override def hashCode = {
+ var hc = 0
+ implicit def b2i(b : Boolean) = if (b) 1 else 0
+ // assum enclClass/enclMethod/outer are all interned already.
+ hc += tree.hashCodeStructure
+ def f(txt : Context) = if (txt eq this) 0 else System.identityHashCode(txt)
+ hc += f(enclClass)
+ hc += f(enclMethod)
+ hc += f(outer)
+ hc += owner.hashCode
+ hc += scope.hashCode
+ hc += variance.hashCode
+ hc += _undetparams.hashCode
+ hc += depth
+ hc += imports.hashCode
+ hc += prefix.hashCode
+ hc += inConstructorSuffix
+ hc += checking
+ hc += retyping
+ hc += savedTypeBounds.hashCode
+ hc += (if (unit eq null) 0 else unit.hashCode)
+ hc
+ }
+ }
+ 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 {
case ImportType(expr) => expr
@@ -495,6 +590,9 @@ trait Contexts { self: Analyzer =>
var renamed = false
var selectors = tree.selectors
while (selectors != Nil && result == NoSymbol) {
+ if (selectors.head._1 != nme.WILDCARD)
+ notifyImport(name, qual.tpe, selectors.head._1, selectors.head._2)
+
if (selectors.head._2 == name.toTermName)
result = qual.tpe.member(
if (name.isTypeName) selectors.head._1.toTypeName else selectors.head._1)
@@ -508,6 +606,13 @@ trait Contexts { self: Analyzer =>
}
override def toString() = tree.toString()
+
+ override def hashCode = tree.hashCodeStructure + depth
+ override def equals(that : Any) = that match {
+ case that : ImportInfo =>
+ depth == that.depth && (tree equalsStructure that.tree)
+ case _ => false
+ }
}
class ImplicitInfo(val name: Name, val pre: Type, val sym: Symbol) {
@@ -521,5 +626,31 @@ trait Contexts { self: Analyzer =>
val NoImplicitInfo = new ImplicitInfo(null, null, null)
- case class ImportType(expr: Tree) extends Type
+ case class ImportType(expr: Tree) extends Type {
+ override def equals(that : Any) = that match {
+ case ImportType(expr) =>
+ if (inIDE) this.expr equalsStructure expr
+ else this.expr == expr
+ case _ => false
+ }
+ 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 1cdcf6210a..938a07f5bf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -34,10 +34,21 @@ trait EtaExpansion { self: Analyzer =>
* tree is already attributed
* </p>
*/
- def etaExpand(tree: Tree): Tree = {
+ def etaExpand(unit : CompilationUnit, tree: Tree): Tree = {
val tpe = tree.tpe
- var cnt = 0
- def freshName() = { cnt = cnt + 1; newTermName("eta$" + cnt) }
+ val symbolHash = if (!inIDE) "" else Integer.toString(tree.symbol.hashCode, 10 + ('z' - 'a')) + "$"
+ var cnt = 0 // for NoPosition
+ def freshName(pos : util.Position, n : Int) = {
+ cnt += 1
+ if (pos == util.NoPosition) {
+ newTermName("eta$" + symbolHash + (cnt - 1))
+ } else if (n == 0) {
+ newTermName(unit.fresh.newName(pos, "eta$" + symbolHash))
+ } else {
+ newTermName(unit.fresh.newName(pos, "eta$" + symbolHash + n + "$"))
+ }
+ }
+ // { cnt = cnt + 1; newTermName("eta$" + cnt) }
val defs = new ListBuffer[Tree]
/** Append to <code>defs</code> value definitions for all non-stable
@@ -50,7 +61,7 @@ trait EtaExpansion { self: Analyzer =>
def liftout(tree: Tree): Tree =
if (treeInfo.isPureExpr(tree)) tree
else {
- val vname: Name = freshName()
+ val vname: Name = freshName(tree.pos, 0)
defs += atPos(tree.pos)(ValDef(Modifiers(SYNTHETIC), vname, TypeTree(), tree))
Ident(vname) setPos tree.pos
}
@@ -76,8 +87,13 @@ trait EtaExpansion { self: Analyzer =>
case mt: ImplicitMethodType =>
tree
case MethodType(formals, restpe) =>
+ var cnt0 = 0
+ def cnt = {
+ cnt0 += 1
+ cnt0 - 1
+ }
val params = formals map (formal =>
- ValDef(Modifiers(SYNTHETIC | PARAM), freshName(), TypeTree()
+ ValDef(Modifiers(SYNTHETIC | PARAM), freshName(tree.pos, cnt), TypeTree()
.setType(formal), EmptyTree))
val args = params map (param => Ident(param.name))
val applyArgs =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index b79fca75f9..015c0636c8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -245,7 +245,7 @@ trait Infer {
private def withDisambiguation[T](tp1: Type, tp2: Type)(op: => T): T = {
def explainName(sym: Symbol) = {
- if (!sym.name.toString.endsWith(")")) {
+ if (!sym.name.toString.endsWith(")") && !inIDE) {
sym.name = newTypeName(sym.name.toString+"(in "+sym.owner+")")
}
}
@@ -259,7 +259,7 @@ trait Infer {
val name = sym1.name
explainName(sym1)
explainName(sym2)
- if (sym1.owner == sym2.owner) sym2.name = newTypeName("(some other)"+sym2.name)
+ if (sym1.owner == sym2.owner && !inIDE) sym2.name = newTypeName("(some other)"+sym2.name)
patches += (sym1, sym2, name)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 9138b2d412..a6409c6398 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -39,14 +39,18 @@ trait Namers { self: Analyzer =>
}
}
/** overridden by IDE to not manually enter value parameters */
- protected final def doEnterValueParams = !inIDE;
- protected def inIDE = false;
+ protected final def doEnterValueParams = true // !inIDE;
+ // can't use the other ones.
+ protected def newDecls(classSym : Symbol) : Scope = newClassScope
- class Namer(val context: Context) {
+ private class NormalNamer(context : Context) extends Namer(context)
+ def newNamer(context : Context) : Namer = new NormalNamer(context)
+
+ abstract class Namer(val context: Context) {
val typer = newTyper(context)
- def setPrivateWithin(tree: Tree, sym: Symbol, mods: Modifiers): Symbol = {
+ def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym = {
if (!mods.privateWithin.isEmpty)
sym.privateWithin = typer.qualifyingClassContext(tree, mods.privateWithin).owner
sym
@@ -75,6 +79,10 @@ 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)
+ }
def namerOf(sym: Symbol): Namer = {
@@ -82,46 +90,51 @@ trait Namers { self: Analyzer =>
if (innerNamerCache eq null)
innerNamerCache =
if (!isTemplateContext(context)) this
- else new Namer(context.make(context.tree, context.owner, newScope))
+ else newNamer(context.make(context.tree, context.owner, scopeFor(context.tree)))
innerNamerCache
}
def primaryConstructorParamNamer: Namer = { //todo: can we merge this with SCCmode?
val classContext = context.enclClass
- val outerContext = classContext.outer.outer
- val paramContext = outerContext.makeNewScope(outerContext.tree, outerContext.owner)
- classContext.owner.unsafeTypeParams foreach(sym => paramContext.scope.enter(sym))
- new Namer(paramContext)
- }
-
- if (sym.isTerm &&
- (sym.hasFlag(PARAM) && sym.owner.isPrimaryConstructor || sym.hasFlag(PARAMACCESSOR)))
- primaryConstructorParamNamer
- else
- innerNamer
+ val paramContext = makeConstructorScope(classContext)
+ val unsafeTypeParams = context.owner.unsafeTypeParams
+ unsafeTypeParams foreach(sym => paramContext.scope.enter(sym))
+ newNamer(paramContext)
+ }
+ if (sym.isTerm) {
+ if (sym.hasFlag(PARAM) && sym.owner.isPrimaryConstructor)
+ primaryConstructorParamNamer
+ else if (sym.hasFlag(PARAMACCESSOR) && !inIDE)
+ primaryConstructorParamNamer
+ else innerNamer
+ } else innerNamer
}
+ protected def conflict(newS : Symbol, oldS : Symbol) : Boolean = {
+ (!oldS.isSourceMethod ||
+ nme.isSetterName(newS.name) ||
+ newS.owner.isPackageClass) &&
+ !((newS.owner.isTypeParameter || newS.owner.isAbstractType) &&
+ newS.name.length==1 && newS.name(0)=='_') //@M: allow repeated use of `_' for higher-order type params
+ }
+ protected def setInfo[Sym <: Symbol](sym : Sym)(tpe : LazyType) : Sym = sym.setInfo(tpe)
private def doubleDefError(pos: Position, sym: Symbol) {
context.error(pos,
sym.name.toString() + " is already defined as " +
(if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString()))
}
- def enterInScope[A <: Symbol](sym: A): A = {
+ 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 &&
- (!prev.sym.isSourceMethod ||
- nme.isSetterName(sym.name) ||
- sym.owner.isPackageClass) &&
- !((sym.owner.isTypeParameter || sym.owner.isAbstractType)
- && sym.name.length==1 && sym.name(0)=='_')) { //@M: allow repeated use of `_' for higher-order type params
+ if ((prev ne null) && prev.owner == context.scope && conflict(sym, prev.sym)) {
doubleDefError(sym.pos, prev.sym)
- sym setInfo ErrorType
+ if (!inIDE) sym setInfo ErrorType // don't do this in IDE for stability
+ context.scope unlink prev.sym
+ context.scope enter sym
} else context.scope enter sym
} else context.scope enter sym
- sym
}
def enterPackageSymbol(pos: Position, name: Name): Symbol = {
@@ -133,79 +146,102 @@ trait Namers { self: Analyzer =>
} else {
val cowner = if (context.owner == EmptyPackageClass) RootClass else context.owner
val pkg = cowner.newPackage(pos, name)
- pkg.moduleClass.setInfo(new PackageClassInfoType(newScope, pkg.moduleClass))
+ // IDE: newScope should be ok because packages are never destroyed.
+ if (inIDE) assert(pkg.moduleClass.rawInfoSafe.isEmpty || !pkg.moduleClass.rawInfo.isComplete)
+ pkg.moduleClass.setInfo(new PackageClassInfoType(newScope, pkg.moduleClass, null))
pkg.setInfo(pkg.moduleClass.tpe)
enterInScope(pkg)
}
}
- def inConstructorFlag: long =
+ def inConstructorFlag: Long =
if (context.owner.isConstructor && !context.inConstructorSuffix || context.owner.isEarly) INCONSTRUCTOR
else 0l
- private def enterClassSymbol(pos: Position, flags: long, name: Name): Symbol = {
- var c: Symbol = context.scope.lookup(name)
- if (c.isType && !currentRun.compiles(c) && context.scope == c.owner.info.decls) {
- updatePosFlags(c, pos, flags)
+ def enterClassSymbol(tree : ClassDef): Symbol = {
+ var c: Symbol = context.scope.lookup(tree.name);
+ // Never take the first path in the IDE because we could be completing c.owner's type!
+ // the other path will handle symbol re-use well enough.
+ if (!inIDE && c.isType && context.scope == c.owner.info.decls && !currentRun.compiles(c)) {
+ updatePosFlags(c, tree.pos, tree.mods.flags)
+ setPrivateWithin(tree, c, tree.mods)
} else {
- c = enterInScope(context.owner.newClass(pos, name)).setFlag(flags | inConstructorFlag)
+ //if (inIDE && c != NoSymbol) currentRun.compiles(c) // in IDE, will unload/save non-source symbol
+ var sym = context.owner.newClass(tree.pos, tree.name)
+ sym = sym.setFlag(tree.mods.flags | inConstructorFlag)
+ sym = setPrivateWithin(tree, sym, tree.mods)
+ c = enterInScope(sym)
}
if (c.owner.isPackageClass) {
- val file = context.unit.source.getFile()
+ val file = context.unit.source.file
val clazz = c.asInstanceOf[ClassSymbol]
if (settings.debug.value && (clazz.sourceFile ne null) && !clazz.sourceFile.equals(file)) {
Console.err.println("SOURCE MISMATCH: " + clazz.sourceFile + " vs. " + file + " SYM=" + c);
}
clazz.sourceFile = file
if (clazz.sourceFile ne null) {
- assert(!currentRun.compiles(clazz) || clazz.sourceFile == currentRun.symSource(c));
+ assert(inIDE || !currentRun.compiles(clazz) || clazz.sourceFile == currentRun.symSource(c));
currentRun.symSource(c) = clazz.sourceFile
}
}
+ assert(c.name.toString.indexOf('(') == -1)
c
}
-
- private def enterModuleSymbol(pos: Position, flags: long, name: Name): Symbol = {
- var m: Symbol = context.scope.lookup(name)
- if (m.isModule && !m.isPackage && !currentRun.compiles(m) &&
- (context.scope == m.owner.info.decls)) {
- updatePosFlags(m, pos, flags)
+ def enterModuleSymbol(tree : ModuleDef): Symbol = {
+ // .pos, mods.flags | MODULE | FINAL, name
+ assert(tree.name.isTermName)
+ var m: Symbol = context.scope.lookup(tree.name)
+ if (!inIDE && m.isModule && !m.isPackage && (context.scope == m.owner.info.decls) &&
+ !currentRun.compiles(m)) {
+ updatePosFlags(m, tree.pos, tree.mods.flags|MODULE|FINAL)
+ setPrivateWithin(tree, m, tree.mods)
} else {
- if (m.isTerm && !m.isPackage && !currentRun.compiles(m) && (context.scope == m.owner.info.decls))
+ if (m.isTerm && !m.isPackage && currentRun.compiles(m) && (context.scope == m.owner.info.decls))
context.scope.unlink(m)
- m = context.owner.newModule(pos, name)
- m.setFlag(flags)
- m.moduleClass.setFlag(flags | inConstructorFlag)
- enterInScope(m)
+
+ m = context.owner.newModule(tree.pos, tree.name)
+ m.setFlag(tree.mods.flags)
+ m = setPrivateWithin(tree, m, tree.mods)
+ m = enterInScope(m)
+
+ m.moduleClass.setFlag(tree.mods.flags|MODULE|FINAL| inConstructorFlag)
+ setPrivateWithin(tree, m.moduleClass, tree.mods)
}
if (m.owner.isPackageClass) {
- m.moduleClass.sourceFile = context.unit.source.getFile()
+ m.moduleClass.sourceFile = context.unit.source.file
currentRun.symSource(m) = m.moduleClass.sourceFile
}
m
}
- private def enterCaseFactorySymbol(pos: Position, flags: long, name: Name): Symbol = {
+ def enterCaseFactorySymbol(tree : ClassDef): Symbol = {
+ val pos = tree.pos
+ val flags = tree.mods.flags & AccessFlags | METHOD | CASE
+ val name = tree.name.toTermName
var m: Symbol = context.scope.lookup(name)
- if (m.isTerm && !m.isPackage && !currentRun.compiles(m) && context.scope == m.owner.info.decls) {
+ if (!inIDE && m.isTerm && !m.isPackage && !currentRun.compiles(m) && context.scope == m.owner.info.decls) {
updatePosFlags(m, pos, flags)
+ setPrivateWithin(tree, m, tree.mods)
} else {
- m = enterInScope(context.owner.newMethod(pos, name)).setFlag(flags)
+ // recycle the old fashion way.
+ m = enterInScope{
+ var sym = context.owner.newMethod(pos, name).setFlag(flags)
+ sym = setPrivateWithin(tree, sym, tree.mods)
+ sym
+ }
}
if (m.owner.isPackageClass)
- currentRun.symSource(m) = context.unit.source.getFile()
+ currentRun.symSource(m) = context.unit.source.file
m
}
-
def enterSyms(trees: List[Tree]): Namer = {
var namer : Namer = this
for (tree <- trees) {
val txt = namer.enterSym(tree)
- if (!(txt eq namer.context)) namer = new Namer(txt)
+ if (!(txt eq namer.context)) namer = newNamer(txt)
}
namer
}
-
def newTypeSkolems(tparams: List[Symbol]): List[Symbol] = {
val tskolems = tparams map (_.newTypeSkolem)
val ltp = new LazyType {
@@ -216,7 +252,6 @@ trait Namers { self: Analyzer =>
tskolems foreach (_.setInfo(ltp))
tskolems
}
-
/** Replace type parameters with their TypeSkolems, which can later be deskolemized to the original type param
* (a skolem is a representation of a bound variable when viewed outside its scope)
*/
@@ -237,10 +272,15 @@ trait Namers { self: Analyzer =>
override val typeParams: List[Symbol]= tparams map (_.symbol) //@M
override def complete(sym: Symbol) {
if(ownerSym.isAbstractType) //@M an abstract type's type parameters are entered -- TODO: change to isTypeMember ?
- new Namer(ctx.makeNewScope(owner, ownerSym)).enterSyms(tparams) //@M
+ newNamer(ctx.makeNewScope(owner, ownerSym)).enterSyms(tparams) //@M
restp.complete(sym)
}
}
+ def reuse[T <: Tree](tree: T) = if (!inIDE) tree else {
+ val tree0 = tree.duplicate
+ //tree0.symbol = tree.symbol
+ tree0
+ }
def enterSym(tree: Tree): Context = {
@@ -253,11 +293,11 @@ 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 ?
- new Namer(context.makeNewScope(tree, sym)).enterSyms(tparams)
+ newNamer(context.makeNewScope(tree, sym)).enterSyms(tparams)
ltype = new LazyPolyType(tparams, ltype, tree, sym, context) //@M
if (sym.isTerm) skolemize(tparams)
}
- sym.setInfo(ltype)
+ setInfo(sym)(ltype)
}
def finish = finishWith(List())
@@ -267,45 +307,43 @@ trait Namers { self: Analyzer =>
tree match {
case PackageDef(name, stats) =>
tree.symbol = enterPackageSymbol(tree.pos, name)
- val namer = new Namer(
+ val namer = newNamer(
context.make(tree, tree.symbol.moduleClass, tree.symbol.info.decls))
namer.enterSyms(stats)
- case ClassDef(mods, name, tparams, impl) =>
+ case tree @ ClassDef(mods, name, tparams, impl) =>
+ tree.symbol = enterClassSymbol(tree)
+ finishWith(tparams)
if ((mods.flags & CASE) != 0) { // enter case factory method.
- tree.symbol = enterCaseFactorySymbol(
- tree.pos, mods.flags & AccessFlags | METHOD | CASE, name.toTermName)
- tree.symbol.setInfo(namerOf(tree.symbol).caseFactoryCompleter(tree))
- setPrivateWithin(tree, tree.symbol, mods)
+ val sym = enterCaseFactorySymbol(tree)
+ setInfo(sym)(namerOf(sym).caseFactoryCompleter(reuse(tree)))
}
- tree.symbol = enterClassSymbol(tree.pos, mods.flags, name)
- setPrivateWithin(tree, tree.symbol, mods)
- finishWith(tparams)
- case ModuleDef(mods, name, _) =>
- tree.symbol = enterModuleSymbol(tree.pos, mods.flags | MODULE | FINAL, name)
- setPrivateWithin(tree, tree.symbol, mods)
- setPrivateWithin(tree, tree.symbol.moduleClass, mods)
- tree.symbol.moduleClass.setInfo(namerOf(tree.symbol).moduleClassTypeCompleter(tree))
+ 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)))
finish
+
case ValDef(mods, name, tp, rhs) =>
if (context.owner.isClass && (mods.flags & (PRIVATE | LOCAL)) != (PRIVATE | LOCAL)
|| (mods.flags & LAZY) != 0) {
val accflags: Long = ACCESSOR |
(if ((mods.flags & MUTABLE) != 0) mods.flags & ~MUTABLE & ~PRESUPER
else mods.flags & ~PRESUPER | STABLE)
- val getter = owner.newMethod(tree.pos, name).setFlag(accflags)
- getter.setInfo(namerOf(getter).getterTypeCompleter(tree))
+ var getter = owner.newMethod(tree.pos, name).setFlag(accflags)
setPrivateWithin(tree, getter, mods)
- enterInScope(getter)
+ getter = enterInScope(getter).asInstanceOf[TermSymbol]
+ setInfo(getter)(namerOf(getter).getterTypeCompleter(tree))
if ((mods.flags & MUTABLE) != 0) {
- val setter = owner.newMethod(tree.pos, nme.getterToSetter(name))
+ var setter = owner.newMethod(tree.pos, nme.getterToSetter(name))
.setFlag(accflags & ~STABLE & ~CASEACCESSOR)
- setter.setInfo(namerOf(setter).setterTypeCompleter(tree))
setPrivateWithin(tree, setter, mods)
- enterInScope(setter)
+ setter = enterInScope(setter).asInstanceOf[TermSymbol]
+ setInfo(setter)(namerOf(setter).setterTypeCompleter(tree))
}
tree.symbol =
- if ((mods.flags & DEFERRED) == 0) {
- val vsym =
+ if ((mods.flags & DEFERRED) == 0) { // not deferred
+ var vsym =
if (!context.owner.isClass) {
assert((mods.flags & LAZY) != 0) // if not a field, it has to be a lazy val
owner.newValue(tree.pos, name + "$lzy" ).setFlag(mods.flags | MUTABLE)
@@ -313,39 +351,39 @@ trait Namers { self: Analyzer =>
owner.newValue(tree.pos, nme.getterToLocal(name))
.setFlag(mods.flags & FieldFlags | PRIVATE | LOCAL | (if ((mods.flags & LAZY) != 0) MUTABLE else 0))
}
- val value = enterInScope(vsym)
- value.setInfo(namerOf(value).typeCompleter(tree))
+ vsym = enterInScope(vsym).asInstanceOf[TermSymbol]
+ setInfo(vsym)(namerOf(vsym).typeCompleter(tree))
if ((mods.flags & LAZY) != 0)
- value.setLazyAccessor(getter)
- value
+ vsym.setLazyAccessor(getter)
+ vsym
} else getter;
} else {
- tree.symbol = enterInScope(owner.newValue(tree.pos, name))
- .setFlag(mods.flags)
+ tree.symbol = enterInScope(owner.newValue(tree.pos, name)
+ .setFlag(mods.flags))
finish
}
case DefDef(mods, nme.CONSTRUCTOR, tparams, _, _, _) =>
- tree.symbol = enterInScope(owner.newConstructor(tree.pos))
- .setFlag(mods.flags | owner.getFlag(ConstrFlags))
- setPrivateWithin(tree, tree.symbol, mods)
+ var sym = owner.newConstructor(tree.pos).setFlag(mods.flags | owner.getFlag(ConstrFlags))
+ setPrivateWithin(tree, sym, mods)
+ tree.symbol = enterInScope(sym)
finishWith(tparams)
case DefDef(mods, name, tparams, _, _, _) =>
- tree.symbol = enterInScope(owner.newMethod(tree.pos, name))
- .setFlag(mods.flags)
- setPrivateWithin(tree, tree.symbol, mods)
+ var sym = (owner.newMethod(tree.pos, name)).setFlag(mods.flags)
+ setPrivateWithin(tree, sym, mods)
+ tree.symbol = enterInScope(sym)
finishWith(tparams)
case TypeDef(mods, name, tparams, _) =>
var flags: Long = mods.flags
if ((flags & PARAM) != 0) flags |= DEFERRED
- tree.symbol = enterInScope(new TypeSymbol(owner, tree.pos, name))
- .setFlag(flags)
- setPrivateWithin(tree, tree.symbol, mods)
+ var sym =new TypeSymbol(owner, tree.pos, name).setFlag(flags)
+ setPrivateWithin(tree, sym, mods)
+ tree.symbol = enterInScope(sym)
finishWith(tparams)
case DocDef(_, defn) =>
enterSym(defn)
case imp @ Import(_, _) =>
tree.symbol = NoSymbol.newImport(tree.pos)
- tree.symbol.setInfo(namerOf(tree.symbol).typeCompleter(tree))
+ setInfo(tree.symbol)(namerOf(tree.symbol).typeCompleter(tree))
return (context.makeNewImport(imp))
case _ =>
}
@@ -451,11 +489,20 @@ trait Namers { self: Analyzer =>
def enterValueParams(owner: Symbol, vparamss: List[List[ValDef]]): List[List[Symbol]] = {
def enterValueParam(param: ValDef): Symbol = if (doEnterValueParams) {
- param.symbol = owner.newValueParameter(param.pos, param.name)
- .setInfo(typeCompleter(param))
- .setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT))
- setPrivateWithin(param, param.symbol, param.mods)
- enterInScope(param.symbol)
+ if (inIDE) param.symbol = {
+ var sym = owner.newValueParameter(param.pos, param.name).
+ setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT))
+ setPrivateWithin(param, sym, param.mods)
+ sym = enterInScope(sym).asInstanceOf[TermSymbol]
+ if (!sym.rawInfoSafe.isDefined || sym.rawInfo.isComplete)
+ setInfo(sym)(typeCompleter(param))
+ sym
+ } else param.symbol = setInfo(
+ enterInScope{
+ val sym = owner.newValueParameter(param.pos, param.name).
+ setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT))
+ setPrivateWithin(param, sym, param.mods)
+ })(typeCompleter(param))
param.symbol
} else param.symbol
vparamss.map(_.map(enterValueParam))
@@ -477,7 +524,7 @@ trait Namers { self: Analyzer =>
def enterSelf(self: ValDef) {
if (!self.tpt.isEmpty) {
clazz.typeOfThis = selfTypeCompleter(self.tpt)
- self.symbol = clazz.thisSym
+ self.symbol = clazz.thisSym.setPos(self.pos)
} else {
self.tpt.tpe = NoType
if (self.name != nme.WILDCARD) {
@@ -489,13 +536,13 @@ trait Namers { self: Analyzer =>
}
if (self.name != nme.WILDCARD) {
self.symbol.name = self.name
- context.scope enter self.symbol
+ self.symbol = context.scope enter self.symbol
}
}
val parents = typer.parentTypes(templ) map checkParent
enterSelf(templ.self)
- val decls = newDecls(templ, clazz)
- new Namer(context.make(templ, clazz, decls)).enterSyms(templ.body)
+ val decls = newDecls(clazz)
+ newNamer(context.make(templ, clazz, decls)).enterSyms(templ.body)
ClassInfoType(parents, decls, clazz)
}
@@ -507,7 +554,14 @@ trait Namers { self: Analyzer =>
val meth = context.owner
val tparamSyms = typer.reenterTypeParams(tparams)
- var vparamSymss = enterValueParams(meth, vparamss)
+ var vparamSymss =
+ if (inIDE && meth.isPrimaryConstructor) {
+ // @S: because they have already been entered this way....
+ assert(true)
+ enterValueParams(meth.owner.owner, vparamss)
+ } else {
+ enterValueParams(meth, vparamss)
+ }
if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) tpt.tpe = context.enclClass.owner.tpe
if (onlyPresentation)
@@ -700,7 +754,7 @@ trait Namers { self: Analyzer =>
val ainfos = for {
annot <- defn.mods.annotations
val ainfo = typer.typedAnnotation(annot)
- if !ainfo.atp.isError
+ if !ainfo.atp.isError && annot != null
} yield ainfo
if (!ainfos.isEmpty) {
val annotated = if (sym.isModule) sym.moduleClass else sym
@@ -712,17 +766,17 @@ trait Namers { self: Analyzer =>
try {
tree match {
case ClassDef(_, _, tparams, impl) =>
- new Namer(makeNewScope(context, tree, sym)).classSig(tparams, impl)
+ newNamer(context.makeNewScope(tree, sym)).classSig(tparams, impl)
case ModuleDef(_, _, impl) =>
val clazz = sym.moduleClass
- clazz.setInfo(new Namer(makeNewScope(context, tree, clazz)).templateSig(impl))
+ clazz.setInfo(newNamer(context.makeNewScope(tree, clazz)).templateSig(impl))
//clazz.typeOfThis = singleType(sym.owner.thisType, sym);
clazz.tpe;
case DefDef(_, _, tparams, vparamss, tpt, rhs) =>
val result =
- new Namer(makeNewScope(context, tree, sym)).methodSig(tparams, vparamss, tpt, rhs);
+ newNamer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs);
checkContractive(sym, result)
case vdef @ ValDef(mods, _, tpt, rhs) =>
@@ -741,7 +795,7 @@ trait Namers { self: Analyzer =>
} else typer1.typedType(tpt).tpe
case TypeDef(_, _, tparams, rhs) =>
- new Namer(makeNewScope(context, tree, sym)).typeDefSig(sym, tparams, rhs) //@M!
+ newNamer(context.makeNewScope(tree, sym)).typeDefSig(sym, tparams, rhs) //@M!
case Import(expr, selectors) =>
val expr1 = typer.typedQualifier(expr)
@@ -813,7 +867,7 @@ trait Namers { self: Analyzer =>
}
if (sym.hasFlag(IMPLICIT) && !sym.isTerm)
context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods")
- if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass)
+ if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass && !inIDE)
context.error(sym.pos, "`implicit' modifier cannot be used for top-level objects")
if (sym.hasFlag(ABSTRACT) && !sym.isClass)
context.error(sym.pos, "`abstract' modifier can be used only for classes; " +
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index aa5a2909e1..7323529d94 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -84,7 +84,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
}
- override def transform(tree: Tree): Tree = tree match {
+ override def transform(tree: Tree): Tree = try { tree match {
case ClassDef(_, _, _, _) =>
checkCompanionNameClashes(tree.symbol)
val decls = tree.symbol.info.decls
@@ -181,6 +181,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
super.transform(tree)
case Apply(fn, args) =>
+ assert(fn.tpe != null)
copy.Apply(tree, transform(fn), transformArgs(args, fn.tpe.paramTypes))
case Function(vparams, body) =>
withInvalidOwner {
@@ -188,6 +189,12 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
case _ =>
super.transform(tree)
+ }} catch {
+ case ex : AssertionError =>
+ if (tree.symbol != null && tree.symbol != NoSymbol)
+ Console.println("TRANSFORM: " + tree.symbol.sourceFile)
+ Console.println("TREE: " + tree)
+ throw ex
}
override def atOwner[A](owner: Symbol)(trans: => A): A = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 8fb892670b..d9ee9071cd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -29,7 +29,11 @@ import scala.collection.mutable.ListBuffer
trait SyntheticMethods { self: Analyzer =>
import global._ // the global environment
import definitions._ // standard classes and methods
- import typer.{typed} // methods to type trees
+ //import global.typer.{typed} // methods to type trees
+ // @S: type hack: by default, we are used from global.analyzer context
+ // so this cast won't fail. If we aren't in global.analyzer, we have
+ // to override this method anyways.
+ protected def typer : Typer = global.typer.asInstanceOf[Typer]
/**
* @param templ ...
@@ -42,15 +46,15 @@ trait SyntheticMethods { self: Analyzer =>
val localContext = if (reporter.hasErrors) context.makeSilent(false) else context
val localTyper = newTyper(localContext)
- def hasImplementation(name: Name): Boolean = {
+ def hasImplementation(name: Name): Boolean = if (inIDE) true else {
val sym = clazz.info.nonPrivateMember(name)
sym.isTerm && !(sym hasFlag DEFERRED)
}
- def hasOverridingImplementation(meth: Symbol): Boolean = {
+ def hasOverridingImplementation(meth: Symbol): Boolean = if (inIDE) true else {
val sym = clazz.info.nonPrivateMember(meth.name)
sym.alternatives exists { sym =>
- sym != meth && !(sym hasFlag DEFERRED) &&
+ sym != meth && !(sym hasFlag DEFERRED) && !(sym hasFlag SYNTHETIC) &&
(clazz.thisType.memberType(sym) matches clazz.thisType.memberType(meth))
}
}
@@ -59,8 +63,11 @@ trait SyntheticMethods { self: Analyzer =>
newSyntheticMethod(name, flags | OVERRIDE, tpe)
def newSyntheticMethod(name: Name, flags: Int, tpe: Type) = {
- val method = clazz.newMethod(clazz.pos, name) setFlag (flags) setInfo tpe
- clazz.info.decls.enter(method)
+ var method = clazz.newMethod(clazz.pos, name) setFlag ({
+ if (inIDE) flags | SYNTHETIC
+ else flags
+ }) setInfo tpe
+ method = clazz.info.decls.enter(method).asInstanceOf[TermSymbol]
method
}
@@ -72,18 +79,18 @@ trait SyntheticMethods { self: Analyzer =>
*/
def productPrefixMethod: Tree = {
val method = syntheticMethod(nme.productPrefix, FINAL, PolyType(List(), StringClass.tpe))
- typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
+ typer.typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
}
def productArityMethod(nargs:Int ): Tree = {
val method = syntheticMethod(nme.productArity, FINAL, PolyType(List(), IntClass.tpe))
- typed(DefDef(method, vparamss => Literal(Constant(nargs))))
+ typer.typed(DefDef(method, vparamss => Literal(Constant(nargs))))
}
def productElementMethod(accs: List[Symbol]): Tree = {
//val retTpe = lub(accs map (_.tpe.resultType))
val method = syntheticMethod(nme.productElement, FINAL, MethodType(List(IntClass.tpe), AnyClass.tpe/*retTpe*/))
- typed(DefDef(method, vparamss => Match(Ident(vparamss.head.head), {
+ typer.typed(DefDef(method, vparamss => Match(Ident(vparamss.head.head), {
(for ((sym,i) <- accs.zipWithIndex) yield {
CaseDef(Literal(Constant(i)),EmptyTree, Ident(sym))
}):::List(CaseDef(Ident(nme.WILDCARD), EmptyTree,
@@ -95,12 +102,12 @@ trait SyntheticMethods { self: Analyzer =>
def moduleToStringMethod: Tree = {
val method = syntheticMethod(nme.toString_, FINAL, MethodType(List(), StringClass.tpe))
- typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
+ typer.typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
}
def tagMethod: Tree = {
val method = syntheticMethod(nme.tag, FINAL, MethodType(List(), IntClass.tpe))
- typed(DefDef(method, vparamss => Literal(Constant(clazz.tag))))
+ typer.typed(DefDef(method, vparamss => Literal(Constant(clazz.tag))))
}
def forwardingMethod(name: Name): Tree = {
@@ -110,7 +117,7 @@ trait SyntheticMethods { self: Analyzer =>
else target.tpe.paramTypes.tail
val method = syntheticMethod(
name, 0, MethodType(paramtypes, target.tpe.resultType))
- typed(DefDef(method, vparamss =>
+ typer.typed(DefDef(method, vparamss =>
Apply(gen.mkAttributedRef(target), This(clazz) :: (vparamss.head map Ident))))
}
@@ -148,7 +155,7 @@ trait SyntheticMethods { self: Analyzer =>
val (pat, guard) = {
val guards = new ListBuffer[Tree]
val params = for ((acc, cpt) <- clazz.caseFieldAccessors zip constrParamTypes) yield {
- val name = context.unit.fresh.newName(acc.name+"$")
+ val name = context.unit.fresh.newName(clazz.pos, acc.name+"$")
val isVarArg = cpt.typeSymbol == RepeatedParamClass
guards += Apply(
Select(
@@ -185,16 +192,16 @@ trait SyntheticMethods { self: Analyzer =>
// but then it is renamed !!!
val method = newSyntheticMethod(nme.readResolve, PROTECTED,
MethodType(List(), ObjectClass.tpe))
- typed(DefDef(method, vparamss => gen.mkAttributedRef(clazz.sourceModule)))
+ typer.typed(DefDef(method, vparamss => gen.mkAttributedRef(clazz.sourceModule)))
}
def newAccessorMethod(tree: Tree): Tree = tree match {
case DefDef(_, _, _, _, _, rhs) =>
- val newAcc = tree.symbol.cloneSymbol
- newAcc.name = context.unit.fresh.newName(tree.symbol.name + "$")
+ var newAcc = tree.symbol.cloneSymbol
+ newAcc.name = context.unit.fresh.newName(tree.symbol.pos, tree.symbol.name + "$")
newAcc.setFlag(SYNTHETIC).resetFlag(ACCESSOR | PARAMACCESSOR | PRIVATE)
- newAcc.owner.info.decls enter newAcc
- val result = typed(DefDef(newAcc, vparamss => rhs.duplicate))
+ newAcc = newAcc.owner.info.decls enter newAcc
+ val result = typer.typed(DefDef(newAcc, vparamss => rhs.duplicate))
log("new accessor method " + result)
result
}
@@ -226,7 +233,7 @@ trait SyntheticMethods { self: Analyzer =>
def addBeanGetterMethod(sym: Symbol) = {
val getter = beanSetterOrGetter(sym)
if (getter != NoSymbol)
- ts += typed(DefDef(
+ ts += typer.typed(DefDef(
getter,
vparamss => if (sym hasFlag DEFERRED) EmptyTree else gen.mkAttributedRef(sym)))
}
@@ -234,7 +241,7 @@ trait SyntheticMethods { self: Analyzer =>
def addBeanSetterMethod(sym: Symbol) = {
val setter = beanSetterOrGetter(sym)
if (setter != NoSymbol)
- ts += typed(DefDef(
+ ts += typer.typed(DefDef(
setter,
vparamss =>
if (sym hasFlag DEFERRED) EmptyTree
@@ -257,7 +264,7 @@ trait SyntheticMethods { self: Analyzer =>
}
}
- if (clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod
+ if (!inIDE && clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod
if (clazz.isModuleClass) {
if (!hasOverridingImplementation(Object_toString)) ts += moduleToStringMethod
} else {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index cd852c8b50..1ef6b935e7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -44,7 +44,6 @@ trait Typers { self: Analyzer =>
superDefs.clear
}
- def newTyper(context: Context): Typer = new Typer(context)
object UnTyper extends Traverser {
override def traverse(tree: Tree) = {
@@ -53,12 +52,20 @@ trait Typers { self: Analyzer =>
super.traverse(tree)
}
}
- def makeNewScope(txt: Context, tree: Tree, sym: Symbol) =
- txt.makeNewScope(tree, sym)
+ // 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
+ }
- def newDecls(tree: CompoundTypeTree) = newScope
- def newDecls(tree: Template, clazz: Symbol) = newScope
- def newTemplateScope(impl: Template, clazz: Symbol) = newScope
// Mode constants
@@ -132,7 +139,7 @@ trait Typers { self: Analyzer =>
private def argMode(fun: Tree, mode: Int) =
if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode else mode
- class Typer(context0: Context) {
+ abstract class Typer(context0: Context) {
import context0.unit
val infer = new Inferencer(context0) {
@@ -177,9 +184,10 @@ trait Typers { self: Analyzer =>
*/
private def inferView(pos: Position, from: Type, name: Name, tp: Type, reportAmbiguous: Boolean): Tree = {
val to = refinedType(List(WildcardType), NoSymbol)
- val psym = (if (name.isTypeName) to.typeSymbol.newAbstractType(pos, name)
- else to.typeSymbol.newValue(pos, name)) setInfo tp
- to.decls.enter(psym)
+ var psym = (if (name.isTypeName) to.typeSymbol.newAbstractType(pos, name)
+ else to.typeSymbol.newValue(pos, name))
+ psym = to.decls enter psym
+ psym setInfo tp
inferView(pos, from, to, reportAmbiguous)
}
@@ -188,7 +196,7 @@ trait Typers { self: Analyzer =>
private var namerCache: Namer = null
def namer = {
if ((namerCache eq null) || namerCache.context != context)
- namerCache = new Namer(context)
+ namerCache = newNamer(context)
namerCache
}
@@ -346,7 +354,7 @@ trait Typers { self: Analyzer =>
this.scope = scope
hiddenSymbols = List()
val tp1 = apply(tree.tpe)
- if (hiddenSymbols.isEmpty) tree setType tp1
+ if (hiddenSymbols.isEmpty || inIDE) tree setType tp1 // @S: because arguments of classes are owned by the classes' owner
else if (hiddenSymbols exists (_.isErroneous)) setError(tree)
else if (isFullyDefined(pt)) tree setType pt //todo: eliminate
else if (tp1.typeSymbol.isAnonymousClass) // todo: eliminate
@@ -412,7 +420,10 @@ trait Typers { self: Analyzer =>
def reenterTypeParams(tparams: List[TypeDef]): List[Symbol] =
for (tparam <- tparams) yield {
- context.scope enter tparam.symbol
+ 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
}
@@ -446,7 +457,7 @@ trait Typers { self: Analyzer =>
*/
def labelTyper(ldef: LabelDef): Typer =
if (ldef.symbol == NoSymbol) { // labeldef is part of template
- val typer1 = newTyper(makeNewScope(context, ldef, context.owner))
+ val typer1 = newTyper(context.makeNewScope(ldef, context.owner))
typer1.enterLabelDef(ldef)
typer1
} else this
@@ -597,7 +608,7 @@ trait Typers { self: Analyzer =>
* If all this fails, error
*/
protected def adapt(tree: Tree, mode: int, pt: Type): Tree = tree.tpe match {
- case ct @ ConstantType(value) if ((mode & TYPEmode) == 0 && (ct <:< pt)) => // (0)
+ case ct @ ConstantType(value) if ((mode & TYPEmode) == 0 && (ct <:< pt) && !inIDE) => // (0)
copy.Literal(tree, value)
case OverloadedType(pre, alts) if ((mode & FUNmode) == 0) => // (1)
inferExprAlternative(tree, pt)
@@ -641,7 +652,7 @@ trait Typers { self: Analyzer =>
(pt <:< functionType(mt.paramTypes map (t => WildcardType), WildcardType))) { // (4.2)
if (settings.debug.value) log("eta-expanding "+tree+":"+tree.tpe+" to "+pt)
checkParamsConvertible(tree.pos, tree.tpe)
- typed(etaExpand(tree), mode, pt)
+ typed(etaExpand(context.unit, tree), mode, pt)
} else if (!meth.isConstructor && mt.paramTypes.isEmpty) { // (4.3)
adapt(typed(Apply(tree, List()) setPos tree.pos), mode, pt)
} else if (context.implicitsEnabled) {
@@ -781,9 +792,6 @@ trait Typers { self: Analyzer =>
}
}
}
-// Console.println("adapt "+tree+":"+tree.tpe+", mode = "+mode+", pt = "+pt)
-// adapt(tree, mode, pt)
-// }
/**
* @param tree ...
@@ -820,7 +828,8 @@ trait Typers { self: Analyzer =>
if (member(qual, name) != NoSymbol) qual
else adaptToMember(qual, name, WildcardType)
- private def typePrimaryConstrBody(cbody: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]]): Tree = {
+ private def typePrimaryConstrBody(clazz : Symbol, cbody: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]]): Tree = {
+ // XXX: see about using the class's symbol....
enclTparams foreach (sym => context.scope.enter(sym))
namer.enterValueParams(context.owner, vparamss)
typed(cbody)
@@ -879,8 +888,8 @@ trait Typers { self: Analyzer =>
val outercontext = context.outer
val cbody2 =
- newTyper(makeNewScope(outercontext, constr, outercontext.owner))
- .typePrimaryConstrBody(
+ newTyper(outercontext.makeNewScope(constr, outercontext.owner))
+ .typePrimaryConstrBody(clazz,
cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (_.map(_.duplicate)))
scall match {
@@ -952,7 +961,8 @@ trait Typers { self: Analyzer =>
//Console.println(context.owner);//DEBUG
//Console.println(context.owner.unsafeTypeParams);//DEBUG
//Console.println(List.fromArray(context.owner.info.closure));//DEBUG
- error(parent.pos, "illegal inheritance;\n self-type "+
+ // disable in IDE, don't know how else to avoid it on refresh
+ if (!inIDE) error(parent.pos, "illegal inheritance;\n self-type "+
selfType+" does not conform to "+parent +
"'s selftype "+parent.tpe.typeOfThis)
if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis)
@@ -992,10 +1002,15 @@ trait Typers { self: Analyzer =>
def typedClassDef(cdef: ClassDef): Tree = {
// attributes(cdef)
val typedMods = typedModifiers(cdef.mods)
- val clazz = cdef.symbol
+ val clazz = cdef.symbol;
+ if (inIDE && clazz == NoSymbol) {
+ assert(true)
+ throw new TypeError("type signature typing failed")
+ }
+ assert(clazz != NoSymbol)
reenterTypeParams(cdef.tparams)
val tparams1 = List.mapConserve(cdef.tparams)(typedTypeDef)
- val impl1 = newTyper(context.make(cdef.impl, clazz, newTemplateScope(cdef.impl, clazz)))
+ val impl1 = newTyper(context.make(cdef.impl, clazz, scopeFor(cdef.impl)))
.typedTemplate(cdef.impl, parentTypes(cdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
copy.ClassDef(cdef, typedMods, cdef.name, tparams1, impl2)
@@ -1011,7 +1026,9 @@ trait Typers { self: Analyzer =>
// attributes(mdef)
val typedMods = typedModifiers(mdef.mods)
val clazz = mdef.symbol.moduleClass
- val impl1 = newTyper(context.make(mdef.impl, clazz, newTemplateScope(mdef.impl, clazz)))
+ if (inIDE && clazz == NoSymbol) throw new TypeError("bad signature")
+ assert(clazz != NoSymbol)
+ val impl1 = newTyper(context.make(mdef.impl, clazz, scopeFor(mdef.impl)))
.typedTemplate(mdef.impl, parentTypes(mdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
@@ -1029,7 +1046,10 @@ trait Typers { self: Analyzer =>
&& !stat.symbol.hasFlag(LAZY) =>
val vdef = copy.ValDef(stat, mods | PRIVATE | LOCAL, nme.getterToLocal(name), tpt, rhs)
val value = vdef.symbol
- val getter = if ((mods hasFlag DEFERRED) || inIDE) value else value.getter(value.owner)
+ val getter = if ((mods hasFlag DEFERRED)) value else value.getter(value.owner)
+ // XXX:
+ if (inIDE && getter == NoSymbol)
+ return Nil
assert(getter != NoSymbol, stat)
if (getter hasFlag OVERLOADED)
error(getter.pos, getter+" is defined twice")
@@ -1080,7 +1100,7 @@ trait Typers { self: Analyzer =>
protected def enterSym(txt: Context, tree: Tree): Context =
if (txt eq context) namer.enterSym(tree)
- else new Namer(txt).enterSym(tree)
+ else newNamer(txt).enterSym(tree)
/**
* @param templ ...
@@ -1090,7 +1110,7 @@ trait Typers { self: Analyzer =>
def typedTemplate(templ: Template, parents1: List[Tree]): Template = {
val clazz = context.owner
if (templ.symbol == NoSymbol)
- templ setSymbol clazz.newLocalDummy(templ.pos)
+ templ setSymbol newLocalDummy(clazz, templ.pos)
val self1 = templ.self match {
case vd @ ValDef(mods, name, tpt, EmptyTree) =>
val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(tpt))
@@ -1102,9 +1122,12 @@ trait Typers { self: Analyzer =>
intersectionType(clazz.info.parents, clazz.owner)
else clazz.typeOfThis
// the following is necessary for templates generated later
- enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templ.body)
+ 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)
validateParentClasses(parents1, selfType)
- if (!phase.erasedTypes)
+ if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members
checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType])
val body =
if (phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)
@@ -1131,7 +1154,10 @@ trait Typers { self: Analyzer =>
val typer1 = constrTyperIf(sym.hasFlag(PARAM) && sym.owner.isConstructor)
val typedMods = typedModifiers(vdef.mods)
- val tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt))
+ var tpt1 = checkNoEscaping.privates(sym, typer1.typedType({
+ if (inIDE) vdef.tpt.duplicate // avoids wrong context sticking
+ else vdef.tpt
+ }))
checkNonCyclic(vdef, tpt1)
val rhs1 =
if (vdef.rhs.isEmpty) {
@@ -1139,7 +1165,9 @@ trait Typers { self: Analyzer =>
error(vdef.pos, "local variables must be initialized")
vdef.rhs
} else {
- newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(vdef.rhs, tpt1.tpe)
+ //assert(vdef.rhs.tpe == null)
+ val rhs = if (inIDE && vdef.rhs.tpe != null) vdef.rhs.duplicate else vdef.rhs
+ newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(rhs, tpt1.tpe)
}
copy.ValDef(vdef, typedMods, vdef.name, tpt1, checkDead(rhs1)) setType NoType
}
@@ -1155,11 +1183,14 @@ trait Typers { self: Analyzer =>
def decompose(call: Tree): (Tree, List[Tree]) = call match {
case Apply(fn, args) =>
val (superConstr, args1) = decompose(fn)
- val formals = fn.tpe.paramTypes
+ val formals = (if (fn.tpe == null && inIDE) ErrorType else fn.tpe).paramTypes
val args2 = if (formals.isEmpty || formals.last.typeSymbol != RepeatedParamClass) args
else args.take(formals.length - 1) ::: List(EmptyTree)
- if (args2.length != formals.length)
- assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug
+ if (args2.length != formals.length) {
+ if (!inIDE)
+ assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug
+ else error(call.pos, "XXX: mismatch " + clazz + " " + formals + " " + args2)
+ }
(superConstr, args1 ::: args2)
case Block(stats, expr) if !stats.isEmpty =>
decompose(stats.last)
@@ -1198,6 +1229,12 @@ trait Typers { self: Analyzer =>
}
()
}
+ } else if (inIDE) { // XXX: maybe add later
+ Console.println("" + superClazz + ":" +
+ superClazz.info.decls.toList.filter(_.hasFlag(PARAMACCESSOR)))
+ error(rhs.pos, "mismatch: " + superParamAccessors +
+ ";" + rhs + ";" + superClazz.info.decls)//debug
+ return
}
}
}
@@ -1215,6 +1252,7 @@ trait Typers { self: Analyzer =>
*/
def typedDefDef(ddef: DefDef): DefDef = {
val meth = ddef.symbol
+ if (inIDE && meth == NoSymbol) throw new TypeError("bad signature")
reenterTypeParams(ddef.tparams)
reenterValueParams(ddef.vparamss)
val tparams1 = List.mapConserve(ddef.tparams)(typedTypeDef)
@@ -1240,7 +1278,8 @@ trait Typers { self: Analyzer =>
error(ddef.pos, "constructor definition not allowed here")
typed(ddef.rhs)
} else {
- transformedOrTyped(ddef.rhs, tpt1.tpe)
+ if (inIDE && ddef.rhs == EmptyTree) EmptyTree
+ else transformedOrTyped(ddef.rhs, tpt1.tpe)
}
if (meth.isPrimaryConstructor && meth.isClassConstructor &&
phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)
@@ -1310,8 +1349,7 @@ trait Typers { self: Analyzer =>
if (stat.isDef) context.scope.enter(stat.symbol)
}
}
- if (!inIDE)
- namer.enterSyms(block.stats)
+ namer.enterSyms(block.stats)
block.stats foreach enterLabelDef
val stats1 = typedStats(block.stats, context.owner)
val expr1 = typed(block.expr, mode & ~(FUNmode | QUALmode), pt)
@@ -1359,7 +1397,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(makeNewScope(context, cdef, context.owner)).typedCase(cdef, pattp, pt))
+ newTyper(context.makeNewScope(cdef, context.owner)).typedCase(cdef, pattp, pt))
/* not yet!
cdef.pat match {
case Literal(Constant(null)) =>
@@ -1410,8 +1448,6 @@ trait Typers { self: Analyzer =>
vparam.symbol
}
// XXX: here to for IDE hooks.
- if (inIDE) // HACK to process arguments types in IDE.
- typedFunctionIDE(fun, context);
val vparams = List.mapConserve(fun.vparams)(typedValDef)
// for (val vparam <- vparams) {
// checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); ()
@@ -1430,8 +1466,7 @@ trait Typers { self: Analyzer =>
}
def typedRefinement(stats: List[Tree]): List[Tree] = {
- if (!inIDE)
- namer.enterSyms(stats)
+ namer.enterSyms(stats)
val stats1 = typedStats(stats, NoSymbol)
for (stat <- stats1 if stat.isDef) {
val member = stat.symbol
@@ -1457,14 +1492,21 @@ trait Typers { self: Analyzer =>
context = context.makeNewImport(imp0)
imp0.symbol.initialize
}
- EmptyTree
+ if ((imp0 ne null) && inIDE) {
+ imp0.symbol.info match {
+ case ImportType(exr) =>
+ imp0.expr.tpe = exr.tpe
+ case _ =>
+ }
+ imp0
+ } else EmptyTree
case _ =>
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
else newTyper(context.make(stat, exprOwner))
val result = checkDead(localTyper.typed(stat))
if (treeInfo.isSelfOrSuperConstrCall(result)) {
context.inConstructorSuffix = true
- if (treeInfo.isSelfConstrCall(result) && result.symbol.pos.offset.get(0) >= exprOwner.enclMethod.pos.offset.get(0))
+ if (!inIDE && treeInfo.isSelfConstrCall(result) && result.symbol.pos.offset.get(0) >= exprOwner.enclMethod.pos.offset.get(0))
error(stat.pos, "called constructor's definition must precede calling constructor's definition")
}
result
@@ -1482,7 +1524,7 @@ trait Typers { self: Analyzer =>
while ((e1 ne null) && e1.owner == scope) {
if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
(e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe)))
- if (!e.sym.isErroneous && !e1.sym.isErroneous)
+ if (!e.sym.isErroneous && !e1.sym.isErroneous && !inIDE)
error(e.sym.pos, e1.sym+" is defined twice"+
{if(!settings.debug.value) "" else " in "+unit.toString});
e1 = scope.lookupNextEntry(e1);
@@ -1593,7 +1635,7 @@ trait Typers { self: Analyzer =>
}
}
- if (fun.symbol == List_apply && args.isEmpty) {
+ if (!inIDE && fun.symbol == List_apply && args.isEmpty) {
atPos(tree.pos) { gen.mkNil setType restpe }
} else
constfold(copy.Apply(tree, fun, args2).setType(ifPatternSkipFormals(restpe)))
@@ -1618,8 +1660,9 @@ 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 = doTypedApply(tree, fun, args2, mode, pt)
- context.undetparams = undetparams
+ val result = if (!inIDE) doTypedApply(tree, fun, args2, mode, pt)
+ else doTypedApply(tree.duplicate,fun.duplicate,args2.map(_.duplicate),mode,pt)
+ context.undetparams = undetparams
result
}
}
@@ -1637,6 +1680,7 @@ trait Typers { self: Analyzer =>
assert(unapp.exists, tree)
val unappType = otpe.memberType(unapp)
val argDummyType = pt // was unappArg
+ // @S: do we need to memoize this?
val argDummy = context.owner.newValue(fun.pos, nme.SELECTOR_DUMMY)
.setFlag(SYNTHETIC)
.setInfo(argDummyType)
@@ -1659,7 +1703,7 @@ trait Typers { self: Analyzer =>
val (unappFormal, freeVars) = freshArgType(unappType)
val context1 = context.makeNewScope(context.tree, context.owner)
freeVars foreach(sym => context1.scope.enter(sym))
- val typer1 = new Typer(context1)
+ val typer1 = newTyper(context1)
arg.tpe = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
//todo: replace arg with arg.asInstanceOf[inferTypedPattern(unappFormal, arg.tpe)] instead.
argDummy.setInfo(arg.tpe) // bq: this line fixed #1281. w.r.t. comment ^^^, maybe good enough?
@@ -1833,10 +1877,10 @@ trait Typers { self: Analyzer =>
val typeParams: List[Symbol] = rawSyms map { sym =>
val name = if (sym.isType) sym.name else newTypeName(sym.name+".type")
val bound = existentialBound(sym)
- val quantified: Symbol = sym.owner.newAbstractType(sym.pos, name)
- quantified setFlag EXISTENTIAL setInfo bound.cloneInfo(quantified)
+ val quantified: Symbol = recycle(sym.owner.newAbstractType(sym.pos, name))
+ trackSetInfo(quantified setFlag EXISTENTIAL)(bound.cloneInfo(quantified))
}
- val typeParamTypes = typeParams map (_.tpe)
+ val typeParamTypes = typeParams map (_.tpe) // don't trackSetInfo here, since type already set!
for (tparam <- typeParams) tparam.setInfo(tparam.info.subst(rawSyms, typeParamTypes))
(typeParams, tp.subst(rawSyms, typeParamTypes))
}
@@ -1916,10 +1960,9 @@ trait Typers { self: Analyzer =>
case t =>
t
}
- val local = sym.owner.newAbstractType(
- sym.pos, unit.fresh.newName(sym.name.toString))
- .setFlag(sym.flags)
- .setInfo(bound)
+ val local = trackSetInfo(recycle(sym.owner.newAbstractType(
+ sym.pos, unit.fresh.newName(sym.pos, sym.name.toString))
+ .setFlag(sym.flags)))(bound)
localInstances += (inst -> local)
addLocals(bound)
}
@@ -2015,8 +2058,10 @@ trait Typers { self: Analyzer =>
else
context.owner.newAbstractType(tree.pos, name) setInfo
mkTypeBounds(AllClass.tpe, AnyClass.tpe)
- if (vble.name == nme.WILDCARD.toTypeName) context.scope.enter(vble)
- else namer.enterInScope(vble)
+ val rawInfo = vble.rawInfo
+ vble = if (vble.name == nme.WILDCARD.toTypeName) context.scope.enter(vble)
+ else namer.enterInScope(vble)
+ trackSetInfo(vble)(rawInfo) // vble could have been recycled, detect changes in type
tree setSymbol vble setType vble.tpe
} else {
if (vble == NoSymbol)
@@ -2031,10 +2076,10 @@ trait Typers { self: Analyzer =>
*/
if ((mode & ALTmode) != 0)
error(tree.pos, "illegal variable in pattern alternative")
- namer.enterInScope(vble)
+ vble = namer.enterInScope(vble)
}
val body1 = typed(body, mode, pt)
- vble.setInfo(
+ trackSetInfo(vble)(
if (treeInfo.isSequenceValued(body)) seqType(body1.tpe)
else body1.tpe)
copy.Bind(tree, name, body1) setSymbol vble setType body1.tpe // buraq, was: pt
@@ -2100,12 +2145,17 @@ trait Typers { self: Analyzer =>
errorTree(tree, "return outside method definition")
} else {
val DefDef(_, _, _, _, restpt, _) = enclMethod.tree
- if (restpt.tpe eq null) {
- errorTree(tree, "method " + enclMethod.owner +
+ var restpt0 = restpt
+ if (inIDE && (restpt0.tpe eq null)) {
+ assert(true)
+ restpt0 = typed(restpt0, TYPEmode, WildcardType)
+ }
+ if (restpt0.tpe eq null) {
+ errorTree(tree, "" + enclMethod.owner +
" has return statement; needs result type")
} else {
context.enclMethod.returnsSeen = true
- val expr1: Tree = typed(expr, restpt.tpe)
+ val expr1: Tree = typed(expr, restpt0.tpe)
copy.Return(tree, checkDead(expr1)) setSymbol enclMethod.owner setType AllClass.tpe
}
}
@@ -2372,7 +2422,7 @@ trait Typers { self: Analyzer =>
if ((mode & SUPERCONSTRmode) != 0) clazz.info.parents.head
else intersectionType(clazz.info.parents)
else {
- val ps = clazz.info.parents filter (p => p.typeSymbol.name == mix)
+ val ps = clazz.info.parents filter (p => compare(p.typeSymbol, mix))
if (ps.isEmpty) {
if (settings.debug.value)
Console.println(clazz.info.parents map (_.typeSymbol.name))//debug
@@ -2429,7 +2479,8 @@ trait Typers { self: Analyzer =>
}
tree.symbol
} else {
- member(qual, name)
+ if (!inIDE) member(qual, name)
+ else verifyAndPrioritize(_ filter (alt => context.isAccessible(alt, qual.tpe, qual.isInstanceOf[Super])))(pt)(member(qual,name))
}
if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) {
val qual1 = adaptToName(qual, name)
@@ -2510,6 +2561,7 @@ trait Typers { self: Analyzer =>
((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) ||
!sym.isSourceMethod || sym.isCaseFactory)
+
if (defSym == NoSymbol) {
var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope
@@ -2520,22 +2572,23 @@ trait Typers { self: Analyzer =>
while (defSym == NoSymbol && cx != NoContext) {
pre = cx.enclClass.prefix
- defEntry = cx.scope.lookupEntry(name)
- if (inIDE && (defEntry ne null) && defEntry.sym.exists) {
- val sym = defEntry.sym
- val namePos : Position = tree.pos
- val symPos : Position = sym.pos
- if (namePos.offset.get < symPos.offset.get) defEntry = null
- }
+ defEntry = if (!inIDE) cx.scope.lookupEntry(name)
+ else verifyAndPrioritize(sym => sym)(pt)(cx.scope.lookupEntry(name))
if ((defEntry ne null) && qualifies(defEntry.sym)) {
defSym = defEntry.sym
- } else if (inIDE) {
- if (cx.outer == cx.enclClass) {
- cx = cx.enclClass
- defSym = pre.member(name) filter (
- sym => sym.exists && context.isAccessible(sym, pre, false))
+ } else if (inIDE) { // IDE: cannot rely on linked scopes.
+ if (cx.outer.owner eq cx.enclClass.owner) {
+ //cx = cx.outer
+ defSym =
+ verifyAndPrioritize{ // enables filtering of auto completion
+ _ filter (sym => qualifies(sym) && context.isAccessible(sym, pre, false))
+ }(pt)(pre.member(name) filter (
+ sym => qualifies(sym) && context.isAccessible(sym, pre, false)))
}
- if (defSym == NoSymbol) cx = cx.outer
+ val oldScope = cx.scope
+ cx = cx.outer
+ while (cx.scope == oldScope && !(cx.outer.owner eq cx.enclClass.owner)) // can't skip
+ cx = cx.outer
} else {
cx = cx.enclClass
defSym = pre.member(name) filter (
@@ -2562,7 +2615,7 @@ trait Typers { self: Analyzer =>
// imported symbols take precedence over package-owned symbols in different
// compilation units. Defined symbols take precedence over errenous imports.
if (defSym.owner.isPackageClass &&
- (!currentRun.compiles(defSym) ||
+ ((!inIDE && !currentRun.compiles(defSym)) ||
(context.unit ne null) && defSym.sourceFile != context.unit.source.file))
defSym = NoSymbol
else if (impSym.isError)
@@ -2614,9 +2667,14 @@ trait Typers { self: Analyzer =>
}
}
if (defSym.owner.isPackageClass) pre = defSym.owner.thisType
- if (defSym.isThisSym) typed1(This(defSym.owner) setPos tree.pos, mode, pt)
+ if (defSym.isThisSym) {
+ val tree1 = typed1(This(defSym.owner) setPos tree.pos, mode, pt)
+ if (inIDE) {
+ Ident(defSym.name) setType tree1.tpe setSymbol defSym setPos tree.pos
+ } else tree1
+ }
else {
- val tree1 = if (qual == EmptyTree) tree
+ var tree1 = if (qual == EmptyTree) tree
else atPos(tree.pos)(Select(qual, name))
// atPos necessary because qualifier might come from startContext
stabilize(checkAccessible(tree1, defSym, pre, qual), pre, mode, pt)
@@ -2627,7 +2685,7 @@ trait Typers { self: Analyzer =>
val parents1 = List.mapConserve(templ.parents)(typedType)
if (parents1 exists (_.tpe.isError)) tree setType ErrorType
else {
- val decls = newDecls(tree.asInstanceOf[CompoundTypeTree])
+ val decls = scopeFor(tree)
val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls)
newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ.body)
tree setType self
@@ -2636,6 +2694,8 @@ trait Typers { self: Analyzer =>
def typedAppliedTypeTree(tpt: Tree, args: List[Tree]) = {
val tpt1 = typed1(tpt, mode | FUNmode | TAPPmode, WildcardType)
+ // @S: shouldn't be necessary now, fixed a problem with SimpleTypeProxy not relaying typeParams calls.
+ // if (inIDE) tpt1.symbol.info // @S: seems like typeParams call doesn't force completion of symbol type in IDE.
val tparams = tpt1.symbol.typeParams
if (tpt1.tpe.isError) {
@@ -2654,7 +2714,7 @@ trait Typers { self: Analyzer =>
// note: can't use args1 in selector, because Bind's got replaced
case Bind(_, _) =>
if (arg.symbol.isAbstractType)
- arg.symbol setInfo
+ arg.symbol setInfo // XXX, feedback. don't trackSymInfo here!
TypeBounds(lub(List(arg.symbol.info.bounds.lo, tparam.info.bounds.lo)),
glb(List(arg.symbol.info.bounds.hi, tparam.info.bounds.hi)))
case _ =>
@@ -2675,24 +2735,25 @@ trait Typers { self: Analyzer =>
//if (settings.debug.value && tree.isDef) log("typing definition of "+sym);//DEBUG
tree match {
case PackageDef(name, stats) =>
+ assert(sym.moduleClass ne NoSymbol)
val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
.typedStats(stats, NoSymbol)
copy.PackageDef(tree, name, stats1) setType NoType
case tree @ ClassDef(_, _, _, _) =>
- newTyper(makeNewScope(context, tree, sym)).typedClassDef(tree)
+ newTyper(context.makeNewScope(tree, sym)).typedClassDef(tree)
case tree @ ModuleDef(_, _, _) =>
- newTyper(makeNewScope(context, tree, sym.moduleClass)).typedModuleDef(tree)
+ newTyper(context.makeNewScope(tree, sym.moduleClass)).typedModuleDef(tree)
case vdef @ ValDef(_, _, _, _) =>
typedValDef(vdef)
case ddef @ DefDef(_, _, _, _, _, _) =>
- newTyper(makeNewScope(context, tree, sym)).typedDefDef(ddef)
+ newTyper(context.makeNewScope(tree, sym)).typedDefDef(ddef)
case tdef @ TypeDef(_, _, _, _) =>
- newTyper(makeNewScope(context, tree, sym)).typedTypeDef(tdef)
+ newTyper(context.makeNewScope(tree, sym)).typedTypeDef(tdef)
case ldef @ LabelDef(_, _, _) =>
labelTyper(ldef).typedLabelDef(ldef)
@@ -2712,7 +2773,7 @@ trait Typers { self: Analyzer =>
typedAnnotated(annot, typed(arg, mode, pt))
case tree @ Block(_, _) =>
- newTyper(makeNewScope(context, tree, context.owner))
+ newTyper(context.makeNewScope(tree, context.owner))
.typedBlock(tree, mode, pt)
case Sequence(elems) =>
@@ -2753,9 +2814,9 @@ trait Typers { self: Analyzer =>
case tree @ Function(_, _) =>
if (tree.symbol == NoSymbol)
- tree.symbol = context.owner.newValue(tree.pos, nme.ANON_FUN_NAME)
- .setFlag(SYNTHETIC).setInfo(NoType)
- newTyper(makeNewScope(context, tree, tree.symbol)).typedFunction(tree, mode, pt)
+ tree.symbol = recycle(context.owner.newValue(tree.pos, nme.ANON_FUN_NAME)
+ .setFlag(SYNTHETIC).setInfo(NoType))
+ newTyper(context.makeNewScope(tree, tree.symbol)).typedFunction(tree, mode, pt)
case Assign(lhs, rhs) =>
typedAssign(lhs, rhs)
@@ -2763,11 +2824,12 @@ trait Typers { self: Analyzer =>
case If(cond, thenp, elsep) =>
typedIf(cond, thenp, elsep)
- case Match(selector, cases) =>
+ case tree @ Match(selector, cases) =>
if (selector == EmptyTree) {
val arity = if (isFunctionType(pt)) pt.normalize.typeArgs.length - 1 else 1
val params = for (i <- List.range(0, arity)) yield
- ValDef(Modifiers(PARAM | SYNTHETIC), unit.fresh.newName("x$"), TypeTree(), EmptyTree)
+ ValDef(Modifiers(PARAM | SYNTHETIC),
+ unit.fresh.newName(tree.pos, "x" + i + "$"), TypeTree(), EmptyTree)
val ids = for (p <- params) yield Ident(p.name)
val selector1 = atPos(tree.pos) { if (arity == 1) ids.head else gen.mkTuple(ids) }
val body = copy.Match(tree, selector1, cases)
@@ -2920,14 +2982,14 @@ trait Typers { self: Analyzer =>
copy.TypeBoundsTree(tree, lo1, hi1) setType mkTypeBounds(lo1.tpe, hi1.tpe)
case etpt @ ExistentialTypeTree(_, _) =>
- newTyper(makeNewScope(context, tree, context.owner)).typedExistentialTypeTree(etpt)
+ newTyper(context.makeNewScope(tree, context.owner)).typedExistentialTypeTree(etpt)
case TypeTree() =>
// we should get here only when something before failed
// and we try again (@see tryTypedApply). In that case we can assign
// whatever type to tree; we just have to survive until a real error message is issued.
tree setType AnyClass.tpe
-
+ case EmptyTree if inIDE => EmptyTree // just tolerate it in the IDE.
case _ =>
throw new Error("unexpected tree: " + tree.getClass + "\n" + tree)//debug
}