-
Notifications
You must be signed in to change notification settings - Fork 309
/
AddMissingOverride.scala
110 lines (89 loc) · 3.12 KB
/
AddMissingOverride.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package org.scalaide.extensions
package saveactions
import scala.tools.nsc.ast.parser.Tokens
object AddMissingOverrideSetting extends SaveActionSetting(
id = ExtensionSetting.fullyQualifiedName[AddMissingOverride],
name = "Add missing override keyword",
description = "Adds the override keyword to all symbols that override another symbol.",
codeExample = """|trait T {
| def method: Int
| def value: Int
| type Type
|}
|class C extends T {
| def method = 0
| def value = 0
| type Type = Int
|}
|""".stripMargin
)
trait AddMissingOverride extends SaveAction with CompilerSupport {
import global._
override def setting = AddMissingOverrideSetting
override def perform() = {
def canOverride(sym: Symbol) = sym.isOverridingSymbol && !sym.isOverride && !sym.isAbstractOverride
val symbolWithoutOverride = filter {
case d: ValDef if isJavaField(getterOf(d.symbol)) ⇒
false
case d: DefDef if isJavaField(d.symbol) ⇒
false
case d: ValDef if d.mods.positions.contains(Tokens.VAR) && !overridesVar(getterOf(d.symbol)) ⇒
false
case d: ValDef =>
val getter = getterOf(d.symbol)
canOverride(if (getter != NoSymbol) getter else d.symbol)
case d @ (_: DefDef | _: TypeDef) =>
canOverride(d.symbol)
}
val addOverrideKeyword = transform {
case d: MemberDef =>
val mods = d.mods.withFlag(Flag.OVERRIDE)
d match {
case d: DefDef =>
val lazyValMods =
if (mods.hasFlag(Flag.LAZY))
if (mods.positions.contains(Flag.LAZY))
mods
else
mods.withFlag(Flag.LAZY).withFlag(Tokens.VAL)
else
mods
d.copy(mods = lazyValMods) replaces d
case d: ValDef =>
val valMods =
if (mods.positions.contains(Tokens.VAR) || mods.positions.contains(Tokens.VAL))
mods
else
mods.withFlag(Tokens.VAL)
d.copy(mods = valMods) replaces d
case d: TypeDef =>
d.copy(mods = mods) replaces d
}
}
val refactoring = topdown {
matchingChildren {
symbolWithoutOverride &> addOverrideKeyword
}
}
transformFile(refactoring)
}
private def getterOf(sym: Symbol): Symbol =
sym.getterIn(sym.owner)
private def overridesVar(symbol: Symbol): Boolean = {
val base = symbol.owner
val baseType = base.toType
val bcs = base.info.baseClasses dropWhile (symbol.owner != _) drop 1
bcs exists { sym ⇒
symbol.matchingSymbol(sym, baseType).setterIn(sym) != NoSymbol
}
}
private def isJavaField(symbol: Symbol): Boolean = {
val base = symbol.owner
val baseType = base.toType
val bcs = base.info.baseClasses dropWhile (symbol.owner != _) drop 1
bcs exists { sym ⇒
val s = symbol.matchingSymbol(sym, baseType)
s.isJava && !s.isMethod
}
}
}