cairo_lang_defs/
diagnostic_utils.rs1use std::fmt;
2
3use cairo_lang_debug::DebugWithDb;
4use cairo_lang_filesystem::ids::{FileId, SpanInFile};
5use cairo_lang_filesystem::span::{TextSpan, TextWidth};
6use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
7use cairo_lang_syntax::node::{SyntaxNode, TypedSyntaxNode};
8use salsa::Database;
9
10#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
12pub struct StableLocation<'db> {
13 stable_ptr: SyntaxStablePtrId<'db>,
14 inner_span: Option<(TextWidth, TextWidth)>,
18}
19
20impl<'db> StableLocation<'db> {
21 pub fn new(stable_ptr: SyntaxStablePtrId<'db>) -> Self {
22 Self { stable_ptr, inner_span: None }
23 }
24
25 pub fn with_inner_span(
26 stable_ptr: SyntaxStablePtrId<'db>,
27 inner_span: (TextWidth, TextWidth),
28 ) -> Self {
29 Self { stable_ptr, inner_span: Some(inner_span) }
30 }
31
32 pub fn file_id(&self, db: &'db dyn Database) -> FileId<'db> {
33 self.stable_ptr.file_id(db)
34 }
35
36 pub fn from_ast<TNode: TypedSyntaxNode<'db>>(db: &'db dyn Database, node: &TNode) -> Self {
37 Self::new(node.as_syntax_node().stable_ptr(db))
38 }
39
40 pub fn syntax_node(&self, db: &'db dyn Database) -> SyntaxNode<'db> {
42 self.stable_ptr.lookup(db)
43 }
44
45 pub fn stable_ptr(&self) -> SyntaxStablePtrId<'db> {
47 self.stable_ptr
48 }
49
50 pub fn span_in_file(&self, db: &'db dyn Database) -> SpanInFile<'db> {
52 match self.inner_span {
53 Some((start, width)) => {
54 let start = self.syntax_node(db).offset(db).add_width(start);
55 SpanInFile {
56 file_id: self.file_id(db),
57 span: TextSpan::new_with_width(start, width),
58 }
59 }
60 None => {
61 let syntax_node = self.syntax_node(db);
62 SpanInFile { file_id: self.file_id(db), span: syntax_node.span_without_trivia(db) }
63 }
64 }
65 }
66
67 pub fn span_in_file_until(
70 &self,
71 db: &'db dyn Database,
72 until_stable_ptr: SyntaxStablePtrId<'db>,
73 ) -> SpanInFile<'db> {
74 let start = self.stable_ptr.lookup(db).span_start_without_trivia(db);
75 let end = until_stable_ptr.lookup(db).span_end_without_trivia(db);
76 SpanInFile { file_id: self.stable_ptr.file_id(db), span: TextSpan::new(start, end) }
77 }
78}
79
80impl<'db> DebugWithDb<'db> for StableLocation<'db> {
81 type Db = dyn Database;
82
83 fn fmt(&self, f: &mut fmt::Formatter<'_>, db: &'db dyn Database) -> fmt::Result {
84 let diag_location = self.span_in_file(db);
85 diag_location.fmt_location(f, db)
86 }
87}