Skip to main content

ass_core/analysis/linting/
issue.rs

1//! Lint issue and source-location types.
2//!
3//! Defines [`IssueLocation`], describing where a problem occurs in source,
4//! and [`LintIssue`], the rich diagnostic produced by linting rules along
5//! with its builder-style construction API.
6
7use super::{IssueCategory, IssueSeverity};
8use alloc::string::String;
9
10/// Location information for a lint issue.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct IssueLocation {
13    /// Line number (1-based)
14    pub line: usize,
15    /// Column number (1-based)
16    pub column: usize,
17    /// Byte offset in source
18    pub offset: usize,
19    /// Length of the problematic span
20    pub length: usize,
21    /// The problematic text span
22    pub span: String,
23}
24
25/// A single lint issue found in the script.
26#[derive(Debug, Clone)]
27pub struct LintIssue {
28    /// Severity level
29    severity: IssueSeverity,
30    /// Category of issue
31    category: IssueCategory,
32    /// Human-readable message
33    message: String,
34    /// Optional detailed description
35    description: Option<String>,
36    /// Location in source (if available)
37    location: Option<IssueLocation>,
38    /// Rule ID that generated this issue
39    rule_id: &'static str,
40    /// Suggested fix (if available)
41    suggested_fix: Option<String>,
42}
43
44impl LintIssue {
45    /// Create a new lint issue.
46    #[must_use]
47    pub const fn new(
48        severity: IssueSeverity,
49        category: IssueCategory,
50        rule_id: &'static str,
51        message: String,
52    ) -> Self {
53        Self {
54            severity,
55            category,
56            message,
57            description: None,
58            location: None,
59            rule_id,
60            suggested_fix: None,
61        }
62    }
63
64    /// Add detailed description.
65    #[must_use]
66    pub fn with_description(mut self, description: String) -> Self {
67        self.description = Some(description);
68        self
69    }
70
71    /// Add location information.
72    #[must_use]
73    pub fn with_location(mut self, location: IssueLocation) -> Self {
74        self.location = Some(location);
75        self
76    }
77
78    /// Add suggested fix.
79    #[must_use]
80    pub fn with_suggested_fix(mut self, fix: String) -> Self {
81        self.suggested_fix = Some(fix);
82        self
83    }
84
85    /// Get severity level.
86    #[must_use]
87    pub const fn severity(&self) -> IssueSeverity {
88        self.severity
89    }
90
91    /// Get issue category.
92    #[must_use]
93    pub const fn category(&self) -> IssueCategory {
94        self.category
95    }
96
97    /// Get issue message.
98    #[must_use]
99    pub fn message(&self) -> &str {
100        &self.message
101    }
102
103    /// Get detailed description.
104    #[must_use]
105    pub fn description(&self) -> Option<&str> {
106        self.description.as_deref()
107    }
108
109    /// Get location information.
110    #[must_use]
111    pub const fn location(&self) -> Option<&IssueLocation> {
112        self.location.as_ref()
113    }
114
115    /// Get rule ID.
116    #[must_use]
117    pub const fn rule_id(&self) -> &'static str {
118        self.rule_id
119    }
120
121    /// Get suggested fix.
122    #[must_use]
123    pub fn suggested_fix(&self) -> Option<&str> {
124        self.suggested_fix.as_deref()
125    }
126}