#![allow(dead_code)]
use serde::{Deserialize, Serialize};
#[allow(dead_code)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum RelationshipType {
Imports,
Calls,
References,
DocumentedBy,
TestedBy,
Tests,
Contains,
Defines,
Implements,
Implementations,
Extends,
HasMethod,
HasProperty,
Accesses,
MemberOf,
Decorates,
Wraps,
BelongsTo,
MethodOverrides,
MethodImplements,
Queries,
EntryPointOf,
StepInProcess,
}
impl RelationshipType {
pub fn as_str(&self) -> &'static str {
match self {
RelationshipType::Imports => "imports",
RelationshipType::Calls => "calls",
RelationshipType::References => "references",
RelationshipType::DocumentedBy => "documented_by",
RelationshipType::TestedBy => "tested_by",
RelationshipType::Tests => "tests",
RelationshipType::Contains => "contains",
RelationshipType::Defines => "defines",
RelationshipType::Implements => "implements",
RelationshipType::Implementations => "implementations",
RelationshipType::Extends => "extends",
RelationshipType::HasMethod => "has_method",
RelationshipType::HasProperty => "has_property",
RelationshipType::Accesses => "accesses",
RelationshipType::MemberOf => "member_of",
RelationshipType::Decorates => "decorates",
RelationshipType::Wraps => "wraps",
RelationshipType::BelongsTo => "belongs_to",
RelationshipType::MethodOverrides => "method_overrides",
RelationshipType::MethodImplements => "method_implements",
RelationshipType::Queries => "queries",
RelationshipType::EntryPointOf => "entry_point_of",
RelationshipType::StepInProcess => "step_in_process",
}
}
#[allow(dead_code)]
pub fn from_str(s: &str) -> Option<Self> {
match s {
"imports" => Some(RelationshipType::Imports),
"calls" => Some(RelationshipType::Calls),
"references" => Some(RelationshipType::References),
"documented_by" => Some(RelationshipType::DocumentedBy),
"tested_by" => Some(RelationshipType::TestedBy),
"tests" => Some(RelationshipType::Tests),
"contains" => Some(RelationshipType::Contains),
"defines" => Some(RelationshipType::Defines),
"implements" => Some(RelationshipType::Implements),
"implementations" => Some(RelationshipType::Implementations),
"extends" => Some(RelationshipType::Extends),
"has_method" => Some(RelationshipType::HasMethod),
"has_property" => Some(RelationshipType::HasProperty),
"accesses" => Some(RelationshipType::Accesses),
"member_of" => Some(RelationshipType::MemberOf),
"decorates" => Some(RelationshipType::Decorates),
"wraps" => Some(RelationshipType::Wraps),
"belongs_to" => Some(RelationshipType::BelongsTo),
"method_overrides" => Some(RelationshipType::MethodOverrides),
"method_implements" => Some(RelationshipType::MethodImplements),
"queries" => Some(RelationshipType::Queries),
"entry_point_of" => Some(RelationshipType::EntryPointOf),
"step_in_process" => Some(RelationshipType::StepInProcess),
_ => None,
}
}
}
impl std::fmt::Display for RelationshipType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CodeElement {
pub qualified_name: String,
pub element_type: String,
pub name: String,
pub file_path: String,
pub line_start: u32,
pub line_end: u32,
pub language: String,
pub parent_qualified: Option<String>,
#[serde(default)]
pub cluster_id: Option<String>,
#[serde(default)]
pub cluster_label: Option<String>,
#[serde(default)]
pub metadata: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Relationship {
#[serde(skip)]
#[allow(dead_code)]
pub id: Option<String>,
pub source_qualified: String,
pub target_qualified: String,
pub rel_type: String,
pub confidence: f64,
pub metadata: serde_json::Value,
}
impl Relationship {
pub fn severity(&self, depth: u32) -> &'static str {
if depth == 1 && self.confidence >= 0.85 {
"WILL BREAK"
} else if depth == 1 && self.confidence >= 0.60 {
"LIKELY AFFECTED"
} else {
"MAY BE AFFECTED"
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BusinessLogic {
#[serde(skip)]
#[allow(dead_code)]
pub id: Option<String>,
pub element_qualified: String,
pub description: String,
pub user_story_id: Option<String>,
pub feature_id: Option<String>,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BusinessLogicWithDoc {
pub business_logic: BusinessLogic,
pub doc_links: Vec<DocLink>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocLink {
pub doc_qualified: String,
pub doc_title: String,
pub context: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TraceabilityEntry {
pub element_qualified: String,
pub description: String,
pub user_story_id: Option<String>,
pub feature_id: Option<String>,
pub doc_links: Vec<DocLink>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TraceabilityReport {
pub element_qualified: String,
pub entries: Vec<TraceabilityEntry>,
pub count: usize,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Document {
#[serde(skip)]
pub id: Option<String>,
pub title: String,
pub content: String,
pub file_path: String,
pub generated_from: Vec<String>,
pub last_updated: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ContextMetric {
pub tool_name: String,
pub timestamp: i64,
pub project_path: String,
pub input_tokens: i32,
pub output_tokens: i32,
pub output_elements: i32,
pub execution_time_ms: i32,
pub baseline_tokens: i32,
pub baseline_lines_scanned: i32,
pub tokens_saved: i32,
pub savings_percent: f64,
pub correct_elements: Option<i32>,
pub total_expected: Option<i32>,
pub f1_score: Option<f64>,
pub query_pattern: Option<String>,
pub query_file: Option<String>,
pub query_depth: Option<i32>,
pub success: bool,
#[serde(default)]
pub is_deleted: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricsSummary {
pub total_invocations: i64,
pub total_tokens_saved: i64,
pub average_savings_percent: f64,
pub average_correctness_percent: f64,
pub retention_days: i32,
pub by_tool: Vec<ToolMetrics>,
pub by_day: Vec<DailyMetrics>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolMetrics {
pub tool_name: String,
pub calls: i64,
pub avg_savings_percent: f64,
pub avg_correctness_percent: f64,
pub total_saved: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DailyMetrics {
pub date: String,
pub calls: i64,
pub savings: i64,
pub correctness: f64,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_code_element_creation() {
let elem = CodeElement {
qualified_name: "src/main.rs::main".to_string(),
element_type: "function".to_string(),
name: "main".to_string(),
file_path: "src/main.rs".to_string(),
line_start: 1,
line_end: 5,
language: "rust".to_string(),
parent_qualified: None,
metadata: serde_json::json!({}),
..Default::default()
};
assert_eq!(elem.name, "main");
}
#[test]
fn test_relationship_creation() {
let rel = Relationship {
id: None,
source_qualified: "a.go".to_string(),
target_qualified: "b.go".to_string(),
rel_type: "imports".to_string(),
confidence: 1.0,
metadata: serde_json::json!({}),
};
assert_eq!(rel.rel_type, "imports");
assert_eq!(rel.confidence, 1.0);
}
#[test]
fn test_relationship_type_display() {
assert_eq!(RelationshipType::Imports.as_str(), "imports");
assert_eq!(
RelationshipType::Implementations.as_str(),
"implementations"
);
assert_eq!(format!("{}", RelationshipType::Calls), "calls");
}
#[test]
fn test_relationship_type_from_str() {
assert_eq!(
RelationshipType::from_str("imports"),
Some(RelationshipType::Imports)
);
assert_eq!(
RelationshipType::from_str("implementations"),
Some(RelationshipType::Implementations)
);
assert_eq!(RelationshipType::from_str("unknown"), None);
}
}