#![cfg_attr(coverage_nightly, coverage(off))]
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::process::Command;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CachedDeadCodeResult {
pub tree_hash: String,
pub pmat_version: String,
pub timestamp: chrono::DateTime<chrono::Utc>,
pub report: AccurateDeadCodeReport,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccurateDeadCodeReport {
pub files_with_dead_code: Vec<FileDeadCode>,
pub total_dead_items: usize,
pub dead_code_percentage: f64,
pub total_lines: usize,
pub dead_lines: usize,
pub dead_by_type: HashMap<String, usize>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileDeadCode {
pub file_path: PathBuf,
pub dead_items: Vec<DeadItem>,
pub file_dead_percentage: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeadItem {
pub name: String,
pub kind: DeadCodeKind,
pub line: usize,
pub column: usize,
pub message: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum DeadCodeKind {
Function,
Method,
Struct,
Enum,
Variant,
Field,
Constant,
Static,
Module,
Trait,
TypeAlias,
Suppressed,
Other(String),
}
pub struct CargoDeadCodeAnalyzer {
project_path: PathBuf,
exclude_tests: bool,
exclude_examples: bool,
exclude_benches: bool,
max_depth: usize,
use_cache: bool,
force_refresh: bool,
}
impl CargoDeadCodeAnalyzer {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub fn new(project_path: impl AsRef<Path>) -> Self {
Self {
project_path: project_path.as_ref().to_path_buf(),
exclude_tests: true,
exclude_examples: true,
exclude_benches: true,
max_depth: 8,
use_cache: true,
force_refresh: false,
}
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn include_tests(mut self) -> Self {
self.exclude_tests = false;
self
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn include_examples(mut self) -> Self {
self.exclude_examples = false;
self
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn include_benches(mut self) -> Self {
self.exclude_benches = false;
self
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn with_max_depth(mut self, max_depth: usize) -> Self {
self.max_depth = max_depth;
self
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn without_cache(mut self) -> Self {
self.use_cache = false;
self
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn force_refresh(mut self) -> Self {
self.force_refresh = true;
self
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub async fn analyze_dead_code(project_path: impl AsRef<Path>) -> Result<AccurateDeadCodeReport> {
let analyzer = CargoDeadCodeAnalyzer::new(project_path);
analyzer.analyze().await
}
include!("cargo_dead_code_analyzer/cache_operations.rs");
include!("cargo_dead_code_analyzer/analysis.rs");
include!("cargo_dead_code_analyzer/parsing.rs");
include!("cargo_dead_code_analyzer/tests.rs");