KogenCredo.QuerySupport (KogenCredo v0.1.0)

View Source

Private plumbing shared by the Repo/query warning checks.

It only wraps what every check repeats: file-path scoping from the :included_paths / :excluded_paths params, the parsed AST, Repo receiver options from :repo_names / :repo_modules, and pipe expansion.

Pipe expansion rewrites a |> f(b) to f(a, b) everywhere, so detectors only have to reason about the nested-call form. It is purely syntactic.

Summary

Functions

The way inspect/1 shows the atom with this name ("user_id" is ":user_id"), without creating the atom.

Every def/defp/defmacro/defmacrop clause in the tree.

Rewrites a |> f(b) into f(a, b) throughout the tree.

Parsed AST with pipes expanded, or nil when the file did not parse.

Every {name, arity} a function head defines. A head with default arguments (def f(a, b \\ 1)) also defines the lower arities.

True when the file passes the :included_paths / :excluded_paths globs.

True when the atom from the analysed code is one of the configured names/1.

Splits a file into lexical module scopes: [{module_segments | nil, body}].

Config values as names. Function, field and repo names may be given as atoms or strings in .credo.exs; they are compared with the atoms of the analysed code by name (see listed?/2), so nothing is converted to an atom and a name that the code never mentions simply never matches.

Removes duplicate {line, trigger} entries, keeping order.

Functions

atom_label(name)

@spec atom_label(String.t()) :: String.t()

The way inspect/1 shows the atom with this name ("user_id" is ":user_id"), without creating the atom.

defs(ast)

@spec defs(Macro.t()) :: [Macro.t()]

Every def/defp/defmacro/defmacrop clause in the tree.

expand_pipes(ast)

@spec expand_pipes(Macro.t()) :: Macro.t()

Rewrites a |> f(b) into f(a, b) throughout the tree.

expanded_ast(source_file)

@spec expanded_ast(Credo.SourceFile.t()) :: Macro.t() | nil

Parsed AST with pipes expanded, or nil when the file did not parse.

head_keys(arg1)

@spec head_keys(Macro.t()) :: [{atom(), arity()}]

Every {name, arity} a function head defines. A head with default arguments (def f(a, b \\ 1)) also defines the lower arities.

in_scope?(source_file, params, check)

@spec in_scope?(Credo.SourceFile.t(), keyword(), module()) :: boolean()

True when the file passes the :included_paths / :excluded_paths globs.

listed?(atom, names)

@spec listed?(term(), [String.t()]) :: boolean()

True when the atom from the analysed code is one of the configured names/1.

module_scopes(ast)

@spec module_scopes(Macro.t()) :: [{[atom()] | nil, Macro.t()}]

Splits a file into lexical module scopes: [{module_segments | nil, body}].

Each defmodule with a literal alias name becomes its own scope (nested names are the concatenation of the enclosing names), and its body has nested defmodules cut out, so a function is only ever seen next to the functions of its own module. The first scope, with nil, is the code outside any module. A defmodule whose name is not a literal alias stays inline in the enclosing scope.

names(list)

@spec names([atom() | String.t()]) :: [String.t()]

Config values as names. Function, field and repo names may be given as atoms or strings in .credo.exs; they are compared with the atoms of the analysed code by name (see listed?/2), so nothing is converted to an atom and a name that the code never mentions simply never matches.

repo_opts(params, check)

@spec repo_opts(
  keyword(),
  module()
) :: keyword()

Options for KogenCredo.SafetySupport.repo_receiver?/3 from check params.

uniq_hits(hits)

@spec uniq_hits([{pos_integer(), String.t(), String.t()}]) :: [
  {pos_integer(), String.t(), String.t()}
]

Removes duplicate {line, trigger} entries, keeping order.