1use std::fmt::{self, Debug};
2
3pub use itoa::Buffer;
4use rspack_cacheable::cacheable;
5use swc_core::common::{SourceMap, Span};
6
7#[cacheable]
9#[derive(Debug, Clone, Copy)]
10pub struct SourcePosition {
11 pub line: usize,
12 pub column: usize,
13}
14
15impl From<(u32, u32)> for SourcePosition {
16 fn from(range: (u32, u32)) -> Self {
17 Self {
18 line: range.0 as usize,
19 column: range.1 as usize,
20 }
21 }
22}
23
24#[cacheable]
27#[derive(Debug, Clone)]
28pub struct RealDependencyLocation {
29 pub start: SourcePosition,
30 pub end: Option<SourcePosition>,
31}
32
33impl RealDependencyLocation {
34 pub fn new(start: SourcePosition, end: Option<SourcePosition>) -> Self {
35 Self { start, end }
36 }
37
38 pub fn from_span(span: &Span, source_map: &SourceMap) -> Self {
39 let start_char_pos = source_map.lookup_char_pos(span.lo);
40 let end_char_pos = source_map.lookup_char_pos(span.hi);
41 RealDependencyLocation::new(
42 SourcePosition {
43 line: start_char_pos.line,
44 column: start_char_pos.col_display,
45 },
46 Some(SourcePosition {
47 line: end_char_pos.line,
48 column: end_char_pos.col_display,
49 }),
50 )
51 }
52}
53
54impl fmt::Display for RealDependencyLocation {
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56 if let Some(end) = self.end {
57 let mut start_line_buffer = itoa::Buffer::new();
58 let start_line = start_line_buffer.format(self.start.line);
59 let mut start_col_buffer = itoa::Buffer::new();
60 let start_col = start_col_buffer.format(self.start.column);
61 if self.start.line == end.line && self.start.column == end.column {
62 write!(f, "{}:{}", start_line, start_col)
63 } else if self.start.line == end.line {
64 let mut end_col_buffer = itoa::Buffer::new();
65 let end_col = end_col_buffer.format(end.column);
66 write!(f, "{}:{}-{}", start_line, start_col, end_col)
67 } else {
68 let mut end_line_buffer = itoa::Buffer::new();
69 let end_line = end_line_buffer.format(end.line);
70 let mut end_col_buffer = itoa::Buffer::new();
71 let end_col = end_col_buffer.format(end.column);
72 write!(f, "{}:{}-{}:{}", start_line, start_col, end_line, end_col)
73 }
74 } else {
75 let mut start_line_buffer = itoa::Buffer::new();
76 let start_line = start_line_buffer.format(self.start.line);
77 let mut start_col_buffer = itoa::Buffer::new();
78 let start_col = start_col_buffer.format(self.start.column);
79 write!(f, "{}:{}", start_line, start_col)
80 }
81 }
82}
83
84#[cacheable]
86#[derive(Debug, Clone)]
87pub struct SyntheticDependencyLocation {
88 pub name: String,
89}
90
91impl SyntheticDependencyLocation {
92 pub fn new(name: &str) -> Self {
93 SyntheticDependencyLocation {
94 name: name.to_string(),
95 }
96 }
97}
98
99impl fmt::Display for SyntheticDependencyLocation {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 write!(f, "{}", self.name)
102 }
103}
104
105#[cacheable]
106#[derive(Debug, Clone)]
107pub enum DependencyLocation {
108 Real(RealDependencyLocation),
109 Synthetic(SyntheticDependencyLocation),
110}
111
112impl DependencyLocation {
113 pub fn from_span(span: &Span, source_map: &SourceMap) -> Self {
114 DependencyLocation::Real(RealDependencyLocation::from_span(span, source_map))
115 }
116}
117
118impl fmt::Display for DependencyLocation {
119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120 let loc = match self {
121 DependencyLocation::Real(real) => real.to_string(),
122 DependencyLocation::Synthetic(synthetic) => synthetic.to_string(),
123 };
124 write!(f, "{loc}")
125 }
126}