~/bend-docscommunity

src/rules.bend source

src/rules.bend on the hub · documented module

# src/rules: every rule, and its group. A rule is a module under# rules/<group>/ with `check(src) -> List<Finding>`, run over each file read# once (src/src.bend); a project rule has `check(ds) -> List<Finding>` and# sees every file at once, as the digests of rules/digest.bend. The directory# names the group, and codes.bend says it again for the config.# Adding one is adding it here and a row in codes.bend. One rule is not# listed here, `noqa` (rules/style/noqa.bend): it reads the other rules'# graded findings, so the planner runs it after them (lint/plan.bend).# The groups are what a bolt.bend switches at once: correctness (what will# fail or blow up), suspicious (what is probably a slip), style, laws, and# pedantic (advice that is noisy on idiomatic code: off unless a project# asks for it).import Baseimport ./finding.bend as Fimport ./codes.bend as Codesimport ./src.bend as Srcimport ./rules/digest.bend as Digestimport ./config.bend as Configimport ./rules/style/doc.bend as Docimport ./rules/suspicious/unused.bend as Unusedimport ./rules/correctness/hole.bend as Holeimport ./rules/style/space.bend as Spaceimport ./rules/style/wrap.bend as Wrapimport ./rules/style/param.bend as Paramimport ./rules/correctness/pick.bend as Pickimport ./rules/laws/law.bend as Lawimport ./rules/suspicious/strict.bend as Strictimport ./rules/suspicious/eager.bend as Eagerimport ./rules/pedantic/tail.bend as Tailimport ./rules/suspicious/concat.bend as Concatimport ./rules/suspicious/index.bend as Indeximport ./rules/suspicious/table.bend as Tableimport ./rules/suspicious/hoist.bend as Hoistimport ./rules/suspicious/ring.bend as Ringimport ./rules/suspicious/rewalk.bend as Rewalkimport ./rules/suspicious/unit.bend as Unitimport ./rules/correctness/put.bend as Putimport ./rules/correctness/escape.bend as Escapeimport ./rules/correctness/strings.bend as Stringsimport ./rules/correctness/chars.bend as Charsimport ./rules/correctness/twice.bend as Twiceimport ./rules/correctness/arms.bend as Armsimport ./rules/correctness/foreign.bend as Foreignimport ./rules/suspicious/fuel.bend as Fuelimport ./rules/laws/closed.bend as Closedimport ./rules/laws/trace.bend as Traceimport ./rules/laws/unsafe.bend as Unsafe# the file a Src was read fromdef on.path(ss: Src.Src) -> String:  Src.Src{path, _text, _toks, _tree, _bound, _items} = ss  path# findings put at a path: a per-file rule reports on its own file, so this# keeps what each rule gave and makes it hold by constructiondef on.at(+path: String, fs: List<&2, F.Finding>) -> List<&2, F.Finding>:  match fs:    case Nil{}:      Nil{}    case Con{F.Finding{_path, line, col, len, rule, msg}, rest}:      F.Finding{path, line, col, len, rule, msg} <> on.at(path, rest)# every rule's findings on a file read once, as each rule gives themdef on.rules(+ss: Src.Src) -> List<&2, F.Finding>:  List.concat(&2, F.Finding, [    Doc.check(ss),    Unused.check(ss),    Hole.check(ss),    Space.check(ss),    Wrap.check(ss),    Param.check(ss),    Pick.check(ss),    Strict.check(ss),    Eager.check(ss),    Tail.check(ss),    Concat.check(ss),    Index.check(ss),    Table.check(ss),    Hoist.check(ss),    Ring.check(ss),    Rewalk.check(ss),    Unit.check(ss),    Put.check(ss),    Escape.check(ss),    Strings.check(ss),    Chars.check(ss),    Twice.check(ss),    Arms.check(ss),    Foreign.check(ss),    Fuel.check(ss),    Closed.check(ss)])# every rule's findings on a file read once, each at that filedef on(+ss: Src.Src) -> List<&2, F.Finding>:  on.at(on.path(ss), on.rules(ss))# every rule's findings on a filedef all(+path: String, +text: String) -> List<&2, F.Finding>:  on(Src.of(path, text))# every project rule's findings on the files and SPEC.md's text (None when# there is none): each file is read down to its digest once# (rules/digest.bend), and the rules run over thosedef project(srcs: List<&2, Src.Src>, whole: Bool, spec: Maybe<&2, String>) -> List<&2, F.Finding>:  +ds = Digest.all(srcs)  List.concat(&2, F.Finding, [Law.check(ds), Unsafe.check(ds), Trace.check(whole, spec, ds)])# the group a rule is in; an unknown slug grades with correctnessdef group(+rule: String) -> String:  +named = Codes.group(rule)  Bool.pick(String, String.is_empty(named), "correctness", named)# the findings at the levels a config gives their rules; the ones set off# are droppeddef graded(+cfg: Config.Config, fs: List<&2, F.Finding>) -> List<&2, F.Graded>:  match fs:    case Nil{}:      Nil{}    case Con{F.Finding{path, line, col, len, +rule, msg}, rest}:      +more = graded(cfg, rest)      +l = Config.level(cfg, group(rule), rule)      Bool.pick(List<&2, F.Graded>, Config.is_off(l), more,        F.Graded{l, F.Finding{path, line, col, len, rule, msg}} <> more)