Packages

Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.

Current section

Files

Jump to
raxol lib mix tasks raxol.dialyzer.ex.disabled
Raw

lib/mix/tasks/raxol.dialyzer.ex.disabled

defmodule Mix.Tasks.Raxol.Dialyzer do
@moduledoc """
Comprehensive Dialyzer tasks for the Raxol project with PLT caching.
This module provides enhanced Dialyzer functionality with intelligent PLT
management, performance tracking, and detailed reporting.
## Available Commands
- `mix raxol.dialyzer` - Run full Dialyzer analysis with caching
- `mix raxol.dialyzer --setup` - Build PLT files from scratch
- `mix raxol.dialyzer --check` - Quick check against existing PLT
- `mix raxol.dialyzer --clean` - Clean all PLT files and caches
- `mix raxol.dialyzer --stats` - Show PLT and analysis statistics
- `mix raxol.dialyzer --profile` - Run with performance profiling
## PLT Caching Strategy
The task uses a two-tier PLT caching system:
- Core PLT: Contains Erlang/OTP and stable dependencies
- Local PLT: Contains project-specific modules and volatile dependencies
This approach minimizes rebuild times while ensuring analysis accuracy.
"""
use Mix.Task
@shortdoc "Enhanced Dialyzer analysis with PLT caching for Raxol"
@switches [
setup: :boolean,
check: :boolean,
clean: :boolean,
stats: :boolean,
profile: :boolean,
format: :string,
verbose: :boolean
]
def run(args) do
{opts, _args, _} = OptionParser.parse(args, switches: @switches)
ensure_plt_directory()
cond do
opts[:setup] -> setup_plt()
opts[:check] -> quick_check()
opts[:clean] -> clean_plt()
opts[:stats] -> show_stats()
opts[:profile] -> run_with_profiling()
true -> run_analysis(opts)
end
end
defp ensure_plt_directory do
File.mkdir_p!("priv/plts")
end
defp setup_plt do
info("๐Ÿ”ง Setting up Dialyzer PLT files...")
start_time = System.monotonic_time(:millisecond)
# Clean existing PLTs
clean_plt_files()
# Build core PLT
info("๐Ÿ“ฆ Building core PLT (Erlang/OTP + stable deps)...")
case Mix.shell().cmd("mix dialyzer --plt") do
0 ->
info("โœ… Core PLT built successfully")
_ ->
error("โŒ Failed to build core PLT")
exit({:shutdown, 1})
end
elapsed = System.monotonic_time(:millisecond) - start_time
info("๐ŸŽฏ PLT setup completed in #{elapsed}ms")
show_plt_info()
end
defp quick_check do
info("โšก Running quick Dialyzer check...")
unless plt_exists?() do
info("โš ๏ธ PLT files not found. Building...")
setup_plt()
end
start_time = System.monotonic_time(:millisecond)
case Mix.shell().cmd("mix dialyzer --format short") do
0 ->
elapsed = System.monotonic_time(:millisecond) - start_time
info("โœ… No issues found (#{elapsed}ms)")
_ ->
error("โŒ Issues detected - run 'mix raxol.dialyzer' for full analysis")
exit({:shutdown, 1})
end
end
defp run_analysis(opts) do
info("๐Ÿ” Running comprehensive Dialyzer analysis...")
unless plt_exists?() do
info("๐Ÿ”ง PLT files not found. Setting up...")
setup_plt()
end
format = opts[:format] || "dialyxir"
verbose_flag = if opts[:verbose], do: " --verbose", else: ""
start_time = System.monotonic_time(:millisecond)
case Mix.shell().cmd("mix dialyzer --format #{format}#{verbose_flag}") do
0 ->
elapsed = System.monotonic_time(:millisecond) - start_time
info("โœ… Analysis completed successfully (#{elapsed}ms)")
show_analysis_summary()
_ ->
error("โŒ Analysis found issues")
info(
"๐Ÿ’ก Tip: Check .dialyzer_ignore.exs to filter known false positives"
)
exit({:shutdown, 1})
end
end
defp run_with_profiling do
info("๐Ÿ“Š Running Dialyzer with performance profiling...")
# Ensure PLT exists
unless plt_exists?() do
setup_plt()
end
start_time = System.monotonic_time(:millisecond)
memory_before = :erlang.memory(:total)
case Mix.shell().cmd("mix dialyzer --format dialyxir") do
0 ->
elapsed = System.monotonic_time(:millisecond) - start_time
memory_after = :erlang.memory(:total)
# MB
memory_used = (memory_after - memory_before) / 1_048_576
info("๐Ÿ“ˆ Performance Profile:")
info(" โฑ๏ธ Time: #{elapsed}ms")
info(" ๐Ÿง  Memory: #{Float.round(memory_used, 2)}MB")
show_plt_info()
_ ->
error("โŒ Analysis failed during profiling")
exit({:shutdown, 1})
end
end
defp clean_plt do
info("๐Ÿงน Cleaning Dialyzer PLT files...")
clean_plt_files()
info("โœ… PLT files cleaned")
end
defp show_stats do
info("๐Ÿ“Š Dialyzer PLT Statistics")
info("=" <> String.duplicate("=", 40))
show_plt_info()
show_config_info()
show_analysis_summary()
end
defp clean_plt_files do
plt_files = Path.wildcard("priv/plts/*.plt")
hash_files = Path.wildcard("priv/plts/*.plt.hash")
(plt_files ++ hash_files)
|> Enum.each(&File.rm/1)
end
defp plt_exists? do
File.exists?("priv/plts/core.plt") ||
File.exists?("priv/plts/local.plt") ||
File.exists?(
"_build/#{Mix.env()}/dialyxir_erlang-#{System.otp_release()}_elixir-#{System.version()}.plt"
)
end
defp show_plt_info do
plt_files = Path.wildcard("priv/plts/*.plt")
if Enum.empty?(plt_files) do
info("๐Ÿ“ PLT Status: No PLT files found")
else
info("๐Ÿ“ PLT Status:")
plt_files
|> Enum.each(fn file ->
stat = File.stat!(file)
# MB
size = Float.round(stat.size / 1_048_576, 2)
mtime = Calendar.strftime(stat.mtime, "%Y-%m-%d %H:%M:%S")
info(" ๐Ÿ“„ #{Path.basename(file)}: #{size}MB (#{mtime})")
end)
end
end
defp show_config_info do
config = Mix.Project.config()[:dialyzer] || []
info("โš™๏ธ Configuration:")
info(" ๐Ÿ“ฆ PLT Apps: #{inspect(config[:plt_add_apps] || [])}")
info(" ๐Ÿšฉ Flags: #{inspect(config[:flags] || [])}")
info(" ๐Ÿ™ˆ Ignore File: #{config[:ignore_warnings] || "none"}")
end
defp show_analysis_summary do
ignore_file = ".dialyzer_ignore.exs"
if File.exists?(ignore_file) do
content = File.read!(ignore_file)
ignore_count =
content |> String.split("\n") |> Enum.count(&(&1 =~ ~r/^\s*~r/))
info("๐Ÿ“‹ Analysis Summary:")
info(" ๐Ÿ”‡ Ignore patterns: #{ignore_count}")
info(" ๐Ÿ“ Ignore file: #{ignore_file}")
end
end
defp info(message), do: Mix.shell().info(message)
defp error(message), do: Mix.shell().error(message)
end