-
Notifications
You must be signed in to change notification settings - Fork 1
/
CouplingBetweenObjects.scala
48 lines (39 loc) · 1.74 KB
/
CouplingBetweenObjects.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
package codeAnalysis.metrics.baseline
import codeAnalysis.analyser.Compiler
import codeAnalysis.analyser.metric.{Metric, MetricProducer, MetricResult, ObjectMetric}
import codeAnalysis.util.Constants.basicTypes
import scala.util.matching.Regex
object CouplingBetweenObjects extends MetricProducer {
override def apply(compiler: Compiler): Metric = new CouplingBetweenObjects(compiler)
}
class CouplingBetweenObjects(override val compiler: Compiler) extends ObjectMetric {
import global.{SymbolExtensions, TreeExtensions}
def fanOut(tree: global.ImplDef): Set[global.Symbol] = filterSymbols(tree)(tree.collectTraverse {
case tree if tree.getTypeSymbol != null => tree.getTypeSymbol
})
def fanIn(tree: global.ImplDef): Set[global.Symbol] = {
val name = tree.symbol.nameString
val qualifiedName = tree.symbol.qualifiedName
val nameFilter = Regex.quote(name).r
filterSymbols(tree)(compiler.treesFromFilteredSources(nameFilter).flatMap(_.asInstanceOf[global.Tree].collectTraverse {
case tree: global.ImplDef if tree.existsTraverse {
case tree if tree.symbol != null => tree.symbol.qualifiedName == qualifiedName
} => tree.symbol
}))
}
def filterSymbols(tree: global.ImplDef)(symbols: List[global.Symbol]): Set[global.Symbol] = symbols.toSet.filterNot {
case _: global.NoSymbol => true
case _: global.PackageClassSymbol => true
case symbol => tree.symbol == symbol || basicTypes(symbol.qualifiedName)
}
override def run(tree: global.ImplDef): List[MetricResult] = {
val out = fanOut(tree)
val in = fanIn(tree)
val total = out ++ in
List(
MetricResult("FanOut", out.size),
MetricResult("FanIn", in.size),
MetricResult("CouplingBetweenObjects", total.size)
)
}
}