blob: 05296d93e58c73d5574e6d8124a3a07c9fd8f400 (
plain) (
blame)
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
|
package dotty.tools.dotc
package transform
import core._
import DenotTransformers.SymTransformer
import Phases.Phase
import Contexts.Context
import Flags._
import Symbols._
import SymDenotations.SymDenotation
import ast.Trees._
import collection.mutable
import Decorators._
import NameOps._
import TreeTransforms.{TreeTransform, MiniPhase}
import dotty.tools.dotc.transform.TreeTransforms.TransformerInfo
/** Remove companion objects that are empty */
class DropEmptyCompanions extends MiniPhase { thisTransform =>
import ast.tpd._
override def phaseName = "dropEmpty"
val treeTransform = new Transform(Set())
class Transform(dropped: Set[Symbol]) extends TreeTransform {
def phase = thisTransform
/** Is `tree` an empty companion object? */
private def isEmptyCompanion(tree: Tree)(implicit ctx: Context) = tree match {
case TypeDef(_, impl: Template) =>
tree.symbol.is(Module) &&
tree.symbol.companionClass.exists &&
impl.body.forall(_.symbol.isPrimaryConstructor)
case _ =>
false
}
/** A transform which has all empty companion objects in `stats`
* recorded in its `dropped` set.
*/
private def localTransform(stats: List[Tree])(implicit ctx: Context) =
new Transform(stats.filter(isEmptyCompanion).map(_.symbol).toSet)
override def prepareForTemplate(tree: Template)(implicit ctx: Context) =
localTransform(tree.body)
override def prepareForStats(trees: List[Tree])(implicit ctx: Context) =
if (ctx.owner is Package) localTransform(trees) else this
/** Symbol is a $lzy field representing a module */
private def isLazyModuleVar(sym: Symbol)(implicit ctx: Context) =
sym.name.isLazyLocal &&
sym.owner.info.decl(sym.name.asTermName.nonLazyName).symbol.is(Module)
/** Symbol should be dropped together with a dropped companion object.
* Such symbols are:
* - lzy fields pointing to modules,
* - vals and getters representing modules.
*/
private def toDrop(sym: Symbol)(implicit ctx: Context): Boolean =
(sym.is(Module) || isLazyModuleVar(sym)) &&
dropped.contains(sym.info.resultType.typeSymbol)
/** Tree should be dropped because it (is associated with) an empty
* companion object. Such trees are
* - module classes of empty companion objects
* - definitions of lazy module variables or assignments to them.
* - vals and getters for empty companion objects
*/
private def toDrop(stat: Tree)(implicit ctx: Context): Boolean = stat match {
case stat: TypeDef => dropped.contains(stat.symbol)
case stat: ValOrDefDef => toDrop(stat.symbol)
case stat: Assign => toDrop(stat.lhs.symbol)
case _ => false
}
override def transformStats(stats: List[Tree])(implicit ctx: Context, info: TransformerInfo) =
stats.filterNot(toDrop)
}
}
|