Skip to content

Commit cd1faf7

Browse files
dak2claude
andcommitted
Remove unused position-conversion machinery from Buffer
line_ranges, line_count, line, pos_to_loc, loc_to_pos, and last_position had no callers outside their own tests, and their byte-offset semantics diverge from Ruby's character-offset RBS::Buffer anyway. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 43408ac commit cd1faf7

1 file changed

Lines changed: 2 additions & 164 deletions

File tree

rust/ruby-rbs/src/buffer.rs

Lines changed: 2 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,15 @@
1-
use std::cell::OnceCell;
2-
use std::ops::Range;
31
use std::path::{Path, PathBuf};
42

5-
/// A signature file's content with byte position <-> line/column conversion,
6-
/// mirroring `RBS::Buffer`.
7-
///
8-
/// Positions and columns are byte offsets, unlike Ruby's character offsets;
9-
/// they agree on ASCII-only content. Use the parser's `RBSLocationRange` when
10-
/// character offsets are needed.
3+
/// A signature file's content, mirroring `RBS::Buffer`.
114
#[derive(Debug, Clone)]
125
pub struct Buffer {
136
name: PathBuf,
147
content: String,
15-
line_ranges: OnceCell<Vec<Range<usize>>>,
168
}
179

1810
impl Buffer {
1911
pub fn new(name: PathBuf, content: String) -> Self {
20-
Self {
21-
name,
22-
content,
23-
line_ranges: OnceCell::new(),
24-
}
12+
Self { name, content }
2513
}
2614

2715
pub fn name(&self) -> &Path {
@@ -31,154 +19,4 @@ impl Buffer {
3119
pub fn content(&self) -> &str {
3220
&self.content
3321
}
34-
35-
fn line_ranges(&self) -> &[Range<usize>] {
36-
self.line_ranges
37-
.get_or_init(|| compute_line_ranges(&self.content))
38-
}
39-
40-
pub fn line_count(&self) -> usize {
41-
self.line_ranges().len()
42-
}
43-
44-
/// Returns the 1-origin `line` without its line terminator.
45-
pub fn line(&self, line: usize) -> Option<&str> {
46-
let range = self.line_ranges().get(line.checked_sub(1)?)?;
47-
Some(&self.content[range.clone()])
48-
}
49-
50-
/// A position past the end of the content maps to `(line_count + 1, 0)`,
51-
/// same as the Ruby implementation.
52-
pub fn pos_to_loc(&self, pos: usize) -> (usize, usize) {
53-
let ranges = self.line_ranges();
54-
let index = ranges.partition_point(|range| range.end < pos);
55-
match ranges.get(index) {
56-
Some(range) => (index + 1, pos.saturating_sub(range.start)),
57-
None => (ranges.len() + 1, 0),
58-
}
59-
}
60-
61-
pub fn loc_to_pos(&self, line: usize, column: usize) -> usize {
62-
let ranges = self.line_ranges();
63-
let range = match line.checked_sub(1) {
64-
None => ranges.last(),
65-
Some(index) => ranges.get(index),
66-
};
67-
match range {
68-
Some(range) => range.start + column,
69-
None => self.last_position(),
70-
}
71-
}
72-
73-
pub fn last_position(&self) -> usize {
74-
self.line_ranges().last().map_or(0, |range| range.end)
75-
}
76-
}
77-
78-
fn compute_line_ranges(content: &str) -> Vec<Range<usize>> {
79-
let mut ranges = Vec::new();
80-
let mut offset = 0;
81-
82-
for line in content.split_inclusive('\n') {
83-
let without_terminator = match line.strip_suffix('\n') {
84-
Some(l) => l.strip_suffix('\r').unwrap_or(l),
85-
None => line.strip_suffix('\r').unwrap_or(line),
86-
};
87-
ranges.push(offset..offset + without_terminator.len());
88-
offset += line.len();
89-
}
90-
91-
if content.is_empty() || content.ends_with('\n') {
92-
ranges.push(offset..offset);
93-
}
94-
95-
ranges
96-
}
97-
98-
#[cfg(test)]
99-
mod tests {
100-
use super::*;
101-
102-
fn buffer(content: &str) -> Buffer {
103-
Buffer::new(PathBuf::from("a.rbs"), content.to_string())
104-
}
105-
106-
#[test]
107-
fn lines_of_content_with_trailing_newline() {
108-
let buffer = buffer("123\nabc\n");
109-
assert_eq!(buffer.line_count(), 3);
110-
assert_eq!(buffer.line(1), Some("123"));
111-
assert_eq!(buffer.line(2), Some("abc"));
112-
assert_eq!(buffer.line(3), Some(""));
113-
assert_eq!(buffer.line(4), None);
114-
assert_eq!(buffer.line(0), None);
115-
}
116-
117-
#[test]
118-
fn lines_of_content_without_trailing_newline() {
119-
let buffer = buffer("123\nabc");
120-
assert_eq!(buffer.line_count(), 2);
121-
assert_eq!(buffer.line(2), Some("abc"));
122-
assert_eq!(buffer.last_position(), 7);
123-
}
124-
125-
#[test]
126-
fn empty_content_has_one_empty_line() {
127-
let buffer = buffer("");
128-
assert_eq!(buffer.line_count(), 1);
129-
assert_eq!(buffer.line(1), Some(""));
130-
assert_eq!(buffer.last_position(), 0);
131-
assert_eq!(buffer.pos_to_loc(0), (1, 0));
132-
}
133-
134-
#[test]
135-
fn crlf_is_excluded_from_line_ranges() {
136-
let buffer = buffer("abc\r\ndef\r\n");
137-
assert_eq!(buffer.line(1), Some("abc"));
138-
assert_eq!(buffer.line(2), Some("def"));
139-
assert_eq!(buffer.pos_to_loc(5), (2, 0));
140-
}
141-
142-
#[test]
143-
fn pos_to_loc_matches_ruby_buffer_for_ascii() {
144-
let buffer = buffer("123\nabc\n");
145-
assert_eq!(buffer.pos_to_loc(0), (1, 0));
146-
assert_eq!(buffer.pos_to_loc(3), (1, 3));
147-
assert_eq!(buffer.pos_to_loc(4), (2, 0));
148-
assert_eq!(buffer.pos_to_loc(7), (2, 3));
149-
assert_eq!(buffer.pos_to_loc(8), (3, 0));
150-
assert_eq!(buffer.pos_to_loc(9), (4, 0));
151-
}
152-
153-
#[test]
154-
fn loc_to_pos_matches_ruby_buffer_for_ascii() {
155-
let buffer = buffer("123\nabc\n");
156-
assert_eq!(buffer.loc_to_pos(1, 0), 0);
157-
assert_eq!(buffer.loc_to_pos(2, 3), 7);
158-
assert_eq!(buffer.loc_to_pos(3, 0), 8);
159-
assert_eq!(buffer.loc_to_pos(10, 5), 8);
160-
assert_eq!(buffer.last_position(), 8);
161-
}
162-
163-
#[test]
164-
fn trailing_carriage_return_without_newline_is_chomped() {
165-
let buffer = buffer("abc\ndef\r");
166-
assert_eq!(buffer.line(2), Some("def"));
167-
assert_eq!(buffer.last_position(), 7);
168-
}
169-
170-
#[test]
171-
fn line_zero_maps_to_the_last_line() {
172-
let buffer = buffer("123\nabc");
173-
assert_eq!(buffer.loc_to_pos(0, 2), 6);
174-
}
175-
176-
#[test]
177-
fn the_line_table_is_built_only_on_demand() {
178-
let buffer = buffer("123\nabc\n");
179-
assert!(buffer.line_ranges.get().is_none());
180-
181-
buffer.pos_to_loc(4);
182-
assert!(buffer.line_ranges.get().is_some());
183-
}
18422
}

0 commit comments

Comments
 (0)