1use crate::file_path::WorkspaceFilePath;
4use crate::path::SymbolPath;
5use serde::Serialize;
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
14pub struct FileSpan {
15 pub file: WorkspaceFilePath,
17 pub start: u32,
19 pub end: u32,
21}
22
23impl FileSpan {
24 pub fn new(file: WorkspaceFilePath, start: u32, end: u32) -> Self {
26 Self { file, start, end }
27 }
28
29 pub fn len(&self) -> u32 {
31 self.end.saturating_sub(self.start)
32 }
33
34 pub fn is_empty(&self) -> bool {
36 self.start >= self.end
37 }
38
39 pub fn contains(&self, offset: u32) -> bool {
41 offset >= self.start && offset < self.end
42 }
43
44 pub fn overlaps(&self, other: &FileSpan) -> bool {
46 self.file == other.file && self.start < other.end && other.start < self.end
47 }
48}
49
50impl std::fmt::Display for FileSpan {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "{}:{}-{}", self.file, self.start, self.end)
53 }
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Default)]
58pub enum Visibility {
59 Public,
61 Crate,
63 Super,
65 Restricted(Box<SymbolPath>),
67 #[default]
69 Private,
70}
71
72impl Visibility {
73 #[inline]
75 pub fn is_public(&self) -> bool {
76 matches!(self, Visibility::Public)
77 }
78
79 #[inline]
81 pub fn is_crate_visible(&self) -> bool {
82 matches!(self, Visibility::Public | Visibility::Crate)
83 }
84
85 #[inline]
87 pub fn is_private(&self) -> bool {
88 matches!(self, Visibility::Private)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_file_span() {
98 let file = WorkspaceFilePath::new_for_test("src/lib.rs", "/workspace", "test_crate");
99 let span = FileSpan::new(file, 10, 20);
100
101 assert_eq!(span.len(), 10);
102 assert!(!span.is_empty());
103 assert!(span.contains(10));
104 assert!(span.contains(19));
105 assert!(!span.contains(20));
106 }
107
108 #[test]
109 fn test_span_overlap() {
110 let file = WorkspaceFilePath::new_for_test("src/lib.rs", "/workspace", "test_crate");
111 let span1 = FileSpan::new(file.clone(), 10, 20);
112 let span2 = FileSpan::new(file.clone(), 15, 25);
113 let span3 = FileSpan::new(file.clone(), 20, 30);
114
115 assert!(span1.overlaps(&span2));
116 assert!(!span1.overlaps(&span3)); }
118}