chore: added more @spec
This commit is contained in:
82
test/bds/spec_coverage_test.exs
Normal file
82
test/bds/spec_coverage_test.exs
Normal file
@@ -0,0 +1,82 @@
|
||||
defmodule BDS.SpecCoverageTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
@section_10_files [
|
||||
"lib/bds/tags.ex",
|
||||
"lib/bds/templates.ex",
|
||||
"lib/bds/scripts.ex",
|
||||
"lib/bds/post_links.ex"
|
||||
]
|
||||
|
||||
@section_10_editor_globs [
|
||||
"lib/bds/desktop/shell_live/*editor.ex",
|
||||
"lib/bds/desktop/shell_live/*_editor/*.ex"
|
||||
]
|
||||
|
||||
describe "CODESMELL Section 10" do
|
||||
test "smaller contexts have specs for all public functions" do
|
||||
root = File.cwd!()
|
||||
|
||||
offenders =
|
||||
section_10_files(root)
|
||||
|> Enum.flat_map(fn relative_path ->
|
||||
relative_path
|
||||
|> Path.join("")
|
||||
|> then(&Path.join(root, &1))
|
||||
|> public_functions_without_specs(relative_path)
|
||||
end)
|
||||
|
||||
assert offenders == []
|
||||
end
|
||||
end
|
||||
|
||||
defp section_10_files(root) do
|
||||
editor_files =
|
||||
@section_10_editor_globs
|
||||
|> Enum.flat_map(fn pattern -> Path.wildcard(Path.join(root, pattern)) end)
|
||||
|> Enum.map(&Path.relative_to(&1, root))
|
||||
|
||||
(@section_10_files ++ editor_files)
|
||||
|> Enum.uniq()
|
||||
|> Enum.sort()
|
||||
end
|
||||
|
||||
defp public_functions_without_specs(path, relative_path) do
|
||||
source = File.read!(path)
|
||||
{:ok, ast} = Code.string_to_quoted(source)
|
||||
|
||||
specs = spec_names(source)
|
||||
|
||||
ast
|
||||
|> public_defs()
|
||||
|> Enum.uniq_by(fn {_line, name, arity} -> {name, arity} end)
|
||||
|> Enum.reject(fn {_line, name, _arity} -> MapSet.member?(specs, name) end)
|
||||
|> Enum.map(fn {line, name, arity} -> "#{relative_path}:#{line}:#{name}/#{arity}" end)
|
||||
end
|
||||
|
||||
defp spec_names(source) do
|
||||
~r/^\s*@spec\s+([a-zA-Z_][a-zA-Z0-9_?!]*)\s*\(/m
|
||||
|> Regex.scan(source)
|
||||
|> Enum.map(fn [_match, name] -> String.to_atom(name) end)
|
||||
|> MapSet.new()
|
||||
end
|
||||
|
||||
defp public_defs(ast) do
|
||||
{_ast, defs} =
|
||||
Macro.prewalk(ast, [], fn
|
||||
{:def, meta, [head | _]} = node, acc ->
|
||||
{name, arity} = public_def_name_arity(head)
|
||||
{node, [{Keyword.fetch!(meta, :line), name, arity} | acc]}
|
||||
|
||||
node, acc ->
|
||||
{node, acc}
|
||||
end)
|
||||
|
||||
Enum.reverse(defs)
|
||||
end
|
||||
|
||||
defp public_def_name_arity({:when, _meta, [head | _guards]}), do: public_def_name_arity(head)
|
||||
|
||||
defp public_def_name_arity({name, _meta, args}) when is_atom(name),
|
||||
do: {name, length(args || [])}
|
||||
end
|
||||
Reference in New Issue
Block a user