tldr_core/patterns/
format.rs1use crate::types::{NamingConvention, PatternReport};
6
7pub fn format_pattern_report_text(report: &PatternReport) -> String {
9 let mut output = String::new();
10
11 output.push_str("# Pattern Analysis Report\n\n");
13
14 output.push_str("## Summary\n");
16 output.push_str(&format!(
17 "- Files analyzed: {}\n",
18 report.metadata.files_analyzed
19 ));
20 output.push_str(&format!(
21 "- Files skipped: {}\n",
22 report.metadata.files_skipped
23 ));
24 output.push_str(&format!("- Duration: {}ms\n", report.metadata.duration_ms));
25 output.push_str(&format!(
26 "- Patterns found: {}\n\n",
27 report.metadata.patterns_after_filter
28 ));
29
30 if !report
32 .metadata
33 .language_distribution
34 .files_by_language
35 .is_empty()
36 {
37 output.push_str("### Languages\n");
38 for (lang, count) in &report.metadata.language_distribution.files_by_language {
39 output.push_str(&format!("- {}: {} files\n", lang, count));
40 }
41 output.push('\n');
42 }
43
44 if let Some(ref pattern) = report.soft_delete {
46 output.push_str("## Soft Delete Pattern\n");
47 output.push_str(&format!("- Detected: {}\n", pattern.detected));
48 output.push_str(&format!(
49 "- Confidence: {:.0}%\n",
50 pattern.confidence * 100.0
51 ));
52 if !pattern.column_names.is_empty() {
53 output.push_str(&format!("- Columns: {}\n", pattern.column_names.join(", ")));
54 }
55 output.push('\n');
56 }
57
58 if let Some(ref pattern) = report.error_handling {
59 output.push_str("## Error Handling\n");
60 output.push_str(&format!(
61 "- Confidence: {:.0}%\n",
62 pattern.confidence * 100.0
63 ));
64 if !pattern.patterns.is_empty() {
65 output.push_str(&format!("- Patterns: {}\n", pattern.patterns.join(", ")));
66 }
67 if !pattern.exception_types.is_empty() {
68 output.push_str(&format!(
69 "- Exception types: {}\n",
70 pattern.exception_types.join(", ")
71 ));
72 }
73 output.push('\n');
74 }
75
76 if let Some(ref pattern) = report.naming {
77 output.push_str("## Naming Conventions\n");
78 output.push_str(&format!(
79 "- Consistency: {:.0}%\n",
80 pattern.consistency_score * 100.0
81 ));
82 output.push_str(&format!(
83 "- Functions: {}\n",
84 convention_name(&pattern.functions)
85 ));
86 output.push_str(&format!(
87 "- Classes: {}\n",
88 convention_name(&pattern.classes)
89 ));
90 output.push_str(&format!(
91 "- Constants: {}\n",
92 convention_name(&pattern.constants)
93 ));
94 if let Some(ref prefix) = pattern.private_prefix {
95 output.push_str(&format!("- Private prefix: '{}'\n", prefix));
96 }
97 if !pattern.violations.is_empty() {
98 output.push_str(&format!("- Violations: {}\n", pattern.violations.len()));
99 }
100 output.push('\n');
101 }
102
103 if let Some(ref pattern) = report.resource_management {
104 output.push_str("## Resource Management\n");
105 output.push_str(&format!(
106 "- Confidence: {:.0}%\n",
107 pattern.confidence * 100.0
108 ));
109 if !pattern.patterns.is_empty() {
110 output.push_str(&format!("- Patterns: {}\n", pattern.patterns.join(", ")));
111 }
112 output.push('\n');
113 }
114
115 if let Some(ref pattern) = report.validation {
116 output.push_str("## Input Validation\n");
117 output.push_str(&format!(
118 "- Confidence: {:.0}%\n",
119 pattern.confidence * 100.0
120 ));
121 if !pattern.frameworks.is_empty() {
122 output.push_str(&format!(
123 "- Frameworks: {}\n",
124 pattern.frameworks.join(", ")
125 ));
126 }
127 if !pattern.patterns.is_empty() {
128 output.push_str(&format!("- Patterns: {}\n", pattern.patterns.join(", ")));
129 }
130 output.push('\n');
131 }
132
133 if let Some(ref pattern) = report.test_idioms {
134 output.push_str("## Test Idioms\n");
135 output.push_str(&format!(
136 "- Confidence: {:.0}%\n",
137 pattern.confidence * 100.0
138 ));
139 if let Some(ref framework) = pattern.framework {
140 output.push_str(&format!("- Framework: {}\n", framework));
141 }
142 if !pattern.patterns.is_empty() {
143 output.push_str(&format!("- Patterns: {}\n", pattern.patterns.join(", ")));
144 }
145 output.push_str(&format!("- Fixture usage: {}\n", pattern.fixture_usage));
146 output.push_str(&format!("- Mock usage: {}\n", pattern.mock_usage));
147 output.push('\n');
148 }
149
150 if let Some(ref pattern) = report.import_patterns {
151 output.push_str("## Import Patterns\n");
152 output.push_str(&format!("- Grouping: {:?}\n", pattern.grouping_style));
153 output.push_str(&format!("- Style: {:?}\n", pattern.absolute_vs_relative));
154 output.push_str(&format!("- Star imports: {:?}\n", pattern.star_imports));
155 if !pattern.alias_conventions.is_empty() {
156 output.push_str("- Aliases:\n");
157 for alias in &pattern.alias_conventions {
158 output.push_str(&format!(" - {} -> {}\n", alias.module, alias.alias));
159 }
160 }
161 output.push('\n');
162 }
163
164 if let Some(ref pattern) = report.type_coverage {
165 output.push_str("## Type Coverage\n");
166 output.push_str(&format!(
167 "- Overall: {:.0}%\n",
168 pattern.coverage_overall * 100.0
169 ));
170 output.push_str(&format!(
171 "- Functions: {:.0}%\n",
172 pattern.coverage_functions * 100.0
173 ));
174 output.push_str(&format!(
175 "- Variables: {:.0}%\n",
176 pattern.coverage_variables * 100.0
177 ));
178 output.push_str(&format!("- TypeVar usage: {}\n", pattern.typevar_usage));
179 if !pattern.generic_patterns.is_empty() {
180 output.push_str(&format!(
181 "- Generic patterns: {}\n",
182 pattern.generic_patterns.join(", ")
183 ));
184 }
185 output.push('\n');
186 }
187
188 if let Some(ref pattern) = report.api_conventions {
189 output.push_str("## API Conventions\n");
190 output.push_str(&format!(
191 "- Confidence: {:.0}%\n",
192 pattern.confidence * 100.0
193 ));
194 if let Some(ref framework) = pattern.framework {
195 output.push_str(&format!("- Framework: {}\n", framework));
196 }
197 if !pattern.patterns.is_empty() {
198 output.push_str(&format!("- Patterns: {}\n", pattern.patterns.join(", ")));
199 }
200 if let Some(ref orm) = pattern.orm_usage {
201 output.push_str(&format!("- ORM: {}\n", orm));
202 }
203 output.push('\n');
204 }
205
206 if let Some(ref pattern) = report.async_patterns {
207 output.push_str("## Async/Concurrency\n");
208 output.push_str(&format!(
209 "- Confidence: {:.0}%\n",
210 pattern.concurrency_confidence * 100.0
211 ));
212 if !pattern.patterns.is_empty() {
213 output.push_str(&format!("- Patterns: {}\n", pattern.patterns.join(", ")));
214 }
215 if !pattern.sync_primitives.is_empty() {
216 output.push_str(&format!(
217 "- Sync primitives: {}\n",
218 pattern.sync_primitives.join(", ")
219 ));
220 }
221 output.push('\n');
222 }
223
224 if !report.constraints.is_empty() {
226 output.push_str("## LLM Constraints\n");
227 for constraint in &report.constraints {
228 output.push_str(&format!(
229 "- [{}] {}\n",
230 constraint.category, constraint.rule
231 ));
232 }
233 output.push('\n');
234 }
235
236 if !report.conflicts.is_empty() {
238 output.push_str("## Conflicts Detected\n");
239 for conflict in &report.conflicts {
240 output.push_str(&format!("- {}\n", conflict));
241 }
242 output.push('\n');
243 }
244
245 output
246}
247
248fn convention_name(conv: &NamingConvention) -> &'static str {
249 match conv {
250 NamingConvention::SnakeCase => "snake_case",
251 NamingConvention::CamelCase => "camelCase",
252 NamingConvention::PascalCase => "PascalCase",
253 NamingConvention::UpperSnakeCase => "UPPER_SNAKE_CASE",
254 NamingConvention::Mixed => "Mixed",
255 }
256}