use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ContextType {
Rail,
Panel,
Modal,
Form,
List,
State,
Api,
Util,
Other,
}
impl std::fmt::Display for ContextType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ContextType::Rail => write!(f, "rail"),
ContextType::Panel => write!(f, "panel"),
ContextType::Modal => write!(f, "modal"),
ContextType::Form => write!(f, "form"),
ContextType::List => write!(f, "list"),
ContextType::State => write!(f, "state"),
ContextType::Api => write!(f, "api"),
ContextType::Util => write!(f, "util"),
ContextType::Other => write!(f, "other"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Crowd {
pub pattern: String,
pub members: Vec<CrowdMember>,
pub score: f32,
pub issues: Vec<CrowdIssue>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub context_type: Option<ContextType>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrowdMember {
pub file: String,
pub match_reason: MatchReason,
pub importer_count: usize,
pub similarity_scores: Vec<(String, f32)>,
#[serde(default)]
pub is_test: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum MatchReason {
NameMatch {
matched: String,
},
ImportSimilarity {
similarity: f32,
},
ExportSimilarity {
similar_to: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum CrowdIssue {
NameCollision {
files: Vec<String>,
},
UsageAsymmetry {
primary: String,
underused: Vec<String>,
},
ExportOverlap {
files: Vec<String>,
overlap: Vec<String>,
},
Fragmentation {
categories: Vec<String>,
},
}