diff options
author | Martin Odersky <odersky@gmail.com> | 2009-07-30 07:41:22 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-07-30 07:41:22 +0000 |
commit | db045cb8ddbd725fc545da5296bf0cdd722c20ce (patch) | |
tree | ba2b4458a1b61e4d90beb917c087458dc117f860 | |
parent | 74a6eeaf0948cbf59e327108c47aa41013c7fb9f (diff) | |
download | scala-db045cb8ddbd725fc545da5296bf0cdd722c20ce.tar.gz scala-db045cb8ddbd725fc545da5296bf0cdd722c20ce.tar.bz2 scala-db045cb8ddbd725fc545da5296bf0cdd722c20ce.zip |
rewrite of positions in compiler
39 files changed, 523 insertions, 607 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index e842c96641..e65469e0a4 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -31,7 +31,6 @@ import backend.jvm.GenJVM import backend.msil.GenMSIL import backend.opt.{Inliners, ClosureElimination, DeadCodeElimination} import backend.icode.analysis._ -import interactive._ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable with CompilationUnits diff --git a/src/compiler/scala/tools/nsc/interactive/Positions.scala b/src/compiler/scala/tools/nsc/Positions.scala index b8be2b1fbb..88c54e6671 100755 --- a/src/compiler/scala/tools/nsc/interactive/Positions.scala +++ b/src/compiler/scala/tools/nsc/Positions.scala @@ -1,8 +1,7 @@ package scala.tools.nsc -package interactive import ast.Trees -import scala.tools.nsc.util.{SourceFile, Position, RangePosition, OffsetPosition, NoPosition, SyntheticOffsetPosition, WorkScheduler} +import scala.tools.nsc.util.{SourceFile, Position, RangePosition, OffsetPosition, NoPosition, WorkScheduler} import scala.collection.mutable.ListBuffer trait Positions { @@ -18,7 +17,12 @@ self: scala.tools.nsc.Global => */ def wrappingPos(trees: List[Tree]): Position = trees.head.pos - def makeTransparent(pos: Position) = pos + /** Ensure that given tree has no positions that overlap with + * any of the positions of `others`. This is done by + * shortening the range or assinging TransparentPositions + * to some of the nodes in `tree`. + */ + def ensureNonOverlapping(tree: Tree, others: List[Tree]) {} def validatePositions(tree: Tree) {} } diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 2baf578914..edfca57be6 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -244,7 +244,7 @@ abstract class TreeGen // var m$: T = null; or, if class member: local var m$: T = _; def mkModuleVarDef(accessor: Symbol) = { - val mvar = accessor.owner.newVariable(accessor.pos.toSynthetic, nme.moduleVarName(accessor.name)) + val mvar = accessor.owner.newVariable(accessor.pos.focus, nme.moduleVarName(accessor.name)) .setInfo(accessor.tpe.finalResultType) .setFlag(MODULEVAR); if (mvar.owner.isClass) { @@ -305,11 +305,11 @@ abstract class TreeGen if (treeInfo.isPureExpr(expr)) { within(() => expr); } else { - val temp = owner.newValue(expr.pos.toSynthetic, unit.fresh.newName(expr.pos, "ev$")) - .setFlag(SYNTHETIC).setInfo(expr.tpe); - atPos(expr.pos) { - Block(List(ValDef(temp, expr)), within(() => Ident(temp) setType expr.tpe)) - } + val temp = owner.newValue(expr.pos.makeTransparent, unit.fresh.newName(expr.pos, "ev$")) + .setFlag(SYNTHETIC).setInfo(expr.tpe) + val containing = within(() => Ident(temp) setPos temp.pos.focus setType expr.tpe) + ensureNonOverlapping(containing, List(expr)) + Block(List(ValDef(temp, expr)), containing) setPos (containing.pos union expr.pos) } def evalOnceAll(exprs: List[Tree], owner: Symbol, unit: CompilationUnit)(within: (List[() => Tree]) => Tree): Tree = { @@ -319,15 +319,16 @@ abstract class TreeGen if (treeInfo.isPureExpr(expr)) { exprs1 += (() => expr) } else { - val temp = owner.newValue(expr.pos.toSynthetic, unit.fresh.newName(expr.pos)) + val temp = owner.newValue(expr.pos.makeTransparent, unit.fresh.newName(expr.pos, "ev$")) .setFlag(SYNTHETIC).setInfo(expr.tpe) vdefs += ValDef(temp, expr) - exprs1 += (() => Ident(temp) setType expr.tpe) + exprs1 += (() => Ident(temp) setPos temp.pos.focus setType expr.tpe) } } val prefix = vdefs.toList - val result = within(exprs1.toList) - if (prefix.isEmpty) result - else Block(prefix, result) setPos (prefix.head.pos union result.pos) + val containing = within(exprs1.toList) + ensureNonOverlapping(containing, exprs) + if (prefix.isEmpty) containing + else Block(prefix, containing) setPos (prefix.head.pos union containing.pos) } } diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index c005d0690e..b3f54f453d 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -105,7 +105,7 @@ trait Trees { } val id = nodeCount - //assert(id != 225) +// assert(id != 14427) nodeCount += 1 private var rawpos: Position = NoPosition @@ -118,19 +118,16 @@ trait Trees { def tpe_=(t: Type) = rawtpe = t def setPos(pos: Position): this.type = { - pos match { - case SyntheticAliasPosition(orig) => assert(orig != this) - case _ => - } // !!! - rawpos = pos; + rawpos = pos +/* + for (c <- this.children) + if (c.pos.isOpaqueRange && !pos.includes(c.pos)) { + assert(false, "non-enclosing positions in "+this) + } +*/ this } - def setOriginal(tree: Tree): this.type = tree.pos match { - case SyntheticAliasPosition(orig) => setOriginal(orig) - case _ => setPos(if (tree.pos.isDefined) SyntheticAliasPosition(tree) else tree.pos) - } - def setType(tp: Type): this.type = { /*assert(kindingIrrelevant(tp) || !kindStar || !tp.isHigherKinded, tp+" should not be higher-kinded");*/ @@ -177,7 +174,7 @@ trait Trees { /** The direct child trees of this tree * EmptyTrees are always omitted. Lists are collapsed. */ - def children(): List[Tree] = { + def children: List[Tree] = { def subtrees(x: Any): List[Tree] = x match { case EmptyTree => List() case t: Tree => List(t) @@ -252,15 +249,16 @@ trait Trees { } else false } + /** Make a copy of this tree, keeping all attributes, + * except that all positions are focussed (so nothing + * in this tree will be found when searching by position). + */ def duplicate: this.type = (duplicator transform this).asInstanceOf[this.type] def shallowDuplicate: this.type = ((new ShallowDuplicator(this)) transform this).asInstanceOf[this.type] - def syntheticDuplicate: this.type = - (syntheticDuplicator transform this).asInstanceOf[this.type] - def copyAttrs(tree: Tree): this.type = { rawpos = tree.rawpos tpe = tree.tpe @@ -297,13 +295,9 @@ trait Trees { private lazy val duplicator = new Transformer { override val treeCopy = new StrictTreeCopier - } - - private lazy val syntheticDuplicator = new Transformer { - override val treeCopy = new StrictTreeCopier override def transform(t: Tree) = { val t1 = super.transform(t) - if (t1 ne t) t1.setOriginal(t) + if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus t1 } } @@ -436,7 +430,9 @@ trait Trees { def ValDef(sym: Symbol, rhs: Tree): ValDef = atPos(sym.pos) { - ValDef(Modifiers(sym.flags), sym.name, TypeTree(sym.tpe), rhs) setSymbol sym + ValDef(Modifiers(sym.flags), sym.name, + TypeTree(sym.tpe) setPos sym.pos.focus, + rhs) setSymbol sym } def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree) @@ -473,7 +469,7 @@ trait Trees { sym.name, sym.typeParams map TypeDef, vparamss, - TypeTree(sym.tpe.finalResultType), + TypeTree(sym.tpe.finalResultType) setPos sym.pos.focus, rhs) setSymbol sym } @@ -492,9 +488,7 @@ trait Trees { /** Abstract type, type parameter, or type alias */ case class TypeDef(mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) - extends MemberDef { - def namePos = pos.offset.map(n => n - name.length).getOrElse(-1) - } + extends MemberDef /** A TypeDef node which defines given `sym' with given tight hand side `rhs'. */ def TypeDef(sym: Symbol, rhs: Tree): TypeDef = @@ -603,17 +597,20 @@ trait Trees { // create parameters for <init> as synthetic trees. var vparamss1 = vparamss map (vps => vps.map { vd => - atPos(vd) { + atPos(vd.pos.focus) { ValDef( Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM) | PARAM) withAnnotations vd.mods.annotations, - vd.name, vd.tpt.syntheticDuplicate, vd.rhs.syntheticDuplicate) + vd.name, vd.tpt.duplicate, vd.rhs.duplicate) }}) val (edefs, rest) = body span treeInfo.isEarlyDef val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef val (lvdefs, gvdefs) = List.unzip { evdefs map { case vdef @ ValDef(mods, name, tpt, rhs) => - val fld = treeCopy.ValDef(vdef.syntheticDuplicate, mods, name, TypeTree() setOriginal tpt, EmptyTree) + val fld = treeCopy.ValDef( + vdef.duplicate, mods, name, + atPos(vdef.pos.focus) { TypeTree() setOriginal tpt setPos tpt.pos.focus }, // atPos in case + EmptyTree) val local = treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs) (local, fld) } @@ -859,10 +856,11 @@ trait Trees { case class TypeTree() extends TypTree { override def symbol = if (tpe == null) null else tpe.typeSymbol - def original: Tree = pos match { - case SyntheticAliasPosition(orig) => orig - case _ => null - } + private var orig: Tree = null // should be EmptyTree? + + def original: Tree = orig + + def setOriginal(tree: Tree): this.type = { orig = tree; setPos(tree.pos); this } override def isEmpty = (tpe eq null) || tpe == NoType } @@ -878,10 +876,6 @@ trait Trees { case class Annotated(annot: Tree, arg: Tree) extends Tree { override def isType = arg.isType override def isTerm = arg.isTerm - override def setPos(pos: Position) : this.type = { -// assert(pos.start != 27934, this) - super.setPos(pos) - } } /** Singleton type, eliminated by RefCheck */ @@ -1706,7 +1700,7 @@ trait Trees { if (tree.tpe ne null) tree.tpe = typeSubst(tree.tpe) super.traverse(tree) } - override def apply[T <: Tree](tree: T): T = super.apply(tree.syntheticDuplicate) + override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate) override def toString() = "TreeTypeSubstituter("+from+","+to+")" } @@ -1724,7 +1718,7 @@ trait Trees { if (tree.hasSymbol) subst(from, to) super.traverse(tree) } - override def apply[T <: Tree](tree: T): T = super.apply(tree.syntheticDuplicate) + override def apply[T <: Tree](tree: T): T = super.apply(tree.duplicate) override def toString() = "TreeSymSubstituter("+from+","+to+")" } @@ -1754,29 +1748,12 @@ trait Trees { } } - object syntheticMaker extends Traverser { - override def traverse(t: Tree) { - if (!t.pos.isSynthetic) { - t setPos t.pos.toSynthetic - super.traverse(t) - } - } - } - def atPos[T <: Tree](pos: Position)(tree: T): T = { posAssigner.pos = pos posAssigner.traverse(tree) tree } - def atPos[T <: Tree](original: Tree)(tree: T): T = - atPos(SyntheticAliasPosition(original))(tree) - - def makeSynthetic[T <: Tree](tree: T): T = { - syntheticMaker.traverse(tree) - tree - } - class ForeachTreeTraverser(f: Tree => Unit) extends Traverser { override def traverse(t: Tree) { f(t) @@ -1851,23 +1828,5 @@ trait Trees { def hasSymbol : Boolean def isTop : Boolean } - - /** A position to be used for synthetic trees that correspond to some original tree - * @note Trees with synthetic positions may not contain trees with real positions inside them! - */ - case class SyntheticAliasPosition(original: Tree) extends Position { - override def isDefined: Boolean = true - override def isSynthetic: Boolean = true - override def offset: Option[Int] = original.pos.offset - override def source: Option[SourceFile] = original.pos.source - override def start: Int = original.pos.start - override def point: Int = original.pos.point - override def end: Int = original.pos.end - override def underlying = original.pos.underlying - override def focusStart = original.pos.focusStart - override def focusPoint = original.pos.focusPoint - override def focusEnd = original.pos.focusEnd - override def show = "["+ underlying.show +"]" - } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 0c1198cdcf..4f5be7cce0 100755 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -150,7 +150,6 @@ self => def o2p(offset: Int): Position def r2p(start: Int, mid: Int, end: Int): Position - def t2p(tree: Tree): Position = SyntheticAliasPosition(tree) //private implicit def p2i(pos: Position) = pos.offset.get /** whether a non-continuable syntax error has been seen */ @@ -220,7 +219,9 @@ self => placeholderTypes = List() var t = op if (!placeholderTypes.isEmpty && t.isInstanceOf[AppliedTypeTree]) { - t = atPos(t.pos) { ExistentialTypeTree(t, placeholderTypes.reverse) } + val expos = t.pos + ensureNonOverlapping(t, placeholderTypes) + t = atPos(expos) { ExistentialTypeTree(t, placeholderTypes.reverse) } placeholderTypes = List() } placeholderTypes = placeholderTypes ::: savedPlaceholderTypes @@ -342,9 +343,9 @@ self => ret } - def errorTypeTree = TypeTree().setType(ErrorType).setPos(o2p(in.offset).toSynthetic) - def errorTermTree = Literal(Constant(null)).setPos(o2p(in.offset).toSynthetic) - def errorPatternTree = Ident(nme.WILDCARD).setPos(o2p(in.offset).toSynthetic) + def errorTypeTree = TypeTree().setType(ErrorType).setPos(o2p(in.offset)) + def errorTermTree = Literal(Constant(null)).setPos(o2p(in.offset)) + def errorPatternTree = Ident(nme.WILDCARD).setPos(o2p(in.offset)) /** Check that type parameter is not by name T* */ def checkNotByName(t: Tree) = t match { @@ -451,13 +452,13 @@ self => tree match { case Ident(name) => removeAsPlaceholder(name) - ValDef(Modifiers(Flags.PARAM), name, TypeTree() setPos o2p(tree.pos.end), EmptyTree) + ValDef(Modifiers(Flags.PARAM), name, TypeTree() setPos o2p(tree.pos.endOrPoint), EmptyTree) case Typed(tree @ Ident(name), tpe) if (tpe.isType) => // get the ident! removeAsPlaceholder(name) ValDef(Modifiers(Flags.PARAM), name, tpe, EmptyTree) case _ => syntaxError(tree.pos, "not a legal formal parameter", false) - ValDef(Modifiers(Flags.PARAM), nme.ERROR, errorTypeTree setPos o2p(tree.pos.end).toSynthetic, EmptyTree) + ValDef(Modifiers(Flags.PARAM), nme.ERROR, errorTypeTree setPos o2p(tree.pos.endOrPoint), EmptyTree) } } @@ -536,7 +537,7 @@ self => leftAssoc && prec == precedence(opstack.head.operator))) { val opinfo = opstack.head opstack = opstack.tail - top = atPos(opinfo.operand.pos.start, opinfo.offset) { + top = atPos(opinfo.operand.pos.startOrPoint, opinfo.offset) { makeBinop(isExpr, opinfo.operand, opinfo.operator, top) } } @@ -560,7 +561,7 @@ self => def selector(t: Tree): Tree = { val point = in.offset //assert(t.pos.isDefined, t) - Select(t, ident(false)) setPos r2p(t.pos.start, point, in.lastOffset) + Select(t, ident(false)) setPos r2p(t.pos.startOrPoint, point, in.lastOffset) } /** Path ::= StableId @@ -613,7 +614,7 @@ self => def selectors(t: Tree, typeOK: Boolean, dotOffset: Int): Tree = if (typeOK && in.token == TYPE) { in.nextToken() - atPos(t.pos.start, dotOffset) { SingletonTypeTree(t) } + atPos(t.pos.startOrPoint, dotOffset) { SingletonTypeTree(t) } } else { val t1 = selector(t) if (in.token == DOT) { selectors(t1, typeOK, in.skipToken()) } @@ -774,7 +775,7 @@ self => val op = ident() val tycon = atPos(opOffset) { Ident(op.toTypeName) } newLineOptWhenFollowing(isTypeIntroToken) - def mkOp(t1: Tree) = atPos(t.pos.start, opOffset) { AppliedTypeTree(tycon, List(t, t1)) } + def mkOp(t1: Tree) = atPos(t.pos.startOrPoint, opOffset) { AppliedTypeTree(tycon, List(t, t1)) } if (leftAssoc) infixTypeRest(mkOp(compoundType(isPattern)), isPattern, InfixMode.LeftOp) else @@ -797,7 +798,7 @@ self => in.nextToken(); ts += annotType(isPattern) } newLineOptWhenFollowedBy(LBRACE) - atPos(t.pos.start) { + atPos(t.pos.startOrPoint) { if (in.token == LBRACE) { // Warn if they are attempting to refine Unit; we can't be certain it's // scala.Unit they're refining because at this point all we have is an @@ -853,12 +854,12 @@ self => val hashOffset = in.skipToken() val nameOffset = in.offset val name = ident(false) - val sel = atPos(t.pos.start, if (name == nme.ERROR) hashOffset else nameOffset) { + val sel = atPos(t.pos.startOrPoint, if (name == nme.ERROR) hashOffset else nameOffset) { SelectFromTypeTree(t, name.toTypeName) } simpleTypeRest(sel, isPattern) } else if (in.token == LBRACKET) { - simpleTypeRest(atPos(t.pos.start) { AppliedTypeTree(t, typeArgs(isPattern, false)) }, isPattern) + simpleTypeRest(atPos(t.pos.startOrPoint) { AppliedTypeTree(t, typeArgs(isPattern, false)) }, isPattern) } else { t } @@ -1046,7 +1047,7 @@ self => if (in.token == EQUALS) { t match { case Ident(_) | Select(_, _) | Apply(_, _) => - t = atPos(t.pos.start, in.skipToken()) { makeAssign(t, expr()) } + t = atPos(t.pos.startOrPoint, in.skipToken()) { makeAssign(t, expr()) } case _ => } } else if (in.token == COLON) { @@ -1057,7 +1058,7 @@ self => val uscorePos = in.skipToken() if (isIdent && in.name == nme.STAR) { in.nextToken() - t = atPos(t.pos.start, colonPos) { + t = atPos(t.pos.startOrPoint, colonPos) { Typed(t, atPos(uscorePos) { Ident(nme.WILDCARD_STAR.toTypeName) }) } } else { @@ -1066,13 +1067,13 @@ self => } else if (in.token == AT) { t = (t /: annotations(false, false)) (makeAnnotated) } else { - t = atPos(t.pos.start, colonPos) { + t = atPos(t.pos.startOrPoint, colonPos) { val tpt = if (location == Local) typ() else infixType(false, InfixMode.FirstOp) if (isWildcard(t)) (placeholderParams: @unchecked) match { case (vd @ ValDef(mods, name, _, _)) :: rest => - placeholderParams = treeCopy.ValDef(vd, mods, name, tpt.syntheticDuplicate, EmptyTree) :: rest + placeholderParams = treeCopy.ValDef(vd, mods, name, tpt.duplicate, EmptyTree) :: rest } // this does not correspond to syntax, but is necessary to // accept closures. We might restrict closures to be between {...} only. @@ -1080,7 +1081,7 @@ self => } } } else if (in.token == MATCH) { - t = atPos(t.pos.start, in.skipToken()) { + t = atPos(t.pos.startOrPoint, in.skipToken()) { Match(stripParens(t), surround(LBRACE, RBRACE)(caseClauses(), Nil)) } } @@ -1093,7 +1094,7 @@ self => case _ => false } if (in.token == ARROW && (location != InTemplate || lhsIsTypedParamList)) { - t = atPos(t.pos.start, in.skipToken()) { + t = atPos(t.pos.startOrPoint, in.skipToken()) { Function(convertToParams(t), if (location != InBlock) expr() else block()) } } @@ -1119,7 +1120,7 @@ self => val topinfo = opstack.head opstack = opstack.tail val od = stripParens(reduceStack(true, base, topinfo.operand, 0, true)) - return atPos(od.pos.start, topinfo.offset) { + return atPos(od.pos.startOrPoint, topinfo.offset) { Select(od, topinfo.operator.encode) } } @@ -1174,9 +1175,9 @@ self => case USCORE => val start = in.offset val pname = freshName(o2p(start), "x$") - val id = atPos(start) (Ident(pname)) in.nextToken() - val param = atPos(t2p(id)){ makeSyntheticParam(pname) } + val id = atPos(start) (Ident(pname)) + val param = atPos(id.pos.focus){ makeSyntheticParam(pname) } placeholderParams = param :: placeholderParams id case LPAREN => @@ -1213,7 +1214,7 @@ self => val t1 = stripParens(t) t1 match { case Ident(_) | Select(_, _) => - val tapp = atPos(t1.pos.start, in.offset) { + val tapp = atPos(t1.pos.startOrPoint, in.offset) { TypeApply(t1, typeArgs(false, true)) } simpleExprRest(tapp, true) @@ -1221,7 +1222,7 @@ self => t1 } case LPAREN | LBRACE if (canApply) => - val app = atPos(t.pos.start, in.offset) { + val app = atPos(t.pos.startOrPoint, in.offset) { // look for anonymous function application like (f _)(x) and // translate to (f _).apply(x), bug #460 val sel = t match { @@ -1234,7 +1235,7 @@ self => } simpleExprRest(app, true) case USCORE => - atPos(t.pos.start, in.skipToken()) { + atPos(t.pos.startOrPoint, in.skipToken()) { Typed(stripParens(t), Function(List(), EmptyTree)) } case _ => @@ -1360,7 +1361,7 @@ self => if (in.token == IF) enums += makeFilter(in.offset, guard()) } - def makeFilter(start: Int, tree: Tree) = Filter(r2p(start, tree.pos.point, tree.pos.end), tree) + def makeFilter(start: Int, tree: Tree) = Filter(r2p(start, tree.pos.point, tree.pos.endOrPoint), tree) /* -------- PATTERNS ------------------------------------------- */ @@ -1398,7 +1399,7 @@ self => val p = pattern2(seqOK) p match { case Ident(name) if (treeInfo.isVarPattern(p) && in.token == COLON) => - atPos(p.pos.start, in.skipToken()) { Typed(p, compoundType(true)) } + atPos(p.pos.startOrPoint, in.skipToken()) { Typed(p, compoundType(true)) } case _ => p } @@ -1419,7 +1420,7 @@ self => pattern3(seqOK) } else if (treeInfo.isVarPattern(p)) { in.nextToken() - atPos(p.pos.start) { Bind(name, pattern3(seqOK)) } + atPos(p.pos.startOrPoint) { Bind(name, pattern3(seqOK)) } } else { p } @@ -1438,7 +1439,7 @@ self => val base = opstack var top = simplePattern(seqOK) if (seqOK && isIdent && in.name == STAR) - return atPos(top.pos.start, in.skipToken())(Star(stripParens(top))) + return atPos(top.pos.startOrPoint, in.skipToken())(Star(stripParens(top))) while (isIdent && in.name != BAR) { top = reduceStack( @@ -1498,7 +1499,7 @@ self => else t case USCORE => in.nextToken() - atPos(start) { Ident(nme.WILDCARD) } + atPos(start, start) { Ident(nme.WILDCARD) } case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL => atPos(start) { literal(false) } @@ -1762,7 +1763,7 @@ self => val t = typ() if (isIdent && in.name == STAR) { in.nextToken() - atPos(t.pos.start, t.pos.point) { + atPos(t.pos.startOrPoint, t.pos.point) { AppliedTypeTree( rootScalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t)) } @@ -1834,7 +1835,7 @@ self => def bound(tok: Int, default: Name): Tree = if (in.token == tok) { in.nextToken(); typ() } - else atPos(o2p(in.lastOffset).toSynthetic) { rootScalaDot(default.toTypeName) } + else atPos(o2p(in.lastOffset)) { rootScalaDot(default.toTypeName) } /* -------- DEFS ------------------------------------------- */ @@ -2008,7 +2009,7 @@ self => } trees } - (lhs.toList.init flatMap (mkDefs(_, tp.syntheticDuplicate, rhs.syntheticDuplicate))) ::: mkDefs(lhs.last, tp, rhs) + (lhs.toList.init flatMap (mkDefs(_, tp.duplicate, rhs.duplicate))) ::: mkDefs(lhs.last, tp, rhs) } /** VarDef ::= PatDef @@ -2047,7 +2048,7 @@ self => val start = in.skipToken() if (in.token == THIS) { atPos(start, in.skipToken()) { - val vparamss = paramClauses(nme.CONSTRUCTOR, implicitClassViews map (_.syntheticDuplicate), false) + val vparamss = paramClauses(nme.CONSTRUCTOR, implicitClassViews map (_.duplicate), false) newLineOptWhenFollowedBy(LBRACE) val rhs = if (in.token == LBRACE) { atPos(in.offset) { constrBlock(vparamss) } @@ -2184,7 +2185,7 @@ self => val implicitViewBuf = new ListBuffer[Tree] val tparams = typeParamClauseOpt(name, implicitViewBuf) implicitClassViews = implicitViewBuf.toList - val tstart = (in.offset::implicitClassViews.map(_.pos.start)).min + val tstart = (in.offset::implicitClassViews.map(_.pos.startOrPoint)).min if (!implicitClassViews.isEmpty && mods.hasFlag(Flags.TRAIT)) { syntaxError("traits cannot have type parameters with <% bounds", false) implicitClassViews = List() @@ -2301,7 +2302,7 @@ self => if (mods.hasFlag(Flags.CASE)) parents = parents ::: List(productConstr) val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart atPos(tstart0) { - Template(parents, self, constrMods, vparamss, argss, body, o2p(tstart).toSynthetic) + Template(parents, self, constrMods, vparamss, argss, body, o2p(tstart)) } } @@ -2362,7 +2363,7 @@ self => def makePackageObject(start: Int, objDef: ModuleDef): PackageDef = objDef match { case ModuleDef(mods, name, impl) => makePackaging( - start, atPos(o2p(objDef.pos.start)){ Ident(name) }, List(ModuleDef(mods, nme.PACKAGEkw, impl))) + start, atPos(o2p(objDef.pos.startOrPoint)){ Ident(name) }, List(ModuleDef(mods, nme.PACKAGEkw, impl))) } /** Packaging ::= package QualId [nl] `{' TopStatSeq `}' @@ -2520,7 +2521,7 @@ self => stats ++= localDef if (in.token == RBRACE || in.token == CASE) { syntaxError("block must end in result expression, not in definition", false) - stats += Literal(()).setPos(o2p(in.offset).toSynthetic) + stats += Literal(()).setPos(o2p(in.offset)) } else acceptStatSep() } else if (isStatSep) { in.nextToken() diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala index d8f43cae2b..100ba462a4 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala @@ -24,11 +24,8 @@ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParse unit.body = if (unit.source.file.name.endsWith(".java")) new JavaUnitParser(unit).parse() else if (!global.reporter.incompleteHandled) new UnitParser(unit).smartParse() - else { - val result = new UnitParser(unit).parse() - if (global.settings.Yrangepos.value) global.validatePositions(unit.body) - result - } + else new UnitParser(unit).parse() + if (global.settings.Yrangepos.value) global.validatePositions(unit.body) } } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index fe06b663b2..fc18cfb195 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -9,7 +9,7 @@ package ast.parser import symtab.Flags._ import scala.collection.mutable.ListBuffer -import scala.tools.nsc.util.{Position, SyntheticOffsetPosition} +import scala.tools.nsc.util.Position /** Methods for building trees, used in the parser. All the trees * returned by this class must be untyped. @@ -39,7 +39,7 @@ abstract class TreeBuilder { private object patvarTransformer extends Transformer { override def transform(tree: Tree): Tree = tree match { case Ident(name) if (treeInfo.isVarPattern(tree) && name != nme.WILDCARD) => - atPos(tree.pos)(Bind(name, atPos(tree) (Ident(nme.WILDCARD)))) + atPos(tree.pos)(Bind(name, atPos(tree.pos.focus) (Ident(nme.WILDCARD)))) case Typed(id @ Ident(name), tpt) if (treeInfo.isVarPattern(id) && name != nme.WILDCARD) => atPos(tree.pos.withPoint(id.pos.point)) { Bind(name, atPos(tree.pos.withStart(tree.pos.point)) { @@ -61,40 +61,47 @@ abstract class TreeBuilder { } } - /** Traverse pattern and collect all variable names with their types in buffer */ + /** Traverse pattern and collect all variable names with their types in buffer + * The variables keep their positions; whereas the pattern is converted to be synthetic + * for all nodes that contain a variable position. + */ private object getvarTraverser extends Traverser { val buf = new ListBuffer[(Name, Tree, Position)] def init: Traverser = { buf.clear; this } - override def traverse(tree: Tree): Unit = tree match { - case Bind(name, Typed(tree1, tpt)) => - if ((name != nme.WILDCARD) && (buf.iterator forall (name !=))) { - buf += ((name, if (treeInfo.mayBeTypePat(tpt)) TypeTree() else tpt, tree.pos)) - } - traverse(tree1) - case Bind(name, tree1) => - if ((name != nme.WILDCARD) && (buf.iterator forall (name !=))) { - // can assume only name range as position, as otherwise might overlap - // with binds embedded in pattern tree1 - val start = tree.pos.start - val end = start + name.decode.length - - // if the name range does overlap the bind we assume it is - // a fresh name (ie. generated from for(... ; (a, b) <- (1, 2) ...)) - // make it transparent - val namePos0 = r2p(start, start, end) - val namePos = if (namePos0 overlaps tree.pos) makeTransparent(namePos0) else namePos0 - buf += ((name, TypeTree(), namePos)) - } - traverse(tree1) - case _ => - super.traverse(tree) + def namePos(tree: Tree, name: Name): Position = + if (!tree.pos.isRange || name.toString.contains('$')) tree.pos.focus + else { + val start = tree.pos.start + val end = start + name.decode.length + r2p(start, start, end) + } + override def traverse(tree: Tree): Unit = { + val bl = buf.length + tree match { + case Bind(name, Typed(tree1, tpt)) => + if ((name != nme.WILDCARD) && (buf.iterator forall (name !=))) { + buf += ((name, if (treeInfo.mayBeTypePat(tpt)) TypeTree() else tpt.duplicate, namePos(tree, name))) + } + traverse(tree1) + case Bind(name, tree1) => + if ((name != nme.WILDCARD) && (buf.iterator forall (name !=))) { + // can assume only name range as position, as otherwise might overlap + // with binds embedded in pattern tree1 + buf += ((name, TypeTree(), namePos(tree, name))) + //println("found var "+name+" at "+namePos.show) //DEBUG + } + traverse(tree1) + case _ => + super.traverse(tree) + } + if (buf.length > bl) tree setPos tree.pos.makeTransparent } } /** Returns list of all pattern variables, possibly with their types, * without duplicates */ - private def getVariables(tree: Tree): List[(Name, Tree,Position)] = { + private def getVariables(tree: Tree): List[(Name, Tree, Position)] = { getvarTraverser.init.traverse(tree) getvarTraverser.buf.toList } @@ -158,7 +165,7 @@ abstract class TreeBuilder { /** Create positioned tree representing an object creation <new parents { stats } * @param npos the position of the new - * @param cpos the position of the anonymous class startig with parents + * @param cpos the position of the anonymous class starting with parents */ def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], argss: List[List[Tree]], npos: Position, cpos: Position): Tree = @@ -174,11 +181,11 @@ abstract class TreeBuilder { atPos(cpos) { ClassDef( Modifiers(FINAL), x, Nil, - Template(parents, self, NoMods, List(Nil), argss, stats, cpos.toSynthetic)) + Template(parents, self, NoMods, List(Nil), argss, stats, cpos.focus)) }), atPos(npos) { New( - Ident(x) setPos npos.toSynthetic, + Ident(x) setPos npos.focus, List(Nil)) } ) @@ -200,7 +207,7 @@ abstract class TreeBuilder { /** Create tree representing a while loop */ def makeWhile(lname: Name, cond: Tree, body: Tree): Tree = { - val continu = atPos(o2p(body.pos.end)) { Apply(Ident(lname), Nil) } + val continu = atPos(o2p(body.pos.endOrPoint)) { Apply(Ident(lname), Nil) } val rhs = If(cond, Block(List(body), continu), Literal(())) LabelDef(lname, Nil, rhs) } @@ -234,7 +241,7 @@ abstract class TreeBuilder { List( makeVisitor( List( - CaseDef(pat1.syntheticDuplicate, EmptyTree, Literal(true)), + CaseDef(pat1.duplicate, EmptyTree, Literal(true)), CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))), false, nme.CHECK_IF_REFUTABLE_STRING @@ -310,7 +317,7 @@ abstract class TreeBuilder { * the limits given by pat and body. */ def makeClosure(pos: Position, pat: Tree, body: Tree): Tree = { - def splitpos = makeTransparent(wrappingPos(List(pat, body)).withPoint(pos.point)) + def splitpos = wrappingPos(List(pat, body)).withPoint(pos.point).makeTransparent matchVarPattern(pat) match { case Some((name, tpt)) => Function( @@ -345,12 +352,12 @@ abstract class TreeBuilder { /** A reference to the name bound in Bind `pat`. */ def makeValue(pat: Tree): Tree = pat match { - case Bind(name, _) => Ident(name) setPos pat.pos.toSynthetic + case Bind(name, _) => Ident(name) setPos pat.pos.focus } /** The position of the closure that starts with generator at position `genpos`. */ - def closurePos(genpos: Position) = r2p(genpos.start, genpos.point, body.pos.end) + def closurePos(genpos: Position) = r2p(genpos.startOrPoint, genpos.point, body.pos.endOrPoint) // val result = enums match { @@ -361,7 +368,7 @@ abstract class TreeBuilder { makeFor(mapName, flatMapName, rest, body)) case ValFrom(pos, pat, rhs) :: Filter(_, test) :: rest => makeFor(mapName, flatMapName, - ValFrom(pos, pat, makeCombination(rhs.pos union test.pos, nme.filter, rhs, pat.syntheticDuplicate, test)) :: rest, + ValFrom(pos, pat, makeCombination(rhs.pos union test.pos, nme.filter, rhs, pat.duplicate, test)) :: rest, body) case ValFrom(pos, pat, rhs) :: rest => val valeqs = rest.take(definitions.MaxTupleArity - 1).takeWhile(_.isInstanceOf[ValEq]); @@ -376,8 +383,8 @@ abstract class TreeBuilder { val rhs1 = makeForYield( List(ValFrom(pos, defpat1, rhs)), Block(pdefs, atPos(wrappingPos(ids)) { makeTupleTerm(ids, true) }) setPos wrappingPos(pdefs)) - val allpats = (pat :: pats) map (_.syntheticDuplicate) - val vfrom1 = ValFrom(r2p(pos.start, pos.point, rhs1.pos.end), atPos(wrappingPos(allpats)) { makeTuple(allpats, false) } , rhs1) + val allpats = (pat :: pats) map (_.duplicate) + val vfrom1 = ValFrom(r2p(pos.startOrPoint, pos.point, rhs1.pos.endOrPoint), atPos(wrappingPos(allpats)) { makeTuple(allpats, false) } , rhs1) makeFor(mapName, flatMapName, vfrom1 :: rest1, body) case _ => EmptyTree //may happen for erroneous input @@ -428,8 +435,9 @@ abstract class TreeBuilder { def makeVisitor(cases: List[CaseDef], checkExhaustive: Boolean): Tree = makeVisitor(cases, checkExhaustive, "x$") - private def makeUnchecked(expr: Tree): Tree = + private def makeUnchecked(expr: Tree): Tree = atPos(expr.pos) { Annotated(New(scalaDot(definitions.UncheckedClass.name), List(Nil)), expr) + } /** Create visitor <x => x match cases> */ def makeVisitor(cases: List[CaseDef], checkExhaustive: Boolean, prefix: String): Tree = { @@ -465,25 +473,24 @@ abstract class TreeBuilder { // val/var x_N = t$._N val pat1 = patvarTransformer.transform(pat) val vars = getVariables(pat1) - val matchExpr = atPos(rhs.pos){ + val matchExpr = atPos((pat1.pos union rhs.pos).makeTransparent) { Match( makeUnchecked(rhs), List( - makeSynthetic( - atPos(rhs.pos) { - CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map Ident, true)) - }))) - + atPos(pat1.pos) { + CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map Ident, true)) + } + )) } vars match { case List((vname, tpt, pos)) => - List(atPos(pat.pos union rhs.pos) { + List(atPos(pat.pos union pos union rhs.pos) { ValDef(mods, vname, tpt, matchExpr) }) case _ => val tmp = freshName() val firstDef = - atPos(rhs.pos) { + atPos(matchExpr.pos) { ValDef(Modifiers(PRIVATE | LOCAL | SYNTHETIC | (mods.flags & LAZY)), tmp, TypeTree(), matchExpr) } diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index bee6674fd1..aa18d5226d 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -199,7 +199,7 @@ abstract class GenICode extends SubComponent { private def genLoad(tree: Tree, ctx: Context, expectedType: TypeKind): Context = { var generatedType = expectedType if (settings.debug.value) - log("at line: " + (tree.pos).line.map(_.toString).getOrElse(tree.pos.toString)) + log("at line: " + (if (tree.pos.isDefined) tree.pos.line else tree.pos)) /** * Generate code for primitive arithmetic operations. @@ -1427,10 +1427,10 @@ abstract class GenICode extends SubComponent { case None => val local = ctx.makeLocal(l.pos, definitions.AnyRefClass.typeConstructor, eqEqTempName.toString) //assert(!l.pos.source.isEmpty, "bad position, unit = "+unit+", tree = "+l+", pos = "+l.pos.source) - assert(l.pos.source.get == unit.source) - assert(r.pos.source.get == unit.source) - local.start = (l.pos).line.get - local.end = (r.pos).line.get + assert(l.pos.source == unit.source) + assert(r.pos.source == unit.source) + local.start = (l.pos).line + local.end = (r.pos).line local } diff --git a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala index 812d77f4ff..1dd51a3741 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala @@ -129,7 +129,7 @@ trait Printers { self: ICodes => // if (settings.Xdce.value) // print(if (i.useful) " " else " * "); if (settings.debug.value) - print(i.pos.line.map(_.toString).getOrElse("")) + if (i.pos.isDefined) print(i.pos.line.toString) println(i.toString()) } } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 2184b554f8..cf9be28042 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -1269,9 +1269,9 @@ abstract class GenJVM extends SubComponent { // assert(instr.pos.source.isEmpty || instr.pos.source.get == (clasz.cunit.source), "sources don't match") // val crtLine = instr.pos.line.get(lastLineNr); val crtLine = try { - (instr.pos).line.get + (instr.pos).line } catch { - case _: NoSuchElementException => + case _: UnsupportedOperationException => log("Warning: wrong position in: " + method) lastLineNr } @@ -1439,7 +1439,7 @@ abstract class GenJVM extends SubComponent { log("Converting from: " + src + " to: " + dst); if (dst == BOOL) { Console.println("Illegal conversion at: " + clasz + - " at: " + pos.source.get + ":" + pos.line.getOrElse(-1)); + " at: " + pos.source + ":" + pos.line); } else jcode.emitT2T(javaType(src), javaType(dst)); diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala index 58e1e598bc..cbfa4161bd 100644 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala @@ -504,10 +504,7 @@ abstract class GenMSIL extends SubComponent { } } - val line = (sym.pos).line match { - case Some(l) => l - case None => 0 - } + val line = sym.pos.line tBuilder.setPosition(line, iclass.cunit.source.file.name) if (isTopLevelModule(sym)) { @@ -1217,12 +1214,7 @@ abstract class GenMSIL extends SubComponent { needAdditionalRet = false - val currentLineNr = (instr.pos).line match { - case Some(line) => line - case None => - log("Warning: wrong position in: " + method) - lastLineNr - } // if getting line number fails + val currentLineNr = instr.pos.line if (currentLineNr != lastLineNr) { mcode.setPosition(currentLineNr) @@ -1677,8 +1669,7 @@ abstract class GenMSIL extends SubComponent { case DOUBLE => mcode.Emit(OpCodes.Conv_R8) case _ => Console.println("Illegal conversion at: " + clasz + - " at: " + pos.source.get + ":" + - pos.line.get) + " at: " + pos.source + ":" + pos.line) } case ArrayLength(_) => diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index 4fda69a66e..d46b5b4b89 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -42,7 +42,7 @@ trait CompilerControl { self: Global => } /** The compilation unit corresponding to a position */ - def unitOf(pos: Position): RichCompilationUnit = unitOf(pos.source.get) + def unitOf(pos: Position): RichCompilationUnit = unitOf(pos.source) /** Remove the CompilationUnit corresponding to the given SourceFile * from consideration for recompilation. diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala index f90434b4bc..70557ac5c6 100755 --- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala +++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala @@ -56,7 +56,7 @@ trait ContextTrees { self: Global => */ def addContext(contexts: Contexts, context: Context) { val cpos = context.tree.pos - if (isTransparent(cpos)) + if (cpos.isTransparent) for (t <- context.tree.children flatMap solidDescendants) addContext(contexts, context, t.pos) else @@ -68,7 +68,7 @@ trait ContextTrees { self: Global => */ def addContext(contexts: Contexts, context: Context, cpos: Position) { try { - if (!cpos.isDefined || cpos.isSynthetic) {} + if (!cpos.isRange) {} else if (contexts.isEmpty) contexts += new ContextTree(cpos, context) else { val hi = contexts.length - 1 diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 2f74e1635f..1b77d612cb 100755 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -24,6 +24,8 @@ self => import definitions._ + settings.Xprintpos.value = true + override def onlyPresentation = true /** A list indicating in which order some units should be typechecked. @@ -67,8 +69,7 @@ self => } if (activeLocks == 0) { if (context.unit != null && - !result.pos.isSynthetic && - !isTransparent(result.pos) && + result.pos.isOpaqueRange && (result.pos includes context.unit.targetPos)) { integrateNew() var located = new Locator(context.unit.targetPos) locateIn result @@ -368,7 +369,7 @@ self => class TreeReplacer(from: Tree, to: Tree) extends Transformer { override def transform(t: Tree): Tree = { if (t == from) to - else if ((t.pos includes from.pos) || isTransparent(t.pos)) super.transform(t) + else if ((t.pos includes from.pos) || t.pos.isTransparent) super.transform(t) else t } } diff --git a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala index 527efae4b5..4f0d8edfa5 100755 --- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala +++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala @@ -2,7 +2,7 @@ package scala.tools.nsc package interactive import ast.Trees -import scala.tools.nsc.util.{SourceFile, Position, RangePosition, OffsetPosition, NoPosition, SyntheticOffsetPosition, WorkScheduler} +import scala.tools.nsc.util.{SourceFile, Position, RangePosition, OffsetPosition, NoPosition, WorkScheduler} import scala.collection.mutable.ListBuffer /** Handling range positions @@ -29,50 +29,40 @@ self: scala.tools.nsc.Global => def isFree = tree == EmptyTree } - class TransparentPosition(source0: SourceFile, start: Int, point: Int, end: Int) extends RangePosition(source0, start, point, end) { - override def show = "<"+super.show+">" - } - - def isTransparent(pos: Position) = pos.isInstanceOf[TransparentPosition] - - def isRange(pos: Position) = pos.isInstanceOf[RangePosition] && !isTransparent(pos) - - protected var splitAllowed = false - override def rangePos(source: SourceFile, start: Int, point: Int, end: Int) = new RangePosition(source, start, point, end) - /** A position that wraps the non-empty set of trees. + /** A position that wraps a set of trees. + * The point of the wrapping position is the point of the default position. + * If some of the trees are ranges, returns a range position enclosing all ranges + * Otherwise returns default position. + */ + def wrappingPos(default: Position, trees: List[Tree]): Position = { + val ranged = trees filter (_.pos.isRange) + if (ranged.isEmpty) default.focus + else new RangePosition(default.source, (ranged map (_.pos.start)).min, default.point, (ranged map (_.pos.end)).max) + } + + /** A position that wraps a non-empty set of trees. * The point of the wrapping position is the point of the first trees' position. - * If all some the trees are non-synthetic, returns a range position enclosing the non-synthetic trees - * Otherwise returns a synthetic offset position to point. + * If some of the trees are ranges, returns a range position enclosing all ranges + * Otherwise returns first tree's position. */ override def wrappingPos(trees: List[Tree]): Position = { val headpos = trees.head.pos - if (headpos.isDefined) { - val source = headpos.source.get - val point = headpos.point - val nonsynthetic = trees filter (t => t.pos.isDefined && !t.pos.isSynthetic) - if (nonsynthetic.isEmpty) - new SyntheticOffsetPosition(source, point) - else - new RangePosition(source, (nonsynthetic map (_.pos.start)).min, point, (nonsynthetic map (_.pos.end)).max) - } else { - headpos - } + if (headpos.isDefined) wrappingPos(headpos, trees) else headpos } - override def makeTransparent(pos: Position) = pos match { - case rp: RangePosition if (!rp.isSynthetic) => - new TransparentPosition(rp.source.get, rp.start, rp.point, rp.end) - case _ => - pos - } +/* + override def integratePos(tree: Tree, pos: Position) = + if (pos.isSynthetic && !tree.pos.isSynthetic) tree.syntheticDuplicate + else tree +*/ // -------------- ensuring no overlaps ------------------------------- def solidDescendants(tree: Tree): List[Tree] = - if (isTransparent(tree.pos)) tree.children flatMap solidDescendants + if (tree.pos.isTransparent) tree.children flatMap solidDescendants else List(tree) /** A free range from `lo` to `hi` */ @@ -95,7 +85,7 @@ self: scala.tools.nsc.Global => assert(conflicting.nonEmpty) rs case r :: rs1 => - assert(!isTransparent(t.pos)) + assert(!t.pos.isTransparent) if (r.isFree && (r.pos includes t.pos)) { // println("subdividing "+r+"/"+t.pos) maybeFree(t.pos.end, r.pos.end) ::: List(Range(t.pos, t)) ::: maybeFree(r.pos.start, t.pos.start) ::: rs1 @@ -110,67 +100,31 @@ self: scala.tools.nsc.Global => if (ts.head == t) replacement ::: ts.tail else ts.head :: replace(ts.tail, t, replacement) - /** Ensure that given list of trees has mutually non-overlapping positions, - * by assinging TransparentPositions to some of them, if necessary + /** Ensure that given tree has no positions that overlap with + * any of the positions of `others`. This is done by + * shortening the range or assinging TransparentPositions + * to some of the nodes in `tree`. */ - def ensureNonOverlapping(cts: List[Tree]): Unit = { - - def isSplittable(node: Tree) = node match { - case Function(_, _) | CaseDef(_, _, _) | Match(_, _) => true - case _ => false - } - - /** Do a pass over all child trees `cts`, where `ranges` reflects positions previously - * encountered. If there are overlaps, break up one node by making its position a TransparentPosition - * and do another pass of `ensureOverlapping`. - * @param ranges The current list of non-overlapping ranges, - * both occupied and free, sorted from later to earlier. - * No TransparentPositions allowed here! - * @param trees The list of trees to insert in ranges. - */ - def iterate(ranges: List[Range], trees: List[Tree]): Unit = trees match { - case List() => - ; - case tree :: trees1 => - if (isTransparent(tree.pos)) - iterate(ranges, solidDescendants(tree) ::: trees1) - else if (!tree.pos.isDefined || tree.pos.isSynthetic) - iterate(ranges, trees1) - else { - val conflicting = new ListBuffer[Tree] - val ranges1 = insert(ranges, tree, conflicting) -// println("inserted "+tree+"; ranges = "+ranges1) - if (conflicting.isEmpty) { - iterate(ranges1, trees1) - } else { - val splitNode = - if (conflicting.size == 1 && (conflicting.head.pos includes tree.pos)) { - //println("*** splitting \n"+conflicting.head+"\n--- because it conflicts with ---\n"+tree) - //println(tree.id) - conflicting.head - } else { - //println("*** splitting \n"+tree+"\n--- because it conflicts with trees in ---\n"+conflicting) - //println(tree.id) - tree - } - //throw new Error()//debug - -// println("splitting "+splitNode) - splitNode setPos new TransparentPosition(splitNode.pos.source.get, splitNode.pos.start, splitNode.pos.point, splitNode.pos.end) - ensureNonOverlapping(replace(cts, splitNode, solidDescendants(splitNode))) - } - } + override def ensureNonOverlapping(tree: Tree, others: List[Tree]) { + def isOverlapping(pos: Position) = + pos.isRange && (others exists (pos overlaps _.pos)) + if (isOverlapping(tree.pos)) { + val children = tree.children + children foreach (ensureNonOverlapping(_, others)) + if (tree.pos.isOpaqueRange) { + val wpos = wrappingPos(tree.pos.focus, children) + tree setPos (if (isOverlapping(wpos)) tree.pos.makeTransparent else wpos) + } } -// println("ensure non overlap "+cts) - if (phase.id <= currentRun.typerPhase.id) - iterate(List(maxFree), cts) } - /** Does given list of trees have mutually non-overlapping positions? */ + /** Does given list of trees have mutually non-overlapping positions? + * pre: None of the trees is transparent + */ def findOverlapping(cts: List[Tree]): List[(Tree, Tree)] = { var ranges = List(maxFree) for (ct <- cts) { - if (ct.pos.isDefined && !ct.pos.isSynthetic) { + if (ct.pos.isOpaqueRange) { val conflicting = new ListBuffer[Tree] ranges = insert(ranges, ct, conflicting) if (conflicting.nonEmpty) return conflicting.toList map (t => (t, ct)) @@ -189,20 +143,17 @@ self: scala.tools.nsc.Global => * @param trees The children to position. All children must be positionable. */ private def setChildrenPos(pos: Position, trees: List[Tree]): Unit = try { - var remainingRange = pos for (tree <- trees) { if (!tree.isEmpty && tree.pos == NoPosition) { - val children = tree.children filter (c => !c.isEmpty && !c.pos.isSynthetic) + val children = tree.children if (children.isEmpty) { - tree setPos new OffsetPosition(pos.source.get, remainingRange.start) + tree setPos pos.focus } else { - setChildrenPos(remainingRange, children) - tree setPos wrappingPos(children) + setChildrenPos(pos, children) + tree setPos wrappingPos(pos, children) } - remainingRange = new RangePosition(pos.source.get, tree.pos.end, pos.point, pos.end) } } - ensureNonOverlapping(trees) } catch { case ex: Exception => println("error while set children pos "+pos+" of "+trees) @@ -213,7 +164,7 @@ self: scala.tools.nsc.Global => * This means: Set position of a node and position all its unpositioned children. */ override def atPos[T <: Tree](pos: Position)(tree: T): T = - if (isRange(pos)) { + if (pos.isOpaqueRange) { if (!tree.isEmpty && tree.pos == NoPosition) { tree.setPos(pos) val children = tree.children @@ -231,11 +182,7 @@ self: scala.tools.nsc.Global => override def validatePositions(tree: Tree) { def reportTree(prefix : String, tree : Tree) { - val source = tree.pos.source match { - case Some(sf) => " in file "+sf - case None => "" - } - + val source = if (tree.pos.isDefined) tree.pos.source else "" inform("== "+prefix+" tree ["+tree.id+"] of type "+tree.productPrefix+" at "+tree.pos.show+source) inform("") inform(tree.toString) @@ -258,8 +205,8 @@ self: scala.tools.nsc.Global => if (!tree.isEmpty) { if (!tree.pos.isDefined) error("Unpositioned tree ["+tree.id+"]") { reportTree("Unpositioned", tree) } - if (!tree.pos.isSynthetic) { - if (encltree.pos.isSynthetic) + if (tree.pos.isRange) { + if (!encltree.pos.isRange) error("Synthetic tree ["+encltree.id+"] contains nonsynthetic tree ["+tree.id+"]") { reportTree("Enclosing", encltree) reportTree("Enclosed", tree) @@ -306,8 +253,8 @@ self: scala.tools.nsc.Global => this.last } override def traverse(t: Tree) { - if (!t.pos.isSynthetic && (t.pos includes pos)) { - if (!isTransparent(t.pos)) last = t + if (t.pos includes pos) { + if (!t.pos.isTransparent) last = t super.traverse(t) } } diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 1e6e5b297c..a9747325e0 100755 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -24,7 +24,7 @@ trait JavaParsers extends JavaScanners { class JavaUnitParser(val unit: global.CompilationUnit) extends JavaParser { val in = new JavaUnitScanner(unit) def freshName(pos : Position, prefix : String) = unit.fresh.newName(pos, prefix) - implicit def i2p(offset : Int) : Position = new OffsetPosition(unit.source,offset) + implicit def i2p(offset : Int) : Position = new OffsetPosition(unit.source, offset) def warning(pos : Int, msg : String) : Unit = unit.warning(pos, msg) def syntaxError(pos: Int, msg: String) : Unit = unit.error(pos, msg) } @@ -35,7 +35,7 @@ trait JavaParsers extends JavaScanners { protected def posToReport: Int = in.currentPos protected def freshName(pos : Position, prefix : String): Name protected implicit def i2p(offset : Int) : Position - private implicit def p2i(pos : Position): Int = pos.offset.getOrElse(-1) + private implicit def p2i(pos : Position): Int = if (pos.isDefined) pos.point else -1 /** The simple name of the package of the currently parsed file */ private var thisPackageName: Name = nme.EMPTY diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index ab6de92b7a..50c166c38e 100755 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -975,7 +975,7 @@ trait JavaScanners { def error (pos: Int, msg: String) = unit. error(pos, msg) def incompleteInputError(pos: Int, msg: String) = unit.incompleteInputError(pos, msg) def deprecationWarning(pos: Int, msg: String) = unit.deprecationWarning(pos, msg) - implicit def p2g(pos: Position): Int = pos.offset.getOrElse(-1) + implicit def p2g(pos: Position): Int = if (pos.isDefined) pos.point else -1 implicit def g2p(pos: Int): Position = new OffsetPosition(unit.source, pos) } } diff --git a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala index b9e4046a41..6c76968149 100644 --- a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala +++ b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala @@ -204,12 +204,12 @@ class SemanticTokens(val compiler: Global) { val map = new scala.collection.mutable.LinkedHashMap[Int,Symbol] map.clear // populate the map. class visitor extends walker.Visitor { - def contains(pos : Position) = map.contains(pos.offset.get) - def apply(pos : Position) = map(pos.offset.get) - def update(pos : Position, sym : Symbol) : Unit = if (pos.offset.isDefined) { - val offset = pos.offset.get + def contains(pos : Position) = map.contains(pos.point) + def apply(pos : Position) = map(pos.point) + def update(pos : Position, sym : Symbol) : Unit = if (pos.isDefined) { + val offset = pos.point map(offset) = sym - val isDef = pos.offset == sym.pos.offset + val isDef = pos.point == sym.pos.point list.put(offset, (if (isDef) new Def(sym) else new Use(sym, NoType))); } } @@ -224,10 +224,10 @@ class SemanticTokens(val compiler: Global) { def build(tree0: Tree): Unit = try { /* if (tree0.pos != NoPosition) */ tree0 match { case tree: ImplDef => - val pos = eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.offset.get) + val pos = eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.point) if (pos == -1) { - } else buildDef(tree.symbol, eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.offset.get)); + } else buildDef(tree.symbol, eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.point)); tree match { case cdef: ClassDef => build(cdef.tparams) case _ => ; @@ -242,7 +242,7 @@ class SemanticTokens(val compiler: Global) { // todo: review whether this is correct, or whether abstract getters should be included. { val pos : Int = if (tree.name.toString().equals("<init>")) -1 else - eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.offset.get); + eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.point); if (false) Console.err.println("VALDEF: tree=" + tree + " sym=" + tree.symbol + " pos0=" + tree.symbol.pos + " alias=" + tree.symbol.alias + " pos1=" + pos + " pos2=" + tree.pos.dbgString + " " + tree.symbol.hasFlag(Flags.SYNTHETIC)); @@ -256,8 +256,8 @@ class SemanticTokens(val compiler: Global) { build(ddef.tparams); for (l0 <- ddef.vparamss; arg <- l0) { - val pos0 : Int = if (!unit.source.beginsWith(arg.pos.offset.get, "val ")) arg.pos.offset.get; - else unit.source.skipWhitespace(arg.pos.offset.get + ("val ").length()); + val pos0 : Int = if (!unit.source.beginsWith(arg.pos.point, "val ")) arg.pos.point; + else unit.source.skipWhitespace(arg.pos.point + ("val ").length()); buildDef(arg.symbol, pos0); build(arg.tpt); } @@ -281,7 +281,7 @@ class SemanticTokens(val compiler: Global) { case tree: PackageDef => //Console.err.println("PACKAGE: " + tree.name); if (false) { - val pos = eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.offset.getOrElse(-1)) + val pos = eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.pointOrElse(-1)) if (pos != -1) buildDef(tree.symbol, pos) } @@ -290,13 +290,13 @@ class SemanticTokens(val compiler: Global) { for (arg <- tree.vparams if arg.pos != NoPosition) { val name = arg.name.toString().trim() val pos: Int = - if (unit.source.beginsWith(arg.pos.offset.getOrElse(-1), "val ")) - unit.source.skipWhitespace(arg.pos.offset.getOrElse(-1) + ("val ").length()) - else if (unit.source.asInstanceOf[BatchSourceFile].content(arg.pos.offset.get) == ':') { - var posx : Int = arg.pos.offset.get + if (unit.source.beginsWith(arg.pos.pointOrElse(-1), "val ")) + unit.source.skipWhitespace(arg.pos.pointOrElse(-1) + ("val ").length()) + else if (unit.source.asInstanceOf[BatchSourceFile].content(arg.pos.point) == ':') { + var posx : Int = arg.pos.point while (unit.source.asInstanceOf[BatchSourceFile].content(posx - 1).isWhitespace) posx = posx - 1 posx - name.length() - } else arg.pos.offset.get + } else arg.pos.point buildDef(arg.symbol, pos) build(arg.tpt) } @@ -314,13 +314,13 @@ class SemanticTokens(val compiler: Global) { def buildT( tree : Tree, tpe : Type) : Unit = if (tree.pos != NoPosition) tpe match { case tpe0 : TypeRef => tree match { case apt : AppliedTypeTree => - buildUse(tpe.typeSymbol, apt.tpt.pos.offset.getOrElse(-1), tpe0); + buildUse(tpe.typeSymbol, apt.tpt.pos.pointOrElse(-1), tpe0); //Console.err.println("APT: " + treex + " vs. " + treex.original); //Console.err.println("APT: " + treex.pos + " vs. " + treex.original.pos + " " + unit.source.dbg(treex.original.pos)); //Console.err.println("APT: " + apt.tpt + " sym0=" + apt.tpt.symbol + " sym1=" + tpe0.sym + " apt.args=" + apt.args + " tpe0.args=" + tpe0.args); buildTs (apt.args, tpe0.args); - case ident : Ident => buildUse(tpe0.sym, ident.pos.offset.getOrElse(-1), tpe0); + case ident : Ident => buildUse(tpe0.sym, ident.pos.pointOrElse(-1), tpe0); case select : Select => if (select.symbol == NoSymbol) try { @@ -336,10 +336,10 @@ class SemanticTokens(val compiler: Global) { case tpt : TypeTree => if (tpt.symbol ne null) { Console.err.println("SYM0 " + tpt.symbol + " " + (tpt.pos).dbgString); - buildUse(tpt.symbol, tpt.pos.offset.getOrElse(-1), tpe0); + buildUse(tpt.symbol, tpt.pos.pointOrElse(-1), tpe0); } else if (tpe0.typeSymbol ne null) { //Console.err.println("TYPE_SYM1 " + tpe0.symbol + " " + unit.source.dbg(tpt.pos)); - buildUse(tpe0.typeSymbol, tpt.pos.offset.getOrElse(-1), tpe0); + buildUse(tpe0.typeSymbol, tpt.pos.pointOrElse(-1), tpe0); } else { Console.err.println("UNKNOWN TPT0: " + (tpt.pos).dbgString + " tpt=" + tpt + " " + tpt.symbol + " tpe0="+ tpe0 + " " + tpe0.typeSymbol + " tpe0.args=" + tpe0.args); } @@ -385,7 +385,7 @@ class SemanticTokens(val compiler: Global) { if (false) Console.err.println("UNKNOWN TPE10: " + tpe0 + " " + tree + " " + tree.getClass() + " " + (tree.pos).dbgString); } case tpe0 : SingleType => tree match { - case ident : Ident => buildUse(tpe0.sym, ident.pos.offset.getOrElse(-1), tpe0); + case ident : Ident => buildUse(tpe0.sym, ident.pos.pointOrElse(-1), tpe0); case select : Select => buildUse(tpe0.termSymbol, selectPos(select), tpe0); //Console.err.println("QUALIFIER-0: " + select.qualifier + " " + unit.source.dbg(select.qualifier.pos) + " " + tpe0.prefix + " " + tpe0.prefix.getClass() + " " + tpe0.prefix.getClass().getSuperclass() +" " + tpe0.prefix.widen + " " + tpe0.prefix.toLongString); @@ -419,16 +419,16 @@ class SemanticTokens(val compiler: Global) { case tree: AbsTypeDef => //Console.err.println("ABS: " + tree.symbol + " " + unit.source.dbg(tree.namePos) + " " + tree.pos.dbgString); buildDef(tree.symbol, tree.namePos) - buildDef(tree.symbol, tree.pos.offset.getOrElse(-1)) + buildDef(tree.symbol, tree.pos.pointOrElse(-1)) build(tree.tparams); //@M build(tree.lo) build(tree.hi) */ case tree: Bind => - buildDef(tree.symbol, tree.pos.offset.getOrElse(-1)) + buildDef(tree.symbol, tree.pos.pointOrElse(-1)) build(tree.body) case tree: Ident => - buildUse(tree.symbol, tree.pos.offset.getOrElse(-1), tree.tpe) + buildUse(tree.symbol, tree.pos.pointOrElse(-1), tree.tpe) case tree: Select => try { build(tree.qualifier) @@ -436,7 +436,7 @@ class SemanticTokens(val compiler: Global) { case e : Error => Console.err.println("SELECTQ: " + tree + " " + tree.qualifier + " " + (tree.qualifier.pos).dbgString); throw e; } try { - if (tree.pos.offset.isDefined && tree.pos.offset.get >= unit.source.length) { + if (tree.pos.isDefined && tree.pos.point >= unit.source.length) { if (false) Console.err.println("BAD_SELECT_QUALIFIER " + tree + " @ " + (tree.pos).dbgString); } else { @@ -490,11 +490,11 @@ class SemanticTokens(val compiler: Global) { case tree : Alternative => build(tree.trees); case tree : This => - if (tree.symbol ne null) buildUse(tree.symbol, tree.pos.offset.getOrElse(-1), tree.tpe); + if (tree.symbol ne null) buildUse(tree.symbol, tree.pos.pointOrElse(-1), tree.tpe); //Thread.dumpStack(); case tree : TypeDef => //Console.err.println("ALIAS: " + tree); - build(tree.rhs); build(tree.tparams); buildDef(tree.symbol, tree.pos.offset.getOrElse(-1)); + build(tree.rhs); build(tree.tparams); buildDef(tree.symbol, tree.pos.pointOrElse(-1)); case tree : DocDef => build(tree.definition); case tree: Import => build(tree.expr) case tree: AppliedTypeTree => ; @@ -550,7 +550,7 @@ class SemanticTokens(val compiler: Global) { def selectPos(tree: Select): Int = if (tree.pos == NoPosition) -1 else { val buf = unit.source.asInstanceOf[BatchSourceFile].content - if (tree.pos.offset.get >= buf.length) { + if (tree.pos.point >= buf.length) { if (false) { Console.err.println("" + tree + "@" + tree.pos + " not in " + unit.source.file.name + "[" + buf.length + "]"); @@ -561,13 +561,13 @@ class SemanticTokens(val compiler: Global) { } val pos : Int = - if (buf(tree.pos.offset.get) != '.') tree.pos.offset.get + if (buf(tree.pos.point) != '.') tree.pos.point else { def f(x : Int) : Int = { if (buf(x).isWhitespace) f(x + 1) else x } - f(tree.pos.offset.get + 1) + f(tree.pos.point + 1) } pos }; diff --git a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala index aed42ca406..941b698b2a 100644 --- a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala @@ -53,7 +53,7 @@ abstract class AbstractReporter extends Reporter { private def testAndLog(pos: Position, severity: Severity): Boolean = { if (pos eq null) return false if (pos.offset.isEmpty) return false - val fpos = pos.focusPoint + val fpos = pos.focus if ((positions contains fpos) && positions(fpos) >= severity) return true positions += (fpos -> severity) false diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index 4ee4a4fccc..ca7b264d22 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -49,27 +49,20 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr /** Prints the message with the given position indication. */ def printMessage(posIn: Position, msg: String) { - if (posIn ne null) { - val pos = posIn.inUltimateSource(posIn.source.getOrElse(null)) - val buf = new StringBuilder(msg) - if (!pos.source.isEmpty) { - buf.insert(0, " ") - buf.insert(0, pos.line.map(ln => ":" + pos.line.get + ":").getOrElse(":")) - } - //println(getSource.file) - pos match { - case FakePos(msg) => - buf.insert(0, msg + " ") - case _ if !pos.source.isEmpty => - val file = pos.source.get.file - buf.insert(0, if (shortname) file.name else file.path) - case _ => - } - printMessage(buf.toString()) - if (!pos.line.isEmpty) + val pos = if (posIn eq null) NoPosition + else if (posIn.isDefined) posIn.inUltimateSource(posIn.source) + else posIn + pos match { + case FakePos(fmsg) => + printMessage(fmsg+" "+msg) + case NoPosition => + printMessage(msg) + case _ => + val buf = new StringBuilder(msg) + val file = pos.source.file + printMessage((if (shortname) file.name else file.path)+":"+pos.line+": "+msg) printSourceLine(pos) - } else - printMessage(msg) + } } def print(pos: Position, msg: String, severity: Severity) { @@ -88,16 +81,8 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr * * @param pos ... */ - def printColumnMarker(pos: Position) = if (!pos.column.isEmpty) { - val buffer = new StringBuilder(pos.column.get) - var i = 1 - while (i < pos.column.get) { - buffer.append(' ') - i += 1 - } - if (pos.column.get > 0) buffer.append('^') - printMessage(buffer.toString()) - } + def printColumnMarker(pos: Position) = + if (pos.isDefined) { printMessage(" " * (pos.column - 1) + "^") } /** Prints the number of errors and warnings if their are non-zero. */ def printSummary() { diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala index 3ecd8f2a6e..9e42db2fce 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala @@ -120,4 +120,6 @@ abstract class SymbolTable extends Names /** The phase which has given index as identifier */ val phaseWithId: Array[Phase] + + def ensureNonOverlapping(tree: Tree, others: List[Tree]) } diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 05c0614620..364ed5432d 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -248,7 +248,7 @@ trait Symbols { var cnt = 0 def freshName() = { cnt += 1; newTermName("x$" + cnt) } def param(tp: Type) = - newValueParameter(owner.pos, freshName()).setFlag(SYNTHETIC).setInfo(tp) + newValueParameter(owner.pos.focus, freshName()).setFlag(SYNTHETIC).setInfo(tp) argtypess map (_.map(param)) } diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index f8188246f8..5375f77569 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -2553,7 +2553,6 @@ A type's typeSymbol should never be inspected directly. newAnnots } - def mapOver(annot: AnnotationInfo): Option[AnnotationInfo] = { val AnnotationInfo(atp, args, assocs) = annot @@ -2827,6 +2826,7 @@ A type's typeSymbol should never be inspected directly. /** A base class to compute all substitutions */ abstract class SubstMap[T](from: List[Symbol], to: List[T]) extends TypeMap { + /** Are `sym' and `sym1' the same. * Can be tuned by subclasses. */ @@ -2953,20 +2953,16 @@ A type's typeSymbol should never be inspected directly. object trans extends TypeMapTransformer { override def transform(tree: Tree) = tree match { - case tree@Ident(_) if from contains tree.symbol => + case Ident(name) if from contains tree.symbol => val totpe = to(from.indexOf(tree.symbol)) - if (!totpe.isStable) { - giveup() - } else { - tree.duplicate.setType(totpe) - } + if (!totpe.isStable) giveup() + else Ident(name).setPos(tree.pos).setSymbol(tree.symbol).setType(totpe) case _ => super.transform(tree) } } trans.transform(tree) - } - + } } @@ -3039,7 +3035,7 @@ A type's typeSymbol should never be inspected directly. object treeTrans extends TypeMapTransformer { override def transform(tree: Tree): Tree = tree match { - case tree@Ident(name) => + case Ident(name) => tree.tpe.withoutAnnotations match { case DeBruijnIndex(level, pid) => if (level == 1) { @@ -3052,9 +3048,12 @@ A type's typeSymbol should never be inspected directly. setType typeRef(NoPrefix, sym, Nil)) } } else - tree.duplicate.setType( - DeBruijnIndex(level-1, pid)) - case _ => super.transform(tree) + Ident(name) + .setPos(tree.pos) + .setSymbol(tree.symbol) + .setType(DeBruijnIndex(level-1, pid)) + case _ => + super.transform(tree) } case _ => super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 1fa2ba58d2..806b054ee6 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -711,7 +711,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast. sym1 + ":" + atRefc(tpe1.toString) + (if (sym1.owner == root) "" else sym1.locationString) + " and\n" + sym2 + ":" + atRefc(tpe2.toString) + - (if (sym2.owner == root) " at line " + (sym2.pos).line.get else sym2.locationString) + + (if (sym2.owner == root) " at line " + (sym2.pos).line else sym2.locationString) + "\nhave same type" + (if (atRefc(tpe1 =:= tpe2)) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe))) sym1.setInfo(ErrorType) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index c02d2cd27d..71caf89010 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -630,7 +630,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { def mkCheckedAccessor(clazz: Symbol, retVal: Tree, offset: Int, pos: Position): Tree = { val bitmapSym = bitmapFor(clazz, offset) val mask = LIT(1 << (offset % FLAGS_PER_WORD)) - val msg = "Uninitialized field: " + unit.source + ": " + pos.line.get + val msg = "Uninitialized field: " + unit.source + ": " + pos.line val result = IF (mkTest(clazz, mask, bitmapSym, false)) . THEN (retVal) . diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 3306b1f63a..b96ce58370 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -362,7 +362,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { localTyper.typed { atPos(fun.pos) { Block( - List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, fun.pos.toSynthetic)), + List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, fun.pos)), Typed( New(TypeTree(anonClass.tpe), List(List())), TypeTree(fun.tpe))) diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala index a7b00894dd..acef0154b2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala @@ -55,6 +55,7 @@ trait Analyzer extends AnyRef def apply(unit: CompilationUnit) { try { unit.body = newTyper(rootContext(unit)).typed(unit.body) + if (global.settings.Yrangepos.value) global.validatePositions(unit.body) for (workItem <- unit.toCheck) workItem() } finally { unit.toCheck.clear() diff --git a/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala index 2714e72640..caa1e027d5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala +++ b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala @@ -405,7 +405,7 @@ abstract class DeVirtualize extends InfoTransform with TypingTransformers { } } atPos(clazz.pos) { - ClassDef(cclazz, Modifiers(0), vparamss, List(List()), pfields ::: overrideBridges, clazz.pos.toSynthetic) + ClassDef(cclazz, Modifiers(0), vparamss, List(List()), pfields ::: overrideBridges, clazz.pos.focus) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala index 118e06bf6a..314aee531c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala +++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala @@ -76,8 +76,10 @@ trait EtaExpansion { self: Analyzer => if (treeInfo.isPureExpr(tree)) tree else { val vname: Name = freshName(tree.pos, 0) - defs += atPos(tree.pos)(ValDef(Modifiers(SYNTHETIC), vname, TypeTree(), tree)) - Ident(vname) setPos tree.pos.toSynthetic + defs += atPos(tree.pos) { + ValDef(Modifiers(SYNTHETIC), vname, TypeTree(), tree) + } + Ident(vname) setPos tree.pos.focus } val tree1 = tree match { // a partial application using named arguments has the following form: @@ -99,7 +101,7 @@ trait EtaExpansion { self: Analyzer => case Ident(name) => tree } - if (tree1 ne tree) tree1 setPos makeTransparent(tree1.pos) + if (tree1 ne tree) tree1 setPos tree1.pos.makeTransparent tree1 } @@ -114,8 +116,9 @@ trait EtaExpansion { self: Analyzer => tree case MethodType(paramSyms, restpe) => val params = paramSyms map (sym => - ValDef(Modifiers(SYNTHETIC | PARAM), sym.name, TypeTree(sym.tpe), EmptyTree)) - atPos(makeTransparent(tree.pos)) { + ValDef(Modifiers(SYNTHETIC | PARAM), + sym.name, TypeTree(sym.tpe) , EmptyTree)) + atPos(tree.pos.makeTransparent) { Function(params, expand(Apply(tree, params map gen.paramToArg), restpe)) } case _ => diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index ee640ef749..9295ba261d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -130,6 +130,8 @@ self: Analyzer => class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context) extends Typer(context0) { + assert(tree.isEmpty || tree.pos.isDefined) + import infer._ /** Is implicit info `info1` better than implicit info `info2`? @@ -293,7 +295,7 @@ self: Analyzer => isCompatible(depoly(info.tpe), wildPt) && isStable(info.pre)) { - val itree = atPos(tree) { + val itree = atPos(tree.pos.focus) { if (info.pre == NoPrefix) Ident(info.name) else Select(gen.mkAttributedQualifier(info.pre), info.name) } @@ -307,8 +309,9 @@ self: Analyzer => val itree1 = if (isView) typed1( - Apply(itree, List(Ident("<argument>").setType(approximate(pt.typeArgs.head)))), - EXPRmode, approximate(pt.typeArgs.tail.head)) + atPos(itree.pos) ( + Apply(itree, List(Ident("<argument>").setType(approximate(pt.typeArgs.head))))), + EXPRmode, approximate(pt.typeArgs.tail.head)) else typed1(itree, EXPRmode, wildPt) @@ -338,6 +341,7 @@ self: Analyzer => // to methTypeArgs val result = new SearchResult(itree2, subst) if (traceImplicits) println("RESULT = "+result) + // println("RESULT = "+itree+"///"+itree1+"///"+itree2)//DEBUG result } else { if (traceImplicits) println("incompatible???") @@ -595,7 +599,7 @@ self: Analyzer => def manifestFactoryCall(constructor: String, args: Tree*): Tree = if (args contains EmptyTree) EmptyTree else - typed(atPos(tree) { + typed(atPos(tree.pos.focus) { Apply( TypeApply( Select(gen.mkAttributedRef(ManifestModule), constructor), @@ -657,9 +661,14 @@ self: Analyzer => * but keep within sizeLimit entries */ def cacheResult(key: AnyRef): SearchResult = implicitsCache get key match { - case Some(r) => + case Some(sr: SearchResult) => hits += 1 - r + if (sr == SearchFailure) sr + else { + val result = new SearchResult(sr.tree.duplicate, sr.subst) + for (t <- result.tree) t.setPos(tree.pos.focus) + result + } case None => misses += 1 val r = searchImplicit(implicitsOfExpectedType, false) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 0bc9d4d0f6..e5e0774ade 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -161,8 +161,10 @@ trait Namers { self: Analyzer => else m.owner.isClass && context.scope == m.owner.info.decls } + /** Enter symbol into context's scope and return symbol itself */ def enterInScope(sym: Symbol): Symbol = enterInScope(sym, context.scope) + /** Enter symbol into given scope and return symbol itself */ def enterInScope(sym: Symbol, scope: Scope): Symbol = { // allow for overloaded methods if (!(sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass)) { @@ -386,7 +388,9 @@ trait Namers { self: Analyzer => setInfo(setter)(namerOf(setter).setterTypeCompleter(vd)) } tree.symbol = - if (!mods.hasFlag(DEFERRED)) { + if (mods.hasFlag(DEFERRED)) { + getter setPos tree.pos // unfocus getter position, because there won't be a separate value + } else { var vsym = if (!context.owner.isClass) { assert((mods.flags & LAZY) != 0) // if not a field, it has to be a lazy val @@ -396,12 +400,12 @@ trait Namers { self: Analyzer => .setFlag(mods.flags & FieldFlags | PRIVATE | LOCAL | (if (mods.hasFlag(LAZY)) MUTABLE else 0)) } - vsym = enterInScope(vsym).asInstanceOf[TermSymbol] + enterInScope(vsym) setInfo(vsym)(namerOf(vsym).typeCompleter(tree)) if ((mods.flags & LAZY) != 0) vsym.setLazyAccessor(getter) vsym - } else getter + } addBeanGetterSetter(vd, getter) } case DefDef(mods, nme.CONSTRUCTOR, tparams, _, _, _) => @@ -450,7 +454,7 @@ trait Namers { self: Analyzer => } def enterAliasMethod(tree: Tree, name: Name, flags: Long, mods: Modifiers): TermSymbol = - enterNewMethod(tree, name, flags, mods, SyntheticAliasPosition(tree)) + enterNewMethod(tree, name, flags, mods, tree.pos.focus) private def addBeanGetterSetter(vd: ValDef, getter: Symbol) { def isAnn(ann: Tree, demand: String) = ann match { @@ -478,9 +482,9 @@ trait Namers { self: Analyzer => val getterName = if (hasBoolBP) "is" + beanName else "get" + beanName val getterMods = Modifiers(flags, mods.privateWithin, - mods.annotations map (_.syntheticDuplicate)) - val beanGetterDef = atPos(vd.pos) { - DefDef(getterMods, getterName, Nil, List(Nil), tpt.syntheticDuplicate, + mods.annotations map (_.duplicate)) + val beanGetterDef = atPos(vd.pos.focus) { + DefDef(getterMods, getterName, Nil, List(Nil), tpt.duplicate, if (mods hasFlag DEFERRED) EmptyTree else Select(This(getter.owner.name), name)) } enterSyntheticSym(beanGetterDef) @@ -491,14 +495,13 @@ trait Namers { self: Analyzer => // create and enter the symbol here, add the tree in Typer.addGettterSetter. val setterName = "set" + beanName val setter = enterAliasMethod(vd, setterName, flags, mods) - .setPos(SyntheticAliasPosition(vd)) + .setPos(vd.pos.focus) setInfo(setter)(namerOf(setter).setterTypeCompleter(vd)) } } } } - // --- Lazy Type Assignment -------------------------------------------------- def typeCompleter(tree: Tree) = mkTypeCompleter(tree) { sym => @@ -746,7 +749,7 @@ trait Namers { self: Analyzer => if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) { tpt.tpe = context.enclClass.owner.tpe - tpt setPos meth.pos + tpt setPos meth.pos.focus } if (onlyPresentation && methodArgumentNames != null) @@ -872,7 +875,7 @@ trait Namers { self: Analyzer => for (vparam <- vparams) { if (vparam.tpt.isEmpty) { vparam.tpt.tpe = pfs.head - vparam.tpt setPos vparam.pos + vparam.tpt setPos vparam.pos.focus vparam.symbol setInfo pfs.head } pfs = pfs.tail @@ -925,6 +928,8 @@ trait Namers { self: Analyzer => var posCounter = 1 + // Martin to Lukas: this needs to be reviewed in light of range positions. + // for each value parameter, create the getter method if it has a default argument. previous // denotes the parameter lists which are on the left side of the current one. these get added // to the default getter. Example: "def foo(a: Int)(b: Int = a)" gives "foo$default$1(a: Int) = a" @@ -944,7 +949,7 @@ trait Namers { self: Analyzer => var deftParams = tparams map copyUntyped[TypeDef] val defvParamss = previous map (_.map(p => { // in the default getter, remove the default parameter - val p1 = atPos(p.pos) { ValDef(p.mods &~ DEFAULTPARAM, p.name, p.tpt.syntheticDuplicate, EmptyTree) } + val p1 = atPos(p.pos.focus) { ValDef(p.mods &~ DEFAULTPARAM, p.name, p.tpt.duplicate, EmptyTree) } UnTyper.traverse(p1) p1 })) @@ -991,9 +996,9 @@ trait Namers { self: Analyzer => } val defTpt = subst(copyUntyped(vparam.tpt)) - val defRhs = copyUntyped(vparam.rhs) + val defRhs = copyUntyped(vparam.rhs)// this should not be synthetic? - val defaultTree = atPos(vparam.pos) { + val defaultTree = atPos(vparam.pos.focus) { DefDef( Modifiers(meth.flags & (PRIVATE | PROTECTED | FINAL)) | SYNTHETIC | DEFAULTPARAM | oflag, name, deftParams, defvParamss, defTpt, defRhs) @@ -1020,7 +1025,7 @@ trait Namers { self: Analyzer => val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol)) // compute result type from rhs tpt.tpe = widenIfNotFinal(meth, typer.computeType(rhs, pt), pt) - tpt setPos meth.pos + tpt setPos meth.pos.focus tpt.tpe } else typer.typedType(tpt).tpe) } @@ -1129,7 +1134,7 @@ trait Namers { self: Analyzer => sym, newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType), WildcardType) - tpt setOriginal vdef + tpt setPos vdef.pos.focus tpt.tpe } } else typer1.typedType(tpt).tpe diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 830503d37a..8760cd85dc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -327,8 +327,10 @@ trait NamesDefaults { self: Analyzer => else TypeApply(default1, targs.map(_.duplicate)).setPos(pos) val default2 = (default1 /: previousArgss)((tree, args) => Apply(tree, args.map(_.duplicate)).setPos(pos)) - if (positional) default2 - else atPos(pos) { AssignOrNamedArg(Ident(p.name), default2) } + atPos(pos) { + if (positional) default2 + else AssignOrNamedArg(Ident(p.name), default2) + } }) (givenArgs ::: defaultArgs, Nil) } else (givenArgs, missing filter (! _.hasFlag(DEFAULTPARAM))) diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index 23f90b1b8e..07914fbc27 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -67,7 +67,7 @@ trait SyntheticMethods extends ast.TreeDSL { newSyntheticMethod(name, flags | OVERRIDE, tpeCons) def newSyntheticMethod(name: Name, flags: Int, tpeCons: Symbol => Type) = { - val method = clazz.newMethod(clazz.pos.toSynthetic, name) setFlag (flags | SYNTHETICMETH) + val method = clazz.newMethod(clazz.pos.focus, name) setFlag (flags | SYNTHETICMETH) method setInfo tpeCons(method) clazz.info.decls.enter(method).asInstanceOf[TermSymbol] } @@ -169,7 +169,7 @@ trait SyntheticMethods extends ast.TreeDSL { // returns (Apply, Bind) def makeTrees(acc: Symbol, cpt: Type): (Tree, Bind) = { - val varName = context.unit.fresh.newName(clazz.pos.toSynthetic, acc.name + "$") + val varName = context.unit.fresh.newName(clazz.pos.focus, acc.name + "$") val (eqMethod, binding) = if (cpt.isVarargs) (nme.sameElements, Star(WILD())) else (nme.EQ , WILD() ) @@ -215,7 +215,7 @@ trait SyntheticMethods extends ast.TreeDSL { def newAccessorMethod(tree: Tree): Tree = tree match { case DefDef(_, _, _, _, _, rhs) => var newAcc = tree.symbol.cloneSymbol - newAcc.name = context.unit.fresh.newName(tree.symbol.pos.toSynthetic, tree.symbol.name + "$") + newAcc.name = context.unit.fresh.newName(tree.symbol.pos.focus, tree.symbol.name + "$") newAcc setFlag SYNTHETIC resetFlag (ACCESSOR | PARAMACCESSOR | PRIVATE) newAcc = newAcc.owner.info.decls enter newAcc val result = typer typed { DEF(newAcc) === rhs.duplicate } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6ef2f61deb..0b50b0b94d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -301,7 +301,7 @@ trait Typers { self: Analyzer => case t => t } "\n Note that "+tree.symbol+" is not stable because its type, "+tree.tpe+", is volatile." - } else "")) + } else "")) /** Would tree be a stable (i.e. a pure expression) if the type * of its symbol was not volatile? @@ -767,7 +767,7 @@ trait Typers { self: Analyzer => val tparams1 = cloneSymbols(tparams) val tree1 = if (tree.isType) tree else TypeApply(tree, tparams1 map (tparam => - TypeTree(tparam.tpe) setOriginal tree)) setPos tree.pos + TypeTree(tparam.tpe) setPos tree.pos.focus)) setPos tree.pos context.undetparams = context.undetparams ::: tparams1 adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt) case mt: ImplicitMethodType if ((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) => // (4.1) @@ -1018,7 +1018,7 @@ trait Typers { self: Analyzer => val supertpt1 = typedType(supertpt) if (!supertpt1.tpe.isError) { mixins = supertpt1 :: mixins - supertpt = TypeTree(supertpt1.tpe.parents.head) setOriginal supertpt /* setPos supertpt.pos */ + supertpt = TypeTree(supertpt1.tpe.parents.head) setPos supertpt.pos.focus } } @@ -1033,26 +1033,26 @@ trait Typers { self: Analyzer => // A method to replace a super reference by a New in a supercall def transformSuperCall(scall: Tree): Tree = (scall: @unchecked) match { case Apply(fn, args) => - treeCopy.Apply(scall, transformSuperCall(fn), args map (_.syntheticDuplicate)) + treeCopy.Apply(scall, transformSuperCall(fn), args map (_.duplicate)) case Select(Super(_, _), nme.CONSTRUCTOR) => treeCopy.Select( scall, - New(TypeTree(supertpe) setOriginal supertpt) setType supertpe setPos supertpt.pos, + atPos(supertpt.pos.focus)(New(TypeTree(supertpe)) setType supertpe), nme.CONSTRUCTOR) } treeInfo.firstConstructor(templ.body) match { case constr @ DefDef(_, _, _, vparamss, _, cbody @ Block(cstats, cunit)) => // Convert constructor body to block in environment and typecheck it - val cstats1: List[Tree] = cstats map (_.syntheticDuplicate) + val cstats1: List[Tree] = cstats map (_.duplicate) val scall = if (cstats.isEmpty) EmptyTree else cstats.last val cbody1 = scall match { case Apply(_, _) => treeCopy.Block(cbody, cstats1.init, - if (supertparams.isEmpty) cunit.syntheticDuplicate + if (supertparams.isEmpty) cunit.duplicate else transformSuperCall(scall)) case _ => - treeCopy.Block(cbody, cstats1, cunit.syntheticDuplicate) + treeCopy.Block(cbody, cstats1, cunit.duplicate) } val outercontext = context.outer @@ -1060,14 +1060,14 @@ trait Typers { self: Analyzer => val cscope = outercontext.makeNewScope(constr, outercontext.owner)(ParentTypesScopeKind(clazz)) val cbody2 = newTyper(cscope) // called both during completion AND typing. .typePrimaryConstrBody(clazz, - cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (_.map(_.syntheticDuplicate))) + cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (_.map(_.duplicate))) scall match { case Apply(_, _) => val sarg = treeInfo.firstArgument(scall) if (sarg != EmptyTree && supertpe.typeSymbol != firstParent) error(sarg.pos, firstParent+" is a trait; does not take constructor arguments") - if (!supertparams.isEmpty) supertpt = TypeTree(cbody2.tpe) setPos supertpt.pos + if (!supertparams.isEmpty) supertpt = TypeTree(cbody2.tpe) setPos supertpt.pos.focus case _ => if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments") } @@ -1238,10 +1238,10 @@ trait Typers { self: Analyzer => */ def addGetterSetter(stat: Tree): List[Tree] = stat match { case ValDef(mods, name, tpt, rhs) - if (mods.flags & (PRIVATE | LOCAL)) != (PRIVATE | LOCAL) - && !stat.symbol.isModuleVar => + if (mods.flags & (PRIVATE | LOCAL)) != (PRIVATE | LOCAL) && !stat.symbol.isModuleVar => + val isDeferred = mods hasFlag DEFERRED val value = stat.symbol - val getter = if ((mods hasFlag DEFERRED)) value else value.getter(value.owner) + val getter = if (isDeferred) value else value.getter(value.owner) assert(getter != NoSymbol, stat) if (getter hasFlag OVERLOADED) error(getter.pos, getter+" is defined twice") @@ -1252,20 +1252,22 @@ trait Typers { self: Analyzer => if (value.hasFlag(LAZY)) List(stat) else { val vdef = treeCopy.ValDef(stat, mods | PRIVATE | LOCAL, nme.getterToLocal(name), tpt, rhs) - val getterDef: DefDef = atPos(vdef) { - val result = DefDef(getter, - if (mods hasFlag DEFERRED) EmptyTree - else typed( - atPos(vdef) { gen.mkCheckInit(Select(This(value.owner), value)) }, - EXPRmode, value.tpe)) - result.tpt.asInstanceOf[TypeTree] setOriginal tpt /* setPos tpt.pos */ - checkNoEscaping.privates(getter, result.tpt) - treeCopy.DefDef(result, result.mods, result.name, - result.tparams, result.vparamss, result.tpt, result.rhs) + val getterDef: DefDef = atPos(vdef.pos.focus) { + if (isDeferred) { + val r = DefDef(getter, EmptyTree) + r.tpt.asInstanceOf[TypeTree].setOriginal(tpt) // keep type tree of original abstract field + r + } else { + val rhs = gen.mkCheckInit(Select(This(value.owner), value)) + val r = DefDef(getter, typed(rhs, EXPRmode, value.tpe)) + r.tpt.setPos(tpt.pos.focus) + r + } } + checkNoEscaping.privates(getter, getterDef.tpt) def setterDef(setter: Symbol): DefDef = { setter.setAnnotations(value.annotations) - val result = atPos(vdef)( + val result = atPos(vdef.pos.focus)( DefDef(setter, if ((mods hasFlag DEFERRED) || (setter hasFlag OVERLOADED)) EmptyTree @@ -1705,6 +1707,7 @@ trait Typers { self: Analyzer => else "")) ErrorType } + if (!vparam.tpt.pos.isDefined) vparam.tpt setPos vparam.pos.focus } enterSym(context, vparam) if (context.retyping) context.scope enter vparam.symbol @@ -1748,7 +1751,7 @@ trait Typers { self: Analyzer => def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { val inBlock = exprOwner == context.owner def includesTargetPos(tree: Tree) = - !tree.pos.isSynthetic && context.unit != null && (tree.pos includes context.unit.targetPos) + tree.pos.isRange && context.unit != null && (tree.pos includes context.unit.targetPos) val localTarget = stats exists includesTargetPos def typedStat(stat: Tree): Tree = { if (context.owner.isRefinementClass && !treeInfo.isDeclaration(stat)) @@ -1982,7 +1985,7 @@ trait Typers { self: Analyzer => */ def tryTupleApply: Option[Tree] = { // if 1 formal, 1 arg (a tuple), otherwise unmodified args - val tupleArgs = actualArgs(tree.pos, args, formals.length) + val tupleArgs = actualArgs(tree.pos.makeTransparent, args, formals.length) if (tupleArgs.length != args.length) { // expected one argument, but got 0 or >1 ==> try applying to tuple @@ -2046,7 +2049,7 @@ trait Typers { self: Analyzer => true case _ => false } - val (allArgs, missing) = addDefaults(args, qual, targs, previousArgss, params, fun.pos) + val (allArgs, missing) = addDefaults(args, qual, targs, previousArgss, params, fun.pos.focus) if (allArgs.length == formals.length) { // useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]() context.diagnostic = "Error occured in an application involving default arguments." :: context.diagnostic @@ -2400,7 +2403,7 @@ trait Typers { self: Analyzer => // and then stripping the "self =>" and substituting // in the supplied selfsym. val funcparm = ValDef(NoMods, nme.self, TypeTree(selfsym.info), EmptyTree) - val func = Function(List(funcparm), ann.syntheticDuplicate) + val func = Function(List(funcparm), ann.duplicate) // The .duplicate of annot.constr // deals with problems that // accur if this annotation is @@ -2732,7 +2735,7 @@ trait Typers { self: Analyzer => ann.tpe = arg1.tpe.withAnnotation(annotInfo) } val atype = ann.tpe - Typed(arg1, TypeTree(atype) setOriginal tree) setPos tree.pos setType atype + Typed(arg1, TypeTree(atype) setOriginal tree setPos tree.pos.focus) setPos tree.pos setType atype } } @@ -2857,7 +2860,7 @@ trait Typers { self: Analyzer => if (tpt1.hasSymbol && !tpt1.symbol.typeParams.isEmpty) { context.undetparams = cloneSymbols(tpt1.symbol.typeParams) tpt1 = TypeTree() - .setOriginal(tpt1) /* .setPos(tpt1.pos) */ + .setOriginal(tpt1) .setType(appliedType(tpt1.tpe, context.undetparams map (_.tpe))) } /** If current tree <tree> appears in <val x(: T)? = <tree>> @@ -2972,7 +2975,7 @@ trait Typers { self: Analyzer => setError(tree) case _ => errorTree(tree, treeSymTypeMsg(fun)+" does not take type parameters.") - } + } /** * @param args ... @@ -3065,7 +3068,7 @@ trait Typers { self: Analyzer => if (fun2.symbol == Array_apply) { val checked = gen.mkCheckInit(res) // this check is needed to avoid infinite recursion in Duplicators - // (calling typed1 more than once for the same tree + // (calling typed1 more than once for the same tree) if (checked ne res) typed { atPos(tree.pos)(checked) } else res } else res @@ -3102,12 +3105,14 @@ trait Typers { self: Analyzer => def mkAssign(vble: Tree): Tree = Assign( vble, - Apply(Select(vble.syntheticDuplicate, prefix) setPos fun.pos, args) setPos tree.pos + Apply( + Select(vble.duplicate, prefix) setPos fun.pos.focus, args) setPos tree.pos.makeTransparent ) setPos tree.pos val tree1 = qual match { case Select(qualqual, vname) => gen.evalOnce(qualqual, context.owner, context.unit) { qq => - mkAssign(Select(qq(), vname) setPos qual.pos) + val qq1 = qq() + mkAssign(Select(qq1, vname) setPos qq1.pos) } case Apply(Select(table, nme.apply), indices) => gen.evalOnceAll(table :: indices, context.owner, context.unit) { ts => @@ -3228,8 +3233,8 @@ trait Typers { self: Analyzer => qual.tpe.widen+" does not have a constructor" else decode(name)+" is not a member of "+qual.tpe.widen + - (if ((context.unit ne null) && - ((for(a <- qual.pos.line; b <- tree.pos.line) yield a < b).getOrElse(false))) + (if ((context.unit ne null) && // Martin: why is this condition needed? + qual.pos.isDefined && tree.pos.isDefined && qual.pos.line < tree.pos.line) "\npossible cause: maybe a semicolon is missing before `"+decode(name)+"'?" else "")) } @@ -3383,7 +3388,7 @@ trait Typers { self: Analyzer => imports1 = imports1.tail } defSym = impSym - qual = atPos(tree.pos.focusStart)(resetPos(imports.head.qual.syntheticDuplicate)) + qual = atPos(tree.pos.focusStart)(resetPos(imports.head.qual.duplicate)) pre = qual.tpe } else { if (settings.debug.value) { @@ -3710,16 +3715,14 @@ trait Typers { self: Analyzer => case etpt @ ExistentialTypeTree(_, _) => newTyper(context.makeNewScope(tree, context.owner)).typedExistentialTypeTree(etpt, mode) - case TypeTree() => - tree.pos match { - case SyntheticAliasPosition(original) => - tree setType typedType(original, mode).tpe - case _ => - // 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 tpt @ TypeTree() => + if (tpt.original != null) + tree setType typedType(tpt.original, mode).tpe + else + // 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 _ => throw new Error("unexpected tree: " + tree.getClass + "\n" + tree)//debug } @@ -3731,7 +3734,7 @@ trait Typers { self: Analyzer => * @param pt ... * @return ... */ - def typed(tree: Tree, mode: Int, pt: Type): Tree = { + def typed(tree: Tree, mode: Int, pt: Type): Tree = { def dropExistential(tp: Type): Type = tp match { case ExistentialType(tparams, tpe) => @@ -3776,9 +3779,11 @@ trait Typers { self: Analyzer => (context.unit.source ne null) && (tree ne null)) logError("AT: " + (tree.pos).dbgString, ex); throw(ex) +/* case ex: java.lang.Error => Console.println("exception when typing "+tree+", pt = "+pt) throw ex +*/ //debug } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index 74c51405e4..7944e940ef 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -23,7 +23,7 @@ trait Unapplies extends ast.TreeDSL private def isVarargs(vd: ValDef) = treeInfo isRepeatedParamType vd.tpt private def isByName(vd: ValDef) = treeInfo isByNameParamType vd.tpt - private def toIdent(x: DefTree) = Ident(x.name) + private def toIdent(x: DefTree) = Ident(x.name) setPos x.pos.focus /** returns type list for return type of the extraction */ def unapplyTypeList(ufn: Symbol, ufntpe: Type) = { @@ -94,12 +94,12 @@ trait Unapplies extends ast.TreeDSL } def copyUntyped[T <: Tree](tree: T): T = - applyAndReturn[T](UnTyper traverse _)(tree.syntheticDuplicate) + applyAndReturn[T](UnTyper traverse _)(tree.duplicate) def copyUntypedInvariant(td: TypeDef): TypeDef = applyAndReturn[TypeDef](UnTyper traverse _)( treeCopy.TypeDef(td, td.mods &~ (COVARIANT | CONTRAVARIANT), td.name, - td.tparams map (_.syntheticDuplicate), td.rhs.syntheticDuplicate) + td.tparams, td.rhs).duplicate ) private def classType(cdef: ClassDef, tparams: List[TypeDef]): Tree = { @@ -135,11 +135,11 @@ trait Unapplies extends ast.TreeDSL companionModuleDef(cdef, parents ::: List(gen.scalaScalaObjectConstr)) } - def companionModuleDef(cdef: ClassDef, parents: List[Tree]): ModuleDef = atPos(cdef) { + def companionModuleDef(cdef: ClassDef, parents: List[Tree]): ModuleDef = atPos(cdef.pos.focus) { ModuleDef( Modifiers(cdef.mods.flags & AccessFlags | SYNTHETIC, cdef.mods.privateWithin), cdef.name.toTermName, - Template(parents, emptyValDef, NoMods, Nil, List(Nil), Nil, cdef.impl.pos.toSynthetic)) + Template(parents, emptyValDef, NoMods, Nil, List(Nil), Nil, cdef.impl.pos.focus)) } private val caseMods = Modifiers(SYNTHETIC | CASE) @@ -149,7 +149,7 @@ trait Unapplies extends ast.TreeDSL def caseModuleApplyMeth(cdef: ClassDef): DefDef = { val tparams = cdef.tparams map copyUntypedInvariant val cparamss = constrParamss(cdef) - atPos(cdef.pos)( + atPos(cdef.pos.focus)( DefDef(caseMods, nme.apply, tparams, cparamss, classType(cdef, tparams), New(classType(cdef, tparams), cparamss map (_ map gen.paramToArg))) ) @@ -166,7 +166,7 @@ trait Unapplies extends ast.TreeDSL } val cparams = List(ValDef(Modifiers(PARAM | SYNTHETIC), paramName, classType(cdef, tparams), EmptyTree)) - atPos(cdef.pos)( + atPos(cdef.pos.focus)( DefDef(caseMods, method, tparams, List(cparams), TypeTree(), caseClassUnapplyReturnValue(paramName, cdef.symbol)) ) @@ -184,12 +184,12 @@ trait Unapplies extends ast.TreeDSL // not good enough to just duplicated the (untyped) tpt tree; the parameter types are removed here // and re-added in ``finishWith'' in the namer. def paramWithDefault(vd: ValDef) = - treeCopy.ValDef(vd, vd.mods | DEFAULTPARAM, vd.name, TypeTree() setOriginal vd.tpt, toIdent(vd)) + treeCopy.ValDef(vd, vd.mods | DEFAULTPARAM, vd.name, atPos(vd.pos.focus)(TypeTree() setOriginal vd.tpt), toIdent(vd)) val paramss = cparamss map (_ map paramWithDefault) val classTpe = classType(cdef, tparams) - Some(atPos(cdef.pos)( + Some(atPos(cdef.pos.focus)( DefDef(Modifiers(SYNTHETIC), nme.copy, tparams, paramss, classTpe, New(classTpe, paramss map (_ map toIdent))) )) diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala index 71de35d29e..a63454fd44 100644 --- a/src/compiler/scala/tools/nsc/util/Position.scala +++ b/src/compiler/scala/tools/nsc/util/Position.scala @@ -8,49 +8,61 @@ package scala.tools.nsc package util object Position { - // a static field - private val tabInc = 8 + val tabInc = 8 } trait Position { - import Position.tabInc - - /** An optional value containing the point of this position as an offset in a source file, - * or None if not defined - */ - def offset: Option[Int] = None /** An optional value containing the source file referred to by this position, or * None if not defined. */ - def source: Option[SourceFile] = None + def source: SourceFile = throw new UnsupportedOperationException("Position.source") /** Is this position neither a NoPosition nor a FakePosition? * If isDefined is true, offset and source are both defined. */ def isDefined: Boolean = false - /** Is this position a synthetic position? */ - def isSynthetic: Boolean = false + /** Is this position a transparent position? */ + def isTransparent: Boolean = false + + /** Is this position a range position? */ + def isRange: Boolean = false + + /** Is this position a non-transparent range position? */ + def isOpaqueRange: Boolean = false + + /** if opaque range, make this position transparent */ + def makeTransparent: Position = this - /** if possible, make this position a synthetic one */ - def toSynthetic: Position = this + /** The start of the position's range, error if not a range position */ + def start: Int = throw new UnsupportedOperationException("Position.start") - /** The start of the position's range */ - def start: Int = point + /** The start of the position's range, or point if not a range position */ + def startOrPoint: Int = point /** The point (where the ^ is) of the position */ - def point: Int = offset.get + def point: Int = throw new UnsupportedOperationException("Position.point") - /** The end of the position's range */ - def end: Int = point + /** The point (where the ^ is) of the position, or else `default' if undefined */ + def pointOrElse(default: Int): Int = default - def startOrElse(d: Int) = offset.getOrElse(d) - def pointOrElse(d: Int) = offset.getOrElse(d) - def endOrElse(d: Int) = offset.getOrElse(d) + /** The end of the position's range, error if not a range position */ + def end: Int = throw new UnsupportedOperationException("Position.end") + /** The end of the position's range, or point if not a range position */ + def endOrPoint: Int = point + + @deprecated("use point instead") + def offset: Option[Int] = if (isDefined) Some(point) else None + + /** The same position with a different start value (if a range) */ def withStart(off: Int) = this + + /** The same position with a different end value (if a range) */ def withEnd(off: Int) = this + + /** The same position with a different point value (if a range or offset) */ def withPoint(off: Int) = this /** If this is a range, the union with the other range, with the point of this position. @@ -58,11 +70,6 @@ trait Position { */ def union(pos: Position) = this - /** The underlying position; for a SyntheticAliasPosition this is the underlying position - * of the aliased tree. - */ - def underlying = this - /** If this is a range position, the offset position of its start. * Otherwise the position itself */ @@ -71,7 +78,7 @@ trait Position { /** If this is a range position, the offset position of its point. * Otherwise the position itself */ - def focusPoint = this + def focus = this /** If this is a range position, the offset position of its end. * Otherwise the position itself @@ -79,72 +86,51 @@ trait Position { def focusEnd = this /** Does this position include the given position `pos`. - * This holds if both positions are defined, and the range [start..end] of this position + * This holds this is a range position and its range [start..end] * is the same or covers the range of the given position. */ - def includes(pos: Position) = - isDefined && pos.isDefined && start <= pos.start && pos.end <= end + def includes(pos: Position) = false /** Does this position properly include the given position `pos` ("properly" meaning their * ranges are not the same)? */ def properlyIncludes(pos: Position) = - includes(pos) && (start < pos.start || pos.end < end) + includes(pos) && (start < pos.startOrPoint || pos.endOrPoint < end) /** Does this position precede that position? * This holds if both positions are defined and the end point of this position * is not larger than the start point of the given position. */ def precedes(pos: Position) = - isDefined && pos.isDefined && end <= pos.start + isDefined && pos.isDefined && endOrPoint <= pos.startOrPoint /** Does this position properly precede the given position `pos` ("properly" meaning their ranges * do not share a common point). */ def properlyPrecedes(pos: Position) = - precedes(pos) && start < pos.end + isDefined && pos.isDefined && startOrPoint < pos.endOrPoint /** Does this position overlap with that position? - * This holds if both positions are defined and there is an interval of + * This holds if both positions are ranges and there is an interval of * non-zero length that is shared by both position ranges. */ def overlaps(pos: Position) = - isDefined && pos.isDefined && - (pos.start < end && start < pos.end) || (start < pos.end && pos.start < end) + isRange && pos.isRange && + ((pos.start < end && start < pos.end) || (start < pos.end && pos.start < end)) /** Does this position cover the same range as that position? + * Holds only if both position are ranges */ def sameRange(pos: Position) = - isDefined && pos.isDefined && start == pos.start && end == pos.end - - def line: Option[Int] = - if (offset.isEmpty || source.isEmpty) None - else Some(source.get.offsetToLine(offset.get) + 1) - - def column: Option[Int] = - if (offset.isEmpty || source.isEmpty) - None - else { - var column = 1 - // find beginning offset for line - val line = source.get.offsetToLine(offset.get) - var coffset = source.get.lineToOffset(line) - var continue = true - while (continue) { - if (coffset == offset.getOrElse(-1)) continue = false - else if (source.get.asInstanceOf[BatchSourceFile].content(coffset) == '\t') - column = ((column - 1) / tabInc * tabInc) + tabInc + 1 - else column += 1 - coffset += 1 - } - Some(column) - } + isRange && pos.isRange && start == pos.start && end == pos.end + + def line: Int = throw new UnsupportedOperationException("Position.line") + + def column: Int = throw new UnsupportedOperationException("Position.column") - def lineContent: String = { - val line = this.line - if (!line.isEmpty) source.get.lineToString(line.get - 1) + def lineContent: String = + if (isDefined) source.lineToString(line - 1) else "NO_LINE" - } /** Map this position to a position in an original source * file. If the SourceFile is a normal SourceFile, simply @@ -153,77 +139,89 @@ trait Position { def inUltimateSource(source : SourceFile) = if (source == null) this else source.positionInUltimateSource(this) - def dbgString = { - (if (source.isEmpty) "" else "source-" + source.get.path) + - (if (line.isEmpty) "" else "line-" + line.get) + - (if (offset.isEmpty) "" - else if (offset.get >= source.get.length) "out-of-bounds-" + offset.get - else { - val ret = "offset=" + offset.get; - var add = ""; - /* - while (offset.get + add.length < source.get.length && - add.length < 10) add = add + source.get.content(offset.get + add.length()); - */ - ret + " c[0..9]=\"" + add + "\""; - }) - } + def dbgString = toString def show: String = "["+toString+"]" } -case object NoPosition extends Position +case object NoPosition extends Position { + override def dbgString = toString +} + case class FakePos(msg: String) extends Position { - override def toString=msg + override def toString = msg } -case class OffsetPosition(source0: SourceFile, offset0: Int) extends Position { - override def source = Some(source0) - override def offset = Some(offset0) - override def withPoint(off: Int) = new OffsetPosition(source0, off) +class OffsetPosition(override val source: SourceFile, override val point: Int) extends Position { override def isDefined = true - override def toSynthetic: Position = new SyntheticOffsetPosition(source0, offset0) + override def pointOrElse(default: Int): Int = point + override def withPoint(off: Int) = new OffsetPosition(source, off) + + override def line: Int = source.offsetToLine(point) + 1 + + override def column: Int = { + var idx = source.lineToOffset(source.offsetToLine(point)) + var col = 0 + while (idx != point) { + col += (if (source.content(idx) == '\t') Position.tabInc - col % Position.tabInc else 1) + idx += 1 + } + col + 1 + } + + override def union(pos: Position) = + if (pos.isRange) pos else this + override def equals(that : Any) = that match { - case that : OffsetPosition => offset0 == that.offset0 && source0.file == that.source0.file - case that => false + case that : OffsetPosition => point == that.point && source.file == that.source.file + case that => false } - override def hashCode = offset0 * 37 + source0.file.hashCode + override def hashCode = point * 37 + source.file.hashCode + + override def dbgString = + "source-"+source.path+ + ",line-"+line+ + (if (point >= source.length) ",out-of-bounds-"+point + else ",offset="+point) + override def show = "["+point+"]" } -class SyntheticOffsetPosition(source0: SourceFile, offset0: Int) extends OffsetPosition(source0, offset0) { - override def isSynthetic = true - override def toSynthetic = this - override def withPoint(off: Int) = new SyntheticOffsetPosition(source0, off) - override def show = "<["+point+"]>" -/* +/** new for position ranges */ +class RangePosition(source: SourceFile, override val start: Int, point: Int, override val end: Int) +extends OffsetPosition(source, point) { + if (start > end) assert(false, "bad position: "+show) + override def isRange: Boolean = true + override def isOpaqueRange: Boolean = true + override def startOrPoint: Int = start + override def endOrPoint: Int = end + override def withStart(off: Int) = new RangePosition(source, off, point, end) + override def withEnd(off: Int) = new RangePosition(source, start, point, off) + override def withPoint(off: Int) = new RangePosition(source, start, off, end) + override def focusStart = new OffsetPosition(source, start) + override def focus = { + if (focusCache eq NoPosition) focusCache = new OffsetPosition(source, point) + focusCache + } + override def focusEnd = new OffsetPosition(source, end) + override def makeTransparent = new TransparentPosition(source, start, point, end) + override def includes(pos: Position) = pos.isDefined && start <= pos.startOrPoint && pos.endOrPoint <= end override def union(pos: Position) = - if (pos.isDefined && !pos.isSynthetic) pos - else this -*/ + if (pos.isRange) new RangePosition(source, start min pos.start, point, end max pos.end) else this + override def toString = "RangePosition("+source+", "+start+", "+point+", "+end+")" + override def show = "["+start+":"+end+"]" + private var focusCache: Position = NoPosition } -/** new for position ranges */ -class RangePosition(source0: SourceFile, override val start: Int, override val point: Int, override val end: Int) -extends OffsetPosition(source0, point) { - override def isDefined = true - override def startOrElse(d: Int) = start - override def pointOrElse(d: Int) = point - override def withStart(off: Int) = new RangePosition(source0, off, point, end) - override def withEnd(off: Int) = new RangePosition(source0, start, point, off) - override def withPoint(off: Int) = new RangePosition(source0, start, off, end) - override def endOrElse(d: Int) = end - override def focusStart = OffsetPosition(source0, start) - override def focusPoint = OffsetPosition(source0, point) - override def focusEnd = OffsetPosition(source0, end) - override def toString = "RangePosition("+source0+", "+start+", "+point+", "+end+")" - override def show = "["+start+":"+end+"]" - override def union(pos: Position) = - if (pos.isDefined && !pos.isSynthetic) new RangePosition(source0, start min pos.start, point, end max pos.end) - else this +class TransparentPosition(source: SourceFile, start: Int, point: Int, end: Int) extends RangePosition(source, start, point, end) { + override def isOpaqueRange: Boolean = false + override def isTransparent = true + override def makeTransparent = this + override def show = "<"+start+":"+end+">" } + diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala index 3744262be6..2d8d963ca3 100644 --- a/src/compiler/scala/tools/nsc/util/SourceFile.scala +++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala @@ -82,16 +82,16 @@ class BatchSourceFile(val file : AbstractFile, val content: Array[Char]) extends def underlyingLength = length def start = 0 - override def identifier(pos: Position, compiler: Global) = pos match { - case OffsetPosition(source, offset) if source == this && offset != -1 => + override def identifier(pos: Position, compiler: Global) = + if (pos.isDefined && pos.source == this && pos.point != -1) { def isOK(c: Char) = { import compiler.syntaxAnalyzer.{ isOperatorPart, isIdentifierPart } isIdentifierPart(c) || isOperatorPart(c) } - Some(new String(content drop offset takeWhile isOK)) - case _ => + Some(new String(content drop pos.point takeWhile isOK)) + } else { super.identifier(pos, compiler) - } + } def isLineBreak(idx: Int) = if (idx >= length) false else content(idx) match { @@ -112,6 +112,9 @@ class BatchSourceFile(val file : AbstractFile, val content: Array[Char]) extends private var lastLine = 0 + /** Convert offset to line in this source file + * Lines are numbered from 0 + */ def offsetToLine(offset: Int): Int = { val lines = lineIndices def findLine(lo: Int, hi: Int, mid: Int): Int = diff --git a/src/library/scala/Product.scala b/src/library/scala/Product.scala index bae88f52d7..85c562fee8 100644 --- a/src/library/scala/Product.scala +++ b/src/library/scala/Product.scala @@ -32,6 +32,7 @@ trait Product extends AnyRef { */ def productArity: Int + /** An iterator that returns all fields of this product */ def productIterator: Iterator[Any] = new Iterator[Any] { private var c: Int = 0 private val cmax = productArity diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check index a6200419ce..d8eb03fbaf 100644 --- a/test/files/neg/names-defaults-neg.check +++ b/test/files/neg/names-defaults-neg.check @@ -93,10 +93,6 @@ List[Int]'s type parameters do not match type T's expected parameters: class Lis Error occured in an application involving default arguments. test4() ^ -error: type mismatch; - found : List[Int] - required: List[List[scala.List[List[X forSome { type X }]]]] -Error occured in an application involving default arguments. names-defaults-neg.scala:80: error: type mismatch; found : List[Int] required: scala.List[scala.List[?]] @@ -117,4 +113,4 @@ names-defaults-neg.scala:105: error: multiple overloaded alternatives of method names-defaults-neg.scala:108: error: multiple overloaded alternatives of method bar define default arguments def bar(i: Int = 129083) = i ^ -29 errors found +28 errors found |