deepseek_rust_cli/tools/file/
analysis.rs1use std::{collections::HashMap, path::Path};
2
3use anyhow::Result;
4use async_trait::async_trait;
5use serde_json::Value;
6use walkdir::WalkDir;
7
8use crate::{agent::types::UndoAction, tools::base::Tool};
9
10pub struct ProjectSummaryTool;
11#[async_trait]
12impl Tool for ProjectSummaryTool {
13 fn name(&self) -> &str {
14 "summarize_project"
15 }
16 async fn execute(
17 &self,
18 _args: &HashMap<String, Value>,
19 _undo: &mut Vec<UndoAction>,
20 _cwd: Option<&Path>,
21 ) -> Result<String> {
22 let mut extensions: HashMap<String, usize> = HashMap::new();
23 let mut total_files = 0;
24 let mut total_lines = 0;
25 let mut core_files = Vec::new();
26
27 for entry in WalkDir::new(".").into_iter().filter_map(|e| e.ok()) {
28 if entry.file_type().is_file() {
29 let path = entry.path();
30 if path.to_string_lossy().contains(".git")
31 || path.to_string_lossy().contains("target")
32 {
33 continue;
34 }
35
36 total_files += 1;
37 if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
38 *extensions.entry(ext.to_string()).or_insert(0) += 1;
39 }
40
41 let name = entry.file_name().to_string_lossy();
43 if name == "Cargo.toml"
44 || name == "package.json"
45 || name == "main.rs"
46 || name == "lib.rs"
47 {
48 core_files.push(path.display().to_string());
49 }
50
51 if let Ok(content) = std::fs::read_to_string(path) {
53 total_lines += content.lines().count();
54 }
55 }
56 }
57
58 let mut summary = format!(
59 "Project Summary:\n- Total Files: {}\n- Total Lines: {}\n\nCore Files Found:\n",
60 total_files, total_lines
61 );
62 for f in core_files {
63 summary.push_str(&format!(" - {}\n", f));
64 }
65
66 summary.push_str("\nFile Extensions:\n");
67 let mut ext_list: Vec<_> = extensions.into_iter().collect();
68 ext_list.sort_by_key(|x| std::cmp::Reverse(x.1));
69 for (ext, count) in ext_list.into_iter().take(10) {
70 summary.push_str(&format!(" - .{}: {} files\n", ext, count));
71 }
72
73 Ok(summary)
74 }
75}
76
77pub struct ListTodoTasksTool;
78#[async_trait]
79impl Tool for ListTodoTasksTool {
80 fn name(&self) -> &str {
81 "list_todo_tasks"
82 }
83 async fn execute(
84 &self,
85 _args: &HashMap<String, Value>,
86 _undo: &mut Vec<UndoAction>,
87 _cwd: Option<&Path>,
88 ) -> Result<String> {
89 let mut tasks = Vec::new();
90 let keywords = ["TODO", "FIXME", "HACK", "BUG"];
91
92 for entry in WalkDir::new(".").into_iter().filter_map(|e| e.ok()) {
93 if entry.file_type().is_file() {
94 let path = entry.path();
95 if path.to_string_lossy().contains(".git")
96 || path.to_string_lossy().contains("target")
97 {
98 continue;
99 }
100
101 if let Ok(content) = std::fs::read_to_string(path) {
102 for (i, line) in content.lines().enumerate() {
103 for kw in &keywords {
104 if line.contains(kw) {
105 tasks.push(format!(
106 "{}:{}: {}",
107 path.display(),
108 i + 1,
109 line.trim()
110 ));
111 }
112 }
113 }
114 }
115 }
116 }
117
118 if tasks.is_empty() {
119 Ok("No TODO/FIXME tasks found in project.".to_string())
120 } else {
121 Ok(format!(
122 "Found {} tasks:\n\n{}",
123 tasks.len(),
124 tasks.join("\n")
125 ))
126 }
127 }
128}