Packages
metastatic
0.4.2
0.26.0
0.25.0
0.24.1
0.24.0
0.23.0
0.22.2
0.22.1
0.22.0
0.21.3
0.21.2
0.21.1
0.21.0
0.20.3
0.20.2
0.20.1
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.2
0.9.1
0.9.0
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.2
0.4.1
0.4.0
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Cross-language code meta-model library using unified MetaAST representation. Parse, transform, and translate code across Python, Elixir, Ruby, Erlang, Haskell, and more via a shared three-tuple AST format.
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/metastatic.purity_check.ex
defmodule Mix.Tasks.Metastatic.PurityCheck do
@moduledoc """
Analyzes code purity for a given file.
## Usage
mix metastatic.purity_check FILE [options]
## Options
* `--format` - Output format: text (default), json, or detailed
* `--language` - Source language: python, elixir, or erlang (auto-detected if not specified)
## Examples
# Basic purity check
mix metastatic.purity_check my_file.py
# JSON output
mix metastatic.purity_check my_file.py --format json
# Detailed report
mix metastatic.purity_check my_file.ex --format detailed
## Exit Codes
* 0 - Pure (no side effects)
* 1 - Impure (has side effects)
* 2 - Error during analysis
"""
@shortdoc "Analyzes code purity"
use Mix.Task
alias Metastatic.Analysis.Purity
alias Metastatic.Analysis.Purity.Formatter
alias Metastatic.Builder
@impl Mix.Task
def run(args) do
{opts, files, _invalid} =
OptionParser.parse(args,
strict: [format: :string, language: :string],
aliases: [f: :format, l: :language]
)
format = parse_format(opts[:format])
language = parse_language(opts[:language])
case files do
[] ->
Mix.shell().error("Error: No file specified")
Mix.shell().info("Usage: mix metastatic.purity_check FILE [options]")
exit({:shutdown, 2})
[file | _] ->
analyze_file(file, language, format)
end
end
defp analyze_file(file, language, format) do
unless File.exists?(file) do
Mix.shell().error("Error: File not found: #{file}")
exit({:shutdown, 2})
end
source = File.read!(file)
lang = language || detect_language(file)
case Builder.from_source(source, lang) do
{:ok, document} ->
case Purity.analyze(document) do
{:ok, result} ->
output = Formatter.format(result, format)
Mix.shell().info(output)
# Exit with appropriate code
if result.pure? do
exit({:shutdown, 0})
else
exit({:shutdown, 1})
end
# {:error, reason} ->
# Mix.shell().error("Analysis error: #{inspect(reason)}")
# exit({:shutdown, 2})
end
{:error, reason} ->
Mix.shell().error("Parse error: #{inspect(reason)}")
exit({:shutdown, 2})
end
end
defp parse_format(nil), do: :text
defp parse_format("text"), do: :text
defp parse_format("json"), do: :json
defp parse_format("detailed"), do: :detailed
defp parse_format(other) do
Mix.shell().error("Unknown format: #{other}")
Mix.shell().info("Valid formats: text, json, detailed")
exit({:shutdown, 2})
end
defp parse_language(nil), do: nil
defp parse_language("python"), do: :python
defp parse_language("elixir"), do: :elixir
defp parse_language("erlang"), do: :erlang
defp parse_language(other) do
Mix.shell().error("Unknown language: #{other}")
Mix.shell().info("Valid languages: python, elixir, erlang")
exit({:shutdown, 2})
end
defp detect_language(file) do
case Path.extname(file) do
".py" ->
:python
".ex" ->
:elixir
".exs" ->
:elixir
".erl" ->
:erlang
".hrl" ->
:erlang
other ->
Mix.shell().error("Cannot detect language from extension: #{other}")
Mix.shell().info("Please specify --language option")
exit({:shutdown, 2})
end
end
end