Skip to main content

tldr_cli/commands/
complexity.rs

1//! Complexity command - Calculate function complexity metrics
2//!
3//! Returns ComplexityMetrics with cyclomatic, cognitive, nesting_depth, and lines_of_code.
4//! Auto-routes through daemon when available for ~35x speedup.
5
6use std::path::PathBuf;
7
8use anyhow::Result;
9use clap::Args;
10
11use tldr_core::types::ComplexityMetrics;
12use tldr_core::{calculate_complexity, detect_or_parse_language, validate_file_path, Language};
13
14use crate::commands::daemon_router::{params_with_file_function, try_daemon_route};
15use crate::output::{format_complexity_text, OutputFormat, OutputWriter};
16
17/// Calculate complexity metrics for a function
18#[derive(Debug, Args)]
19pub struct ComplexityArgs {
20    /// file containing the function
21    pub file: PathBuf,
22
23    /// Function name to analyze
24    pub function: String,
25
26    /// Programming language (auto-detect if not specified)
27    #[arg(long, short = 'l')]
28    pub lang: Option<Language>,
29}
30
31impl ComplexityArgs {
32    /// Run the complexity command
33    pub fn run(&self, format: OutputFormat, quiet: bool) -> Result<()> {
34        let writer = OutputWriter::new(format, quiet);
35
36        // Validate file path exists (M28: shared validator - returns PathNotFound error)
37        let validated_path = validate_file_path(self.file.to_str().unwrap_or_default(), None)?;
38
39        // Try daemon first for cached result (use file's parent as project root)
40        let project = validated_path.parent().unwrap_or(&validated_path);
41        if let Some(result) = try_daemon_route::<ComplexityMetrics>(
42            project,
43            "complexity",
44            params_with_file_function(&validated_path, &self.function),
45        ) {
46            if writer.is_text() {
47                writer.write_text(&format_complexity_text(&result))?;
48            } else {
49                writer.write(&result)?;
50            }
51            return Ok(());
52        }
53
54        // Fallback to direct compute
55
56        // Detect or parse language (uses shared validator M28)
57        let language =
58            detect_or_parse_language(self.lang.as_ref().map(|l| l.as_str()), &validated_path)?;
59
60        writer.progress(&format!(
61            "Calculating complexity for {} in {} ({:?})...",
62            self.function,
63            validated_path.display(),
64            language
65        ));
66
67        // Calculate complexity - the function takes file path as string
68        let result = calculate_complexity(
69            validated_path.to_str().unwrap_or_default(),
70            &self.function,
71            language,
72        )?;
73
74        // Output based on format
75        if writer.is_text() {
76            writer.write_text(&format_complexity_text(&result))?;
77        } else {
78            writer.write(&result)?;
79        }
80
81        Ok(())
82    }
83}