Skip to content
This repository was archived by the owner on Sep 3, 2020. It is now read-only.

Commit 7c7e481

Browse files
committed
Merge pull request #62 from sschaef/ordering-for-modifiers
Add ordering for modifiers
2 parents 8806437 + 84043c1 commit 7c7e481

File tree

2 files changed

+110
-3
lines changed

2 files changed

+110
-3
lines changed

org.scala-refactoring.library/src/main/scala/scala/tools/refactoring/common/PimpedTrees.scala

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -882,17 +882,61 @@ trait PimpedTrees {
882882
* object.
883883
*/
884884
object ModifierTree {
885-
def unapply(m: global.Modifiers) = {
886-
Some(m.positions.toList map {
885+
def unapply(m: global.Modifiers): Option[List[ModifierTree]] = {
886+
val flagSorter = Ordering.by((pair: (Long, Position)) => flagPosition(pair._1))
887+
val sortedMods = m.positions.toList.sorted(flagSorter)
888+
889+
Some(sortedMods map {
887890
// hack to get rid of override modifiers
888891
// couldn't figure out how to remove a flag from the positions map (michael)
889-
case (Flags.OVERRIDE, _) if (m.flags & Flags.OVERRIDE) == 0 => ModifierTree(0)
892+
case (Flags.OVERRIDE, _) if (m.flags & Flags.OVERRIDE) == 0 =>
893+
ModifierTree(0)
890894
case (flag, pos) if pos.isRange =>
891895
ModifierTree(flag) setPos (pos withEnd (pos.end + 1))
892896
case (flag, _) =>
893897
ModifierTree(flag)
894898
})
895899
}
900+
import Flags._
901+
902+
/**
903+
* Defines an ordering for flags. A lower value means that the flag shoud be
904+
* shown at an earlier position.
905+
*
906+
* Returns `0` if to a given value no ordering could be found.
907+
*/
908+
private def flagPosition(flag: Long): Int = flag match {
909+
case OVERRIDE => 1
910+
case PRIVATE => 3
911+
case PROTECTED => 3
912+
case FINAL => 5
913+
case ABSTRACT => 6
914+
case SEALED => 8
915+
case IMPLICIT => 10
916+
case CASE => 15
917+
case LAZY => 15
918+
case TRAIT => 20
919+
case METHOD => 20
920+
case Tokens.VAL => 20
921+
case Tokens.VAR => 20
922+
case Tokens.TYPE => 20
923+
case Tokens.DEF => 20
924+
case _ => 0
925+
}
926+
}
927+
928+
implicit class RichModifiers(mods: global.Modifiers) {
929+
930+
/**
931+
* Returns a copy of the modifiers with an attached flag whose position
932+
* is `NoPosition`. Usage:
933+
* {{{
934+
* val newMods = mods.withFlag(Flag.OVERRIDE).withFlag(Flag.FINAL)
935+
* }}}
936+
* Note: Combining flags with one `withFlag` call does not work.
937+
*/
938+
def withFlag(flag: Long): global.Modifiers =
939+
mods.copy(flags = mods.flags | flag) setPositions mods.positions + (flag -> NoPosition)
896940
}
897941

898942
/**

org.scala-refactoring.library/src/test/scala/scala/tools/refactoring/tests/sourcegen/ReusingPrinterTest.scala

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,67 @@ class ReusingPrinterTest extends TestHelper with SilentTracing {
8383
d.copy(tpt = newTpt) replaces d
8484
}}}
8585

86+
@Test
87+
def add_override_flag() = """
88+
trait T {
89+
def meth: Int
90+
}
91+
trait TT extends T {
92+
override def meth = 0
93+
}
94+
""" becomes """
95+
trait T {
96+
def meth: Int
97+
}
98+
trait TT extends T {
99+
override def meth = 0
100+
}
101+
""" after topdown { matchingChildren {
102+
filter {
103+
case d: DefDef =>
104+
d.symbol.isOverridingSymbol && !d.symbol.isOverride
105+
} &>
106+
transform {
107+
case d: DefDef =>
108+
d.copy(mods = d.mods.withFlag(Flag.OVERRIDE)) replaces d
109+
}
110+
}}
111+
112+
@Test
113+
def add_override_protected_abstract_flag() = """
114+
trait T {
115+
protected def meth: Int = 0
116+
}
117+
trait TT extends T {
118+
def meth = super.meth + 0
119+
}
120+
""" becomes """
121+
trait T {
122+
protected def meth: Int = 0
123+
}
124+
trait TT extends T {
125+
override protected abstract def meth = super.meth + 0
126+
}
127+
""" after topdown { matchingChildren {
128+
filter {
129+
case d: DefDef =>
130+
d.symbol.isOverridingSymbol && !d.symbol.isOverride
131+
} &>
132+
transform {
133+
case d: DefDef =>
134+
d.copy(mods = d.mods.withFlag(Flag.ABSTRACT).withFlag(Flag.OVERRIDE).withFlag(Flag.PROTECTED)) replaces d
135+
}
136+
}}
137+
138+
@Test
139+
def add_final_case_flag() = """
140+
class C(i: Int)
141+
""" becomes """
142+
private final case class C(i: Int)
143+
""" after topdown { matchingChildren {
144+
transform {
145+
case d: ClassDef =>
146+
d.copy(mods = d.mods.withFlag(Flag.FINAL).withFlag(Flag.CASE).withFlag(Flag.PRIVATE)) replaces d
147+
}
148+
}}
86149
}

0 commit comments

Comments
 (0)