Dialyzer Integration
Integrating Dialyzer into development workflow and CI/CD pipelines.
Local Development
Initial Setup
Install dialyxir
mix deps.get
Build initial PLT (takes time first run)
mix dialyzer --plt
Run analysis
mix dialyzer
Incremental Analysis
Only analyze changed files
mix dialyzer --incremental
Force rebuild PLT
mix dialyzer --clean
CI/CD Integration
GitHub Actions
name: Dialyzer user-invocable: false
on: [push, pull_request]
jobs: dialyzer: runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Elixir
uses: erlef/setup-beam@v1
with:
elixir-version: '1.15'
otp-version: '26'
- name: Restore dependencies cache
uses: actions/cache@v3
with:
path: deps
key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }}
- name: Restore PLT cache
uses: actions/cache@v3
id: plt-cache
with:
path: priv/plts
key: ${{ runner.os }}-plt-${{ hashFiles('**/mix.lock') }}
- name: Install dependencies
run: mix deps.get
- name: Create PLTs
if: steps.plt-cache.outputs.cache-hit != 'true'
run: mix dialyzer --plt
- name: Run Dialyzer
run: mix dialyzer --format github
GitLab CI
dialyzer: stage: test script: - mix local.hex --force - mix local.rebar --force - mix deps.get - mix dialyzer cache: paths: - _build/ - deps/ - priv/plts/
IDE Integration
VS Code (ElixirLS)
{ "elixirLS.dialyzerEnabled": true, "elixirLS.dialyzerFormat": "dialyxir_long", "elixirLS.dialyzerWarnOpts": [ "error_handling", "underspecs", "unmatched_returns" ] }
Vim/Neovim (coc-elixir)
{ "elixir.dialyzer.enabled": true }
Pre-commit Hooks
Using Husky/Lefthook
lefthook.yml
pre-commit: commands: dialyzer: glob: "*.ex" run: mix dialyzer --incremental
Git Hook Script
#!/bin/sh
.git/hooks/pre-commit
echo "Running Dialyzer..." mix dialyzer --incremental --quiet
if [ $? -ne 0 ]; then echo "Dialyzer found issues. Commit aborted." exit 1 fi
Team Workflow
Shared PLT Strategy
mix.exs
def project do [ dialyzer: [ plt_core_path: "priv/plts", plt_local_path: "priv/plts", plt_add_apps: [:mix, :ex_unit], # Shared across team via git plt_file: {:no_warn, "priv/plts/project.plt"} ] ] end
Baseline Approach
Generate baseline
mix dialyzer > dialyzer_baseline.txt
Check for new warnings
mix dialyzer | diff - dialyzer_baseline.txt
Performance Optimization
Parallel Analysis
def project do [ dialyzer: [ flags: [:error_handling], # Use multiple cores plt_add_deps: :app_tree ] ] end
Selective Analysis
Only check specific paths
mix dialyzer lib/critical/ test/important_test.exs
Incremental Mode
Much faster after initial run
mix dialyzer --incremental
Monitoring and Reporting
Custom Formatter
lib/custom_dialyzer_formatter.ex
defmodule CustomDialyzerFormatter do def format(warnings) do warnings |> Enum.map(&format_warning/1) |> Enum.join("\n") end
defp format_warning(warning) do # Custom formatting logic end end
Metrics Collection
Count warnings over time
mix dialyzer | grep -c "warning:" >> dialyzer_metrics.log
Troubleshooting
PLT Issues
Remove and rebuild
rm -rf _build/dev/.plt priv/plts/.plt mix dialyzer --plt
Memory Issues
Increase VM memory
elixir --erl "+hms 4096" -S mix dialyzer
Slow Analysis
Use incremental mode
mix dialyzer --incremental
Or analyze subset
mix dialyzer lib/core/