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