diff --git a/crates/nil/src/convert.rs b/crates/nil/src/convert.rs index 7e9c0a6..666c8d5 100644 --- a/crates/nil/src/convert.rs +++ b/crates/nil/src/convert.rs @@ -217,12 +217,8 @@ pub(crate) fn to_text_edit(line_map: &LineMap, edit: TextEdit) -> lsp::TextEdit } pub(crate) fn to_semantic_tokens(line_map: &LineMap, hls: &[HlRange]) -> Vec { - // We must now exceed the last line. - let line_count = line_map.line_count(); - if line_count == 0 { - return Vec::new(); - } - let last_line = line_count - 1; + // We must not exceed the last line. + let last_line = line_map.last_line(); let mut toks = Vec::with_capacity(hls.len()); let (mut prev_line, mut prev_start) = (0, 0); diff --git a/crates/nil/src/vfs.rs b/crates/nil/src/vfs.rs index e97df8d..e86d80b 100644 --- a/crates/nil/src/vfs.rs +++ b/crates/nil/src/vfs.rs @@ -148,6 +148,10 @@ impl Vfs { #[derive(Debug, PartialEq, Eq)] pub struct LineMap { + /// Invariant: + /// - Have at least two elements. + /// - The first must be 0. + /// - The last must be the length of original text. line_starts: Vec, char_diffs: HashMap>, } @@ -211,8 +215,8 @@ impl LineMap { Some((text, this)) } - pub fn line_count(&self) -> u32 { - self.line_starts.len() as u32 - 1 + pub fn last_line(&self) -> u32 { + self.line_starts.len() as u32 - 2 } pub fn pos_for_line_col(&self, line: u32, mut col: u32) -> TextSize { @@ -325,15 +329,15 @@ mod tests { } #[test] - fn line_count() { + fn last_line() { let (_, map) = LineMap::normalize("".into()).unwrap(); - assert_eq!(map.line_count(), 1); + assert_eq!(map.last_line(), 0); let (_, map) = LineMap::normalize("\n".into()).unwrap(); - assert_eq!(map.line_count(), 2); + assert_eq!(map.last_line(), 1); let (_, map) = LineMap::normalize("foo\nbar".into()).unwrap(); - assert_eq!(map.line_count(), 2); + assert_eq!(map.last_line(), 1); let (_, map) = LineMap::normalize("foo\nbar\n".into()).unwrap(); - assert_eq!(map.line_count(), 3); + assert_eq!(map.last_line(), 2); } #[test]