cairo_lang_defs/
diagnostic_utils.rs

1use std::fmt;
2
3use cairo_lang_debug::DebugWithDb;
4use cairo_lang_diagnostics::DiagnosticLocation;
5use cairo_lang_filesystem::ids::FileId;
6use cairo_lang_filesystem::span::TextSpan;
7use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
8use cairo_lang_syntax::node::{SyntaxNode, TypedSyntaxNode};
9
10use crate::db::DefsGroup;
11
12/// A stable location of a real, concrete syntax.
13#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
14pub struct StableLocation(SyntaxStablePtrId);
15impl StableLocation {
16    pub fn new(stable_ptr: SyntaxStablePtrId) -> Self {
17        Self(stable_ptr)
18    }
19
20    pub fn file_id(&self, db: &dyn DefsGroup) -> FileId {
21        self.0.file_id(db.upcast())
22    }
23
24    pub fn from_ast<TNode: TypedSyntaxNode>(node: &TNode) -> Self {
25        Self(node.as_syntax_node().stable_ptr())
26    }
27
28    /// Returns the [SyntaxNode] that corresponds to the [StableLocation].
29    pub fn syntax_node(&self, db: &dyn DefsGroup) -> SyntaxNode {
30        self.0.lookup(db.upcast())
31    }
32
33    /// Returns the [DiagnosticLocation] that corresponds to the [StableLocation].
34    pub fn diagnostic_location(&self, db: &dyn DefsGroup) -> DiagnosticLocation {
35        let syntax_node = self.syntax_node(db);
36        DiagnosticLocation {
37            file_id: self.file_id(db),
38            span: syntax_node.span_without_trivia(db.upcast()),
39        }
40    }
41
42    /// Returns the [DiagnosticLocation] that corresponds to the [StableLocation].
43    pub fn diagnostic_location_until(
44        &self,
45        db: &dyn DefsGroup,
46        until_stable_ptr: SyntaxStablePtrId,
47    ) -> DiagnosticLocation {
48        let syntax_db = db.upcast();
49        let start = self.0.lookup(syntax_db).span_start_without_trivia(syntax_db);
50        let end = until_stable_ptr.lookup(syntax_db).span_end_without_trivia(syntax_db);
51        DiagnosticLocation { file_id: self.0.file_id(syntax_db), span: TextSpan { start, end } }
52    }
53}
54
55impl DebugWithDb<dyn DefsGroup> for StableLocation {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>, db: &dyn DefsGroup) -> fmt::Result {
57        let diag_location = self.diagnostic_location(db);
58        diag_location.fmt_location(f, db.upcast())
59    }
60}