Skip to content

Commit 1edf96b

Browse files
committed
Enhanced code refactoring
1 parent 2e14923 commit 1edf96b

File tree

2 files changed

+409
-6
lines changed

2 files changed

+409
-6
lines changed

crates/cli/src/commands/doctor.rs

Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
//! Doctor command implementation for system validation
2+
3+
use crate::cli::{Cli, Commands};
4+
use anyhow::{Result, Context};
5+
use colored::*;
6+
use console::Term;
7+
use smart_diff_parser::{Parser, LanguageDetector, Language};
8+
use smart_diff_semantic::SemanticAnalyzer;
9+
use smart_diff_engine::{DiffEngine, RefactoringDetector, SimilarityScorer};
10+
use std::collections::HashMap;
11+
use tracing::{info, warn, error};
12+
13+
pub async fn run(cli: Cli) -> Result<()> {
14+
if let Commands::Doctor { component, fix } = cli.command {
15+
let term = Term::stdout();
16+
17+
if !cli.quiet {
18+
term.write_line(&format!("{}", "Smart Code Diff - System Diagnostics".bold().blue()))?;
19+
term.write_line(&format!("{}", "=".repeat(45).dim()))?;
20+
term.write_line("")?;
21+
}
22+
23+
let mut issues_found = 0;
24+
let mut issues_fixed = 0;
25+
26+
// Check core components
27+
if component.is_none() || component.as_deref() == Some("parser") {
28+
let (parser_issues, parser_fixes) = check_parser_system(&term, fix, cli.quiet).await?;
29+
issues_found += parser_issues;
30+
issues_fixed += parser_fixes;
31+
}
32+
33+
if component.is_none() || component.as_deref() == Some("semantic") {
34+
let (semantic_issues, semantic_fixes) = check_semantic_system(&term, fix, cli.quiet).await?;
35+
issues_found += semantic_issues;
36+
issues_fixed += semantic_fixes;
37+
}
38+
39+
if component.is_none() || component.as_deref() == Some("engine") {
40+
let (engine_issues, engine_fixes) = check_diff_engine(&term, fix, cli.quiet).await?;
41+
issues_found += engine_issues;
42+
issues_fixed += engine_fixes;
43+
}
44+
45+
if component.is_none() || component.as_deref() == Some("languages") {
46+
let (lang_issues, lang_fixes) = check_language_support(&term, fix, cli.quiet).await?;
47+
issues_found += lang_issues;
48+
issues_fixed += lang_fixes;
49+
}
50+
51+
if component.is_none() || component.as_deref() == Some("config") {
52+
let (config_issues, config_fixes) = check_configuration(&term, fix, cli.quiet).await?;
53+
issues_found += config_issues;
54+
issues_fixed += config_fixes;
55+
}
56+
57+
// Summary
58+
if !cli.quiet {
59+
term.write_line("")?;
60+
term.write_line(&format!("{}", "Diagnostic Summary".bold().green()))?;
61+
term.write_line(&format!("{}", "-".repeat(20).dim()))?;
62+
63+
if issues_found == 0 {
64+
term.write_line(&format!("{} All systems are functioning correctly!", "✓".green().bold()))?;
65+
} else {
66+
term.write_line(&format!("{} {} issues found", "⚠".yellow().bold(), issues_found))?;
67+
68+
if fix && issues_fixed > 0 {
69+
term.write_line(&format!("{} {} issues automatically fixed", "✓".green().bold(), issues_fixed))?;
70+
}
71+
72+
if issues_found > issues_fixed {
73+
term.write_line(&format!("{} {} issues require manual attention",
74+
"!".red().bold(),
75+
issues_found - issues_fixed))?;
76+
}
77+
}
78+
}
79+
80+
// Exit with error code if issues remain
81+
if issues_found > issues_fixed {
82+
std::process::exit(1);
83+
}
84+
85+
Ok(())
86+
} else {
87+
unreachable!("Doctor command should have been matched")
88+
}
89+
}
90+
91+
/// Check parser system functionality
92+
async fn check_parser_system(term: &Term, fix: bool, quiet: bool) -> Result<(usize, usize)> {
93+
if !quiet {
94+
term.write_line(&format!("{}", "Checking Parser System...".bold()))?;
95+
}
96+
97+
let mut issues = 0;
98+
let mut fixes = 0;
99+
100+
// Test language detector
101+
let language_detector = LanguageDetector::new();
102+
103+
// Test basic language detection
104+
let test_cases = vec![
105+
("test.java", Some(Language::Java)),
106+
("test.py", Some(Language::Python)),
107+
("test.js", Some(Language::JavaScript)),
108+
("test.cpp", Some(Language::Cpp)),
109+
("test.c", Some(Language::C)),
110+
];
111+
112+
for (filename, expected) in test_cases {
113+
let detected = language_detector.detect_from_path(std::path::Path::new(filename));
114+
if detected != expected {
115+
issues += 1;
116+
if !quiet {
117+
term.write_line(&format!(" {} Language detection failed for {}: expected {:?}, got {:?}",
118+
"✗".red(), filename, expected, detected))?;
119+
}
120+
} else if !quiet {
121+
term.write_line(&format!(" {} Language detection for {}: {:?}",
122+
"✓".green(), filename, detected.unwrap()))?;
123+
}
124+
}
125+
126+
// Test parser creation for each language
127+
let languages = vec![Language::Java, Language::Python, Language::JavaScript, Language::Cpp, Language::C];
128+
129+
for lang in languages {
130+
match std::panic::catch_unwind(|| Parser::new(lang)) {
131+
Ok(_parser) => {
132+
if !quiet {
133+
term.write_line(&format!(" {} Parser creation for {:?}: OK", "✓".green(), lang))?;
134+
}
135+
}
136+
Err(_) => {
137+
issues += 1;
138+
if !quiet {
139+
term.write_line(&format!(" {} Parser creation for {:?}: FAILED", "✗".red(), lang))?;
140+
}
141+
}
142+
}
143+
}
144+
145+
// Test basic parsing
146+
let test_code = "function test() { return 42; }";
147+
let mut parser = Parser::new(Language::JavaScript);
148+
149+
match parser.parse(test_code, Some("test.js".to_string())) {
150+
Ok(_ast) => {
151+
if !quiet {
152+
term.write_line(&format!(" {} Basic parsing test: OK", "✓".green()))?;
153+
}
154+
}
155+
Err(e) => {
156+
issues += 1;
157+
if !quiet {
158+
term.write_line(&format!(" {} Basic parsing test: FAILED ({})", "✗".red(), e))?;
159+
}
160+
}
161+
}
162+
163+
Ok((issues, fixes))
164+
}
165+
166+
/// Check semantic analysis system
167+
async fn check_semantic_system(term: &Term, fix: bool, quiet: bool) -> Result<(usize, usize)> {
168+
if !quiet {
169+
term.write_line(&format!("{}", "Checking Semantic Analysis System...".bold()))?;
170+
}
171+
172+
let mut issues = 0;
173+
let mut fixes = 0;
174+
175+
// Test semantic analyzer creation
176+
let languages = vec![Language::Java, Language::Python, Language::JavaScript, Language::Cpp, Language::C];
177+
178+
for lang in languages {
179+
match std::panic::catch_unwind(|| SemanticAnalyzer::new(lang)) {
180+
Ok(_analyzer) => {
181+
if !quiet {
182+
term.write_line(&format!(" {} Semantic analyzer for {:?}: OK", "✓".green(), lang))?;
183+
}
184+
}
185+
Err(_) => {
186+
issues += 1;
187+
if !quiet {
188+
term.write_line(&format!(" {} Semantic analyzer for {:?}: FAILED", "✗".red(), lang))?;
189+
}
190+
}
191+
}
192+
}
193+
194+
// Test basic semantic analysis
195+
let test_code = "function add(a, b) { return a + b; }";
196+
let mut parser = Parser::new(Language::JavaScript);
197+
198+
match parser.parse(test_code, Some("test.js".to_string())) {
199+
Ok(ast) => {
200+
let mut analyzer = SemanticAnalyzer::new(Language::JavaScript);
201+
match analyzer.analyze(&ast) {
202+
Ok(_symbols) => {
203+
if !quiet {
204+
term.write_line(&format!(" {} Basic semantic analysis: OK", "✓".green()))?;
205+
}
206+
}
207+
Err(e) => {
208+
issues += 1;
209+
if !quiet {
210+
term.write_line(&format!(" {} Basic semantic analysis: FAILED ({})", "✗".red(), e))?;
211+
}
212+
}
213+
}
214+
}
215+
Err(e) => {
216+
issues += 1;
217+
if !quiet {
218+
term.write_line(&format!(" {} Parse for semantic test: FAILED ({})", "✗".red(), e))?;
219+
}
220+
}
221+
}
222+
223+
Ok((issues, fixes))
224+
}
225+
226+
/// Check diff engine functionality
227+
async fn check_diff_engine(term: &Term, fix: bool, quiet: bool) -> Result<(usize, usize)> {
228+
if !quiet {
229+
term.write_line(&format!("{}", "Checking Diff Engine...".bold()))?;
230+
}
231+
232+
let mut issues = 0;
233+
let mut fixes = 0;
234+
235+
// Test diff engine creation
236+
let languages = vec![Language::Java, Language::Python, Language::JavaScript, Language::Cpp, Language::C];
237+
238+
for lang in languages {
239+
match std::panic::catch_unwind(|| DiffEngine::new(lang)) {
240+
Ok(_engine) => {
241+
if !quiet {
242+
term.write_line(&format!(" {} Diff engine for {:?}: OK", "✓".green(), lang))?;
243+
}
244+
}
245+
Err(_) => {
246+
issues += 1;
247+
if !quiet {
248+
term.write_line(&format!(" {} Diff engine for {:?}: FAILED", "✗".red(), lang))?;
249+
}
250+
}
251+
}
252+
}
253+
254+
// Test similarity scorer
255+
for lang in &languages {
256+
match std::panic::catch_unwind(|| SimilarityScorer::new(*lang)) {
257+
Ok(_scorer) => {
258+
if !quiet {
259+
term.write_line(&format!(" {} Similarity scorer for {:?}: OK", "✓".green(), lang))?;
260+
}
261+
}
262+
Err(_) => {
263+
issues += 1;
264+
if !quiet {
265+
term.write_line(&format!(" {} Similarity scorer for {:?}: FAILED", "✗".red(), lang))?;
266+
}
267+
}
268+
}
269+
}
270+
271+
// Test refactoring detector
272+
for lang in &languages {
273+
match std::panic::catch_unwind(|| RefactoringDetector::new(*lang)) {
274+
Ok(_detector) => {
275+
if !quiet {
276+
term.write_line(&format!(" {} Refactoring detector for {:?}: OK", "✓".green(), lang))?;
277+
}
278+
}
279+
Err(_) => {
280+
issues += 1;
281+
if !quiet {
282+
term.write_line(&format!(" {} Refactoring detector for {:?}: FAILED", "✗".red(), lang))?;
283+
}
284+
}
285+
}
286+
}
287+
288+
Ok((issues, fixes))
289+
}
290+
291+
/// Check language support
292+
async fn check_language_support(term: &Term, fix: bool, quiet: bool) -> Result<(usize, usize)> {
293+
if !quiet {
294+
term.write_line(&format!("{}", "Checking Language Support...".bold()))?;
295+
}
296+
297+
let mut issues = 0;
298+
let mut fixes = 0;
299+
300+
let supported_languages = vec![
301+
(Language::Java, vec!["java"]),
302+
(Language::Python, vec!["py", "pyx", "pyi"]),
303+
(Language::JavaScript, vec!["js", "jsx", "mjs", "cjs"]),
304+
(Language::Cpp, vec!["cpp", "cxx", "cc", "hpp", "hxx", "h"]),
305+
(Language::C, vec!["c", "h"]),
306+
];
307+
308+
for (lang, extensions) in supported_languages {
309+
if !quiet {
310+
term.write_line(&format!(" {} {:?} support: {} extensions",
311+
"✓".green(), lang, extensions.join(", ")))?;
312+
}
313+
}
314+
315+
Ok((issues, fixes))
316+
}
317+
318+
/// Check configuration system
319+
async fn check_configuration(term: &Term, fix: bool, quiet: bool) -> Result<(usize, usize)> {
320+
if !quiet {
321+
term.write_line(&format!("{}", "Checking Configuration System...".bold()))?;
322+
}
323+
324+
let mut issues = 0;
325+
let mut fixes = 0;
326+
327+
// Check if we can create default configurations
328+
let config_tests = vec![
329+
("RefactoringDetectionConfig", || {
330+
smart_diff_engine::RefactoringDetectionConfig::default()
331+
}),
332+
];
333+
334+
for (config_name, create_config) in config_tests {
335+
match std::panic::catch_unwind(create_config) {
336+
Ok(_config) => {
337+
if !quiet {
338+
term.write_line(&format!(" {} {} creation: OK", "✓".green(), config_name))?;
339+
}
340+
}
341+
Err(_) => {
342+
issues += 1;
343+
if !quiet {
344+
term.write_line(&format!(" {} {} creation: FAILED", "✗".red(), config_name))?;
345+
}
346+
}
347+
}
348+
}
349+
350+
Ok((issues, fixes))
351+
}

0 commit comments

Comments
 (0)