bend-lint-api Releases (3): 0.2.0.0 0xd69a1e32f167d67a827d0d362dfcf729 indexed https://jend.leeeet.dev/files.txt?path=bend-lint-api@0.2.0.0 0.1.1.0 0xbf17cd8a773b73dcdd93291552ca53f8 unindexed https://jend.leeeet.dev/files.txt?path=bend-lint-api@0.1.1.0 0.1.0.0 0x2b0a0dcada30f71a8eb4ec2e148b9279 unindexed https://jend.leeeet.dev/files.txt?path=bend-lint-api@0.1.0.0 Definitions (174, 1 to 100 shown): Lint.Quantity (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Quantity) # Program # ======= type Quantity is Data: Erased{} Once{} Many{} Template{} Lint.Span (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Span) # Where something is: its file, and offsets in code points. type Span is Data: Span{path: String, beg: U32, end: U32} Lint.Syntax (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Syntax) # What a syntax node is, as Bend's parser reads it: a declaration, a part of one, a term, or a pattern; with what only # nodes of its kind have: the global name it declares or uses (`target`, as the check names it; an import's is the path # of the file it loads), the binder it declares or a variable uses (numbered per top-level declaration), and its # quantity as written (a `~` parameter's is Template). An import's written path is an ImportPath under it; `import # Base` writes none. A Definition is `unsafe` if Bend's checker trusts its body (`@unsafe def f`, or `def f?`). type Syntax is Data: Import{target: String} ImportPath{} Definition{target: String, unsafe: Bool} Datatype{target: String} Constructor{target: String} … Lint.TypeRef (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=TypeRef) # A type the checker holds: a handle, good in the check it came from. Rules ask about it (show, same, normal). Two types # are the same only over the binders their scopes share: `A` of one def is not `A` of another. type TypeRef is Data: TypeRef{check: U32, handle: U32} Lint.Role (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Role) # What a fact says of its node: the type its term has, or the type its binder declares (a parameter, field, pattern # variable, lambda, forall or let binding). type Role is Data: OfTerm{} OfBinder{} Lint.Fact (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Fact) # What the checker found for a node of the source: what the fact says of it, the quantity (how often the term is # demanded, or the binder's), for a binder of a parameter, lambda, let or case, how often its body uses it (the most of # its checked copies; none for a parameter a match takes apart), and the type. A fact is never wrong, but a node can # have none: a term the checker rewrote into another (a scrutinee used again, a call a template took) is not typed as # itself. A node has one fact per distinct type: pattern compilation can check one term in several branches, under # different refinements. type Fact is Data: Fact{role: Role, quantity: Quantity, used: Maybe<&2, Quantity>, checked: TypeRef} Lint.Node (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node) # A syntax node: what it is, its name as written, where the file writes it (none for what the parser adds), the nodes # under it, in order, and the checker's facts on it, if a rule needs them. An application's nodes are its function, # then its arguments; a block's, its binders, then their values, then the rest of the block. type Node is Data: Node{ syntax: Syntax, name: String, span: Maybe<&2, Span>, kids: List<&2, Node>, facts: List<&2, Fact> } Lint.Source (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Source) # A file the check parsed: its path, its namespace in the check ("" for the checked file), its text, and its nodes: its # imports, then its declarations, each constructor under its type. type Source is Data: Source{path: String, namespace: String, text: String, nodes: List<&2, Node>} Lint.Program (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program) type Program is Data: Program{sources: List<&2, Source>} Lint.Declaration (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declaration) # A name a node declares, and the nodes that use it, in order. type Declaration is Data: Declaration{node: Node, references: List<&2, Node>} Lint.Syntax.target (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Syntax.target) # The global name a node of this kind declares or uses, if any (an import's is the file it loads). def Syntax.target(syntax: Syntax) -> Maybe<&2, String>: Lint.Syntax.used (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Syntax.used) # The global name a node of this kind uses, if it uses one. def Syntax.used(syntax: Syntax) -> Maybe<&2, String>: Lint.Syntax.binder (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Syntax.binder) # The binder a node of this kind declares, or, for a variable, uses. def Syntax.binder(syntax: Syntax) -> Maybe<&2, U32>: Lint.Syntax.declares (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Syntax.declares) # Whether a node of this kind declares a global name (Some{True{}}), a binder of its top-level declaration # (Some{False{}}), or nothing (an import declares an alias, which Declarations below handles). def Syntax.declares(syntax: Syntax) -> Maybe<&2, Bool>: Lint.Node.syntax (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node.syntax) def Node.syntax(node: Node) -> Syntax: Lint.Node.target (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node.target) # "" for a node of a kind that names nothing. def Node.target(node: Node) -> String: Lint.Node.kids (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node.kids) def Node.kids(node: Node) -> List<&2, Node>: Lint.Node.name (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node.name) # "" for no node, as are the next two. def Node.name(node: Maybe<&2, Node>) -> String: Lint.Node.span (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node.span) def Node.span(node: Maybe<&2, Node>) -> Maybe<&2, Span>: Lint.Span.text (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Span.text) def Span.text(source: String, span: Maybe<&2, Span>) -> String: Lint.Name.namespace (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Name.namespace) # The namespace of a global name: what comes before its first ":", or "" for Base and the checked file's own names. def Name.namespace(name: String) -> String: Lint.Node.is_bare (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node.is_bare) # Whether a parameter is written bare (`def f(x)`, filling a law): its quantity is the law's, which its node does not # give. def Node.is_bare(node: Node) -> Bool: Lint.Node.scrutinees.go (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node.scrutinees.go) def Node.scrutinees.go(nodes: List<&2, Node>, out: List<&2, Node>) -> List<&2, Node>: Lint.Node.scrutinees (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node.scrutinees) # The scrutinees of a match, in order: its nodes before its first case. def Node.scrutinees(node: Node) -> List<&2, Node>: Lint.Node.bound (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Node.bound) # The binders of the pattern variables in `nodes`, patterns, and under them, onto `out`. def Node.bound(nodes: List<&2, Node>, out: List<&2, U32>) -> List<&2, U32>: Lint.Above (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Above) # A node above another: the node, and the place among its nodes (from 0) of the one on the way down. type Above is Data: Above{node: Node, at: U32} Lint.Above.of (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Above.of) def Above.of(parent: Maybe<&2, Node>, at: U32, up: List<&2, Above>) -> List<&2, Above>: Lint.visit.go (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=visit.go) def visit.go( ~C: Data, ~A: Data, ~f: @+c: C -> @+path: List<&2, Above> -> @+node: Node -> List<&2, A>, nodes: List<&2, Node>, +c: C, +up: List<&2, Above>, +parent: Maybe<&2, Node>, +at: U32, out: List<&2, A> ) -> List<&2, A>: Lint.visit (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=visit) # `f(c, path, node)` for each node of `nodes` and under them, parents first, in order: `path` holds the nodes above the # node, innermost first. def visit( ~C: Data, ~A: Data, ~f: @+c: C -> @+path: List<&2, Above> -> @+node: Node -> List<&2, A>, c: C, nodes: List<&2, Node> ) -> List<&2, A>: Lint.fold (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=fold) # `f(c, node, s)` for each node of `nodes` and under them, parents first, in order, from `s`. def fold( ~C: Data, ~S: Data, ~f: @+c: C -> @+node: Node -> S -> S, +c: C, nodes: List<&2, Node>, s: S ) -> S: Lint.top (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=top) # The top-level declaration a node is in: the outermost node above it, or the node itself. def top(path: List<&2, Above>, node: Node) -> Node: Lint.calls (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=calls) def calls(called: String, owner: Node) -> Bool: Lint.is_recursive (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=is_recursive) # Whether a node is an application of the definition it is in, below `path`: a step of a loop, as Bend repeats work by # recursion. def is_recursive(path: List<&2, Above>, +node: Node) -> Bool: Lint.is_pair (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=is_pair) # Whether an application's function is Pair: it builds a pair type (`A & B`), whose parts are types. def is_pair(kids: List<&2, Node>) -> Bool: Lint.is_live.go (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=is_live.go) def is_live.go(path: List<&2, Above>, ok: Bool) -> Bool: Lint.is_live (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=is_live) # Whether a node below `path` is in live code: a definition's body, outside types: an annotation's type, an equality, a # function or pair type, a type's arguments. Types and equations are dead: the checker sees them, the program does not # run them. def is_live(path: List<&2, Above>) -> Bool: Lint.definitions (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=definitions) # The definitions of `nodes`, by the name the check gives them: read one with `Names.find`. Of two with one name, the # later is kept. def definitions(nodes: List<&2, Node>, out: Map<&2, Maybe<&2, Node>>) -> Map<&2, Maybe<&2, Node>>: Lint.parameter.go (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=parameter.go) def parameter.go( nodes: List<&2, Node>, found: Maybe<&2, Nat>, +binder: U32, +at: Nat ) -> Maybe<&2, Nat>: Lint.parameter (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=parameter) # Where the parameter that declares `binder` is among `nodes`, a definition's, counting from 0. def parameter(nodes: List<&2, Node>, binder: U32) -> Maybe<&2, Nat>: Lint.Severity (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Severity) # Rules # ===== type Severity is Data: Error{} Warning{} Information{} Hint{} Lint.Severity.show (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Severity.show) def Severity.show(s: Severity) -> String: Lint.Severity.names (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Severity.names) def Severity.names() -> List<&2, Names.Named>: Lint.Operation (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Operation) # An edit a fix asks for: replace a span's text; rename what the declaration written at `at` declares, with each of its # uses; or rename only its uses, to point them at a name the program declares already (to drop a duplicate import, # say). A rename changes an import's alias, the first part of each use (`U` of `U.two`), and any other name's last part. # The linter finds the uses, and drops the fix if the text does not write the name where one of them is. It drops a # Rename of a global name (a def, type, constructor or law), as files the check did not read can use it, and one whose # new name is taken where the declaration is. type Operation is Data: Replace{span: Span, text: String} Rename{at: Span, to: String} RenameUses{at: Span, to: String} Lint.Fix (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Fix) # A way to fix a finding: what it does, and its operations, in any of the program's own files (not Base, nor a hub # package). type Fix is Data: Fix{title: String, operations: List<&2, Operation>} Lint.Finding (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Finding) type Finding is Data: Finding{severity: Severity, span: Span, message: String, fixes: List<&2, Fix>} Lint.Found (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Found) type Found is Data: Found{rule: String, finding: Finding} Lint.finding (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=finding) # A finding at `span`, if `hit` and `span` is known. def finding( severity: Severity, hit: Bool, span: Maybe<&2, Span>, text: String ) -> List<&2, Finding>: Lint.Value (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Value) # Options # ======= type Value is Data: Num{n: U32} Flag{on: Bool} Chars{text: String} Lint.Spec (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Spec) # What an option accepts: a whole number in a range, a flag, text (one of `choices`, unless there are none), or what # one of `specs` accepts. type Spec is Data: NumberOption{min: U32, max: U32} FlagOption{} TextOption{choices: List<&2, String>} AnyOption{specs: List<&2, Spec>} Lint.Declared (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declared) # An option a rule declares: its name, its value when the config gives none, and what it accepts. The config gives # values as `"rule/id": {"name": value}`; a name the rule does not declare, or a value it does not accept, is an error. type Declared is Data: Declared{name: String, default: Value, spec: Spec} Lint.Value.number (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Value.number) # An option's value as a number, a flag or text; a value of another kind, or none, gives 0, False, "". def Value.number(value: Maybe<&2, Value>) -> U32: Lint.Value.flag (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Value.flag) def Value.flag(value: Maybe<&2, Value>) -> Bool: Lint.Value.text (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Value.text) def Value.text(value: Maybe<&2, Value>) -> String: Lint.Imported (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Imported) # What uses a file's imports: the nodes written with an alias's prefix (`U.two`, a fill `def U.law(x):`), by alias; and # those that use Base: a global name with no namespace that the file does not declare (last first). type Imported is Data: Imported{aliases: Map<&2, List<&2, Node>>, base: List<&2, Node>} Lint.Uses (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Uses) # What the declarations of a top-level declaration are read with: the program's files (one of them is what an import # loads), the uses of global names in the files the declarations are read in, by name, the uses of the declaration's # binders, by binder (each last first), and what uses its file's imports. type Uses is Data: Uses{ sources: List<&2, Source>, globals: Map<&2, List<&2, Node>>, binders: Tables.Table>, imported: Imported } Lint.Uses.global.add (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Uses.global.add) def Uses.global.add( used: Maybe<&2, String>, node: Node, m: Map<&2, List<&2, Node>> ) -> Map<&2, List<&2, Node>>: Lint.Uses.global (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Uses.global) def Uses.global(+u: Unit, +node: Node, m: Map<&2, List<&2, Node>>) -> Map<&2, List<&2, Node>>: Lint.Uses.binder.add (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Uses.binder.add) def Uses.binder.add( +t: Tables.Table>, +b: U32, node: Node ) -> Tables.Table>: Lint.Uses.binder (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Uses.binder) def Uses.binder( +u: Unit, +node: Node, t: Tables.Table> ) -> Tables.Table>: Lint.Imported.own.add (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Imported.own.add) def Imported.own.add(target: Maybe<&2, String>, out: Set()) -> Set(): Lint.Imported.own (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Imported.own) # The global names a file's own top-level declarations declare, as a set. def Imported.own(nodes: List<&2, Node>, out: Set()) -> Set(): Lint.Imported.is_base (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Imported.is_base) def Imported.is_base(own: Set(), used: Maybe<&2, String>) -> Bool: Lint.Imported.alias (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Imported.alias) def Imported.alias( prefix: String, node: Node, aliases: Map<&2, List<&2, Node>> ) -> Map<&2, List<&2, Node>>: Lint.Imported.add (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Imported.add) def Imported.add(+own: Set(), +node: Node, uses: Imported) -> Imported: Lint.Imported.of (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Imported.of) def Imported.of(+nodes: List<&2, Node>) -> Imported: Lint.Declarations.namespace (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.namespace) # The namespace of the file at `path`, as the check names it (`found`, once found): "" for Base, or a file the check # did not parse. def Declarations.namespace( sources: List<&2, Source>, +path: String, found: Maybe<&2, String> ) -> String: Lint.Declarations.imported (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.imported) # The uses of an import, in order: of Base (`base`), or of its alias. def Declarations.imported(base: Bool, alias: String, imported: Imported) -> List<&2, Node>: Lint.Declarations.bound (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.bound) def Declarations.bound( binder: Maybe<&2, U32>, binders: Tables.Table> ) -> List<&2, Node>: Lint.Declarations.declared (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.declared) def Declarations.declared( declares: Maybe<&2, Bool>, +node: Node, uses: Uses ) -> List<&2, Declaration>: Lint.Declarations.node (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.node) # A node's declaration, if it declares a name, with its uses, onto `out`. def Declarations.node( +uses: Uses, +node: Node, out: List<&2, Declaration> ) -> List<&2, Declaration>: Lint.Declarations.tops (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.tops) def Declarations.tops( nodes: List<&2, Node>, +sources: List<&2, Source>, +globals: Map<&2, List<&2, Node>>, +imported: Imported, out: List<&2, Declaration> ) -> List<&2, Declaration>: Lint.Declarations.files (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.files) def Declarations.files( files: List<&2, Source>, +sources: List<&2, Source>, +globals: Map<&2, List<&2, Node>>, out: List<&2, Declaration> ) -> List<&2, Declaration>: Lint.Declarations.globals (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.globals) def Declarations.globals( files: List<&2, Source>, m: Map<&2, List<&2, Node>> ) -> Map<&2, List<&2, Node>>: Lint.Declarations.of (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.of) # The declarations of `files`, in order, with their uses in `files`; `sources` are the program's files. def Declarations.of(+files: List<&2, Source>, sources: List<&2, Source>) -> List<&2, Declaration>: Lint.Declarations.when (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Declarations.when) def Declarations.when( declare: Bool, files: List<&2, Source>, sources: List<&2, Source> ) -> List<&2, Declaration>: Lint.Source.is_own (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Source.is_own) def Source.is_own(source: Source) -> Bool: Lint.Program.own (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program.own) # The program's own files: not hub packages. def Program.own(sources: List<&2, Source>) -> List<&2, Source>: Lint.Param (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Param) # A runtime parameter of a definition: its name, and its type as one name ("" if it is not one name). type Param is Data: Param{name: String, ty: String} Lint.Def (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Def) # A definition of the program: its name as the check names it, its runtime parameters, whether it forks, the # definitions it calls by name, and the type it returns, as one name ("" if it is not one name). type Def is Data: Def{ target: String, params: List<&2, Param>, forks: Bool, calls: List<&2, String>, returns: String } Lint.type_name (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=type_name) # The type the first of `nodes` writes, as one name, or "" for another form (an application, a list). def type_name(nodes: List<&2, Node>) -> String: Lint.Quantity.is_runtime (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Quantity.is_runtime) # Whether a parameter of this quantity is there at run time. def Quantity.is_runtime(quantity: Quantity) -> Bool: Lint.Def.params (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Def.params) # The runtime parameters among a definition's nodes, in order, onto `out`. def Def.params(nodes: List<&2, Node>, out: List<&2, Param>) -> List<&2, Param>: Lint.forks (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=forks) # Whether a parallel let (two binders, at least) is among `nodes` or under them, or `found`. def forks(nodes: List<&2, Node>, found: Bool) -> Bool: Lint.Def.called.visit (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Def.called.visit) # The definition an application below `path` calls by name. def Def.called.visit(+u: Unit, +path: List<&2, Above>, +node: Node) -> List<&2, String>: Lint.Def.returned (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Def.returned) # The type a definition's nodes say it returns, as one name, or "". def Def.returned(nodes: List<&2, Node>) -> String: Lint.Def.forks (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Def.forks) def Def.forks(info: Maybe<&2, Def>) -> Bool: Lint.Program.defs.file (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program.defs.file) # The definitions among a file's nodes, by the name the check gives them, onto `out`. def Program.defs.file( nodes: List<&2, Node>, out: Map<&2, Maybe<&2, Def>> ) -> Map<&2, Maybe<&2, Def>>: Lint.Program.defs (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program.defs) # The definitions of the program's files, by the name the check gives them, onto `out`: read one with `Names.find`. def Program.defs( sources: List<&2, Source>, out: Map<&2, Maybe<&2, Def>> ) -> Map<&2, Maybe<&2, Def>>: Lint.Program.callers.if (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program.callers.if) def Program.callers.if(found: Bool, t: String, callers: Set()) -> Set(): Lint.Program.callers.step (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program.callers.step) # `callers` with the definition `info`, if it calls one of them. def Program.callers.step(info: Maybe<&2, Def>, +callers: Set()) -> Set(): Lint.Program.callers.file (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program.callers.file) # `callers` after a step for each definition among a file's nodes, in order. def Program.callers.file( nodes: List<&2, Node>, +defs: Map<&2, Maybe<&2, Def>>, callers: Set() ) -> Set(): Lint.Program.callers.pass (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program.callers.pass) def Program.callers.pass( sources: List<&2, Source>, +defs: Map<&2, Maybe<&2, Def>>, callers: Set() ) -> Set(): Lint.Program.callers.go (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program.callers.go) # Passes over the program until one adds nothing (`same`), or `fuel` runs out. def Program.callers.go( fuel: Nat, same: Bool, +sources: List<&2, Source>, +defs: Map<&2, Maybe<&2, Def>>, +callers: Set() ) -> Set(): Lint.Program.callers (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Program.callers) # `seeds`, and the definitions of the program (`defs`, of `sources`) that call one of them, directly or through others. # A definition calls only those above it, unless it is @unsafe, and the check gives a file's imports before it, so the # first pass, in order, finds nearly all. Each pass but the last adds one at least, so as many passes as there are # definitions find them all. def Program.callers( sources: List<&2, Source>, +defs: Map<&2, Maybe<&2, Def>>, seeds: Set() ) -> Set(): Lint.Here (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Here) # What a file rule sees: the program, from one of its files; that file's declarations, with their uses in it, if a rule # needs them; and the rule's options, each declared one with its value. type Here is Data: Here{ program: Program, source: Source, declarations: List<&2, Declaration>, options: List<&2, Names.Named> } Lint.Whole (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Whole) # What a program rule sees: the program (its files, hub packages aside); every declaration of its files, with their # uses in all of them, if a rule needs them; and the rule's options. type Whole is Data: Whole{ program: Program, declarations: List<&2, Declaration>, options: List<&2, Names.Named> } Lint.Here.of (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Here.of) # The program from one of its files, built once for every file rule that runs on that file: its declarations, if a rule # needs them (`declare`). The runner gives each rule its options. def Here.of(program: Program, +source: Source, declare: Bool) -> Here: Lint.Whole.of (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Whole.of) # The whole program, built once for every program rule: the declarations of its own files, if a rule needs them # (`declare`). def Whole.of(program: Program, declare: Bool) -> Whole: Lint.Here.path (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Here.path) def Here.path(here: Here) -> String: Lint.Here.namespace (https://jend.leeeet.dev/definition.txt?path=bend-lint-api@0.2.0.0/linter/lint.bend&name=Here.namespace) # "" for the checked file. def Here.namespace(here: Here) -> String: More: https://jend.leeeet.dev/packages/bend-lint-api.txt?definitions_offset=100