#![allow(unused)]
#![cfg_attr(coverage_nightly, coverage(off))]
use crate::cli::{ContextFormat, OutputFormat};
use crate::models::template::TemplateResource;
use crate::services::template_service::{list_templates, search_templates};
use crate::stateless_server::StatelessTemplateServer;
use anyhow::Result;
use std::path::{Path, PathBuf};
use std::sync::Arc;
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn handle_list(
server: Arc<StatelessTemplateServer>,
toolchain: Option<String>,
category: Option<String>,
format: OutputFormat,
) -> Result<()> {
let templates =
list_templates(server.as_ref(), toolchain.as_deref(), category.as_deref()).await?;
match format {
OutputFormat::Table => super::super::analysis_utilities::print_table(&templates),
OutputFormat::Json => {
let templates_deref: Vec<&TemplateResource> =
templates.iter().map(std::convert::AsRef::as_ref).collect();
println!("{}", serde_json::to_string_pretty(&templates_deref)?);
}
OutputFormat::Yaml => {
let templates_deref: Vec<&TemplateResource> =
templates.iter().map(std::convert::AsRef::as_ref).collect();
println!("{}", serde_yaml_ng::to_string(&templates_deref)?);
}
_ => super::super::analysis_utilities::print_table(&templates),
}
Ok(())
}
struct MarkdownBuilder {
content: String,
}
impl MarkdownBuilder {
fn new() -> Self {
Self {
content: String::new(),
}
}
fn add_header(&mut self, level: usize, text: &str) {
for _ in 0..level {
self.content.push('#');
}
self.content.push(' ');
self.content.push_str(text);
self.content.push_str("\n\n");
}
fn add_metric(&mut self, label: &str, value: impl std::fmt::Display) {
self.content.push_str(&format!("- **{label}**: {value}\n"));
}
fn add_percentage_metric(&mut self, label: &str, value: f64) {
self.content
.push_str(&format!("- **{label}**: {value:.1}%\n"));
}
fn add_newline(&mut self) {
self.content.push('\n');
}
fn build(self) -> String {
self.content
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn handle_search(
server: Arc<StatelessTemplateServer>,
query: String,
toolchain: Option<String>,
limit: usize,
) -> Result<()> {
let results = search_templates(server.clone(), &query, toolchain.as_deref()).await?;
if results.is_empty() {
eprintln!("No templates found matching '{}'", query);
eprintln!("Hint: use 'pmat list' to see all available templates");
return Ok(());
}
for (i, result) in results.iter().take(limit).enumerate() {
println!(
"{:2}. {} (score: {:.2})",
i + 1,
result.template.uri,
result.relevance
);
if !result.matches.is_empty() {
println!(" Matches: {}", result.matches.join(", "));
}
}
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
#[allow(clippy::too_many_arguments)]
pub async fn handle_context(
toolchain: Option<String>,
project_path: PathBuf,
output: Option<PathBuf>,
format: ContextFormat,
include_large_files: bool,
skip_expensive_metrics: bool,
language: Option<String>,
languages: Option<Vec<String>>,
) -> Result<()> {
use crate::services::deep_context::{
AnalysisType, CacheStrategy, DagType, DeepContextAnalyzer, DeepContextConfig,
};
use crate::services::language_override::{get_effective_languages, LanguageOverride};
let override_opts = LanguageOverride {
language,
languages,
};
let effective_languages = get_effective_languages(&override_opts, &project_path)?;
let toolchain = if !effective_languages.is_empty() {
effective_languages[0].clone()
} else {
detect_or_use_toolchain(toolchain, &project_path)?
};
let config = DeepContextConfig {
include_analyses: if skip_expensive_metrics {
vec![
AnalysisType::Ast,
AnalysisType::Complexity,
AnalysisType::DeadCode,
AnalysisType::Satd,
]
} else {
vec![
AnalysisType::Ast,
AnalysisType::Complexity,
AnalysisType::Churn,
AnalysisType::TechnicalDebtGradient,
AnalysisType::DeadCode,
AnalysisType::Satd,
AnalysisType::Provability,
AnalysisType::BigO,
]
},
period_days: 30, dag_type: DagType::CallGraph,
complexity_thresholds: Some(crate::services::deep_context::ComplexityThresholds {
max_cyclomatic: 20,
max_cognitive: 25,
}),
max_depth: Some(5), include_patterns: vec![], exclude_patterns: vec![
"**/target/**".to_string(),
"**/node_modules/**".to_string(),
"**/build/**".to_string(),
"**/dist/**".to_string(),
"**/.git/**".to_string(),
"**/fuzz/**".to_string(),
],
cache_strategy: CacheStrategy::Normal,
parallel: num_cpus::get(), file_classifier_config: None,
};
let analyzer = DeepContextAnalyzer::new(config);
let context = analyzer.analyze_project(&project_path).await?;
let output_content = generate_enhanced_ast_context(
&toolchain,
&project_path,
&context,
format,
include_large_files,
)
.await?;
write_context_output(output, &output_content).await?;
Ok(())
}
include!("context_generation.rs");
include!("project_analysis.rs");
include!("context_output.rs");
pub use super::utility_serve_handlers::handle_serve;
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub async fn handle_diagnose(args: crate::cli::diagnose::DiagnoseArgs) -> Result<()> {
crate::cli::diagnose::handle_diagnose(args).await
}
#[cfg(test)]
#[path = "utility_handlers_tests.rs"]
mod tests;