aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala32
-rw-r--r--src/dotty/tools/dotc/ast/NavigateAST.scala9
-rw-r--r--src/dotty/tools/dotc/ast/Positioned.scala64
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala2
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala4
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala2
-rw-r--r--src/dotty/tools/dotc/config/Config.scala3
-rw-r--r--src/dotty/tools/dotc/parsing/JavaParsers.scala164
-rw-r--r--src/dotty/tools/dotc/parsing/JavaScanners.scala1
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala98
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala1
-rw-r--r--src/dotty/tools/dotc/typer/FrontEnd.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala16
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala2
-rw-r--r--src/dotty/tools/dotc/typer/VarianceChecker.scala6
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) =>