From 8c06a1a54516bbbeed907da3446b372b732c4329 Mon Sep 17 00:00:00 2001 From: Sean McDirmid Date: Wed, 4 Jun 2008 13:08:18 +0000 Subject: Fixing problem with case classes and companion ... Fixing problem with case classes and companion objects --- .../scala/tools/nsc/symtab/IdeSupport.scala | 35 +++-------------- .../scala/tools/nsc/typechecker/Analyzer.scala | 2 +- .../scala/tools/nsc/typechecker/IdeSupport.scala | 44 ++++++++++------------ .../scala/tools/nsc/typechecker/Namers.scala | 20 +++++++--- 4 files changed, 40 insertions(+), 61 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala b/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala index f8e74a2610..0805d4f820 100644 --- a/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala +++ b/src/compiler/scala/tools/nsc/symtab/IdeSupport.scala @@ -88,32 +88,6 @@ trait IdeSupport extends SymbolTable { // added to global, not analyzers. } 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(MODULE)) e = scope.lookupNextEntry(e) - if (e != null) { - // try to find apply method. - e.sym.moduleClass.rawInfo match { - case ClassInfoType(_,decls : PersistentScope,_) => - val list = reuseMap.get(decls) match { - case Some(list) => list - case None => - val list = new jcl.LinkedList[Symbol] - reuseMap(decls) = list; list - } - decls.toList.foreach{ae=> - if (ae.hasFlag(CASE) && ae.hasFlag(SYNTHETIC)) { - list += ae - decls unlink ae - } - } - case eee => - assert(eee != null) - } - } - } // if def is abstract, will only unlink its name if (sym.isGetter) { val setter = scope lookup nme.getterToSetter(sym.name) @@ -159,7 +133,7 @@ trait IdeSupport extends SymbolTable { // added to global, not analyzers. if (currentClient.makeNoChanges) return scope val buf = new jcl.LinkedList[Symbol] scope.toList.foreach{sym => - if (sym.hasFlag(Flags.CASE) && sym.hasFlag(Flags.SYNTHETIC)) { + if (false && sym.hasFlag(Flags.CASE) && sym.hasFlag(Flags.SYNTHETIC)) { assert(sym != null) } else { buf add sym @@ -402,7 +376,8 @@ trait IdeSupport extends SymbolTable { // added to global, not analyzers. finish(existing) } else if ({ - (symbol.pos,existing.pos) match { + if (existing.hasFlag(symtab.Flags.SYNTHETIC) && existing.name == symbol.name) true + else (symbol.pos,existing.pos) match { case (apos : TrackedPosition, bpos : TrackedPosition) => apos == bpos case (apos : OffsetPosition , bpos : OffsetPosition) => apos == bpos case _ => existing.name == symbol.name @@ -466,8 +441,8 @@ trait IdeSupport extends SymbolTable { // added to global, not analyzers. } // because module var shares space with monomorphic. if (existing.isModuleVar != symbol.isModuleVar) return NotCompatible - if ((existing.flags|LOCKED|INTERFACE|MONOMORPHIC|DEFERRED|ABSTRACT|PRIVATE|PROTECTED|FINAL|SEALED|CASE) != - (symbol. flags|LOCKED|INTERFACE|MONOMORPHIC|DEFERRED|ABSTRACT|PRIVATE|PROTECTED|FINAL|SEALED|CASE)) { + if ((existing.flags|LOCKED|INTERFACE|MONOMORPHIC|DEFERRED|ABSTRACT|PRIVATE|PROTECTED|FINAL|SEALED|CASE|SYNTHETIC) != + (symbol. flags|LOCKED|INTERFACE|MONOMORPHIC|DEFERRED|ABSTRACT|PRIVATE|PROTECTED|FINAL|SEALED|CASE|SYNTHETIC)) { return NotCompatible } if (((existing.flags&(MONOMORPHIC|INTERFACE)) != 0) || diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala index 50fbc23c3d..bca41b1fee 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala @@ -35,7 +35,7 @@ trait Analyzer extends AnyRef val global: Analyzer.this.global.type = Analyzer.this.global val phaseName = "typer" def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) { - resetTyper() + if (!inIDE) resetTyper() def apply(unit: CompilationUnit) { unit.body = newTyper(rootContext(unit)).typed(unit.body) } diff --git a/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala b/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala index 32bc7511a6..4b36bd148c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala +++ b/src/compiler/scala/tools/nsc/typechecker/IdeSupport.scala @@ -75,7 +75,7 @@ trait IdeSupport extends Analyzer { } //if (!hadTypeErrors && pos.owner != null && pos.owner.hasTypeErrors) pos.owner.dirtyTyped - if (pos.owner != null && pos.owner.hasTypeErrors) { + if (pos.owner != null && pos.owner.hasTypeErrors && (!sym0.rawInfo.isComplete || sym0.info == NoType || sym0.info == ErrorType)) { // go back to original type. val oldType = oldTypeFor(sym0) if (oldType != NoType) @@ -178,6 +178,7 @@ trait IdeSupport extends Analyzer { 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! @@ -193,21 +194,6 @@ trait IdeSupport extends Analyzer { } import symtab.Flags._ val set = reuseMap.get(namer.context.scope.asInstanceOf[PersistentScope]) - if (sym.isClass && sym.hasFlag(CASE)) { - // case class, re-add apply unapply methods to module scope - val name = sym.name.toTermName - var e = namer.context.scope.lookupEntry(name) - while (e != null && !e.sym.hasFlag(MODULE)) e = namer.context.scope.lookupNextEntry(e) - if (e != null) e.sym.rawInfo match { - case ClassInfoType(_,decls: PersistentScope,_) => - val set = reuseMap.get(decls) - set.foreach(_.foreach{sym=> - if (sym.hasFlag(CASE) && sym.hasFlag(SYNTHETIC)) - decls enter sym - }) - case _ => - } - } // 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 { @@ -240,6 +226,18 @@ trait IdeSupport extends Analyzer { } case _ => }; if (trees.isEmpty) NoSymbol else trees.last.symbol } + import symtab.Flags._ + if (!typeIsDirty) lastTyped.foreach{ + case tree :DefTree if tree.symbol != null && tree.symbol != NoSymbol && tree.symbol.isClass && tree.symbol.hasFlag(CASE) => + var e = namer.context.scope.lookupEntry(tree.symbol.name.toTermName) + while (e != null && !e.sym.hasFlag(MODULE)) e = namer.context.scope.lookupNextEntry(e) + Console.println("CHECKING: " + e + " " + (if (e != null) caseClassOfModuleClass.contains(e.sym.moduleClass))) + if (e == null) dirtyTyped + // we don't clear caseClassOfModuleClass unless we have to. + else if (!caseClassOfModuleClass.contains(e.sym.moduleClass)) dirtyTyped + case tree : DefTree if tree.symbol != null && tree.symbol != NoSymbol => + case _ => + } if (makeNoChanges) {} else if (!typeIsDirty && !lastTyped.isEmpty) @@ -265,23 +263,19 @@ trait IdeSupport extends Analyzer { } 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) }) - use.foreach{tree=> + if (!makeNoChanges) use.foreach{tree=> if (tree.symbol.isClass && tree.symbol.hasFlag(symtab.Flags.CASE) && tree.symbol.owner.rawInfo.isComplete) { var e = tree.symbol.owner.info.decls.lookupEntry(tree.symbol.name.toTermName) - if (e != null) e.sym.pos match { - case pos : TrackedPosition if pos.owner != null => + assert(e != null) // should have been entered already. + e.sym.pos match { // retype the object if its in the scope. + case pos : TrackedPosition if pos.owner != null && pos.owner != MemoizedTree.this => assert(true) - pos.owner.dirtyTyped - pos.owner.doTyper + pos.owner.dirtyTyped // hope this works! case _ => } () diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 2a1bbe1001..05521a0865 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -43,7 +43,7 @@ trait Namers { self: Analyzer => private class NormalNamer(context : Context) extends Namer(context) def newNamer(context : Context) : Namer = new NormalNamer(context) - private val caseClassOfModuleClass = new HashMap[Symbol, ClassDef] + private[typechecker] val caseClassOfModuleClass = new HashMap[Symbol, ClassDef] def resetNamer() { caseClassOfModuleClass.clear @@ -226,8 +226,8 @@ trait Namers { self: Analyzer => // .pos, mods.flags | MODULE | FINAL, name var m: Symbol = context.scope.lookupWithContext(tree.name)(context.owner) val moduleFlags = tree.mods.flags | MODULE | FINAL - if (!inIDE && m.isModule && !m.isPackage && inCurrentScope(m) && - (!currentRun.compiles(m) || (m hasFlag SYNTHETIC))) { + if (m.isModule && !m.isPackage && inCurrentScope(m) && + ((!inIDE && !currentRun.compiles(m)) || (m hasFlag SYNTHETIC))) { updatePosFlags(m, tree.pos, moduleFlags) setPrivateWithin(tree, m, tree.mods) context.unit.synthetics -= m @@ -546,8 +546,18 @@ trait Namers { self: Analyzer => // unless they exist already Namers.this.caseClassOfModuleClass get clazz match { case Some(cdef) => - addApplyUnapply(cdef, templateNamer) - caseClassOfModuleClass -= clazz + val go = if (inIDE) { // garbage collect in the presentaiton compiler. + assert(cdef.symbol != null && cdef.symbol != NoSymbol) + if (!cdef.symbol.isClass || !cdef.symbol.hasFlag(CASE) || cdef.symbol.rawInfo == NoType) false + else true + } else true + if (go) + addApplyUnapply(cdef, templateNamer) + if (!go || !inIDE) caseClassOfModuleClass -= clazz + if (!go) { + val rem = clazz.linkedModuleOfClass + assert(rem != NoSymbol) + } case None => } ClassInfoType(parents, decls, clazz) -- cgit v1.2.3