rspack_location/
lib.rs

1use std::fmt::{self, Debug};
2
3pub use itoa::Buffer;
4use rspack_cacheable::cacheable;
5use swc_core::common::{SourceMap, Span};
6
7/// Represents a position in the source file, including the line number and column number.
8#[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/// Represents the real location of a dependency in a source file, including both start and optional end positions.
25/// These positions are described in terms of lines and columns in the source code.
26#[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/// Represents a synthetic dependency location, such as a generated dependency.
85#[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}