Skip to main content

shape_ast/error/parse_error/
mod.rs

1//! Structured parse error types for Shape
2//!
3//! These types represent parse errors as structured data rather than strings,
4//! enabling different rendering for CLI vs LSP contexts.
5
6use super::{ErrorCode, SourceLocation};
7
8// Module declarations
9mod formatting;
10mod kinds;
11mod source_context;
12mod suggestions;
13mod tokens;
14
15#[cfg(test)]
16mod tests;
17
18// Re-export all public types
19pub use formatting::{format_error_message, matching_close, rule_to_friendly_name};
20pub use kinds::{
21    ErrorSeverity, IdentifierContext, MissingComponentKind, NumberError, ParseErrorKind,
22    StringDelimiter,
23};
24pub use source_context::{Highlight, HighlightStyle, SourceContext, SourceLine};
25pub use suggestions::{RelatedInfo, Suggestion, SuggestionConfidence, TextEdit};
26pub use tokens::{ExpectedToken, TokenCategory, TokenInfo, TokenKind};
27
28/// A complete structured parse error with all context needed for rendering
29#[derive(Debug, Clone)]
30pub struct StructuredParseError {
31    /// The specific error kind
32    pub kind: ParseErrorKind,
33
34    /// Primary location of the error
35    pub location: SourceLocation,
36
37    /// Optional span end for range errors
38    pub span_end: Option<(usize, usize)>,
39
40    /// The source code snippet around the error
41    pub source_context: SourceContext,
42
43    /// Computed suggestions based on error kind
44    pub suggestions: Vec<Suggestion>,
45
46    /// Related locations (e.g., where a brace was opened)
47    pub related: Vec<RelatedInfo>,
48
49    /// Error severity
50    pub severity: ErrorSeverity,
51
52    /// Error code for documentation lookup
53    pub code: ErrorCode,
54}
55
56impl StructuredParseError {
57    pub fn new(kind: ParseErrorKind, location: SourceLocation) -> Self {
58        Self {
59            kind,
60            location,
61            span_end: None,
62            source_context: SourceContext::default(),
63            suggestions: Vec::new(),
64            related: Vec::new(),
65            severity: ErrorSeverity::Error,
66            code: ErrorCode::E0001,
67        }
68    }
69
70    pub fn with_span_end(mut self, line: usize, col: usize) -> Self {
71        self.span_end = Some((line, col));
72        self
73    }
74
75    pub fn with_source_context(mut self, ctx: SourceContext) -> Self {
76        self.source_context = ctx;
77        self
78    }
79
80    pub fn with_suggestion(mut self, suggestion: Suggestion) -> Self {
81        self.suggestions.push(suggestion);
82        self
83    }
84
85    pub fn with_suggestions(mut self, suggestions: impl IntoIterator<Item = Suggestion>) -> Self {
86        self.suggestions.extend(suggestions);
87        self
88    }
89
90    pub fn with_related(mut self, info: RelatedInfo) -> Self {
91        self.related.push(info);
92        self
93    }
94
95    pub fn with_severity(mut self, severity: ErrorSeverity) -> Self {
96        self.severity = severity;
97        self
98    }
99
100    pub fn with_code(mut self, code: ErrorCode) -> Self {
101        self.code = code;
102        self
103    }
104}
105
106impl std::fmt::Display for StructuredParseError {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        // Simple display - detailed rendering is done by ErrorRenderer
109        write!(f, "{}", format_error_message(&self.kind))
110    }
111}
112
113impl std::error::Error for StructuredParseError {}