slang_frontend/semantic_analysis/
error_collector.rs

1use std::collections::HashSet;
2use slang_error::{CompilerError, ErrorCode};
3use slang_shared::CompilationContext;
4use super::error::SemanticAnalysisError;
5
6/// A centralized error collector that handles error creation, formatting, and deduplication
7/// 
8/// This provides a single source of truth for error handling in the semantic analysis system,
9/// ensuring consistent error formatting and efficient deduplication.
10pub struct ErrorCollector {
11    errors: Vec<CompilerError>,
12    seen_errors: HashSet<ErrorKey>,
13}
14
15/// Key for error deduplication that groups semantically similar errors
16#[derive(Hash, PartialEq, Eq, Clone)]
17struct ErrorKey {
18    code: ErrorCode,
19    line: usize,
20    column: usize,
21    message: String,
22}
23
24impl ErrorCollector {
25    /// Create a new error collector
26    pub fn new() -> Self {
27        Self {
28            errors: Vec::new(),
29            seen_errors: HashSet::new(),
30        }
31    }
32
33    /// Add a semantic analysis error to the collection
34    /// 
35    /// # Arguments
36    /// * `error` - The semantic analysis error to add
37    /// * `context` - The compilation context for error conversion
38    /// 
39    /// # Returns
40    /// `true` if the error was added (not a duplicate), `false` if it was deduplicated
41    pub fn add_semantic_error(&mut self, error: SemanticAnalysisError, context: &CompilationContext) -> bool {
42        let compiler_error = error.to_compiler_error(context);
43        self.add_compiler_error(compiler_error)
44    }
45
46    /// Add a compiler error directly to the collection
47    /// 
48    /// # Arguments
49    /// * `error` - The compiler error to add
50    /// 
51    /// # Returns
52    /// `true` if the error was added (not a duplicate), `false` if it was deduplicated
53    pub fn add_compiler_error(&mut self, error: CompilerError) -> bool {
54        let key = ErrorKey {
55            code: error.error_code,
56            line: error.line,
57            column: error.column,
58            message: error.message.clone(),
59        };
60
61        if self.seen_errors.insert(key) {
62            self.errors.push(error);
63            true
64        } else {
65            false
66        }
67    }
68
69    /// Get all collected errors
70    pub fn into_errors(self) -> Vec<CompilerError> {
71        self.errors
72    }
73
74    /// Check if any errors have been collected
75    pub fn has_errors(&self) -> bool {
76        !self.errors.is_empty()
77    }
78
79    /// Get the number of unique errors collected
80    pub fn error_count(&self) -> usize {
81        self.errors.len()
82    }
83
84}
85
86impl Default for ErrorCollector {
87    fn default() -> Self {
88        Self::new()
89    }
90}