aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-09-24 13:50:27 +0200
committerMartin Odersky <odersky@gmail.com>2016-09-24 15:40:49 +0200
commitfb710457959d1c2d4b983986141875a8fde5992b (patch)
tree18883c09f001538303175148ecc3e50fee99d7c3 /src/dotty/tools/dotc
parent003ea0fba7d37156d890e0dae90f2ce765b08e04 (diff)
downloaddotty-fb710457959d1c2d4b983986141875a8fde5992b.tar.gz
dotty-fb710457959d1c2d4b983986141875a8fde5992b.tar.bz2
dotty-fb710457959d1c2d4b983986141875a8fde5992b.zip
Make positions fit for meta
In particular: - get rid of envelope, it's too complicated and hides too many errors - check that everywhere in parsed trees the position range of a parent node contains the position ranges of its children. - check that all non-empty trees coming from parser have positions. The commit contains lots of fixes to make these checks pass. In particular, it changes the scheme how definitions are positioned. Previously the position of a definition was the token range of the name defined by it. That does obviously not work with the parent/children invariant. Now, the position is the whole definition range, with the point at the defined name (care is taken to not count backticks). Namer is changed to still use the token range of defined name as the position of the symbol.
Diffstat (limited to 'src/dotty/tools/dotc')
-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) =>