Skip to content

Commit 2632952

Browse files
committed
Record syntactic information about modifiers
1 parent 0e3b4aa commit 2632952

File tree

2 files changed

+70
-14
lines changed

2 files changed

+70
-14
lines changed

src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,51 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
9494
class InfixOpBlock(leftOperand: Tree, rightOp: Tree) extends Block(leftOperand :: Nil, rightOp)
9595

9696
// ----- Modifiers -----------------------------------------------------
97+
/** Mod is intended to record syntactic information about modifiers, it's
98+
* NOT a replacement of flagsets.
99+
*
100+
* For any query about semantic information, check `flags` instead.
101+
*/
102+
sealed trait Mod extends Positioned
97103

98-
/** Modifiers and annotations for definitions
99-
* @param flags The set flags
104+
object Mod {
105+
case class Private() extends Mod
106+
107+
case class Protected() extends Mod
108+
109+
case class Val() extends Mod
110+
111+
case class Var() extends Mod
112+
113+
case class Implicit() extends Mod
114+
115+
case class Final() extends Mod
116+
117+
case class Sealed() extends Mod
118+
119+
case class Override() extends Mod
120+
121+
case class Abstract() extends Mod
122+
123+
case class Lazy() extends Mod
124+
125+
case class Inline() extends Mod
126+
127+
case class Type() extends Mod
128+
}
129+
130+
/** Modifiers and annotations for definitions
131+
*
132+
* @param flags The set flags
100133
* @param privateWithin If a private or protected has is followed by a
101134
* qualifier [q], the name q, "" as a typename otherwise.
102135
* @param annotations The annotations preceding the modifiers
103136
*/
104137
case class Modifiers (
105138
flags: FlagSet = EmptyFlags,
106139
privateWithin: TypeName = tpnme.EMPTY,
107-
annotations: List[Tree] = Nil) extends Positioned with Cloneable {
140+
annotations: List[Tree] = Nil,
141+
mods: List[Mod] = Nil) extends Positioned with Cloneable {
108142

109143
def is(fs: FlagSet): Boolean = flags is fs
110144
def is(fc: FlagConjunction): Boolean = flags is fc
@@ -120,7 +154,15 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
120154
if (this.flags == flags) this
121155
else copy(flags = flags)
122156

123-
def withAddedAnnotation(annot: Tree): Modifiers =
157+
def withAddedMod(mod: Mod): Modifiers =
158+
if (mods.exists(_ eq mod)) this
159+
else withMods(mods :+ mod)
160+
161+
def withMods(ms: List[Mod]): Modifiers =
162+
if (mods eq ms) this
163+
else copy(mods = ms)
164+
165+
def withAddedAnnotation(annot: Tree): Modifiers =
124166
if (annotations.exists(_ eq annot)) this
125167
else withAnnotations(annotations :+ annot)
126168

src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,19 @@ object Parsers {
14761476
case SEALED => Sealed
14771477
}
14781478

1479-
/** Drop `private' modifier when followed by a qualifier.
1479+
private def modOfToken(tok: Int): Mod = tok match {
1480+
case ABSTRACT => Mod.Abstract()
1481+
case FINAL => Mod.Final()
1482+
case IMPLICIT => Mod.Implicit()
1483+
case INLINE => Mod.Inline()
1484+
case LAZY => Mod.Lazy()
1485+
case OVERRIDE => Mod.Override()
1486+
case PRIVATE => Mod.Private()
1487+
case PROTECTED => Mod.Protected()
1488+
case SEALED => Mod.Sealed()
1489+
}
1490+
1491+
/** Drop `private' modifier when followed by a qualifier.
14801492
* Contract `abstract' and `override' to ABSOVERRIDE
14811493
*/
14821494
private def normalize(mods: Modifiers): Modifiers =
@@ -1488,10 +1500,12 @@ object Parsers {
14881500
mods
14891501

14901502
private def addModifier(mods: Modifiers): Modifiers = {
1491-
val flag = flagOfToken(in.token)
1503+
val tok = in.token
1504+
val flag = flagOfToken(tok)
1505+
val mod = atPos(in.offset) { in.nextToken(); modOfToken(tok) }
1506+
14921507
if (mods is flag) syntaxError(RepeatedModifier(flag.toString))
1493-
val res = addFlag(mods, flag)
1494-
in.nextToken()
1508+
val res = addFlag(mods, flag).withAddedMod(mod)
14951509
res
14961510
}
14971511

@@ -1614,8 +1628,8 @@ object Parsers {
16141628
mods =
16151629
atPos(start, in.offset) {
16161630
if (in.token == TYPE) {
1617-
in.nextToken()
1618-
mods | Param | ParamAccessor
1631+
val mod = atPos(in.offset) { in.nextToken(); Mod.Type() }
1632+
(mods | Param | ParamAccessor).withAddedMod(mod)
16191633
} else {
16201634
if (mods.hasFlags) syntaxError("`type' expected")
16211635
mods | Param | PrivateLocal
@@ -1670,11 +1684,11 @@ object Parsers {
16701684
mods =
16711685
atPos(start, in.offset) {
16721686
if (in.token == VAL) {
1673-
in.nextToken()
1674-
mods
1687+
val mod = atPos(in.offset) { in.nextToken(); Mod.Val() }
1688+
mods.withAddedMod(mod)
16751689
} else if (in.token == VAR) {
1676-
in.nextToken()
1677-
addFlag(mods, Mutable)
1690+
val mod = atPos(in.offset) { in.nextToken(); Mod.Var() }
1691+
addFlag(mods, Mutable).withAddedMod(mod)
16781692
} else {
16791693
if (!(mods.flags &~ (ParamAccessor | Inline)).isEmpty)
16801694
syntaxError("`val' or `var' expected")

0 commit comments

Comments
 (0)