gobject_ast/model/
comment.rs1use serde::Serialize;
2
3use crate::model::SourceLocation;
4
5#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
6#[serde(rename_all = "snake_case")]
7pub enum CommentKind {
8 Line,
10 Block,
12}
13
14#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
15#[serde(rename_all = "snake_case")]
16pub enum CommentPosition {
17 Leading,
19 Trailing,
21 Inner,
23}
24
25#[derive(Debug, Clone, Serialize)]
26pub struct Comment {
27 pub text: String,
29 pub location: SourceLocation,
31 pub kind: CommentKind,
33 pub position: CommentPosition,
35}
36
37impl Comment {
38 pub fn new(
39 text: String,
40 location: SourceLocation,
41 kind: CommentKind,
42 position: CommentPosition,
43 ) -> Self {
44 Self {
45 text,
46 location,
47 kind,
48 position,
49 }
50 }
51
52 pub fn contains(&self, pattern: &str) -> bool {
54 self.body().to_lowercase().contains(&pattern.to_lowercase())
55 }
56
57 pub fn body(&self) -> &str {
59 let t = self.text.trim();
60 match self.kind {
61 CommentKind::Line => t.strip_prefix("//").unwrap_or(t).trim_start(),
62 CommentKind::Block => t
63 .strip_prefix("/*")
64 .and_then(|s| s.strip_suffix("*/"))
65 .unwrap_or(t)
66 .trim(),
67 }
68 }
69
70 pub fn extract_ignore_rules(&self) -> Option<Vec<String>> {
73 let text = self.body();
74
75 if let Some(after_prefix) = text
76 .strip_prefix("gobject-linter-ignore:")
77 .or_else(|| text.strip_prefix("gobject-linter-ignore-next-line:"))
78 .or_else(|| text.strip_prefix("goblint-ignore:"))
79 .or_else(|| text.strip_prefix("goblint-ignore-next-line:"))
80 {
81 let rules: Vec<String> = after_prefix
82 .split(',')
83 .map(|s| s.trim().to_string())
84 .filter(|s| !s.is_empty())
85 .collect();
86 return Some(rules);
87 }
88
89 None
90 }
91
92 pub fn is_gtk_doc(&self) -> bool {
94 matches!(self.kind, CommentKind::Block)
95 && matches!(self.position, CommentPosition::Leading)
96 && self.text.starts_with("/**")
97 }
98
99 pub fn is_marker(&self) -> bool {
101 let upper = self.body().to_uppercase();
102 upper.contains("TODO")
103 || upper.contains("FIXME")
104 || upper.contains("HACK")
105 || upper.contains("XXX")
106 }
107}