diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/ast/Desugar.scala | 32 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/NavigateAST.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/Positioned.scala | 64 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/TreeInfo.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/Trees.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/untpd.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/config/Config.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/JavaParsers.scala | 164 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/JavaScanners.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/Parsers.scala | 98 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/RefinedPrinter.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/FrontEnd.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 16 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/VarianceChecker.scala | 6 |
15 files changed, 243 insertions, 163 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index 7011d13a0..36cae6378 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -505,7 +505,7 @@ object desugar { val clsTmpl = cpy.Template(tmpl)(self = clsSelf, body = tmpl.body) val cls = TypeDef(clsName, clsTmpl) .withMods(mods.toTypeFlags & RetainedModuleClassFlags | ModuleClassCreationFlags) - Thicket(modul, classDef(cls)) + Thicket(modul, classDef(cls).withPos(mdef.pos)) } } @@ -516,7 +516,7 @@ object desugar { def patDef(pdef: PatDef)(implicit ctx: Context): Tree = { val PatDef(mods, pats, tpt, rhs) = pdef val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt)) - flatTree(pats1 map (makePatDef(mods, _, rhs))) + flatTree(pats1 map (makePatDef(pdef, mods, _, rhs))) } /** If `pat` is a variable pattern, @@ -534,9 +534,9 @@ object desugar { * If the original pattern variable carries a type annotation, so does the corresponding * ValDef or DefDef. */ - def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree)(implicit ctx: Context): Tree = pat match { + def makePatDef(original: Tree, mods: Modifiers, pat: Tree, rhs: Tree)(implicit ctx: Context): Tree = pat match { case VarPattern(named, tpt) => - derivedValDef(named, tpt, rhs, mods) + derivedValDef(original, named, tpt, rhs, mods) case _ => val rhsUnchecked = makeAnnotated(defn.UncheckedAnnot, rhs) val vars = getVariables(pat) @@ -553,7 +553,7 @@ object desugar { case Nil => matchExpr case (named, tpt) :: Nil => - derivedValDef(named, tpt, matchExpr, mods) + derivedValDef(original, named, tpt, matchExpr, mods) case _ => val tmpName = ctx.freshName().toTermName val patMods = mods & (AccessFlags | Lazy) | Synthetic @@ -564,8 +564,8 @@ object desugar { val restDefs = for (((named, tpt), n) <- vars.zipWithIndex) yield - if (mods is Lazy) derivedDefDef(named, tpt, selector(n), mods &~ Lazy) - else derivedValDef(named, tpt, selector(n), mods) + if (mods is Lazy) derivedDefDef(original, named, tpt, selector(n), mods &~ Lazy) + else derivedValDef(original, named, tpt, selector(n), mods) flatTree(firstDef :: restDefs) } } @@ -663,14 +663,18 @@ object desugar { def makeAnnotated(cls: Symbol, tree: Tree)(implicit ctx: Context) = Annotated(untpd.New(untpd.TypeTree(cls.typeRef), Nil), tree) - private def derivedValDef(named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ctx: Context) = { - val vdef = ValDef(named.name.asTermName, tpt, rhs).withMods(mods).withPos(named.pos) + private def derivedValDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ctx: Context) = { + val vdef = ValDef(named.name.asTermName, tpt, rhs) + .withMods(mods) + .withPos(original.pos.withPoint(named.pos.start)) val mayNeedSetter = valDef(vdef) mayNeedSetter } - private def derivedDefDef(named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers) = - DefDef(named.name.asTermName, Nil, Nil, tpt, rhs).withMods(mods).withPos(named.pos) + private def derivedDefDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers) = + DefDef(named.name.asTermName, Nil, Nil, tpt, rhs) + .withMods(mods) + .withPos(original.pos.withPoint(named.pos.start)) /** Main desugaring method */ def apply(tree: Tree)(implicit ctx: Context): Tree = { @@ -760,7 +764,7 @@ object desugar { */ def makeLambda(pat: Tree, body: Tree): Tree = pat match { case VarPattern(named, tpt) => - Function(derivedValDef(named, tpt, EmptyTree, Modifiers(Param)) :: Nil, body) + Function(derivedValDef(pat, named, tpt, EmptyTree, Modifiers(Param)) :: Nil, body) case _ => makeCaseLambda(CaseDef(pat, EmptyTree, body) :: Nil, unchecked = false) } @@ -863,7 +867,7 @@ object desugar { val rhss = valeqs map { case GenAlias(_, rhs) => rhs } val (defpat0, id0) = makeIdPat(pat) val (defpats, ids) = (pats map makeIdPat).unzip - val pdefs = (defpats, rhss).zipped map (makePatDef(Modifiers(), _, _)) + val pdefs = (valeqs, defpats, rhss).zipped.map(makePatDef(_, Modifiers(), _, _)) val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom(defpat0, rhs) :: Nil, Block(pdefs, makeTuple(id0 :: ids))) val allpats = pat :: pats val vfrom1 = new IrrefutableGenFrom(makeTuple(allpats), rhs1) @@ -946,7 +950,7 @@ object desugar { makeFor(nme.map, nme.flatMap, enums, body) orElse tree case PatDef(mods, pats, tpt, rhs) => val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt)) - flatTree(pats1 map (makePatDef(mods, _, rhs))) + flatTree(pats1 map (makePatDef(tree, mods, _, rhs))) case ParsedTry(body, handler, finalizer) => handler match { case Match(EmptyTree, cases) => Try(body, cases, finalizer) diff --git a/src/dotty/tools/dotc/ast/NavigateAST.scala b/src/dotty/tools/dotc/ast/NavigateAST.scala index 2b11f81f3..33aa87d8e 100644 --- a/src/dotty/tools/dotc/ast/NavigateAST.scala +++ b/src/dotty/tools/dotc/ast/NavigateAST.scala @@ -19,10 +19,9 @@ object NavigateAST { case _ => val loosePath = untypedPath(tree, exactMatch = false) throw new - Error(i"""no untyped tree for $tree, pos = ${tree.pos}, envelope = ${tree.envelope} + Error(i"""no untyped tree for $tree, pos = ${tree.pos} |best matching path =\n$loosePath%\n====\n% - |path positions = ${loosePath.map(_.pos)} - |path envelopes = ${loosePath.map(_.envelope)}""") + |path positions = ${loosePath.map(_.pos)}""") } /** The reverse path of untyped trees starting with a tree that closest matches @@ -40,7 +39,7 @@ object NavigateAST { def untypedPath(tree: tpd.Tree, exactMatch: Boolean = false)(implicit ctx: Context): List[Positioned] = tree match { case tree: MemberDef[_] => - untypedPath(tree.envelope) match { + untypedPath(tree.pos) match { case path @ (last: DefTree[_]) :: _ => path case path if !exactMatch => path case _ => Nil @@ -76,7 +75,7 @@ object NavigateAST { path } def singlePath(p: Positioned, path: List[Positioned]): List[Positioned] = - if (p.envelope contains pos) childPath(p.productIterator, p :: path) + if (p.pos contains pos) childPath(p.productIterator, p :: path) else path singlePath(from, Nil) } diff --git a/src/dotty/tools/dotc/ast/Positioned.scala b/src/dotty/tools/dotc/ast/Positioned.scala index e7f5de591..ab9c06ca1 100644 --- a/src/dotty/tools/dotc/ast/Positioned.scala +++ b/src/dotty/tools/dotc/ast/Positioned.scala @@ -3,6 +3,10 @@ package ast import util.Positions._ import util.DotClass +import core.Contexts.Context +import core.Decorators._ +import core.Flags.JavaDefined +import core.StdNames.nme /** A base class for things that have positions (currently: modifiers and trees) */ @@ -16,7 +20,7 @@ abstract class Positioned extends DotClass with Product { */ def pos: Position = curPos - /** Destructively update `curPos` to given position. Also, set any missing + /** Destructively update `curPos` to given position. Also, set any missing * positions in children. */ protected def setPos(pos: Position): Unit = { @@ -24,11 +28,6 @@ abstract class Positioned extends DotClass with Product { if (pos.exists) setChildPositions(pos.toSynthetic) } - /** The envelope containing the item in its entirety. Envelope is different from - * `pos` for definitions (instances of MemberDef). - */ - def envelope: Position = pos.toSynthetic - /** A positioned item like this one with the position set to `pos`. * if the positioned item is source-derived, a clone is returned. * If the positioned item is synthetic, the position is updated @@ -106,8 +105,7 @@ abstract class Positioned extends DotClass with Product { } } - /** The initial, synthetic position. This is usually the union of all positioned children's - * envelopes. + /** The initial, synthetic position. This is usually the union of all positioned children's positions. */ protected def initialPos: Position = { var n = productArity @@ -115,7 +113,7 @@ abstract class Positioned extends DotClass with Product { while (n > 0) { n -= 1 productElement(n) match { - case p: Positioned => pos = pos union p.envelope + case p: Positioned => pos = pos union p.pos case xs: List[_] => pos = unionPos(pos, xs) case _ => } @@ -124,7 +122,7 @@ abstract class Positioned extends DotClass with Product { } private def unionPos(pos: Position, xs: List[_]): Position = xs match { - case (p: Positioned) :: xs1 => unionPos(pos union p.envelope, xs1) + case (p: Positioned) :: xs1 => unionPos(pos union p.pos, xs1) case _ => pos } @@ -138,7 +136,7 @@ abstract class Positioned extends DotClass with Product { false } (this eq that) || - (this.envelope contains that.pos) && { + (this.pos contains that.pos) && { var n = productArity var found = false while (n > 0 && !found) { @@ -148,4 +146,48 @@ abstract class Positioned extends DotClass with Product { found } } + + /** Check that all positioned items in this tree satisfy the following conditions: + * - Parent positions contain child positions + * - If item is a non-empty tree, it has a position + */ + def checkPos(complete: Boolean)(implicit ctx: Context): Unit = try { + import untpd._ + def check(p: Any): Unit = p match { + case p: Positioned => + assert(pos contains p.pos, + s"""position error, parent position does not contain child positon + |parent = $this, + |parent position = $pos, + |child = $p, + |child position = ${p.pos}""".stripMargin) + p match { + case tree: Tree if !tree.isEmpty => + assert(tree.pos.exists, + s"position error: position not set for $tree # ${tree.uniqueId}") + case _ => + } + p.checkPos(complete) + case xs: List[_] => + xs.foreach(check) + case _ => + } + this match { + case tree: DefDef if tree.name == nme.CONSTRUCTOR && tree.mods.is(JavaDefined) => + // Special treatment for constructors coming from Java: + // Leave out tparams, they are copied with wrong positions from parent class + check(tree.mods) + check(tree.vparamss) + case _ => + var n = productArity + while (n > 0) { + n -= 1 + check(productElement(n)) + } + } + } catch { + case ex: AssertionError => + println(i"error while checking $this") + throw ex + } } diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index 7c3f7f385..6c371abc1 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -480,7 +480,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => require(sym.pos.exists) object accum extends TreeAccumulator[List[Tree]] { def apply(x: List[Tree], tree: Tree)(implicit ctx: Context): List[Tree] = { - if (tree.envelope.contains(sym.pos)) + if (tree.pos.contains(sym.pos)) if (definedSym(tree) == sym) tree :: x else { val x1 = foldOver(x, tree) diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index cf11c27fa..4ba4eda0a 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -341,8 +341,6 @@ object Trees { } protected def setMods(mods: Modifiers[T @uncheckedVariance]) = myMods = mods - - override def envelope: Position = rawMods.pos.union(pos).union(initialPos) } /** A ValDef or DefDef tree */ @@ -619,7 +617,6 @@ object Trees { type ThisTree[-T >: Untyped] = Bind[T] override def isType = name.isTypeName override def isTerm = name.isTermName - override def envelope: Position = pos union initialPos } /** tree_1 | ... | tree_n */ @@ -740,6 +737,7 @@ object Trees { val newTrees = trees.map(_.withPos(pos)) new Thicket[T](newTrees).asInstanceOf[this.type] } + override def pos = (NoPosition /: trees) ((pos, t) => pos union t.pos) override def foreachInThicket(op: Tree[T] => Unit): Unit = trees foreach (_.foreachInThicket(op)) } diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala index 6bbb76b89..4e18b1d5c 100644 --- a/src/dotty/tools/dotc/ast/untpd.scala +++ b/src/dotty/tools/dotc/ast/untpd.scala @@ -258,7 +258,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { implicit class UntypedTreeDecorator(val self: Tree) extends AnyVal { def locateEnclosing(base: List[Tree], pos: Position): List[Tree] = { def encloses(elem: Any) = elem match { - case t: Tree => t.envelope contains pos + case t: Tree => t.pos contains pos case _ => false } base.productIterator find encloses match { diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala index 0949d7fee..c188bfab4 100644 --- a/src/dotty/tools/dotc/config/Config.scala +++ b/src/dotty/tools/dotc/config/Config.scala @@ -63,6 +63,9 @@ object Config { */ final val checkNoDoubleBindings = true + /** Check positions for consistency after parsing */ + final val checkPositions = true + /** Show subtype traces for all deep subtype recursions */ final val traceDeepSubTypeRecursions = false diff --git a/src/dotty/tools/dotc/parsing/JavaParsers.scala b/src/dotty/tools/dotc/parsing/JavaParsers.scala index fbb362354..c00cd7c59 100644 --- a/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -10,6 +10,7 @@ import scala.language.implicitConversions import JavaTokens._ import JavaScanners._ +import Scanners.Offset import Parsers._ import core._ import Contexts._ @@ -107,9 +108,6 @@ object JavaParsers { def unimplementedExpr = Ident("???".toTermName) - def makePackaging(pkg: RefTree, stats: List[Tree]): PackageDef = - atPos(pkg.pos) { PackageDef(pkg, stats) } - def makeTemplate(parents: List[Tree], stats: List[Tree], tparams: List[TypeDef], needsDummyConstr: Boolean) = { def pullOutFirstConstr(stats: List[Tree]): (Tree, List[Tree]) = stats match { case (meth: DefDef) :: rest if meth.name == CONSTRUCTOR => (meth, rest) @@ -250,14 +248,14 @@ object JavaParsers { var t: RefTree = atPos(in.offset) { Ident(ident()) } while (in.token == DOT) { in.nextToken() - t = atPos(in.offset) { Select(t, ident()) } + t = atPos(t.pos.start, in.offset) { Select(t, ident()) } } t } def optArrayBrackets(tpt: Tree): Tree = if (in.token == LBRACKET) { - val tpt1 = atPos(in.offset) { arrayOf(tpt) } + val tpt1 = atPos(tpt.pos.start, in.offset) { arrayOf(tpt) } in.nextToken() accept(RBRACKET) optArrayBrackets(tpt1) @@ -294,7 +292,7 @@ object JavaParsers { } while (in.token == DOT) { in.nextToken() - t = typeArgs(atPos(in.offset)(typeSelect(t, ident()))) + t = typeArgs(atPos(t.pos.start, in.offset)(typeSelect(t, ident()))) } convertToTypeId(t) } else { @@ -328,7 +326,7 @@ object JavaParsers { val t1 = convertToTypeId(t) val args = repsep(typeArg, COMMA) acceptClosingAngle() - atPos(t1.pos) { + atPos(t1.pos.start) { AppliedTypeTree(t1, args) } } else t @@ -356,7 +354,11 @@ object JavaParsers { // assumed true unless we see public/private/protected var isPackageAccess = true var annots: List[Tree] = Nil - def addAnnot(sym: ClassSymbol) = annots :+= New(TypeTree(sym.typeRef)).withPos(Position(in.offset)) + def addAnnot(sym: ClassSymbol) = + annots :+= atPos(in.offset) { + in.nextToken() + New(TypeTree(sym.typeRef)) + } while (true) { in.token match { @@ -387,13 +389,10 @@ object JavaParsers { in.nextToken() case NATIVE => addAnnot(NativeAnnot) - in.nextToken() case TRANSIENT => addAnnot(TransientAnnot) - in.nextToken() case VOLATILE => addAnnot(VolatileAnnot) - in.nextToken() case SYNCHRONIZED | STRICTFP => in.nextToken() case _ => @@ -443,16 +442,19 @@ object JavaParsers { } def formalParam(): ValDef = { + val start = in.offset if (in.token == FINAL) in.nextToken() annotations() var t = typ() if (in.token == DOTDOTDOT) { in.nextToken() - t = atPos(t.pos) { + t = atPos(t.pos.start) { PostfixOp(t, nme.raw.STAR) } } - varDecl(Position(in.offset), Modifiers(Flags.JavaDefined | Flags.Param), t, ident().toTermName) + atPos(start, in.offset) { + varDecl(Modifiers(Flags.JavaDefined | Flags.Param), t, ident().toTermName) + } } def optThrows(): Unit = { @@ -462,7 +464,7 @@ object JavaParsers { } } - def methodBody(): Tree = { + def methodBody(): Tree = atPos(in.offset) { skipAhead() accept(RBRACE) // skip block unimplementedExpr @@ -470,16 +472,18 @@ object JavaParsers { def definesInterface(token: Int) = token == INTERFACE || token == AT - def termDecl(mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = { + def termDecl(start: Offset, mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = { val inInterface = definesInterface(parentToken) val tparams = if (in.token == LT) typeParams(Flags.JavaDefined | Flags.Param) else List() val isVoid = in.token == VOID var rtpt = - if (isVoid) { - in.nextToken() - TypeTree(UnitType) withPos Position(in.offset) - } else typ() - var offset = in.offset + if (isVoid) + atPos(in.offset) { + in.nextToken() + TypeTree(UnitType) + } + else typ() + var nameOffset = in.offset val rtptName = rtpt match { case Ident(name) => name case _ => nme.EMPTY @@ -489,14 +493,15 @@ object JavaParsers { val vparams = formalParams() optThrows() List { - atPos(offset) { - DefDef(nme.CONSTRUCTOR, parentTParams, List(vparams), TypeTree(), methodBody()).withMods(mods) + atPos(start) { + DefDef(nme.CONSTRUCTOR, parentTParams, + List(vparams), TypeTree(), methodBody()).withMods(mods) } } } else { var mods1 = mods if (mods is Flags.Abstract) mods1 = mods &~ Flags.Abstract - offset = in.offset + nameOffset = in.offset val name = ident() if (in.token == LPAREN) { // method declaration @@ -510,13 +515,14 @@ object JavaParsers { } else { if (parentToken == AT && in.token == DEFAULT) { val annot = - atPos(offset) { + atPos(nameOffset) { New(Select(scalaDot(nme.runtime), tpnme.AnnotationDefaultATTR), Nil) } mods1 = mods1 withAddedAnnotation annot + val unimplemented = unimplementedExpr skipTo(SEMI) accept(SEMI) - unimplementedExpr + unimplemented } else { accept(SEMI) EmptyTree @@ -524,13 +530,13 @@ object JavaParsers { } //if (inInterface) mods1 |= Flags.Deferred List { - atPos(offset) { + atPos(start, nameOffset) { DefDef(name.toTermName, tparams, List(vparams), rtpt, body).withMods(mods1 | Flags.Method) } } } else { if (inInterface) mods1 |= Flags.Final | Flags.JavaStatic - val result = fieldDecls(Position(offset), mods1, rtpt, name) + val result = fieldDecls(start, nameOffset, mods1, rtpt, name) accept(SEMI) result } @@ -546,19 +552,21 @@ object JavaParsers { * Once we have reached the end of the statement, we know whether * these potential definitions are real or not. */ - def fieldDecls(pos: Position, mods: Modifiers, tpt: Tree, name: Name): List[Tree] = { - val buf = ListBuffer[Tree](varDecl(pos, mods, tpt, name.toTermName)) + def fieldDecls(start: Offset, firstNameOffset: Offset, mods: Modifiers, tpt: Tree, name: Name): List[Tree] = { + val buf = ListBuffer[Tree]( + atPos(start, firstNameOffset) { varDecl(mods, tpt, name.toTermName) }) val maybe = new ListBuffer[Tree] // potential variable definitions. while (in.token == COMMA) { in.nextToken() if (in.token == IDENTIFIER) { // if there's an ident after the comma ... + val nextNameOffset = in.offset val name = ident() if (in.token == EQUALS || in.token == SEMI) { // ... followed by a `=` or `;`, we know it's a real variable definition buf ++= maybe - buf += varDecl(Position(in.offset), mods, tpt, name.toTermName) + buf += atPos(start, nextNameOffset) { varDecl(mods, tpt, name.toTermName) } maybe.clear() } else if (in.token == COMMA) { // ... if there's a comma after the ident, it could be a real vardef or not. - maybe += varDecl(Position(in.offset), mods, tpt, name.toTermName) + maybe += atPos(start, nextNameOffset) { varDecl(mods, tpt, name.toTermName) } } else { // ... if there's something else we were still in the initializer of the // previous var def; skip to next comma or semicolon. skipTo(COMMA, SEMI) @@ -576,35 +584,32 @@ object JavaParsers { buf.toList } - def varDecl(pos: Position, mods: Modifiers, tpt: Tree, name: TermName): ValDef = { + def varDecl(mods: Modifiers, tpt: Tree, name: TermName): ValDef = { val tpt1 = optArrayBrackets(tpt) if (in.token == EQUALS && !(mods is Flags.Param)) skipTo(COMMA, SEMI) val mods1 = if (mods is Flags.Final) mods else mods | Flags.Mutable - atPos(pos) { - ValDef(name, tpt1, if (mods is Flags.Param) EmptyTree else unimplementedExpr).withMods(mods1) - } + ValDef(name, tpt1, if (mods is Flags.Param) EmptyTree else unimplementedExpr).withMods(mods1) } - def memberDecl(mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = in.token match { + def memberDecl(start: Offset, mods: Modifiers, parentToken: Int, parentTParams: List[TypeDef]): List[Tree] = in.token match { case CLASS | ENUM | INTERFACE | AT => - typeDecl(if (definesInterface(parentToken)) mods | Flags.JavaStatic else mods) + typeDecl(start, if (definesInterface(parentToken)) mods | Flags.JavaStatic else mods) case _ => - termDecl(mods, parentToken, parentTParams) + termDecl(start, mods, parentToken, parentTParams) } def makeCompanionObject(cdef: TypeDef, statics: List[Tree]): Tree = atPos(cdef.pos) { + assert(cdef.pos.exists) ModuleDef(cdef.name.toTermName, makeTemplate(List(), statics, List(), false)).withMods((cdef.mods & (Flags.AccessFlags | Flags.JavaDefined)).toTermFlags) } - private val wild = Ident(nme.WILDCARD) withPos Position(-1) - private val wildList = List(wild) // OPT This list is shared for performance. + private def wild = Ident(nme.WILDCARD) + private def wildList = List(wild) // OPT This list is shared for performance. def importCompanionObject(cdef: TypeDef): Tree = - atPos(cdef.pos) { - Import(Ident(cdef.name.toTermName), wildList) - } + Import(Ident(cdef.name.toTermName).withPos(NoPosition), wildList) // Importing the companion object members cannot be done uncritically: see // ticket #2377 wherein a class contains two static inner classes, each of which @@ -633,8 +638,8 @@ object JavaParsers { } def importDecl(): List[Tree] = { + val start = in.offset accept(IMPORT) - val offset = in.offset val buf = new ListBuffer[Name] def collectIdents() : Int = { if (in.token == ASTERISK) { @@ -657,7 +662,7 @@ object JavaParsers { accept(SEMI) val names = buf.toList if (names.length < 2) { - syntaxError(offset, "illegal import", skipIt = false) + syntaxError(start, "illegal import", skipIt = false) List() } else { val qual = ((Ident(names.head): Tree) /: names.tail.init) (Select(_, _)) @@ -667,7 +672,8 @@ object JavaParsers { // case nme.WILDCARD => Pair(ident, Ident(null) withPos Position(-1)) // case _ => Pair(ident, ident) // } - List(atPos(offset)(Import(qual, List(ident)))) + val imp = atPos(start) { Import(qual, List(ident)) } + imp :: Nil } } @@ -679,9 +685,9 @@ object JavaParsers { List() } - def classDecl(mods: Modifiers): List[Tree] = { + def classDecl(start: Offset, mods: Modifiers): List[Tree] = { accept(CLASS) - val offset = in.offset + val nameOffset = in.offset val name = identForType() val tparams = typeParams() val superclass = @@ -693,14 +699,15 @@ object JavaParsers { } val interfaces = interfacesOpt() val (statics, body) = typeBody(CLASS, name, tparams) - addCompanionObject(statics, atPos(offset) { + val cls = atPos(start, nameOffset) { TypeDef(name, makeTemplate(superclass :: interfaces, body, tparams, true)).withMods(mods) - }) + } + addCompanionObject(statics, cls) } - def interfaceDecl(mods: Modifiers): List[Tree] = { + def interfaceDecl(start: Offset, mods: Modifiers): List[Tree] = { accept(INTERFACE) - val offset = in.offset + val nameOffset = in.offset val name = identForType() val tparams = typeParams() val parents = @@ -711,11 +718,12 @@ object JavaParsers { List(javaLangObject()) } val (statics, body) = typeBody(INTERFACE, name, tparams) - addCompanionObject(statics, atPos(offset) { + val iface = atPos(start, nameOffset) { TypeDef( name, tparams, makeTemplate(parents, body, tparams, false)).withMods(mods | Flags.Trait | Flags.JavaInterface | Flags.Abstract) - }) + } + addCompanionObject(statics, iface) } def typeBody(leadingToken: Int, parentName: Name, parentTParams: List[TypeDef]): (List[Tree], List[Tree]) = { @@ -730,7 +738,8 @@ object JavaParsers { val statics = new ListBuffer[Tree] val members = new ListBuffer[Tree] while (in.token != RBRACE && in.token != EOF) { - var mods = modifiers(inInterface) + val start = in.offset + var mods = atPos(start) { modifiers(inInterface) } if (in.token == LBRACE) { skipAhead() // skip init block, we just assume we have seen only static accept(RBRACE) @@ -738,7 +747,7 @@ object JavaParsers { in.nextToken() } else { if (in.token == ENUM || definesInterface(in.token)) mods |= Flags.JavaStatic - val decls = memberDecl(mods, parentToken, parentTParams) + val decls = memberDecl(start, mods, parentToken, parentTParams) (if ((mods is Flags.JavaStatic) || inInterface && !(decls exists (_.isInstanceOf[DefDef]))) statics else @@ -761,10 +770,10 @@ object JavaParsers { Select(javaLangDot(nme.annotation), tpnme.Annotation), scalaAnnotationDot(tpnme.ClassfileAnnotation) ) - def annotationDecl(mods: Modifiers): List[Tree] = { + def annotationDecl(start: Offset, mods: Modifiers): List[Tree] = { accept(AT) accept(INTERFACE) - val offset = in.offset + val nameOffset = in.offset val name = identForType() val (statics, body) = typeBody(AT, name, List()) val constructorParams = body.collect { @@ -774,14 +783,15 @@ object JavaParsers { List(), List(constructorParams), TypeTree(), EmptyTree).withMods(Modifiers(Flags.JavaDefined)) val body1 = body.filterNot(_.isInstanceOf[DefDef]) val templ = makeTemplate(annotationParents, constr :: body1, List(), false) - addCompanionObject(statics, atPos(offset) { + val annot = atPos(start, nameOffset) { TypeDef(name, templ).withMods(mods | Flags.Abstract) - }) + } + addCompanionObject(statics, annot) } - def enumDecl(mods: Modifiers): List[Tree] = { + def enumDecl(start: Offset, mods: Modifiers): List[Tree] = { accept(ENUM) - val offset = in.offset + val nameOffset = in.offset val name = identForType() def enumType = Ident(name) val interfaces = interfacesOpt() @@ -824,10 +834,11 @@ object JavaParsers { val superclazz = Apply(TypeApply( Select(New(javaLangDot(tpnme.Enum)), nme.CONSTRUCTOR), List(enumType)), List(Literal(Constant(null)),Literal(Constant(0)))) - addCompanionObject(consts ::: statics ::: predefs, atPos(offset) { + val enum = atPos(start, nameOffset) { TypeDef(name, List(), makeTemplate(superclazz :: interfaces, body, List(), true)).withMods(mods | Flags.Enum) - }) + } + addCompanionObject(consts ::: statics ::: predefs, enum) } def enumConst(enumType: Tree) = { @@ -848,22 +859,21 @@ object JavaParsers { } } - def typeDecl(mods: Modifiers): List[Tree] = in.token match { - case ENUM => enumDecl(mods) - case INTERFACE => interfaceDecl(mods) - case AT => annotationDecl(mods) - case CLASS => classDecl(mods) + def typeDecl(start: Offset, mods: Modifiers): List[Tree] = in.token match { + case ENUM => enumDecl(start, mods) + case INTERFACE => interfaceDecl(start, mods) + case AT => annotationDecl(start, mods) + case CLASS => classDecl(start, mods) case _ => in.nextToken(); syntaxError("illegal start of type declaration", skipIt = true); List(errorTypeTree) } /** CompilationUnit ::= [package QualId semi] TopStatSeq */ def compilationUnit(): Tree = { - var offset = in.offset + val start = in.offset val pkg: RefTree = if (in.token == AT || in.token == PACKAGE) { annotations() - offset = in.offset accept(PACKAGE) val pkg = qualId() accept(SEMI) @@ -880,13 +890,15 @@ object JavaParsers { buf ++= importDecl() while (in.token != EOF && in.token != RBRACE) { while (in.token == SEMI) in.nextToken() - if (in.token != EOF) - buf ++= typeDecl(modifiers(inInterface = false)) + if (in.token != EOF) { + val start = in.offset + val mods = atPos(start) { modifiers(inInterface = false) } + buf ++= typeDecl(start, mods) + } } + val unit = atPos(start) { PackageDef(pkg, buf.toList) } accept(EOF) - atPos(offset) { - makePackaging(pkg, buf.toList) - } + unit } } } diff --git a/src/dotty/tools/dotc/parsing/JavaScanners.scala b/src/dotty/tools/dotc/parsing/JavaScanners.scala index faac8e163..83e16627c 100644 --- a/src/dotty/tools/dotc/parsing/JavaScanners.scala +++ b/src/dotty/tools/dotc/parsing/JavaScanners.scala @@ -27,6 +27,7 @@ object JavaScanners { def nextToken(): Unit = { if (next.token == EMPTY) { + lastOffset = lastCharOffset fetchToken() } else { diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 97213a685..153b58283 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -63,7 +63,7 @@ object Parsers { atPos(Position(start, end, point))(t) def atPos[T <: Positioned](start: Offset, point: Offset)(t: T): T = - atPos(start, point, in.lastOffset max start)(t) + if (in.lastOffset > start) atPos(start, point, in.lastOffset)(t) else t def atPos[T <: Positioned](start: Offset)(t: T): T = atPos(start, start)(t) @@ -71,7 +71,8 @@ object Parsers { def atPos[T <: Positioned](pos: Position)(t: T): T = if (t.pos.isSourceDerived) t else t.withPos(pos) - def tokenRange = Position(in.offset, in.lastCharOffset, in.offset) + def nameStart: Offset = + if (in.token == BACKQUOTED_IDENT) in.offset + 1 else in.offset def sourcePos(off: Int = in.offset): SourcePosition = source atPos Position(off) @@ -313,8 +314,6 @@ object Parsers { tree } - def emptyConstructor() = atPos(in.offset) { ast.untpd.emptyConstructor } - /* --------------- PLACEHOLDERS ------------------------------------------- */ /** The implicit parameters introduced by `_` in the current expression. @@ -694,9 +693,10 @@ object Parsers { } } else if (in.token == LBRACKET) { + val start = in.offset val tparams = typeParamClause(ParamOwner.TypeParam) if (isIdent && in.name.toString == "->") - atPos(in.skipToken())(TypeLambdaTree(tparams, typ())) + atPos(start, in.skipToken())(TypeLambdaTree(tparams, typ())) else { syntaxErrorOrIncomplete(expectedMessage("`->'")); typ() } } else infixType() @@ -762,7 +762,7 @@ object Parsers { else if (isSimpleLiteral) { SingletonTypeTree(literal()) } else if (in.token == USCORE) { val start = in.skipToken() - typeBounds().withPos(Position(start, in.offset, start)) + typeBounds().withPos(Position(start, in.lastOffset, start)) } else path(thisOK = false, handleSingletonType) match { case r @ SingletonTypeTree(_) => r @@ -866,7 +866,8 @@ object Parsers { def typeParamBounds(pname: TypeName): Tree = { val t = typeBounds() val cbs = contextBounds(pname) - if (cbs.isEmpty) t else atPos(t.pos.start) { ContextBounds(t, cbs) } + if (cbs.isEmpty) t + else atPos((t.pos union cbs.head.pos).start) { ContextBounds(t, cbs) } } def contextBounds(pname: TypeName): List[Tree] = in.token match { @@ -1075,7 +1076,8 @@ object Parsers { val tpt = typeDependingOn(location) if (isWildcard(t) && location != Location.InPattern) { val vd :: rest = placeholderParams - placeholderParams = cpy.ValDef(vd)(tpt = tpt) :: rest + placeholderParams = + cpy.ValDef(vd)(tpt = tpt).withPos(vd.pos union tpt.pos) :: rest } Typed(t, tpt) } @@ -1154,12 +1156,12 @@ object Parsers { case NEW => canApply = false val start = in.skipToken() - val (impl, missingBody) = template(emptyConstructor()) + val (impl, missingBody) = template(emptyConstructor) impl.parents match { case parent :: Nil if missingBody => if (parent.isType) ensureApplied(wrapNew(parent)) else parent case _ => - New(impl) + New(impl.withPos(Position(start, in.lastOffset))) } case _ => if (isLiteral) literal() @@ -1362,15 +1364,15 @@ object Parsers { */ val pattern2 = () => infixPattern() match { case p @ Ident(name) if isVarPattern(p) && in.token == AT => - val pos = in.skipToken() + val offset = in.skipToken() // compatibility for Scala2 `x @ _*` syntax infixPattern() match { case pt @ Ident(tpnme.WILDCARD_STAR) => migrationWarningOrError("The syntax `x @ _*' is no longer supported; use `x : _*' instead", p.pos.start) - atPos(p.pos.start, pos) { Typed(p, pt) } + atPos(p.pos.start, offset) { Typed(p, pt) } case p => - atPos(p.pos.start, pos) { Bind(name, p) } + atPos(p.pos.start, offset) { Bind(name, p) } } case p @ Ident(tpnme.WILDCARD_STAR) => // compatibility for Scala2 `_*` syntax @@ -1590,12 +1592,12 @@ object Parsers { def typeParamClause(ownerKind: ParamOwner.Value): List[TypeDef] = inBrackets { def typeParam(): TypeDef = { val isConcreteOwner = ownerKind == ParamOwner.Class || ownerKind == ParamOwner.Def - val modStart = in.offset + val start = in.offset var mods = annotsAsMods() if (ownerKind == ParamOwner.Class) { mods = modifiers(start = mods) mods = - atPos(modStart, in.offset) { + atPos(start, in.offset) { if (in.token == TYPE) { in.nextToken() mods | Param | ParamAccessor @@ -1605,13 +1607,13 @@ object Parsers { } } } - else mods = atPos(modStart) (mods | Param) + else mods = atPos(start) (mods | Param) if (ownerKind != ParamOwner.Def) { if (isIdent(nme.raw.PLUS)) mods |= Covariant else if (isIdent(nme.raw.MINUS)) mods |= Contravariant if (mods is VarianceFlags) in.nextToken() } - atPos(tokenRange) { + atPos(start, nameStart) { val name = if (isConcreteOwner || in.token != USCORE) ident().toTypeName else { @@ -1645,12 +1647,12 @@ object Parsers { var firstClauseOfCaseClass = ofCaseClass var implicitOffset = -1 // use once def param(): ValDef = { - val modStart = in.offset + val start = in.offset var mods = annotsAsMods() if (owner.isTypeName) { mods = modifiers(start = mods) | ParamAccessor mods = - atPos(modStart, in.offset) { + atPos(start, in.offset) { if (in.token == VAL) { in.nextToken() mods @@ -1663,8 +1665,8 @@ object Parsers { } } } - else mods = atPos(modStart) { mods | Param } - atPos(tokenRange) { + else mods = atPos(start) { mods | Param } + atPos(start, nameStart) { val name = ident() val tpt = if (ctx.settings.YmethodInfer.value && owner.isTermName && in.token != COLON) { @@ -1683,7 +1685,7 @@ object Parsers { if (in.token == EQUALS) { in.nextToken(); expr() } else EmptyTree if (implicitOffset >= 0) { - mods = mods.withPos(mods.pos.withStart(implicitOffset)) + mods = mods.withPos(mods.pos.union(Position(implicitOffset, implicitOffset))) implicitOffset = -1 } ValDef(name, tpt, default).withMods(addFlag(mods, implicitFlag)) @@ -1779,7 +1781,11 @@ object Parsers { else from } - def posMods(start: Int, mods: Modifiers) = atPos(start, in.skipToken())(mods) + def posMods(start: Int, mods: Modifiers) = { + val mods1 = atPos(start)(mods) + in.nextToken() + mods1 + } /** Def ::= val PatDef * | var VarDef @@ -1793,13 +1799,13 @@ object Parsers { */ def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match { case VAL => - patDefOrDcl(posMods(start, mods), in.getDocComment(start)) + patDefOrDcl(start, posMods(start, mods), in.getDocComment(start)) case VAR => - patDefOrDcl(posMods(start, addFlag(mods, Mutable)), in.getDocComment(start)) + patDefOrDcl(start, posMods(start, addFlag(mods, Mutable)), in.getDocComment(start)) case DEF => - defDefOrDcl(posMods(start, mods), in.getDocComment(start)) + defDefOrDcl(start, posMods(start, mods), in.getDocComment(start)) case TYPE => - typeDefOrDcl(posMods(start, mods), in.getDocComment(start)) + typeDefOrDcl(start, posMods(start, mods), in.getDocComment(start)) case _ => tmplDef(start, mods) } @@ -1809,7 +1815,7 @@ object Parsers { * ValDcl ::= Id {`,' Id} `:' Type * VarDcl ::= Id {`,' Id} `:' Type */ - def patDefOrDcl(mods: Modifiers, docstring: Option[Comment] = None): Tree = { + def patDefOrDcl(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): Tree = atPos(start, nameStart) { val lhs = commaSeparated(pattern2) val tpt = typedOpt() val rhs = @@ -1824,7 +1830,7 @@ object Parsers { } else EmptyTree lhs match { case (id @ Ident(name: TermName)) :: Nil => { - cpy.ValDef(id)(name, tpt, rhs).withMods(mods).setComment(docstring) + ValDef(name, tpt, rhs).withMods(mods).setComment(docstring) } case _ => PatDef(mods, lhs, tpt, rhs) } @@ -1835,7 +1841,7 @@ object Parsers { * DefDcl ::= DefSig `:' Type * DefSig ::= id [DefTypeParamClause] ParamClauses */ - def defDefOrDcl(mods: Modifiers, docstring: Option[Comment] = None): Tree = atPos(tokenRange) { + def defDefOrDcl(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): Tree = atPos(start, nameStart) { def scala2ProcedureSyntax(resultTypeStr: String) = { val toInsert = if (in.token == LBRACE) s"$resultTypeStr =" @@ -1910,9 +1916,9 @@ object Parsers { /** TypeDef ::= type Id [TypeParamClause] `=' Type * TypeDcl ::= type Id [TypeParamClause] TypeBounds */ - def typeDefOrDcl(mods: Modifiers, docstring: Option[Comment] = None): Tree = { + def typeDefOrDcl(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): Tree = { newLinesOpt() - atPos(tokenRange) { + atPos(start, nameStart) { val name = ident().toTypeName val tparams = typeParamClauseOpt(ParamOwner.Type) in.token match { @@ -1935,15 +1941,15 @@ object Parsers { val docstring = in.getDocComment(start) in.token match { case TRAIT => - classDef(posMods(start, addFlag(mods, Trait)), docstring) + classDef(start, posMods(start, addFlag(mods, Trait)), docstring) case CLASS => - classDef(posMods(start, mods), docstring) + classDef(start, posMods(start, mods), docstring) case CASECLASS => - classDef(posMods(start, mods | Case), docstring) + classDef(start, posMods(start, mods | Case), docstring) case OBJECT => - objectDef(posMods(start, mods | Module), docstring) + objectDef(start, posMods(start, mods | Module), docstring) case CASEOBJECT => - objectDef(posMods(start, mods | Case | Module), docstring) + objectDef(start, posMods(start, mods | Case | Module), docstring) case _ => syntaxErrorOrIncomplete("expected start of definition") EmptyTree @@ -1953,9 +1959,9 @@ object Parsers { /** ClassDef ::= Id [ClsTypeParamClause] * [ConstrMods] ClsParamClauses TemplateOpt */ - def classDef(mods: Modifiers, docstring: Option[Comment]): TypeDef = atPos(tokenRange) { + def classDef(start: Offset, mods: Modifiers, docstring: Option[Comment]): TypeDef = atPos(start, nameStart) { val name = ident().toTypeName - val constr = atPos(in.offset) { + val constr = atPos(in.lastOffset) { val tparams = typeParamClauseOpt(ParamOwner.Class) val cmods = constrModsOpt() val vparamss = paramClauses(name, mods is Case) @@ -1980,9 +1986,9 @@ object Parsers { /** ObjectDef ::= Id TemplateOpt */ - def objectDef(mods: Modifiers, docstring: Option[Comment] = None): ModuleDef = { + def objectDef(start: Offset, mods: Modifiers, docstring: Option[Comment] = None): ModuleDef = atPos(start, nameStart) { val name = ident() - val template = templateOpt(emptyConstructor()) + val template = templateOpt(emptyConstructor) ModuleDef(name, template).withMods(mods).setComment(docstring) } @@ -2021,12 +2027,12 @@ object Parsers { else { newLineOptWhenFollowedBy(LBRACE) if (in.token == LBRACE) template(constr)._1 - else Template(constr, Nil, EmptyValDef, Nil).withPos(constr.pos.toSynthetic) + else Template(constr, Nil, EmptyValDef, Nil) } /** TemplateBody ::= [nl] `{' TemplateStatSeq `}' */ - def templateBodyOpt(constr: DefDef, parents: List[Tree]) = atPos(constr.pos.start) { + def templateBodyOpt(constr: DefDef, parents: List[Tree]) = { val (self, stats) = if (in.token == LBRACE) templateBody() else (EmptyValDef, Nil) Template(constr, parents, self, stats) @@ -2037,7 +2043,7 @@ object Parsers { if (in.token == WITH) { syntaxError("early definitions are not supported; use trait parameters instead") in.nextToken() - template(emptyConstructor()) + template(emptyConstructor) } r } @@ -2072,7 +2078,7 @@ object Parsers { if (in.token == PACKAGE) { val start = in.skipToken() if (in.token == OBJECT) - stats += objectDef(atPos(start, in.skipToken()) { Modifiers(Package) }) + stats += objectDef(start, atPos(start, in.skipToken()) { Modifiers(Package) }) else stats += packaging(start) } else if (in.token == IMPORT) @@ -2206,7 +2212,7 @@ object Parsers { in.nextToken() if (in.token == OBJECT) { val docstring = in.getDocComment(start) - ts += objectDef(atPos(start, in.skipToken()) { Modifiers(Package) }, docstring) + ts += objectDef(start, atPos(start, in.skipToken()) { Modifiers(Package) }, docstring) if (in.token != EOF) { acceptStatSep() ts ++= topStatSeq() diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 7e2a2893e..701c81a9d 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -253,6 +253,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (vparamss.isEmpty || primaryConstrs.nonEmpty) tparamsTxt else { var modsText = modText(constr.mods, "") + if (!modsText.isEmpty) modsText = " " ~ modsText if (constr.mods.hasAnnotations && !constr.mods.hasFlags) modsText = modsText ~~ " this" withEnclosingDef(constr) { addVparamssText(tparamsTxt ~~ modsText, vparamss) } } diff --git a/src/dotty/tools/dotc/typer/FrontEnd.scala b/src/dotty/tools/dotc/typer/FrontEnd.scala index 6ca69ea45..e008430a7 100644 --- a/src/dotty/tools/dotc/typer/FrontEnd.scala +++ b/src/dotty/tools/dotc/typer/FrontEnd.scala @@ -7,6 +7,7 @@ import Contexts._ import Symbols._ import dotty.tools.dotc.parsing.JavaParsers.JavaParser import parsing.Parsers.Parser +import config.Config import config.Printers.{typr, default} import util.Stats._ import scala.util.control.NonFatal @@ -34,6 +35,7 @@ class FrontEnd extends Phase { else new Parser(unit.source).parse() val printer = if (ctx.settings.Xprint.value.contains("parser")) default else typr printer.println("parsed:\n" + unit.untpdTree.show) + if (Config.checkPositions) unit.untpdTree.checkPos(complete = true) } def enterSyms(implicit ctx: Context) = monitor("indexing") { diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 7a2348cd3..a0862ee38 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -273,6 +273,18 @@ class Namer { typer: Typer => } val inSuperCall = if (ctx.mode is Mode.InSuperCall) InSuperCall else EmptyFlags + + /** The position of the name defined by `tree` + * This is a point position if tree is synthetic, a range position if it comes from source. + * It might also be that tree does not have a position (for instance when synthesized by + * a calling chain from `viewExists`), in that case the return position is NoPosition. + */ + def namePos(tree: MemberDef) = + if (tree.pos.exists) + if (tree.mods.is(Synthetic)) Position(tree.pos.point, tree.pos.point) + else Position(tree.pos.point, tree.pos.point + tree.name.length, tree.pos.point) + else tree.pos + tree match { case tree: TypeDef if tree.isClassDef => val name = checkNoConflict(tree.name.encode).asTypeName @@ -280,7 +292,7 @@ class Namer { typer: Typer => val cls = recordSym(ctx.newClassSymbol( ctx.owner, name, flags | inSuperCall, cls => adjustIfModule(new ClassCompleter(cls, tree)(ctx), tree), - privateWithinClass(tree.mods), tree.pos, ctx.source.file), tree) + privateWithinClass(tree.mods), namePos(tree), ctx.source.file), tree) cls.completer.asInstanceOf[ClassCompleter].init() cls case tree: MemberDef => @@ -315,7 +327,7 @@ class Namer { typer: Typer => recordSym(ctx.newSymbol( ctx.owner, name, flags | deferred | method | higherKinded | inSuperCall1, adjustIfModule(completer, tree), - privateWithinClass(tree.mods), tree.pos), tree) + privateWithinClass(tree.mods), namePos(tree)), tree) case tree: Import => recordSym(ctx.newSymbol( ctx.owner, nme.IMPORT, Synthetic, new Completer(tree), NoSymbol, tree.pos), tree) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 82eda0d0a..dcba7e7c4 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1149,7 +1149,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit if (sym.is(Lazy, butNot = Deferred | Module | Synthetic) && !sym.isVolatile && ctx.scala2Mode && ctx.settings.rewrite.value.isDefined && !ctx.isAfterTyper) - patch(Position(toUntyped(vdef).envelope.start), "@volatile ") + patch(Position(toUntyped(vdef).pos.start), "@volatile ") } def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = track("typedDefDef") { diff --git a/src/dotty/tools/dotc/typer/VarianceChecker.scala b/src/dotty/tools/dotc/typer/VarianceChecker.scala index 274218ee3..d5dd5a024 100644 --- a/src/dotty/tools/dotc/typer/VarianceChecker.scala +++ b/src/dotty/tools/dotc/typer/VarianceChecker.scala @@ -132,11 +132,11 @@ class VarianceChecker()(implicit ctx: Context) { case defn: MemberDef if skip => ctx.debuglog(s"Skipping variance check of ${sym.showDcl}") case tree: TypeDef => - checkVariance(sym, tree.envelope) + checkVariance(sym, tree.pos) case tree: ValDef => - checkVariance(sym, tree.envelope) + checkVariance(sym, tree.pos) case DefDef(_, tparams, vparamss, _, _) => - checkVariance(sym, tree.envelope) + checkVariance(sym, tree.pos) tparams foreach traverse vparamss foreach (_ foreach traverse) case Template(_, _, _, body) => |