use anyhow::Result;
use super::{
add, commands, handle_actor_observe_command, handle_bench_command, handle_coverage_command,
handle_dataflow_debug_command, handle_doc_command, handle_mcp_command, handle_notebook_command,
handle_optimize_command, handle_prove_command, handle_replay_to_tests_command,
handle_serve_command, handle_wasm_command,
};
pub fn derive_quality_gate_flags(
fail_fast: bool,
verbose: bool,
format: &str,
) -> (bool, bool, bool) {
(fail_fast, !verbose, format == "json")
}
pub fn derive_fmt_write_flag(check: bool, stdout: bool) -> bool {
!check && !stdout
}
pub fn derive_coverage_threshold(threshold: Option<f64>) -> f64 {
threshold.unwrap_or(80.0)
}
pub fn derive_color_flag(no_color: bool) -> bool {
!no_color
}
pub fn validate_lint_args(file: Option<&String>, init_config: bool) -> Result<(), &'static str> {
if init_config || file.is_some() {
Ok(())
} else {
Err("Error: Either provide a file or use --all flag")
}
}
pub fn handle_complex_command(command: crate::Commands) -> Result<()> {
match command {
cmd @ (crate::Commands::Ast { .. }
| crate::Commands::Provability { .. }
| crate::Commands::Runtime { .. }
| crate::Commands::Score { .. }
| crate::Commands::QualityGate { .. }
| crate::Commands::Fmt { .. }
| crate::Commands::Lint { .. }
| crate::Commands::Coverage { .. }) => dispatch_analysis(cmd),
cmd => dispatch_tooling(cmd),
}
}
fn dispatch_analysis(command: crate::Commands) -> Result<()> {
match command {
crate::Commands::Ast {
file,
json,
graph,
metrics,
symbols,
deps,
verbose,
output,
} => commands::handle_ast_command(
&file,
json,
graph,
metrics,
symbols,
deps,
verbose,
output.as_deref(),
),
crate::Commands::Provability {
file,
verify,
contracts,
invariants,
termination,
bounds,
verbose,
output,
} => commands::handle_provability_command(
&file,
verify,
contracts,
invariants,
termination,
bounds,
verbose,
output.as_deref(),
),
crate::Commands::Runtime {
file,
profile,
binary,
iterations,
bigo,
bench,
compare,
memory,
verbose,
output,
} => commands::handle_runtime_command(
&file,
profile,
binary,
iterations,
bigo,
bench,
compare.as_deref(),
memory,
verbose,
output.as_deref(),
),
crate::Commands::Score {
path,
depth,
fast,
deep,
watch,
explain,
baseline,
min,
config,
format,
verbose,
output,
} => commands::handle_score_command(
&path,
&depth,
fast,
deep,
watch,
explain,
baseline.as_deref(),
min,
config.as_deref(),
&format,
verbose,
output.as_deref(),
),
crate::Commands::QualityGate {
path,
config,
depth: _,
fail_fast,
format,
export,
ci: _,
verbose,
} => {
let (strict, quiet, json) = derive_quality_gate_flags(fail_fast, verbose, &format);
commands::handle_quality_gate_command(
&path,
config.as_deref(),
strict,
quiet,
json,
verbose,
None,
export.as_deref(),
)
}
crate::Commands::Fmt {
file,
all,
check,
stdout,
diff,
config,
line_width: _,
indent: _,
use_tabs: _,
} => {
let write = derive_fmt_write_flag(check, stdout);
commands::handle_fmt_command(
&file,
check,
write,
config.as_deref(),
all,
diff,
stdout,
false,
)
}
crate::Commands::Lint {
file,
all: _,
fix,
strict,
verbose,
format,
rules,
deny_warnings: _,
max_complexity: _,
config,
init_config,
} => {
if init_config {
println!("Creating default lint configuration...");
Ok(())
} else if let Some(file_path) = file {
commands::handle_lint_command(
&file_path,
fix,
strict,
rules.as_deref(),
format == "json",
verbose,
None, config.as_deref(),
)
} else {
Err(anyhow::anyhow!(
"Error: Either provide a file or use --all flag"
))
}
}
crate::Commands::Prove {
file,
backend,
ml_suggestions,
timeout,
script,
export,
check,
counterexample,
verbose,
format,
} => handle_prove_command(
file.as_deref(),
&backend,
ml_suggestions,
timeout,
script.as_deref(),
export.as_deref(),
check,
counterexample,
verbose,
&format,
),
crate::Commands::Coverage {
path,
threshold,
format,
verbose,
} => handle_coverage_command(
&path,
derive_coverage_threshold(threshold),
&format,
verbose,
),
_ => unreachable!("dispatch_analysis called with non-analysis command"),
}
}
fn dispatch_tooling(command: crate::Commands) -> Result<()> {
match command {
crate::Commands::Notebook {
file,
port,
open,
host,
} => handle_notebook_command(file.as_deref(), port, open, &host),
crate::Commands::Serve {
directory,
port,
host,
verbose,
watch,
debounce,
pid_file,
watch_wasm,
} => handle_serve_command(
&directory,
port,
&host,
verbose,
watch,
debounce,
pid_file.as_deref(),
watch_wasm,
),
crate::Commands::ReplayToTests {
input,
output,
property_tests,
benchmarks,
timeout,
} => handle_replay_to_tests_command(
&input,
output.as_deref(),
property_tests,
benchmarks,
timeout,
),
crate::Commands::Wasm {
file,
output,
target,
wit,
deploy,
deploy_target,
portability,
opt_level,
debug,
simd,
threads,
component_model,
name,
version,
verbose,
} => handle_wasm_command(
&file,
output.as_deref(),
&target,
wit,
deploy,
deploy_target.as_deref(),
portability,
&opt_level,
debug,
simd,
threads,
component_model,
name.as_deref(),
&version,
verbose,
),
crate::Commands::Mcp {
name,
streaming,
timeout,
min_score,
max_complexity,
verbose,
config,
} => handle_mcp_command(
&name,
streaming,
timeout,
min_score,
max_complexity,
verbose,
config.as_deref(),
),
crate::Commands::Add {
package,
version,
dev,
registry: _registry,
} => {
add::handle_add_command(&package, version.as_deref(), dev, false)
}
crate::Commands::Bench {
file,
iterations,
warmup,
format,
output,
verbose,
} => handle_bench_command(
&file,
iterations,
warmup,
&format,
output.as_deref(),
verbose,
),
crate::Commands::Doc {
path,
output,
format,
private,
open,
all,
verbose,
} => handle_doc_command(&path, &output, &format, private, open, all, verbose),
crate::Commands::Optimize {
file,
hardware,
depth,
cache,
branches,
vectorization,
abstractions,
benchmark,
format,
output,
verbose,
threshold,
} => handle_optimize_command(
&file,
&hardware,
&depth,
cache,
branches,
vectorization,
abstractions,
benchmark,
&format,
output.as_deref(),
verbose,
threshold,
),
crate::Commands::ActorObserve {
config,
refresh_interval,
max_traces,
max_actors,
enable_deadlock_detection,
deadlock_interval,
start_mode,
no_color,
format,
export,
duration,
verbose,
filter_actor,
filter_failed,
filter_slow,
} => handle_actor_observe_command(
config.as_deref(),
refresh_interval,
max_traces,
max_actors,
enable_deadlock_detection,
deadlock_interval,
&start_mode,
derive_color_flag(no_color),
&format,
export.as_deref(),
duration,
verbose,
filter_actor.as_deref(),
filter_failed,
filter_slow,
),
crate::Commands::DataflowDebug {
config,
max_rows,
auto_materialize,
enable_profiling,
timeout,
track_memory,
compute_diffs,
sample_rate,
refresh_interval,
no_color,
format,
export,
verbose,
breakpoint,
start_mode,
} => handle_dataflow_debug_command(
config.as_deref(),
max_rows,
auto_materialize,
enable_profiling,
timeout,
track_memory,
compute_diffs,
sample_rate,
refresh_interval,
derive_color_flag(no_color),
&format,
export.as_deref(),
verbose,
&breakpoint,
&start_mode,
),
crate::Commands::Infra(cmd) => {
use crate::handlers::handlers_modules::sovereign::*;
match cmd {
crate::InfraCommands::Plan { file } => handle_infra_plan(&file),
crate::InfraCommands::Apply { file, yes } => handle_infra_apply(&file, yes),
crate::InfraCommands::Drift { file } => handle_infra_drift(&file),
crate::InfraCommands::Status => handle_infra_status(),
crate::InfraCommands::Destroy { file, yes } => handle_infra_destroy(&file, yes),
}
}
crate::Commands::Sim(cmd) => {
use crate::handlers::handlers_modules::sovereign::*;
match cmd {
crate::SimCommands::Run { file, seed } => handle_sim_run(&file, seed),
crate::SimCommands::Inspect { file } => handle_sim_inspect(&file),
crate::SimCommands::Verify { file } => handle_sim_verify(&file),
crate::SimCommands::Export { file, format } => handle_sim_export(&file, &format),
}
}
crate::Commands::Widget(cmd) => {
use crate::handlers::handlers_modules::sovereign::*;
match cmd {
crate::WidgetCommands::Serve { file, port } => handle_widget_serve(&file, port),
crate::WidgetCommands::Build { file, output } => {
handle_widget_build(&file, &output)
}
crate::WidgetCommands::Test { path } => handle_widget_test(&path),
crate::WidgetCommands::Inspect { file } => handle_widget_inspect(&file),
}
}
crate::Commands::Apr(cmd) => {
use crate::handlers::handlers_modules::sovereign::*;
match cmd {
crate::AprCommands::Run { file } => handle_apr_run(&file),
crate::AprCommands::Serve { file, port } => handle_apr_serve(&file, port),
crate::AprCommands::Quantize { file, bits } => handle_apr_quantize(&file, bits),
crate::AprCommands::Inspect { file } => handle_apr_inspect(&file),
crate::AprCommands::Bench { file, iterations } => {
handle_apr_bench(&file, iterations)
}
crate::AprCommands::Eval { file, data } => handle_apr_eval(&file, &data),
}
}
crate::Commands::Model(cmd) => {
use crate::handlers::handlers_modules::sovereign::*;
match cmd {
crate::ModelCommands::Save { name, output } => handle_model_save(&name, &output),
crate::ModelCommands::Load { file } => handle_model_load(&file),
crate::ModelCommands::Export { file, format } => {
handle_model_export(&file, &format)
}
crate::ModelCommands::Import { file } => handle_model_import(&file),
crate::ModelCommands::Inspect { file } => handle_model_inspect(&file),
crate::ModelCommands::Verify { file } => handle_model_verify(&file),
}
}
crate::Commands::Purify { path, fix, verbose } => {
crate::handlers::handlers_modules::sovereign::handle_purify(&path, fix, verbose)
}
crate::Commands::Migrate4to5 { path, dry_run } => {
crate::handlers::handlers_modules::migrate::run_migration(&path, dry_run)?;
Ok(())
}
crate::Commands::Tier {
path,
json,
list,
fail_under,
fail_on_totality_violation,
fail_under_f1,
fail_exempt_density_above,
public_only,
fail_pub_bronze_above,
fail_diff_exempt_density_above,
by_file,
sort_by,
top,
parse_timeout_ms,
baseline,
markdown,
fail_on_scorecard,
config,
exclude,
} => crate::handlers::handlers_modules::provability::handle_provability_command(
&path,
json,
list,
fail_under,
fail_on_totality_violation,
fail_under_f1,
fail_exempt_density_above,
public_only,
fail_pub_bronze_above,
fail_diff_exempt_density_above,
by_file,
&sort_by,
top,
parse_timeout_ms,
baseline.as_deref(),
markdown,
fail_on_scorecard.as_deref(),
config.as_deref(),
&exclude,
),
crate::Commands::Contracts(cmd) => {
use crate::handlers::handlers_modules::sovereign::*;
match cmd {
crate::ContractsCommands::Sync {
path,
output,
verbose,
exclude,
} => handle_contracts_sync(&path, &output, verbose, &exclude),
crate::ContractsCommands::List {
path,
format,
pub_only,
exclude,
} => handle_contracts_list(&path, &format, pub_only, &exclude),
crate::ContractsCommands::Check {
path,
min_coverage,
pub_only,
exclude,
} => handle_contracts_check(&path, min_coverage, pub_only, &exclude),
}
}
crate::Commands::SuggestContracts {
path,
format,
verbose,
pub_only,
exclude,
} => crate::handlers::handlers_modules::sovereign::handle_suggest_contracts(
&path, &format, verbose, pub_only, &exclude,
),
_ => {
eprintln!("Command not yet implemented");
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_quality_gate_flags_all_false() {
let (strict, quiet, json) = derive_quality_gate_flags(false, false, "text");
assert!(!strict);
assert!(quiet); assert!(!json);
}
#[test]
fn test_quality_gate_flags_fail_fast_true() {
let (strict, quiet, json) = derive_quality_gate_flags(true, false, "text");
assert!(strict);
assert!(quiet);
assert!(!json);
}
#[test]
fn test_quality_gate_flags_verbose_true() {
let (strict, quiet, json) = derive_quality_gate_flags(false, true, "text");
assert!(!strict);
assert!(!quiet); assert!(!json);
}
#[test]
fn test_quality_gate_flags_json_format() {
let (strict, quiet, json) = derive_quality_gate_flags(false, false, "json");
assert!(!strict);
assert!(quiet);
assert!(json);
}
#[test]
fn test_quality_gate_flags_all_true() {
let (strict, quiet, json) = derive_quality_gate_flags(true, true, "json");
assert!(strict);
assert!(!quiet);
assert!(json);
}
#[test]
fn test_fmt_write_neither_check_nor_stdout() {
assert!(derive_fmt_write_flag(false, false));
}
#[test]
fn test_fmt_write_check_mode() {
assert!(!derive_fmt_write_flag(true, false));
}
#[test]
fn test_fmt_write_stdout_mode() {
assert!(!derive_fmt_write_flag(false, true));
}
#[test]
fn test_fmt_write_both_check_and_stdout() {
assert!(!derive_fmt_write_flag(true, true));
}
#[test]
fn test_coverage_threshold_none() {
assert!((derive_coverage_threshold(None) - 80.0).abs() < f64::EPSILON);
}
#[test]
fn test_coverage_threshold_some() {
assert!((derive_coverage_threshold(Some(95.0)) - 95.0).abs() < f64::EPSILON);
}
#[test]
fn test_coverage_threshold_zero() {
assert!((derive_coverage_threshold(Some(0.0)) - 0.0).abs() < f64::EPSILON);
}
#[test]
fn test_coverage_threshold_hundred() {
assert!((derive_coverage_threshold(Some(100.0)) - 100.0).abs() < f64::EPSILON);
}
#[test]
fn test_color_flag_no_color_false() {
assert!(derive_color_flag(false)); }
#[test]
fn test_color_flag_no_color_true() {
assert!(!derive_color_flag(true)); }
#[test]
fn test_lint_args_init_config() {
assert!(validate_lint_args(None, true).is_ok());
}
#[test]
fn test_lint_args_with_file() {
let file = "test.ruchy".to_string();
assert!(validate_lint_args(Some(&file), false).is_ok());
}
#[test]
fn test_lint_args_no_file_no_init() {
assert!(validate_lint_args(None, false).is_err());
}
#[test]
fn test_lint_args_file_and_init() {
let file = "test.ruchy".to_string();
assert!(validate_lint_args(Some(&file), true).is_ok());
}
#[test]
fn test_lint_args_error_message() {
let err = validate_lint_args(None, false).unwrap_err();
assert!(err.contains("file") || err.contains("--all"));
}
}