egui_cha_analyzer/
types.rs

1//! Core types for egui flow analysis
2
3/// A UI element found in the code (e.g., button, label, checkbox)
4#[derive(Debug, Clone, PartialEq)]
5pub struct UiElement {
6    /// Type of UI element (button, label, checkbox, etc.)
7    pub element_type: String,
8    /// Label or identifier if available
9    pub label: Option<String>,
10    /// Function/method containing this element
11    pub context: String,
12    /// File path
13    pub file_path: String,
14    /// Line number (0 if unknown)
15    pub line: usize,
16    /// Variable name if response is stored
17    pub response_var: Option<String>,
18}
19
20/// An action triggered by UI interaction
21#[derive(Debug, Clone, PartialEq)]
22pub struct Action {
23    /// Type of action (clicked, changed, dragged, etc.)
24    pub action_type: String,
25    /// The UI element or response variable this action checks
26    pub source: String,
27    /// Function/method containing this action
28    pub context: String,
29    /// File path
30    pub file_path: String,
31    /// Line number (0 if unknown)
32    pub line: usize,
33}
34
35/// A state mutation
36#[derive(Debug, Clone, PartialEq)]
37pub struct StateMutation {
38    /// The state field being mutated
39    pub target: String,
40    /// Type of mutation (assign, increment, method call, etc.)
41    pub mutation_type: String,
42    /// Function/method containing this mutation
43    pub context: String,
44    /// File path
45    pub file_path: String,
46    /// Line number (0 if unknown)
47    pub line: usize,
48}
49
50/// A complete UI flow: UI element -> Action -> State mutations
51/// Represents a causal chain from user interaction to state changes
52#[derive(Debug, Clone)]
53pub struct UiFlow {
54    pub ui_element: UiElement,
55    pub action: Action,
56    pub state_mutations: Vec<StateMutation>,
57    pub context: String,
58}
59
60// ============================================================
61// TEA (The Elm Architecture) specific types
62// ============================================================
63
64/// A DS component that emits a message (e.g., Button::primary("+").on_click(ctx, Msg::Increment))
65#[derive(Debug, Clone, PartialEq)]
66pub struct MsgEmission {
67    /// DS component type (Button, Input, etc.)
68    pub component: String,
69    /// Variant (primary, secondary, ghost, etc.)
70    pub variant: String,
71    /// Label text
72    pub label: Option<String>,
73    /// Action type (on_click, on_change, etc.)
74    pub action: String,
75    /// Message type being emitted (e.g., "Msg::Increment")
76    pub msg: String,
77    /// Function/method containing this emission
78    pub context: String,
79    /// File path
80    pub file_path: String,
81}
82
83/// A message handler in the update function
84#[derive(Debug, Clone, PartialEq)]
85pub struct MsgHandler {
86    /// Message pattern being matched (e.g., "Msg::Increment")
87    pub msg_pattern: String,
88    /// State mutations triggered by this message
89    pub state_mutations: Vec<StateMutation>,
90    /// File path
91    pub file_path: String,
92}
93
94/// A complete TEA flow: DS Component -> Msg -> State changes
95#[derive(Debug, Clone)]
96pub struct TeaFlow {
97    pub emission: MsgEmission,
98    pub handler: Option<MsgHandler>,
99}
100
101/// Analysis result for a single file
102#[derive(Debug, Clone)]
103pub struct FileAnalysis {
104    pub path: String,
105    pub ui_elements: Vec<UiElement>,
106    pub actions: Vec<Action>,
107    pub state_mutations: Vec<StateMutation>,
108    /// Scope-aware flows (UI -> Action -> State with causality)
109    pub flows: Vec<UiFlow>,
110    /// TEA: DS component -> Msg emissions
111    pub msg_emissions: Vec<MsgEmission>,
112    /// TEA: Msg -> State handlers (from update function)
113    pub msg_handlers: Vec<MsgHandler>,
114    /// TEA: Complete flows (emission + handler)
115    pub tea_flows: Vec<TeaFlow>,
116}
117
118impl FileAnalysis {
119    pub fn new(path: String) -> Self {
120        Self {
121            path,
122            ui_elements: Vec::new(),
123            actions: Vec::new(),
124            state_mutations: Vec::new(),
125            flows: Vec::new(),
126            msg_emissions: Vec::new(),
127            msg_handlers: Vec::new(),
128            tea_flows: Vec::new(),
129        }
130    }
131}
132
133/// Aggregated analysis result for multiple files
134#[derive(Debug, Clone, Default)]
135pub struct AnalysisResult {
136    pub files: Vec<FileAnalysis>,
137}
138
139impl AnalysisResult {
140    pub fn new() -> Self {
141        Self::default()
142    }
143
144    pub fn add_file(&mut self, analysis: FileAnalysis) {
145        self.files.push(analysis);
146    }
147
148    pub fn all_ui_elements(&self) -> impl Iterator<Item = &UiElement> {
149        self.files.iter().flat_map(|f| &f.ui_elements)
150    }
151
152    pub fn all_actions(&self) -> impl Iterator<Item = &Action> {
153        self.files.iter().flat_map(|f| &f.actions)
154    }
155
156    pub fn all_state_mutations(&self) -> impl Iterator<Item = &StateMutation> {
157        self.files.iter().flat_map(|f| &f.state_mutations)
158    }
159}