garbage_code_hunter/
utils.rs1fn is_comment_line(trimmed: &str) -> bool {
5 trimmed.starts_with("///")
6 || trimmed.starts_with("//!")
7 || trimmed.starts_with("//")
8 || trimmed.starts_with("/*")
9 || trimmed.starts_with("*")
10}
11
12pub fn find_line_of_str(content: &str, target: &str) -> usize {
14 for (i, line) in content.lines().enumerate() {
15 let trimmed = line.trim();
16 if is_comment_line(trimmed) {
17 continue;
18 }
19 if line.contains(target) {
20 return i + 1;
21 }
22 }
23 1
24}
25
26pub fn find_line_of_str_non_import(content: &str, target: &str) -> usize {
28 for (i, line) in content.lines().enumerate() {
29 let trimmed = line.trim();
30 if is_comment_line(trimmed) || trimmed.starts_with("use ") {
31 continue;
32 }
33 if line.contains(target) {
34 return i + 1;
35 }
36 }
37 1
38}
39
40pub fn count_non_comment_matches(content: &str, target: &str) -> usize {
42 let mut count = 0;
43 for line in content.lines() {
44 let trimmed = line.trim();
45 if is_comment_line(trimmed) {
46 continue;
47 }
48 count += line.matches(target).count();
49 }
50 count
51}
52
53pub fn get_position_from_content(content: &str, byte_offset: usize) -> (usize, usize) {
55 let mut line = 1;
56 let mut col = 1;
57 for (i, ch) in content.char_indices() {
58 if i >= byte_offset {
59 break;
60 }
61 if ch == '\n' {
62 line += 1;
63 col = 1;
64 } else {
65 col += 1;
66 }
67 }
68 (line, col)
69}
70
71pub fn truncate(s: &str, max: usize) -> String {
75 if s.len() <= max {
76 s.to_string()
77 } else {
78 let mut end = max.saturating_sub(3);
79 while !s.is_char_boundary(end) && end > 0 {
81 end -= 1;
82 }
83 format!("{}...", &s[..end])
84 }
85}
86
87pub fn count_non_import_matches(content: &str, target: &str) -> usize {
89 let mut count = 0;
90 for line in content.lines() {
91 let trimmed = line.trim();
92 if is_comment_line(trimmed) || trimmed.starts_with("use ") {
93 continue;
94 }
95 count += line.matches(target).count();
96 }
97 count
98}