graph/fan_out.bend
bend-lint-pack@0.1.1.0 · 64 lines · 8 definitions
1
2
3
4
5
6
7
8
9import Base
10import bend-lint-pack@0.1.1.0/vendor/lint.bend as Lint
11import bend-lint-pack@0.1.1.0/common.bend as Common
12
13def id() -> String:
14 "graph/fan_out"
15
16def facts() -> Lint.Want:
17 Lint.Want{Lint.Program{}, [], [], []}
18
19def message(+name: String, d: U32, max: U32) -> String:
20 "def " ++ name ++ " uses " ++ U32.show(d) ++ " different defs; the limit is " ++ U32.show(max) ++ ". Group related calls behind a helper def."
21
22def judge.one(+d: U32, +max: U32, +owner: String, span: Maybe<&2, Lint.Span>) -> List<&2, Lint.Diag>:
23 Common.when(
24 U32.is_gt(d, max),
25 Common.diag(Lint.Warning{}, message(owner, d, max), span)
26 )
27
28def judge(
29 seen: List<&2, Common.Seen>,
30 +max: U32,
31 +nodes: Set(),
32 +edges: Map<&2, List<&2, String>>,
33 out: List<&2, Lint.Diag>
34) -> List<&2, Lint.Diag>:
35 match seen:
36 case Nil{}:
37 List.reverse(&2, Lint.Diag, out)
38 case Con{Common.Seen{+owner, span}, rest}:
39 judge(
40 rest,
41 max,
42 nodes,
43 edges,
44 Common.onto(
45 judge.one(Common.degree(edges, nodes, owner), max, owner, span),
46 out
47 )
48 )
49
50def verdict(p: Common.Prog, max: U32, scope: Common.Scope) -> List<&2, Lint.Diag>:
51 match p:
52 case Common.Prog{seen, edges, into, nodes, laws}:
53 judge(Common.scoped(scope, seen), max, nodes, edges, [])
54
55def run(input: Lint.Input) -> IO(List<&2, Lint.Diag>):
56 match input:
57 case Lint.Input{+sources, +options}:
58 do IO<List<&2, Lint.Diag>>:
59 g : Common.Graph <- Lint.fold_facts(~Common.Graph, ~Common.Graph.collect, Common.Graph.empty())
60 p : Common.Prog <- Common.Prog.of(sources, g)
61 return verdict(p, Lint.option_number(options, "max", 10), Common.Scope.of(sources, options))
62
63def main() -> IO(Unit):
64 Lint.serve(run)