1pub mod attrs;
13pub mod cycles;
14pub mod finalize;
15pub mod hk;
16pub mod level_graph;
17pub mod relativize;
18pub mod serialize;
19pub mod snapshot;
20pub mod stats;
21
22pub use attrs::{num_attr, round_sig3};
23pub use cycles::annotate_cycles;
24pub use finalize::finalize_graph;
25pub use hk::annotate_hk;
26pub use level_graph::{CycleGroup, LevelGraph, LevelUi};
27pub use relativize::{relativize_graph, relativize_level};
28pub use serialize::{to_canonical_string, to_canonical_string_pretty};
29pub use snapshot::{GitInfo, Snapshot, StageTime};
30pub use stats::compute_stats;
31
32use code_ranker_plugin_api::{
33 attrs::ValueType,
34 level::{AttributeGroup, AttributeSpec},
35};
36use std::collections::BTreeMap;
37
38pub fn coupling_specs() -> (
42 BTreeMap<String, AttributeSpec>,
43 BTreeMap<String, AttributeGroup>,
44) {
45 let mut specs = BTreeMap::new();
46
47 let mut fan_in = AttributeSpec::new(ValueType::Int, "Fan-in");
48 fan_in.group = Some("coupling".into());
49 fan_in.name = Some("Fan-in".into());
50 fan_in.short = Some("Fan-in".into());
51 fan_in.description =
52 Some("Number of nodes that depend on this one. High fan-in means broadly reused.".into());
53 specs.insert("fan_in".to_string(), fan_in);
56
57 let mut fan_out = AttributeSpec::new(ValueType::Int, "Fan-out");
58 fan_out.group = Some("coupling".into());
59 fan_out.name = Some("Fan-out".into());
60 fan_out.short = Some("Fan-out".into());
61 fan_out.description = Some(
62 "Number of nodes this one depends on. High fan-out means many dependencies. \
63 External-library edges are counted separately."
64 .into(),
65 );
66 fan_out.direction = Some("lower_better".into());
69 specs.insert("fan_out".to_string(), fan_out);
70
71 let mut foe = AttributeSpec::new(ValueType::Int, "Fan-out (external)");
72 foe.group = Some("coupling".into());
73 foe.description = Some("Number of distinct external libraries this node depends on.".into());
74 specs.insert("fan_out_external".to_string(), foe);
75
76 let mut hk = AttributeSpec::new(ValueType::Float, "HK");
77 hk.group = Some("coupling".into());
78 hk.name = Some("Henry–Kafura (HK)".into());
79 hk.short = Some("HK".into());
80 hk.description = Some(
81 "Henry–Kafura — combines unit size with incoming/outgoing coupling (internal edges only)."
82 .into(),
83 );
84 hk.formula = Some("sloc × (fan_in × fan_out)²".into());
85 hk.calc = Some("sloc * (fan_in * fan_out) ** 2".into());
86 hk.direction = Some("lower_better".into());
87 hk.abbreviate = Some(true);
88 specs.insert("hk".to_string(), hk);
89
90 let mut cycle = AttributeSpec::new(ValueType::Str, "Cycle");
91 cycle.short = Some("Cycle".into());
92 cycle.description = Some("Cycle kind this node participates in.".into());
93 specs.insert("cycle".to_string(), cycle);
94
95 let mut groups = BTreeMap::new();
96 groups.insert(
97 "coupling".to_string(),
98 AttributeGroup {
99 label: Some("Coupling".to_string()),
100 description: Some("Internal coupling (Henry-Kafura)".to_string()),
101 },
102 );
103 (specs, groups)
104}