Packages
ex_check_ng
1.0.0-rc.2
One task to efficiently run all code analysis & testing tools in an Elixir project. Community-maintained fork of ex_check.
Current section
Files
Jump to
Current section
Files
lib/ex_check/diagnostics/credo.ex
defmodule ExCheck.Diagnostics.Credo do
@moduledoc false
# Parses Credo's default output format: an issue headline (`[R] ↘ message`) followed
# on the next line by a `file.ex:line:col` location. Walked statefully because the two
# halves live on separate lines. A custom `--format` in the user's config yields `[]`.
@behaviour ExCheck.Diagnostics
alias ExCheck.Diagnostics.Diagnostic
@issue ~r/\[([RCWFDE])\]\s+\S\s+(.+?)\s*$/u
@location ~r/([^\s#]+\.exs?):(\d+)(?::(\d+))?/
@impl true
def parse(text) do
text
|> String.split("\n")
|> Enum.reduce({[], nil}, &walk/2)
|> elem(0)
|> Enum.reverse()
end
defp walk(line, {acc, pending}) do
case Regex.run(@issue, line) do
[_, category, message] ->
{acc, {severity(category), message}}
nil ->
case pending && Regex.run(@location, line) do
loc when is_list(loc) -> {[emit(loc, pending) | acc], nil}
_ -> {acc, pending}
end
end
end
defp emit(loc, {severity, message}) do
{file, line, column} = parse_loc(loc)
%Diagnostic{file: file, line: line, column: column, message: message, severity: severity}
end
defp parse_loc([_, file, line]), do: {file, to_int(line), nil}
defp parse_loc([_, file, line, ""]), do: {file, to_int(line), nil}
defp parse_loc([_, file, line, column]), do: {file, to_int(line), to_int(column)}
defp severity("W"), do: :warning
defp severity(_), do: :error
defp to_int(str) do
case Integer.parse(str) do
{int, _} -> int
:error -> nil
end
end
end