use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CodeBase {
pub enums: Vec<EnumInfo>,
pub structs: Vec<StructInfo>,
pub files: Vec<FileInfo>,
}
impl CodeBase {
pub fn new() -> Self {
Self::default()
}
pub fn merge(&mut self, other: CodeBase) {
self.enums.extend(other.enums);
self.structs.extend(other.structs);
self.files.extend(other.files);
}
pub fn total_elements(&self) -> usize {
self.enums.len() + self.structs.len()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileInfo {
pub path: String,
pub enum_count: usize,
pub struct_count: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnumInfo {
pub name: String,
pub doc_comment: Option<String>,
pub file_path: String,
pub line_number: usize,
pub visibility: Visibility,
pub generics: Vec<String>,
pub derives: Vec<String>,
pub attributes: Vec<String>,
pub variants: Vec<EnumVariant>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnumVariant {
pub name: String,
pub doc_comment: Option<String>,
pub fields: Vec<FieldInfo>,
pub discriminant: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StructInfo {
pub name: String,
pub doc_comment: Option<String>,
pub file_path: String,
pub line_number: usize,
pub visibility: Visibility,
pub generics: Vec<String>,
pub derives: Vec<String>,
pub attributes: Vec<String>,
pub fields: Vec<FieldInfo>,
pub methods: Vec<MethodInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldInfo {
pub name: Option<String>,
pub ty: String,
pub doc_comment: Option<String>,
pub visibility: Visibility,
pub attributes: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MethodInfo {
pub name: String,
pub doc_comment: Option<String>,
pub file_path: String,
pub line_number: usize,
pub visibility: Visibility,
pub is_async: bool,
pub is_const: bool,
pub is_unsafe: bool,
pub generics: Vec<String>,
pub parameters: Vec<ParameterInfo>,
pub return_type: Option<String>,
pub receiver: Option<Receiver>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ParameterInfo {
pub name: String,
pub ty: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Receiver {
Value,
Ref,
RefMut,
Explicit(String),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum Visibility {
Private,
Public,
Crate,
Super,
Restricted(String),
}
impl Default for Visibility {
fn default() -> Self {
Visibility::Private
}
}
impl std::fmt::Display for Visibility {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Visibility::Private => write!(f, ""),
Visibility::Public => write!(f, "pub"),
Visibility::Crate => write!(f, "pub(crate)"),
Visibility::Super => write!(f, "pub(super)"),
Visibility::Restricted(path) => write!(f, "pub(in {})", path),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_codebase_new() {
let codebase = CodeBase::new();
assert!(codebase.enums.is_empty());
assert!(codebase.structs.is_empty());
assert!(codebase.files.is_empty());
}
#[test]
fn test_codebase_merge() {
let mut codebase1 = CodeBase::new();
codebase1.enums.push(EnumInfo {
name: "TestEnum".to_string(),
doc_comment: None,
file_path: "test.rs".to_string(),
line_number: 1,
visibility: Visibility::Public,
generics: vec![],
derives: vec![],
attributes: vec![],
variants: vec![],
});
let mut codebase2 = CodeBase::new();
codebase2.structs.push(StructInfo {
name: "TestStruct".to_string(),
doc_comment: None,
file_path: "test.rs".to_string(),
line_number: 10,
visibility: Visibility::Public,
generics: vec![],
derives: vec![],
attributes: vec![],
fields: vec![],
methods: vec![],
});
codebase1.merge(codebase2);
assert_eq!(codebase1.enums.len(), 1);
assert_eq!(codebase1.structs.len(), 1);
}
#[test]
fn test_visibility_display() {
assert_eq!(Visibility::Private.to_string(), "");
assert_eq!(Visibility::Public.to_string(), "pub");
assert_eq!(Visibility::Crate.to_string(), "pub(crate)");
assert_eq!(Visibility::Super.to_string(), "pub(super)");
assert_eq!(
Visibility::Restricted("crate::module".to_string()).to_string(),
"pub(in crate::module)"
);
}
}