This repository was archived by the owner on Sep 15, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathCustom_Scala_EnforceMinimumVisibility.scala
More file actions
80 lines (69 loc) · 2.47 KB
/
Copy pathCustom_Scala_EnforceMinimumVisibility.scala
File metadata and controls
80 lines (69 loc) · 2.47 KB
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
package codacy.patterns
import codacy.base.Pattern
import scala.meta._
case object Custom_Scala_EnforceMinimumVisibility extends Pattern {
override def apply(tree: Tree): Iterable[Result] = tree.collect {
case t: Defn if t.mods.exists(isPrivate) && isInner(t) && !isAccessedInAccompanied(t) =>
Result(message(name(t)), t)
}
private[this] def isInner(tree: Defn) = tree match {
case t @ (_: Defn.Trait | _: Defn.Class | _: Defn.Object) =>
t.parent.exists {
case _: Pkg => false
case _: Pkg.Object => false
case _ => true
}
case _ => true
}
private[this] def name(defn: Defn) = defn match {
case d: Member => d.name.syntax
case d: Defn.Val => d.pats.map(_.syntax).mkString(",")
case d: Defn.Var => d.pats.map(_.syntax).mkString(",")
case other => other.syntax
}
private[this] def isPrivate(mod: Mod) = mod match {
case mod"private" => true
case _ => false
}
private[this] def message(name: String) = Message(s"${name} should have a smaller scope by using private[this]")
//poor man's approach ...
private[this] def isAccessedInAccompanied(defn: Defn) = {
Option(defn)
.collect {
case d: Defn.Def => Set(d.name)
case d: Defn.Val => d.collect { case n: Name => n }.to[Set]
case d: Defn.Var => d.collect { case n: Name => n }.to[Set]
}
.exists(
defNames =>
defn.parent.flatMap(_.parent).exists {
case companion: Defn.Object =>
lazy val rawNames = defNames.map(_.syntax)
companion.parent.map(_.children).getOrElse(Seq.empty).exists {
case accompanied: Defn.Class if companion.name.syntax == accompanied.name.syntax =>
accompanied.templ
.collect {
case q"$expr.$name" if expr.syntax == companion.name.syntax && rawNames.contains(name.syntax) =>
true
}
.exists(identity)
case _ => false
}
case _ => false
}
)
}
private[this] implicit class DefExtensions(val defn: Defn) {
def mods: Seq[Mod] = defn match {
case d: Defn.Class => d.mods
case d: Defn.Def => d.mods
case d: Defn.Trait => d.mods
case d: Defn.Object => d.mods
case d: Defn.Type => d.mods
case d: Defn.Val => d.mods
case d: Defn.Var => d.mods
case d: Defn.Macro => d.mods
case _ => Seq.empty
}
}
}