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 [SyntaxStablePtrId] of the [StableLocation].
34    pub fn stable_ptr(&self) -> SyntaxStablePtrId {
35        self.0
36    }
37
38    /// Returns the [DiagnosticLocation] that corresponds to the [StableLocation].
39    pub fn diagnostic_location(&self, db: &dyn DefsGroup) -> DiagnosticLocation {
40        let syntax_node = self.syntax_node(db);
41        DiagnosticLocation {
42            file_id: self.file_id(db),
43            span: syntax_node.span_without_trivia(db.upcast()),
44        }
45    }
46
47    /// Returns the [DiagnosticLocation] that corresponds to the [StableLocation].
48    pub fn diagnostic_location_until(
49        &self,
50        db: &dyn DefsGroup,
51        until_stable_ptr: SyntaxStablePtrId,
52    ) -> DiagnosticLocation {
53        let syntax_db = db.upcast();
54        let start = self.0.lookup(syntax_db).span_start_without_trivia(syntax_db);
55        let end = until_stable_ptr.lookup(syntax_db).span_end_without_trivia(syntax_db);
56        DiagnosticLocation { file_id: self.0.file_id(syntax_db), span: TextSpan { start, end } }
57    }
58}
59
60impl DebugWithDb<dyn DefsGroup> for StableLocation {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>, db: &dyn DefsGroup) -> fmt::Result {
62        let diag_location = self.diagnostic_location(db);
63        diag_location.fmt_location(f, db.upcast())
64    }
65}