1
+ package analyzer
2
+
3
+ import scala .language .implicitConversions
4
+
5
+ import dotty .tools .dotc ._
6
+ import core ._
7
+ import Contexts .Context
8
+ import plugins ._
9
+ import Phases .Phase
10
+ import ast .tpd
11
+ import transform .MegaPhase .MiniPhase
12
+ import Decorators ._
13
+ import Symbols .Symbol
14
+ import Constants .Constant
15
+ import Types ._
16
+ import transform .{SetDefTree , SetDefTreeOff }
17
+
18
+ class InitChecker extends PluginPhase with StandardPlugin {
19
+ import tpd ._
20
+
21
+ val name : String = " initChecker"
22
+ override val description : String = " checks that under -Yretain-trees we may get tree for all symbols"
23
+
24
+ val phaseName = name
25
+
26
+ override val runsAfter = Set (SetDefTree .name)
27
+ override val runsBefore = Set (SetDefTreeOff .name)
28
+
29
+ def init (options : List [String ]): List [PluginPhase ] = this :: Nil
30
+
31
+ private def checkDef (tree : Tree )(implicit ctx : Context ): Tree = {
32
+ if (tree.symbol.defTree.isEmpty)
33
+ ctx.error(" cannot get tree for " + tree.show, tree.sourcePos)
34
+ tree
35
+ }
36
+
37
+ private def checkable (sym : Symbol )(implicit ctx : Context ): Boolean =
38
+ sym.exists && ! sym.isOneOf(Flags .Package ) && ! sym.isOneOf(Flags .Param ) &&
39
+ (sym.isClass || ! sym.isOneOf(Flags .Case , butNot = Flags .Enum )) // pattern-bound symbols
40
+
41
+ private def checkRef (tree : Tree )(implicit ctx : Context ): Tree =
42
+ if (! checkable(tree.symbol)) tree
43
+ else {
44
+ val helloPkgSym = ctx.requiredPackage(" hello" ).moduleClass
45
+ val libPkgSym = ctx.requiredPackage(" lib" ).moduleClass
46
+ val enclosingPkg = tree.symbol.enclosingPackageClass
47
+
48
+ if (enclosingPkg == helloPkgSym) { // source code
49
+ checkDef(tree)
50
+ ctx.warning(" tree: " + tree.symbol.defTree.show)
51
+ }
52
+ else if (enclosingPkg == libPkgSym) { // tasty from library
53
+ checkDef(tree)
54
+ // check that all sub-definitions have trees set properly
55
+ // make sure that are no cycles in the code
56
+ transformAllDeep(tree.symbol.defTree)
57
+ ctx.warning(" tree: " + tree.symbol.defTree.show)
58
+ }
59
+ else {
60
+ ctx.warning(tree.symbol + " is neither in lib nor hello, owner = " + enclosingPkg, tree.sourcePos)
61
+ }
62
+ tree
63
+ }
64
+
65
+ override def transformValDef (tree : ValDef )(implicit ctx : Context ): Tree = checkDef(tree)
66
+
67
+ override def transformDefDef (tree : DefDef )(implicit ctx : Context ): Tree = checkDef(tree)
68
+
69
+ override def transformTypeDef (tree : TypeDef )(implicit ctx : Context ): Tree = checkDef(tree)
70
+
71
+ override def transformSelect (tree : Select )(implicit ctx : Context ): Tree = checkRef(tree)
72
+
73
+ override def transformIdent (tree : Ident )(implicit ctx : Context ): Tree = checkRef(tree)
74
+
75
+ override def transformTypeTree (tree : TypeTree )(implicit ctx : Context ): Tree = {
76
+ tree.tpe.foreachPart {
77
+ case tp : NamedType => checkRef(TypeTree (tp))
78
+ case _ =>
79
+ }
80
+ tree
81
+ }
82
+ }
0 commit comments