From 26329529e12b8cd9c66427f13445ce3ca1ab4015 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Tue, 18 Oct 2016 16:33:50 +0200 Subject: [PATCH 1/5] Record syntactic information about modifiers --- src/dotty/tools/dotc/ast/untpd.scala | 50 ++++++++++++++++++++-- src/dotty/tools/dotc/parsing/Parsers.scala | 34 ++++++++++----- 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala index 852c3a3469d2..3ffc47bf8b46 100644 --- a/src/dotty/tools/dotc/ast/untpd.scala +++ b/src/dotty/tools/dotc/ast/untpd.scala @@ -94,9 +94,42 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { class InfixOpBlock(leftOperand: Tree, rightOp: Tree) extends Block(leftOperand :: Nil, rightOp) // ----- Modifiers ----------------------------------------------------- + /** Mod is intended to record syntactic information about modifiers, it's + * NOT a replacement of flagsets. + * + * For any query about semantic information, check `flags` instead. + */ + sealed trait Mod extends Positioned - /** Modifiers and annotations for definitions - * @param flags The set flags + object Mod { + case class Private() extends Mod + + case class Protected() extends Mod + + case class Val() extends Mod + + case class Var() extends Mod + + case class Implicit() extends Mod + + case class Final() extends Mod + + case class Sealed() extends Mod + + case class Override() extends Mod + + case class Abstract() extends Mod + + case class Lazy() extends Mod + + case class Inline() extends Mod + + case class Type() extends Mod + } + + /** Modifiers and annotations for definitions + * + * @param flags The set flags * @param privateWithin If a private or protected has is followed by a * qualifier [q], the name q, "" as a typename otherwise. * @param annotations The annotations preceding the modifiers @@ -104,7 +137,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class Modifiers ( flags: FlagSet = EmptyFlags, privateWithin: TypeName = tpnme.EMPTY, - annotations: List[Tree] = Nil) extends Positioned with Cloneable { + annotations: List[Tree] = Nil, + mods: List[Mod] = Nil) extends Positioned with Cloneable { def is(fs: FlagSet): Boolean = flags is fs def is(fc: FlagConjunction): Boolean = flags is fc @@ -120,7 +154,15 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { if (this.flags == flags) this else copy(flags = flags) - def withAddedAnnotation(annot: Tree): Modifiers = + def withAddedMod(mod: Mod): Modifiers = + if (mods.exists(_ eq mod)) this + else withMods(mods :+ mod) + + def withMods(ms: List[Mod]): Modifiers = + if (mods eq ms) this + else copy(mods = ms) + + def withAddedAnnotation(annot: Tree): Modifiers = if (annotations.exists(_ eq annot)) this else withAnnotations(annotations :+ annot) diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 80c8f7b1569f..574a4d4fc753 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1476,7 +1476,19 @@ object Parsers { case SEALED => Sealed } - /** Drop `private' modifier when followed by a qualifier. + private def modOfToken(tok: Int): Mod = tok match { + case ABSTRACT => Mod.Abstract() + case FINAL => Mod.Final() + case IMPLICIT => Mod.Implicit() + case INLINE => Mod.Inline() + case LAZY => Mod.Lazy() + case OVERRIDE => Mod.Override() + case PRIVATE => Mod.Private() + case PROTECTED => Mod.Protected() + case SEALED => Mod.Sealed() + } + + /** Drop `private' modifier when followed by a qualifier. * Contract `abstract' and `override' to ABSOVERRIDE */ private def normalize(mods: Modifiers): Modifiers = @@ -1488,10 +1500,12 @@ object Parsers { mods private def addModifier(mods: Modifiers): Modifiers = { - val flag = flagOfToken(in.token) + val tok = in.token + val flag = flagOfToken(tok) + val mod = atPos(in.offset) { in.nextToken(); modOfToken(tok) } + if (mods is flag) syntaxError(RepeatedModifier(flag.toString)) - val res = addFlag(mods, flag) - in.nextToken() + val res = addFlag(mods, flag).withAddedMod(mod) res } @@ -1614,8 +1628,8 @@ object Parsers { mods = atPos(start, in.offset) { if (in.token == TYPE) { - in.nextToken() - mods | Param | ParamAccessor + val mod = atPos(in.offset) { in.nextToken(); Mod.Type() } + (mods | Param | ParamAccessor).withAddedMod(mod) } else { if (mods.hasFlags) syntaxError("`type' expected") mods | Param | PrivateLocal @@ -1670,11 +1684,11 @@ object Parsers { mods = atPos(start, in.offset) { if (in.token == VAL) { - in.nextToken() - mods + val mod = atPos(in.offset) { in.nextToken(); Mod.Val() } + mods.withAddedMod(mod) } else if (in.token == VAR) { - in.nextToken() - addFlag(mods, Mutable) + val mod = atPos(in.offset) { in.nextToken(); Mod.Var() } + addFlag(mods, Mutable).withAddedMod(mod) } else { if (!(mods.flags &~ (ParamAccessor | Inline)).isEmpty) syntaxError("`val' or `var' expected") From a3527a909df913579141285964c77e4ef4d17dd0 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Wed, 19 Oct 2016 21:40:49 +0200 Subject: [PATCH 2/5] add tests for modifiers --- src/dotty/tools/dotc/parsing/Parsers.scala | 32 +++-- test/test/ModifiersParsingTest.scala | 160 +++++++++++++++++++++ 2 files changed, 182 insertions(+), 10 deletions(-) create mode 100644 test/test/ModifiersParsingTest.scala diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 574a4d4fc753..7b1f2754a457 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1097,8 +1097,9 @@ object Parsers { /** Expr ::= implicit Id `=>' Expr * BlockResult ::= implicit Id [`:' InfixType] `=>' Block */ - def implicitClosure(start: Int, location: Location.Value): Tree = { - val mods = atPos(start) { Modifiers(Implicit) } + def implicitClosure(start: Int, location: Location.Value, implicitMod: Option[Mod] = None): Tree = { + var mods = atPos(start) { Modifiers(Implicit) } + if (implicitMod.nonEmpty) mods = mods.withAddedMod(implicitMod.get) val id = termIdent() val paramExpr = if (location == Location.InBlock && in.token == COLON) @@ -1674,6 +1675,7 @@ object Parsers { */ def paramClauses(owner: Name, ofCaseClass: Boolean = false): List[List[ValDef]] = { var implicitFlag = EmptyFlags + var implicitMod: Mod = null var firstClauseOfCaseClass = ofCaseClass var implicitOffset = -1 // use once def param(): ValDef = { @@ -1722,6 +1724,7 @@ object Parsers { mods = mods.withPos(mods.pos.union(Position(implicitOffset, implicitOffset))) implicitOffset = -1 } + if (implicitMod != null) mods = mods.withAddedMod(implicitMod) ValDef(name, tpt, default).withMods(addFlag(mods, implicitFlag)) } } @@ -1729,7 +1732,8 @@ object Parsers { if (in.token == RPAREN) Nil else { if (in.token == IMPLICIT) { - implicitOffset = in.skipToken() + implicitOffset = in.offset + implicitMod = atPos(in.offset) { in.nextToken(); Mod.Implicit() } implicitFlag = Implicit } commaSeparated(param) @@ -1833,9 +1837,13 @@ object Parsers { */ def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match { case VAL => - patDefOrDcl(start, posMods(start, mods), in.getDocComment(start)) + val mod = atPos(in.offset) { in.nextToken(); Mod.Val() } + val modPos = atPos(start) { mods.withAddedMod(mod) } + patDefOrDcl(start, modPos, in.getDocComment(start)) case VAR => - patDefOrDcl(start, posMods(start, addFlag(mods, Mutable)), in.getDocComment(start)) + val mod = atPos(in.offset) { in.nextToken(); Mod.Var() } + val modPos = atPos(start) { addFlag(mods, Mutable).withAddedMod(mod) } + patDefOrDcl(start, modPos, in.getDocComment(start)) case DEF => defDefOrDcl(start, posMods(start, mods), in.getDocComment(start)) case TYPE => @@ -2198,8 +2206,11 @@ object Parsers { stats.toList } - def localDef(start: Int, implicitFlag: FlagSet): Tree = - defOrDcl(start, addFlag(defAnnotsMods(localModifierTokens), implicitFlag)) + def localDef(start: Int, implicitFlag: FlagSet, implicitMod: Option[Mod] = None): Tree = { + var mods = addFlag(defAnnotsMods(localModifierTokens), implicitFlag) + if (implicitMod.nonEmpty) mods = mods.withAddedMod(implicitMod.get) + defOrDcl(start, mods) + } /** BlockStatSeq ::= { BlockStat semi } [ResultExpr] * BlockStat ::= Import @@ -2219,9 +2230,10 @@ object Parsers { stats += expr(Location.InBlock) else if (isDefIntro(localModifierTokens)) if (in.token == IMPLICIT) { - val start = in.skipToken() - if (isIdent) stats += implicitClosure(start, Location.InBlock) - else stats += localDef(start, ImplicitCommon) + val start = in.offset + val mod = atPos(in.offset) { in.nextToken(); Mod.Implicit() } + if (isIdent) stats += implicitClosure(start, Location.InBlock, Some(mod)) + else stats += localDef(start, ImplicitCommon, Some(mod)) } else { stats += localDef(in.offset, EmptyFlags) } diff --git a/test/test/ModifiersParsingTest.scala b/test/test/ModifiersParsingTest.scala new file mode 100644 index 000000000000..bdcaf76e18dc --- /dev/null +++ b/test/test/ModifiersParsingTest.scala @@ -0,0 +1,160 @@ +package test + +import org.junit.Test +import org.junit.Assert._ + +import dotty.tools.dotc.ast.untpd.modsDeco +import dotty.tools.dotc.ast.untpd._ +import dotty.tools.dotc.ast.{ Trees => d } +import dotty.tools.dotc.parsing.Parsers.Parser +import dotty.tools.dotc.util.SourceFile +import dotty.tools.dotc.core.Contexts.ContextBase + +object ModifiersParsingTest { + implicit val ctx = (new ContextBase).initialCtx + + implicit def parse(code: String): Tree = { + val (_, stats) = new Parser(new SourceFile("", code.toCharArray)).templateStatSeq() + stats match { case List(stat) => stat; case stats => Thicket(stats) } + } + + implicit class TreeDeco(val code: Tree) extends AnyVal { + def firstConstrValDef: ValDef = code match { + case d.TypeDef(_, d.Template(constr, _, _, _)) => + constr.vparamss.head.head + } + + def firstTypeParam: TypeDef = code match { + case d.TypeDef(_, d.Template(constr, _, _, _)) => + constr.tparams.head + } + + def defParam(i: Int): ValDef = code match { + case d.DefDef(_, _, vparamss, _, _) => + vparamss.head.toArray.apply(i) + } + + def defParam(i: Int, j: Int): ValDef = code match { + case d.DefDef(_, _, vparamss, _, _) => + vparamss.toArray.apply(i).toArray.apply(j) + } + + def funParam(i: Int): Tree = code match { + case Function(params, _) => + params.toArray.apply(i) + } + + def field(i: Int): Tree = code match { + case d.TypeDef(_, t: Template) => + t.body.toArray.apply(i) + } + + def field(name: String): Tree = code match { + case d.TypeDef(_, t: Template) => + t.body.find({ + case m: MemberDef => m.name.show == name + case _ => false + }).get + } + + def stat(i: Int): Tree = code match { + case d.Block(stats, expr) => + if (i < stats.length) stats.toArray.apply(i) + else expr + } + + def modifiers: List[Mod] = code match { + case t: MemberDef => t.mods.mods + } + } +} + + +class ModifiersParsingTest { + import ModifiersParsingTest._ + + + @Test def valDef = { + var source: Tree = "class A(var a: Int)" + assert(source.firstConstrValDef.modifiers == List(Mod.Var())) + + source = "class A(val a: Int)" + assert(source.firstConstrValDef.modifiers == List(Mod.Val())) + + source = "class A(private val a: Int)" + assert(source.firstConstrValDef.modifiers == List(Mod.Private(), Mod.Val())) + + source = "class A(protected var a: Int)" + assert(source.firstConstrValDef.modifiers == List(Mod.Protected(), Mod.Var())) + + source = "class A(protected implicit val a: Int)" + assert(source.firstConstrValDef.modifiers == List(Mod.Protected(), Mod.Implicit(), Mod.Val())) + + source = "class A[T]" + assert(source.firstTypeParam.modifiers == List()) + + source = "class A[type T]" + assert(source.firstTypeParam.modifiers == List(Mod.Type())) + } + + @Test def typeDef = { + var source: Tree = "class A" + assert(source.modifiers == List()) + + source = "sealed class A" + assert(source.modifiers == List(Mod.Sealed())) + + source = "implicit class A" + assert(source.modifiers == List(Mod.Implicit())) + + source = "abstract sealed class A" + assert(source.modifiers == List(Mod.Abstract(), Mod.Sealed())) + } + + @Test def fieldDef = { + val source: Tree = + """ + | class A { + | lazy var a = ??? + | lazy private val b = ??? + | final val c = ??? + | + | abstract override def f: Boolean + | inline def g(n: Int) = ??? + | } + """.stripMargin + + assert(source.field("a").modifiers == List(Mod.Lazy(), Mod.Var())) + assert(source.field("b").modifiers == List(Mod.Lazy(), Mod.Private(), Mod.Val())) + assert(source.field("c").modifiers == List(Mod.Final(), Mod.Val())) + assert(source.field("f").modifiers == List(Mod.Abstract(), Mod.Override())) + assert(source.field("g").modifiers == List(Mod.Inline())) + } + + @Test def paramDef = { + var source: Tree = "def f(inline a: Int) = ???" + assert(source.defParam(0).modifiers == List(Mod.Inline())) + + source = "def f(implicit a: Int, b: Int) = ???" + assert(source.defParam(0).modifiers == List(Mod.Implicit())) + assert(source.defParam(1).modifiers == List(Mod.Implicit())) + + source = "def f(x: Int, y: Int)(implicit a: Int, b: Int) = ???" + assert(source.defParam(0, 0).modifiers == List()) + assert(source.defParam(1, 0).modifiers == List(Mod.Implicit())) + } + + @Test def blockDef = { + var source: Tree = "implicit val x : A = ???" + assert(source.modifiers == List(Mod.Implicit(), Mod.Val())) + + source = "implicit var x : A = ???" + assert(source.modifiers == List(Mod.Implicit(), Mod.Var())) + + source = "{ implicit var x : A = ??? }" + assert(source.stat(0).modifiers == List(Mod.Implicit(), Mod.Var())) + + source = "{ implicit x => x * x }" + assert(source.stat(0).funParam(0).modifiers == List(Mod.Implicit())) + } +} From 446bb6c8375166e90d9a1ce099e9139c3aa2f8e8 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Thu, 20 Oct 2016 19:19:05 +0200 Subject: [PATCH 3/5] address review feedback --- src/dotty/tools/dotc/ast/untpd.scala | 28 +++++------ src/dotty/tools/dotc/parsing/Parsers.scala | 55 +++++++++------------- test/test/ModifiersParsingTest.scala | 8 ++-- 3 files changed, 41 insertions(+), 50 deletions(-) diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala index 3ffc47bf8b46..6513dfdc3516 100644 --- a/src/dotty/tools/dotc/ast/untpd.scala +++ b/src/dotty/tools/dotc/ast/untpd.scala @@ -95,36 +95,36 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { // ----- Modifiers ----------------------------------------------------- /** Mod is intended to record syntactic information about modifiers, it's - * NOT a replacement of flagsets. + * NOT a replacement of FlagSet. * * For any query about semantic information, check `flags` instead. */ - sealed trait Mod extends Positioned + sealed abstract class Mod(val flags: FlagSet) extends Positioned object Mod { - case class Private() extends Mod + case class Private() extends Mod(Flags.Private) - case class Protected() extends Mod + case class Protected() extends Mod(Flags.Protected) - case class Val() extends Mod + case class Val() extends Mod(Flags.EmptyFlags) - case class Var() extends Mod + case class Var() extends Mod(Flags.Mutable) - case class Implicit() extends Mod + case class Implicit(flag: FlagSet = Flags.ImplicitCommon) extends Mod(flag) - case class Final() extends Mod + case class Final() extends Mod(Flags.Final) - case class Sealed() extends Mod + case class Sealed() extends Mod(Flags.Sealed) - case class Override() extends Mod + case class Override() extends Mod(Flags.Override) - case class Abstract() extends Mod + case class Abstract() extends Mod(Flags.Abstract) - case class Lazy() extends Mod + case class Lazy() extends Mod(Flags.Lazy) - case class Inline() extends Mod + case class Inline() extends Mod(Flags.Inline) - case class Type() extends Mod + case class Type() extends Mod(Flags.EmptyFlags) } /** Modifiers and annotations for definitions diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 7b1f2754a457..c359ad1b944d 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1465,22 +1465,10 @@ object Parsers { /* -------- MODIFIERS and ANNOTATIONS ------------------------------------------- */ - private def flagOfToken(tok: Int): FlagSet = tok match { - case ABSTRACT => Abstract - case FINAL => Final - case IMPLICIT => ImplicitCommon - case INLINE => Inline - case LAZY => Lazy - case OVERRIDE => Override - case PRIVATE => Private - case PROTECTED => Protected - case SEALED => Sealed - } - private def modOfToken(tok: Int): Mod = tok match { case ABSTRACT => Mod.Abstract() case FINAL => Mod.Final() - case IMPLICIT => Mod.Implicit() + case IMPLICIT => Mod.Implicit(ImplicitCommon) case INLINE => Mod.Inline() case LAZY => Mod.Lazy() case OVERRIDE => Mod.Override() @@ -1502,12 +1490,10 @@ object Parsers { private def addModifier(mods: Modifiers): Modifiers = { val tok = in.token - val flag = flagOfToken(tok) - val mod = atPos(in.offset) { in.nextToken(); modOfToken(tok) } + val mod = atPos(in.skipToken()) { modOfToken(tok) } - if (mods is flag) syntaxError(RepeatedModifier(flag.toString)) - val res = addFlag(mods, flag).withAddedMod(mod) - res + if (mods is mod.flags) syntaxError(RepeatedModifier(flag.toString)) + addMod(mods, mod) } private def compatible(flags1: FlagSet, flags2: FlagSet): Boolean = ( @@ -1533,6 +1519,11 @@ object Parsers { } } + /** Always add the syntactic `mod`, but check and conditionally add semantic `mod.flags` + */ + def addMod(mods: Modifiers, mod: Mod): Modifiers = + addFlag(mods, mod.flags).withAddedMod(mod) + /** AccessQualifier ::= "[" (Id | this) "]" */ def accessQualifierOpt(mods: Modifiers): Modifiers = @@ -1629,7 +1620,7 @@ object Parsers { mods = atPos(start, in.offset) { if (in.token == TYPE) { - val mod = atPos(in.offset) { in.nextToken(); Mod.Type() } + val mod = atPos(in.skipToken()) { Mod.Type() } (mods | Param | ParamAccessor).withAddedMod(mod) } else { if (mods.hasFlags) syntaxError("`type' expected") @@ -1674,7 +1665,6 @@ object Parsers { * Param ::= id `:' ParamType [`=' Expr] */ def paramClauses(owner: Name, ofCaseClass: Boolean = false): List[List[ValDef]] = { - var implicitFlag = EmptyFlags var implicitMod: Mod = null var firstClauseOfCaseClass = ofCaseClass var implicitOffset = -1 // use once @@ -1686,11 +1676,11 @@ object Parsers { mods = atPos(start, in.offset) { if (in.token == VAL) { - val mod = atPos(in.offset) { in.nextToken(); Mod.Val() } + val mod = atPos(in.skipToken()) { Mod.Val() } mods.withAddedMod(mod) } else if (in.token == VAR) { - val mod = atPos(in.offset) { in.nextToken(); Mod.Var() } - addFlag(mods, Mutable).withAddedMod(mod) + val mod = atPos(in.skipToken()) { Mod.Var() } + addMod(mods, mod) } else { if (!(mods.flags &~ (ParamAccessor | Inline)).isEmpty) syntaxError("`val' or `var' expected") @@ -1712,7 +1702,7 @@ object Parsers { if (in.token == ARROW) { if (owner.isTypeName && !(mods is Local)) syntaxError(s"${if (mods is Mutable) "`var'" else "`val'"} parameters may not be call-by-name") - else if (!implicitFlag.isEmpty) + else if (implicitMod != null) syntaxError("implicit parameters may not be call-by-name") } paramType() @@ -1724,8 +1714,8 @@ object Parsers { mods = mods.withPos(mods.pos.union(Position(implicitOffset, implicitOffset))) implicitOffset = -1 } - if (implicitMod != null) mods = mods.withAddedMod(implicitMod) - ValDef(name, tpt, default).withMods(addFlag(mods, implicitFlag)) + if (implicitMod != null) mods = addMod(mods, implicitMod) + ValDef(name, tpt, default).withMods(mods) } } def paramClause(): List[ValDef] = inParens { @@ -1733,8 +1723,7 @@ object Parsers { else { if (in.token == IMPLICIT) { implicitOffset = in.offset - implicitMod = atPos(in.offset) { in.nextToken(); Mod.Implicit() } - implicitFlag = Implicit + implicitMod = atPos(in.skipToken()) { Mod.Implicit(Implicit) } } commaSeparated(param) } @@ -1744,7 +1733,7 @@ object Parsers { if (in.token == LPAREN) paramClause() :: { firstClauseOfCaseClass = false - if (implicitFlag.isEmpty) clauses() else Nil + if (implicitMod == null) clauses() else Nil } else Nil } @@ -1837,12 +1826,12 @@ object Parsers { */ def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match { case VAL => - val mod = atPos(in.offset) { in.nextToken(); Mod.Val() } + val mod = atPos(in.skipToken()) { Mod.Val() } val modPos = atPos(start) { mods.withAddedMod(mod) } patDefOrDcl(start, modPos, in.getDocComment(start)) case VAR => - val mod = atPos(in.offset) { in.nextToken(); Mod.Var() } - val modPos = atPos(start) { addFlag(mods, Mutable).withAddedMod(mod) } + val mod = atPos(in.skipToken()) { Mod.Var() } + val modPos = atPos(start) { addMod(mods, mod) } patDefOrDcl(start, modPos, in.getDocComment(start)) case DEF => defDefOrDcl(start, posMods(start, mods), in.getDocComment(start)) @@ -2231,7 +2220,7 @@ object Parsers { else if (isDefIntro(localModifierTokens)) if (in.token == IMPLICIT) { val start = in.offset - val mod = atPos(in.offset) { in.nextToken(); Mod.Implicit() } + val mod = atPos(in.skipToken()) { Mod.Implicit(ImplicitCommon) } if (isIdent) stats += implicitClosure(start, Location.InBlock, Some(mod)) else stats += localDef(start, ImplicitCommon, Some(mod)) } else { diff --git a/test/test/ModifiersParsingTest.scala b/test/test/ModifiersParsingTest.scala index bdcaf76e18dc..82aa33281ba6 100644 --- a/test/test/ModifiersParsingTest.scala +++ b/test/test/ModifiersParsingTest.scala @@ -9,6 +9,7 @@ import dotty.tools.dotc.ast.{ Trees => d } import dotty.tools.dotc.parsing.Parsers.Parser import dotty.tools.dotc.util.SourceFile import dotty.tools.dotc.core.Contexts.ContextBase +import dotty.tools.dotc.core.Flags object ModifiersParsingTest { implicit val ctx = (new ContextBase).initialCtx @@ -136,12 +137,13 @@ class ModifiersParsingTest { assert(source.defParam(0).modifiers == List(Mod.Inline())) source = "def f(implicit a: Int, b: Int) = ???" - assert(source.defParam(0).modifiers == List(Mod.Implicit())) - assert(source.defParam(1).modifiers == List(Mod.Implicit())) + println(source.defParam(0).modifiers) + assert(source.defParam(0).modifiers == List(Mod.Implicit(Flags.Implicit))) + assert(source.defParam(1).modifiers == List(Mod.Implicit(Flags.Implicit))) source = "def f(x: Int, y: Int)(implicit a: Int, b: Int) = ???" assert(source.defParam(0, 0).modifiers == List()) - assert(source.defParam(1, 0).modifiers == List(Mod.Implicit())) + assert(source.defParam(1, 0).modifiers == List(Mod.Implicit(Flags.Implicit))) } @Test def blockDef = { From c22262f7cc2ad04be8040c882c76ce71efb1e54d Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Sat, 22 Oct 2016 10:58:22 +0200 Subject: [PATCH 4/5] rename val and unnecessary atPos Note that there's no need to explicitly call `atPos` here, because the initializer of `Positioned` will automatically synthesize the initial position from its children elements. Refer to the definition of `Positioned` for more details. --- src/dotty/tools/dotc/parsing/Parsers.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index c359ad1b944d..412173f84279 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1827,12 +1827,12 @@ object Parsers { def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match { case VAL => val mod = atPos(in.skipToken()) { Mod.Val() } - val modPos = atPos(start) { mods.withAddedMod(mod) } - patDefOrDcl(start, modPos, in.getDocComment(start)) + val mods1 = mods.withAddedMod(mod) + patDefOrDcl(start, mods1, in.getDocComment(start)) case VAR => val mod = atPos(in.skipToken()) { Mod.Var() } - val modPos = atPos(start) { addMod(mods, mod) } - patDefOrDcl(start, modPos, in.getDocComment(start)) + val mod1 = addMod(mods, mod) + patDefOrDcl(start, mod1, in.getDocComment(start)) case DEF => defDefOrDcl(start, posMods(start, mods), in.getDocComment(start)) case TYPE => From 24a725db99786eaf5f37903429bfefcf8db12aaf Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Mon, 24 Oct 2016 13:40:01 +0200 Subject: [PATCH 5/5] fix error in rebase merge --- src/dotty/tools/dotc/parsing/Parsers.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 412173f84279..013541c7177c 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1492,7 +1492,7 @@ object Parsers { val tok = in.token val mod = atPos(in.skipToken()) { modOfToken(tok) } - if (mods is mod.flags) syntaxError(RepeatedModifier(flag.toString)) + if (mods is mod.flags) syntaxError(RepeatedModifier(mod.flags.toString)) addMod(mods, mod) }