defmodule Archeometer.Explore.Static do
@moduledoc """
Module for analysing AST and collecting some useful information For now the
schemas are hardcoded. There are
- Modules
- Definitions (functions, macros)
Hopefully in the future a more extendible solution will be in place.
"""
def process_module(full_ast, mod) do
%{
name: Archeometer.Util.Code.resolve_mod_name(full_ast, mod),
num_lines: Archeometer.Util.Code.num_lines(mod)
}
end
def process_def(full_ast, df) do
{type, _meta, _children} = df
with {:ok, {name, _meta, args}} <- Archeometer.Util.Code.get_decl(df) do
{:ok,
%{
name: name,
type: type,
num_lines: Archeometer.Util.Code.num_lines(df),
cc: Credo.Check.Refactor.CyclomaticComplexity.complexity_for(df),
args: args,
module: Archeometer.Util.Code.resolve_mod_name(full_ast, df)
}}
end
end
def module_stats_for(source_files, test_paths) when is_list(source_files),
do: Enum.flat_map(source_files, &module_stats_for(&1, test_paths))
def module_stats_for(source_file, test_paths) do
path = source_file.filename
ast = Credo.SourceFile.ast(source_file)
is_test = Enum.any?(test_paths, &String.starts_with?(path <> "\/", &1))
meta = %{
path: path,
is_test: is_test
}
ast
|> Archeometer.Util.Code.collect_defs(:defmodule)
|> Enum.map(&Map.merge(process_module(ast, &1), meta))
end
def def_stats_for(source_files, defs) when is_list(source_files),
do: Enum.flat_map(source_files, &def_stats_for(&1, defs))
def def_stats_for(source_file, defs) do
ast = Credo.SourceFile.ast(source_file)
ast
|> Archeometer.Util.Code.collect_nodes(defs)
|> Archeometer.Util.Code.collect_defs(defs)
|> Enum.flat_map(fn d ->
case process_def(ast, d) do
{:ok, elem} -> [elem]
{:error, _} -> []
end
end)
end
end