pub mod graphml;
pub mod owned;
pub use graphml::{read_graphml, write_graphml, Error as GraphError};
pub use owned::{OwnedClassNode, OwnedGraph};
use serde::{Deserialize, Serialize};
pub trait ClassNode {
fn id(&self) -> &str;
fn namespace(&self) -> &str;
fn line_count(&self) -> u32;
fn method_count(&self) -> u32;
fn method_connectivity(&self) -> Option<&MethodConnectivity> {
None
}
fn cyclomatic_complexity(&self) -> Option<&serde_json::Value> {
None
}
fn halstead_eta1(&self) -> u32 {
0
}
fn halstead_eta2(&self) -> u32 {
0
}
fn halstead_n1(&self) -> u32 {
0
}
fn halstead_n2(&self) -> u32 {
0
}
fn method_tokens(&self) -> Option<&serde_json::Value> {
None
}
fn method_fingerprints(&self) -> Option<&serde_json::Value> {
None
}
fn call_sequences(&self) -> Option<&serde_json::Value> {
None
}
}
pub trait EdgeKind: Copy {
fn is_method_call(&self) -> bool;
fn is_field_ref(&self) -> bool;
fn is_inheritance(&self) -> bool;
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MethodConnectivity {
#[serde(default)]
pub methods: Vec<String>,
#[serde(default)]
pub edges: Vec<(String, String)>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum EdgeType {
MethodCall,
FieldRef,
Inheritance,
}
impl EdgeKind for EdgeType {
fn is_method_call(&self) -> bool {
matches!(self, EdgeType::MethodCall)
}
fn is_field_ref(&self) -> bool {
matches!(self, EdgeType::FieldRef)
}
fn is_inheritance(&self) -> bool {
matches!(self, EdgeType::Inheritance)
}
}
#[cfg(test)]
mod tests {
use super::*;
static SMALL_GRAPHML: &str =
include_str!("../tests/fixtures/small.graphml");
#[test]
fn graphml_roundtrip() {
let g1 = read_graphml(SMALL_GRAPHML).expect("read original graphml");
assert_eq!(g1.node_count(), 3, "expected 3 nodes");
assert_eq!(g1.edge_count(), 2, "expected 2 edges");
let alpha = g1
.node_weights()
.find(|n| n.id == "com.example.Alpha")
.expect("Alpha node");
assert_eq!(alpha.name, "Alpha");
assert_eq!(alpha.namespace, "com.example");
assert_eq!(alpha.line_count, 42);
assert_eq!(alpha.method_count, 3);
let mc = alpha.method_connectivity().expect("Alpha.methodConnectivity");
assert_eq!(mc.methods.len(), 3);
assert_eq!(mc.edges.len(), 1);
assert_eq!(mc.edges[0].0, "foo");
assert_eq!(mc.edges[0].1, "bar");
let written = write_graphml(&g1).expect("write graphml");
let g2 = read_graphml(&written).expect("read written graphml");
assert_eq!(g2.node_count(), 3);
assert_eq!(g2.edge_count(), 2);
let alpha2 = g2
.node_weights()
.find(|n| n.id == "com.example.Alpha")
.expect("Alpha node (round-trip)");
assert_eq!(alpha2.name, "Alpha");
assert_eq!(alpha2.line_count, 42);
let mc2 = alpha2.method_connectivity().expect("Alpha.methodConnectivity (round-trip)");
assert_eq!(mc2.methods, mc.methods);
assert_eq!(mc2.edges[0].0, "foo");
let edge_types: Vec<EdgeType> = g2.edge_weights().copied().collect();
assert!(edge_types.contains(&EdgeType::MethodCall));
assert!(edge_types.contains(&EdgeType::Inheritance));
}
}