@@ -0,0 +1,99 @@
1+module Generate.Nitpick
2+ ( findDebugUses
3+ )
4+ where
5+
6+
7+import qualified Data.Map as Map
8+import qualified Data.Set as Set
9+
10+import qualified AST.Optimized as Opt
11+import qualified AST.Module.Name as ModuleName
12+import qualified Elm.Package as Pkg
13+import qualified Elm.Name as N
14+
15+
16+
17+-- FIND DEBUG USES
18+
19+
20+findDebugUses :: Pkg.Name -> Opt.Graph -> [N.Name]
21+findDebugUses pkg (Opt.Graph _ graph _) =
22+ Set.toList $ Map.foldrWithKey (addDebugUses pkg) Set.empty graph
23+
24+
25+addDebugUses :: Pkg.Name -> Opt.Global -> Opt.Node -> Set.Set N.Name -> Set.Set N.Name
26+addDebugUses here (Opt.Global (ModuleName.Canonical pkg home) _) node uses =
27+ if pkg == here && nodeHasDebug node then
28+ Set.insert home uses
29+ else
30+ uses
31+
32+
33+nodeHasDebug :: Opt.Node -> Bool
34+nodeHasDebug node =
35+ case node of
36+ Opt.Define expr _ -> hasDebug expr
37+ Opt.DefineTailFunc _ expr _ -> hasDebug expr
38+ Opt.Ctor _ _ _ -> False
39+ Opt.Enum _ _ -> False
40+ Opt.Box _ -> False
41+ Opt.Link _ -> False
42+ Opt.Cycle defs _ -> any (hasDebug . snd) defs
43+ Opt.Manager _ -> False
44+ Opt.Kernel _ _ -> False
45+ Opt.PortIncoming expr _ -> hasDebug expr
46+ Opt.PortOutgoing expr _ -> hasDebug expr
47+
48+
49+hasDebug :: Opt.Expr -> Bool
50+hasDebug expression =
51+ case expression of
52+ Opt.Bool _ -> False
53+ Opt.Chr _ -> False
54+ Opt.Str _ -> False
55+ Opt.Int _ -> False
56+ Opt.Float _ -> False
57+ Opt.VarLocal _ -> False
58+ Opt.VarGlobal _ -> False
59+ Opt.VarEnum _ _ -> False
60+ Opt.VarBox _ -> False
61+ Opt.VarCycle _ _ -> False
62+ Opt.VarDebug _ _ _ _ -> True
63+ Opt.VarKernel _ _ -> False
64+ Opt.List exprs -> any hasDebug exprs
65+ Opt.Function _ expr -> hasDebug expr
66+ Opt.Call e es -> hasDebug e || any hasDebug es
67+ Opt.TailCall _ args -> any (hasDebug . snd) args
68+ Opt.If conds finally -> any (\(c,e) -> hasDebug c || hasDebug e) conds || hasDebug finally
69+ Opt.Let def body -> defHasDebug def || hasDebug body
70+ Opt.Destruct _ expr -> hasDebug expr
71+ Opt.Case _ _ d jumps -> deciderHasDebug d || any (hasDebug . snd) jumps
72+ Opt.Accessor _ -> False
73+ Opt.Access r _ -> hasDebug r
74+ Opt.Update r fs -> hasDebug r || any hasDebug fs
75+ Opt.Record fs -> any hasDebug fs
76+ Opt.Unit -> False
77+ Opt.Tuple a b c -> hasDebug a || hasDebug b || maybe False hasDebug c
78+ Opt.Shader _ -> False
79+
80+
81+defHasDebug :: Opt.Def -> Bool
82+defHasDebug def =
83+ case def of
84+ Opt.Def _ expr -> hasDebug expr
85+ Opt.TailDef _ _ expr -> hasDebug expr
86+
87+
88+deciderHasDebug :: Opt.Decider Opt.Choice -> Bool
89+deciderHasDebug decider =
90+ case decider of
91+ Opt.Leaf (Opt.Inline expr) -> hasDebug expr
92+ Opt.Leaf (Opt.Jump _) -> False
93+ Opt.Chain _ success failure -> deciderHasDebug success || deciderHasDebug failure
94+ Opt.FanOut _ tests fallback -> any (deciderHasDebug . snd) tests || deciderHasDebug fallback
95+
96+
97+
98+-- TODO: FIND GLOBALLY UNUSED DEFINITIONS?
99+-- TODO: FIND PACKAGE USAGE STATS? (e.g. elm-lang/core = 142, author/project = 2, etc.)