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