1use nom_locate::LocatedSpan;
2
3use crate::module::ModuleId;
4#[cfg(feature = "ast-json")]
5use serde::{Deserialize, Serialize};
6
7pub type Span<'a> = LocatedSpan<&'a str, ModuleId>;
12
13#[cfg_attr(feature = "ast-json", derive(Serialize, Deserialize))]
15#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Hash)]
16pub struct Position {
17 pub line: u32,
18 pub column: usize,
19}
20
21impl Default for Position {
22 fn default() -> Self {
23 Position { line: 1, column: 1 }
24 }
25}
26
27impl Position {
28 pub fn new(line: u32, column: usize) -> Self {
30 Position { line, column }
31 }
32}
33
34#[cfg_attr(feature = "ast-json", derive(Serialize, Deserialize))]
36#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Default, Hash)]
37pub struct Range {
38 pub start: Position,
39 pub end: Position,
40}
41
42impl Range {
43 pub fn contains(&self, position: &Position) -> bool {
45 (self.start.line < position.line || (self.start.line == position.line && self.start.column <= position.column))
46 && (self.end.line > position.line || (self.end.line == position.line && self.end.column >= position.column))
47 }
48}
49
50impl<'a> From<Span<'a>> for Range {
51 fn from(span: Span<'a>) -> Self {
52 let fragment = span.fragment();
53 let fragment = if !fragment.starts_with(" ") && fragment.ends_with(" ") {
54 fragment.trim()
55 } else {
56 fragment
57 };
58
59 Range {
60 start: Position {
61 line: span.location_line(),
62 column: span.get_utf8_column(),
63 },
64 end: Position {
65 line: span.location_line(),
66 column: span.get_utf8_column() + fragment.chars().count(),
67 },
68 }
69 }
70}
71
72impl<'a> From<Span<'a>> for Position {
73 fn from(span: Span<'a>) -> Self {
74 Position {
75 line: span.location_line(),
76 column: span.get_utf8_column(),
77 }
78 }
79}