rustpython_parser_vendored/source_location/
mod.rs1mod line_index;
2pub mod newlines;
4
5pub use self::line_index::{LineIndex, OneIndexed};
6use crate::text_size::{TextRange, TextSize};
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9use std::fmt::{Debug, Formatter};
10use std::sync::Arc;
11
12#[derive(Debug)]
14pub struct SourceCode<'src, 'index> {
15 text: &'src str,
16 index: &'index LineIndex,
17}
18
19impl<'src, 'index> SourceCode<'src, 'index> {
20 pub fn new(content: &'src str, index: &'index LineIndex) -> Self {
21 Self {
22 text: content,
23 index,
24 }
25 }
26
27 #[inline]
29 pub fn source_location(&self, offset: TextSize) -> SourceLocation {
30 self.index.source_location(offset, self.text)
31 }
32
33 #[inline]
34 pub fn line_index(&self, offset: TextSize) -> OneIndexed {
35 self.index.line_index(offset)
36 }
37
38 #[inline]
40 pub fn up_to(&self, offset: TextSize) -> &'src str {
41 &self.text[TextRange::up_to(offset)]
42 }
43
44 #[inline]
46 pub fn after(&self, offset: TextSize) -> &'src str {
47 &self.text[usize::from(offset)..]
48 }
49
50 pub fn slice(&self, range: TextRange) -> &'src str {
52 &self.text[range]
53 }
54
55 pub fn line_start(&self, line: OneIndexed) -> TextSize {
56 self.index.line_start(line, self.text)
57 }
58
59 pub fn line_end(&self, line: OneIndexed) -> TextSize {
60 self.index.line_end(line, self.text)
61 }
62
63 pub fn line_range(&self, line: OneIndexed) -> TextRange {
64 self.index.line_range(line, self.text)
65 }
66
67 #[inline]
69 pub fn line_text(&self, index: OneIndexed) -> &'src str {
70 let range = self.index.line_range(index, self.text);
71 &self.text[range]
72 }
73
74 pub fn text(&self) -> &'src str {
76 self.text
77 }
78
79 #[inline]
81 pub fn line_count(&self) -> usize {
82 self.index.line_count()
83 }
84}
85
86impl PartialEq<Self> for SourceCode<'_, '_> {
87 fn eq(&self, other: &Self) -> bool {
88 self.text == other.text
89 }
90}
91
92impl Eq for SourceCode<'_, '_> {}
93
94pub struct SourceFileBuilder {
96 name: Box<str>,
97 code: Box<str>,
98 index: Option<LineIndex>,
99}
100
101impl SourceFileBuilder {
102 pub fn new<Name: Into<Box<str>>, Code: Into<Box<str>>>(name: Name, code: Code) -> Self {
104 Self {
105 name: name.into(),
106 code: code.into(),
107 index: None,
108 }
109 }
110
111 #[must_use]
112 pub fn line_index(mut self, index: LineIndex) -> Self {
113 self.index = Some(index);
114 self
115 }
116
117 pub fn set_line_index(&mut self, index: LineIndex) {
118 self.index = Some(index);
119 }
120
121 pub fn finish(self) -> SourceFile {
123 let index = if let Some(index) = self.index {
124 once_cell::sync::OnceCell::with_value(index)
125 } else {
126 once_cell::sync::OnceCell::new()
127 };
128
129 SourceFile {
130 inner: Arc::new(SourceFileInner {
131 name: self.name,
132 code: self.code,
133 line_index: index,
134 }),
135 }
136 }
137}
138
139#[derive(Clone, Eq, PartialEq)]
143pub struct SourceFile {
144 inner: Arc<SourceFileInner>,
145}
146
147impl Debug for SourceFile {
148 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
149 f.debug_struct("SourceFile")
150 .field("name", &self.name())
151 .field("code", &self.source_text())
152 .finish()
153 }
154}
155
156impl SourceFile {
157 #[inline]
159 pub fn name(&self) -> &str {
160 &self.inner.name
161 }
162
163 #[inline]
164 pub fn slice(&self, range: TextRange) -> &str {
165 &self.source_text()[range]
166 }
167
168 pub fn to_source_code(&self) -> SourceCode {
169 SourceCode {
170 text: self.source_text(),
171 index: self.index(),
172 }
173 }
174
175 fn index(&self) -> &LineIndex {
176 self.inner
177 .line_index
178 .get_or_init(|| LineIndex::from_source_text(self.source_text()))
179 }
180
181 #[inline]
183 pub fn source_text(&self) -> &str {
184 &self.inner.code
185 }
186}
187
188struct SourceFileInner {
189 name: Box<str>,
190 code: Box<str>,
191 line_index: once_cell::sync::OnceCell<LineIndex>,
192}
193
194impl PartialEq for SourceFileInner {
195 fn eq(&self, other: &Self) -> bool {
196 self.name == other.name && self.code == other.code
197 }
198}
199
200impl Eq for SourceFileInner {}
201
202#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Copy)]
203#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
204pub struct SourceLocation {
205 pub row: OneIndexed,
206 pub column: OneIndexed,
207}
208
209impl Default for SourceLocation {
210 fn default() -> Self {
211 Self {
212 row: OneIndexed::MIN,
213 column: OneIndexed::MIN,
214 }
215 }
216}
217
218impl Debug for SourceLocation {
219 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
220 f.debug_struct("SourceLocation")
221 .field("row", &self.row.get())
222 .field("column", &self.column.get())
223 .finish()
224 }
225}