Packages
llm_composer
0.20.1
0.20.2
0.20.1
0.20.0
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.2
0.18.1
0.18.0
0.17.1
0.17.0
0.16.2
0.16.1
0.16.0
0.15.0
0.14.2
0.14.1
0.14.0
0.13.1
0.13.0
0.12.3
0.12.2
0.12.0
0.11.2
0.11.1
0.11.0
0.10.0
0.8.0
0.7.0
0.6.0
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.0
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.0
LlmComposer is an Elixir library that facilitates chat interactions with language models, providing tools to handle user messages, generate responses, and execute functions automatically based on model outputs.
Current section
Files
Jump to
Current section
Files
lib/llm_composer/credo_checks/grouped_functions.ex
if Code.ensure_loaded?(Credo.Check) do
defmodule LlmComposer.CredoChecks.GroupedFunctions do
@moduledoc false
use Credo.Check,
base_priority: :normal,
category: :readability,
explanations: [
check: """
Public and private functions must be grouped, not interleaved.
Keep all `def` clauses together and all `defp` clauses together.
"""
]
alias Credo.IssueMeta
alias Credo.SourceFile
@impl Credo.Check
def run(%SourceFile{} = source_file, params) do
issue_meta = IssueMeta.for(source_file, params)
source_file
|> Credo.Code.prewalk(&traverse(&1, &2), [])
|> check_grouping(issue_meta)
end
defp traverse({kind, meta, [head | _]} = ast, acc) when kind in [:def, :defp] do
name = extract_name(head)
visibility = if kind == :def, do: :public, else: :private
{ast, [{visibility, name, meta[:line]} | acc]}
end
defp traverse(ast, acc), do: {ast, acc}
defp extract_name({:when, _, [head | _]}), do: extract_name(head)
defp extract_name({name, _, _}) when is_atom(name), do: name
defp extract_name(_), do: :unknown
defp check_grouping(collected, issue_meta) do
functions =
collected
|> Enum.reverse()
|> Enum.dedup_by(fn {visibility, name, _line} -> {visibility, name} end)
blocks = Enum.chunk_by(functions, fn {visibility, _, _} -> visibility end)
duplicated_visibilities =
blocks
|> Enum.map(fn [{visibility, _, _} | _] -> visibility end)
|> Enum.frequencies()
|> Enum.filter(fn {_visibility, count} -> count > 1 end)
|> Enum.map(fn {visibility, _} -> visibility end)
blocks
|> mark_offending_blocks(duplicated_visibilities)
|> Enum.map(fn {visibility, name, line} ->
build_issue(visibility, name, line, issue_meta)
end)
end
defp mark_offending_blocks(blocks, duplicated_visibilities) do
{offending, _seen} =
Enum.reduce(blocks, {[], MapSet.new()}, fn [{visibility, name, line} | _], {acc, seen} ->
if visibility in duplicated_visibilities and MapSet.member?(seen, visibility) do
{[{visibility, name, line} | acc], seen}
else
{acc, MapSet.put(seen, visibility)}
end
end)
Enum.reverse(offending)
end
defp build_issue(visibility, name, line_no, issue_meta) do
format_issue(
issue_meta,
message:
"#{visibility} function `#{name}` breaks grouping; keep all public and private functions grouped.",
trigger: to_string(name),
line_no: line_no
)
end
end
end