Skip to main content

oak_pretty_print/comment/
mod.rs

1/// 临时的位置类型
2#[derive(Debug, Clone, PartialEq)]
3pub struct Position {
4    pub line: usize,
5    pub column: usize,
6    pub offset: usize,
7}
8
9/// 临时的源码范围类型
10#[derive(Debug, Clone, PartialEq)]
11pub struct SourceSpan {
12    pub start: Position,
13    pub end: Position,
14}
15
16/// 注释类型
17#[derive(Debug, Clone, PartialEq)]
18pub enum CommentKind {
19    /// 行注释 (如 // 或 #)
20    Line,
21    /// 块注释 (如 /* */ 或 """ """)
22    Block,
23    /// 文档注释 (如 /// 或 /** */)
24    Doc,
25}
26
27/// 注释信息
28#[derive(Debug, Clone, PartialEq)]
29pub struct Comment {
30    /// 注释类型
31    pub kind: CommentKind,
32    /// 注释内容(不包含注释标记)
33    pub content: String,
34    /// 注释在源码中的位置
35    pub span: SourceSpan,
36    /// 是否在行尾
37    pub is_trailing: bool,
38    /// 缩进级别
39    pub indent_level: usize,
40}
41
42impl Comment {
43    pub fn new(kind: CommentKind, content: String, span: SourceSpan) -> Self {
44        Self { kind, content, span, is_trailing: false, indent_level: 0 }
45    }
46
47    pub fn line(content: String, span: SourceSpan) -> Self {
48        Self::new(CommentKind::Line, content, span)
49    }
50
51    pub fn block(content: String, span: SourceSpan) -> Self {
52        Self::new(CommentKind::Block, content, span)
53    }
54
55    pub fn doc(content: String, span: SourceSpan) -> Self {
56        Self::new(CommentKind::Doc, content, span)
57    }
58
59    pub fn with_trailing(mut self, is_trailing: bool) -> Self {
60        self.is_trailing = is_trailing;
61        self
62    }
63
64    pub fn with_indent_level(mut self, level: usize) -> Self {
65        self.indent_level = level;
66        self
67    }
68
69    /// 获取格式化后的注释文本
70    pub fn formatted_text(&self, indent: &str) -> String {
71        let prefix = match self.kind {
72            CommentKind::Line => "//",
73            CommentKind::Block => "/*",
74            CommentKind::Doc => "///",
75        };
76
77        let suffix = match self.kind {
78            CommentKind::Block => " */",
79            _ => "",
80        };
81
82        if self.content.trim().is_empty() {
83            format!("{}{}{}", prefix, self.content, suffix)
84        }
85        else {
86            match self.kind {
87                CommentKind::Line | CommentKind::Doc => {
88                    format!("{} {}", prefix, self.content.trim())
89                }
90                CommentKind::Block => {
91                    if self.content.contains('\n') {
92                        // 多行块注释
93                        let lines: Vec<&str> = self.content.lines().collect();
94                        let mut result = String::new();
95                        result.push_str("/*\n");
96                        for line in lines {
97                            result.push_str(indent);
98                            result.push_str(" * ");
99                            result.push_str(line.trim());
100                            result.push('\n');
101                        }
102                        result.push_str(indent);
103                        result.push_str(" */");
104                        result
105                    }
106                    else {
107                        // 单行块注释
108                        format!("/* {} */", self.content.trim())
109                    }
110                }
111            }
112        }
113    }
114}
115
116/// 注释收集器,用于从源码中提取注释
117#[derive(Debug, Clone, PartialEq)]
118pub struct CommentCollector {
119    comments: Vec<Comment>,
120}
121
122impl CommentCollector {
123    pub fn new() -> Self {
124        Self { comments: Vec::new() }
125    }
126
127    pub fn add_comment(&mut self, comment: Comment) {
128        self.comments.push(comment);
129    }
130
131    pub fn comments(&self) -> &[Comment] {
132        &self.comments
133    }
134
135    pub fn comments_mut(&mut self) -> &mut Vec<Comment> {
136        &mut self.comments
137    }
138
139    /// 获取指定位置范围内的注释
140    pub fn comments_in_range(&self, start: Position, end: Position) -> Vec<&Comment> {
141        self.comments.iter().filter(|comment| comment.span.start.offset >= start.offset && comment.span.end.offset <= end.offset).collect()
142    }
143
144    /// 获取指定位置之前的注释
145    pub fn comments_before(&self, position: Position) -> Vec<&Comment> {
146        self.comments.iter().filter(|comment| comment.span.end.offset <= position.offset).collect()
147    }
148
149    /// 获取指定位置之后的注释
150    pub fn comments_after(&self, position: Position) -> Vec<&Comment> {
151        self.comments.iter().filter(|comment| comment.span.start.offset >= position.offset).collect()
152    }
153
154    /// 获取行尾注释
155    pub fn trailing_comments(&self) -> Vec<&Comment> {
156        self.comments.iter().filter(|comment| comment.is_trailing).collect()
157    }
158
159    /// 清空所有注释
160    pub fn clear(&mut self) {
161        self.comments.clear();
162    }
163
164    /// 按位置排序注释
165    pub fn sort_by_position(&mut self) {
166        self.comments.sort_by(|a, b| a.span.start.offset.cmp(&b.span.start.offset));
167    }
168}
169
170impl Default for CommentCollector {
171    fn default() -> Self {
172        Self::new()
173    }
174}
175
176/// 注释处理器,负责在格式化过程中处理注释
177#[derive(Debug, Clone)]
178pub struct CommentProcessor {
179    collector: CommentCollector,
180    preserve_comments: bool,
181    format_comments: bool,
182}
183
184impl CommentProcessor {
185    pub fn new() -> Self {
186        Self { collector: CommentCollector::new(), preserve_comments: true, format_comments: true }
187    }
188
189    pub fn with_preserve_comments(mut self, preserve: bool) -> Self {
190        self.preserve_comments = preserve;
191        self
192    }
193
194    pub fn with_format_comments(mut self, format: bool) -> Self {
195        self.format_comments = format;
196        self
197    }
198
199    pub fn collector(&self) -> &CommentCollector {
200        &self.collector
201    }
202
203    pub fn collector_mut(&mut self) -> &mut CommentCollector {
204        &mut self.collector
205    }
206
207    /// 处理注释,返回格式化后的注释文本
208    pub fn process_comments(&self, comments: &[Comment], indent: &str) -> Vec<String> {
209        if !self.preserve_comments {
210            return Vec::new();
211        }
212
213        comments
214            .iter()
215            .map(|comment| {
216                if self.format_comments {
217                    comment.formatted_text(indent)
218                }
219                else {
220                    // 保持原始格式
221                    comment.content.clone()
222                }
223            })
224            .collect()
225    }
226
227    /// 在指定位置插入注释
228    pub fn insert_comments_at_position(&self, output: &mut String, position: Position, indent: &str) {
229        let comments = self.collector.comments_before(position);
230        for comment in comments {
231            if !comment.is_trailing {
232                output.push_str(indent);
233                output.push_str(&comment.formatted_text(indent));
234                output.push('\n');
235            }
236        }
237    }
238
239    /// 插入行尾注释
240    pub fn insert_trailing_comment(&self, output: &mut String, position: Position) {
241        let comments = self.collector.comments_after(position);
242        for comment in comments {
243            if comment.is_trailing {
244                output.push(' ');
245                output.push_str(&comment.formatted_text(""));
246                break; // 只处理第一个行尾注释
247            }
248        }
249    }
250}
251
252impl Default for CommentProcessor {
253    fn default() -> Self {
254        Self::new()
255    }
256}