Skip to main content

normalize_analyze/
lib.rs

1//! Shared entity types and ranking infrastructure for analyze commands.
2//!
3//! Provides the [`Entity`] trait for items that appear in ranked lists,
4//! concrete entity types ([`FunctionEntity`], [`ModuleEntity`], [`FileEntity`]),
5//! and the [`rank_pipeline`] for shared sort/stats/truncate logic.
6
7pub mod ranked;
8
9use schemars::JsonSchema;
10use serde::Serialize;
11
12/// An entity that can appear in a ranked list.
13pub trait Entity: Serialize + JsonSchema + Clone {
14    /// Display label for this entity (function name, module path, file path).
15    fn label(&self) -> &str;
16}
17
18/// A function-level entity (for complexity, length, etc.).
19#[derive(Debug, Clone, Serialize, JsonSchema)]
20pub struct FunctionEntity {
21    pub name: String,
22    pub parent: Option<String>,
23    pub file_path: String,
24    pub start_line: usize,
25    pub end_line: usize,
26}
27
28impl Entity for FunctionEntity {
29    fn label(&self) -> &str {
30        &self.name
31    }
32}
33
34/// A module-level entity (for density, health, etc.).
35#[derive(Debug, Clone, Serialize, JsonSchema)]
36pub struct ModuleEntity {
37    pub path: String,
38}
39
40impl Entity for ModuleEntity {
41    fn label(&self) -> &str {
42        &self.path
43    }
44}
45
46/// A file-level entity (for file-scoped rankings).
47#[derive(Debug, Clone, Serialize, JsonSchema)]
48pub struct FileEntity {
49    pub path: String,
50}
51
52impl Entity for FileEntity {
53    fn label(&self) -> &str {
54        &self.path
55    }
56}
57
58/// Truncate a path for display, replacing the beginning with "..." if too long.
59///
60/// Used by many ranked-list formatters to keep tabular output aligned.
61pub fn truncate_path(path: &str, max_len: usize) -> String {
62    if max_len <= 3 {
63        return path.to_string();
64    }
65    if path.len() > max_len {
66        let target = path.len().saturating_sub(max_len - 3);
67        let safe_start = path
68            .char_indices()
69            .map(|(i, _)| i)
70            .find(|&i| i >= target)
71            .unwrap_or(path.len());
72        format!("...{}", &path[safe_start..])
73    } else {
74        path.to_string()
75    }
76}