1+ package dotty .tools .dotc .transform
2+
3+ import dotty .tools .dotc .core ._
4+ import Symbols ._
5+ import scala .Some
6+ import dotty .tools .dotc .transform .TreeTransforms .{NXTransformations , TransformerInfo , TreeTransform , TreeTransformer }
7+ import dotty .tools .dotc .ast .tpd
8+ import dotty .tools .dotc .core .Contexts .Context
9+ import scala .collection .mutable
10+ import dotty .tools .dotc .core .Names .Name
11+ import NameOps ._
12+
13+ object PostTyperTransformers {
14+
15+ import tpd .{TreeTransformer => _ , _ }
16+
17+
18+ /** A trait that's assumed by the transformers that run right after typer.
19+ * Ensures that trees are normalized when seen by other transforms. This means:
20+ * (1) All module class definitions appear after their companion class definitions
21+ * (2) There are no import clauses or named arguments
22+ * (3) All trees designating types are instances of TypeTree
23+ */
24+ abstract class PostTyperTransformer extends TreeTransformer {
25+
26+ /** Reorder statements so that module classes always come after their companion classes, add missing companion classes */
27+ def reorder (stats : List [Tree ])(implicit ctx : Context , info : TransformerInfo ): List [Tree ] = {
28+ val moduleClassDefs = mutable.Map [Name , Tree ]()
29+ def reorder0 (stats : List [Tree ]): List [Tree ] = {
30+ stats match {
31+ case (stat : TypeDef ) :: stats1 if stat.symbol.isClass =>
32+ if (stat.symbol is Flags .Module ) {
33+ moduleClassDefs += (stat.name -> stat)
34+ val stats1r = reorder0(stats1)
35+ if (moduleClassDefs contains stat.name) stat :: stats1r else stats1r
36+ }
37+ else {
38+ val mclsName = stat.name.moduleClassName
39+ moduleClassDefs remove mclsName match {
40+ case Some (mcdef) => stat :: mcdef :: reorder0(stats1)
41+ case None => stat :: reorder0(stats1)
42+ }
43+ }
44+ case stat :: stats1 => stat :: reorder0(stats1)
45+ case Nil => Nil
46+ }
47+ }
48+ reorder0(stats)
49+ }
50+
51+ override def transformStats (trees : List [tpd.Tree ], info : TransformerInfo , current : Int )(implicit ctx : Context ): List [tpd.Tree ] =
52+ super .transformStats(reorder(trees)(ctx, info), info, current)
53+
54+ override def transform (tree : tpd.Tree , info : TransformerInfo , cur : Int )(implicit ctx : Context ): tpd.Tree = tree match {
55+ case tree : Import => EmptyTree
56+ case tree : NamedArg => super .transform(tree.arg, info, cur)
57+ case tree : TypeTree => super .transform(tree, info, cur)
58+ case tree => super .transform(if (tree.isType) TypeTree (tree.tpe) else tree, info, cur)
59+ }
60+ }
61+
62+ }
0 commit comments