From e30c1c3fbf8f70336d985b2b73e5b0f45f3b95f5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 8 Jan 2021 01:39:02 +0300 Subject: Simplify highlighting infra This also fixes the killer whale bug --- crates/ide/src/syntax_highlighting/injector.rs | 83 ++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 crates/ide/src/syntax_highlighting/injector.rs (limited to 'crates/ide/src/syntax_highlighting/injector.rs') diff --git a/crates/ide/src/syntax_highlighting/injector.rs b/crates/ide/src/syntax_highlighting/injector.rs new file mode 100644 index 000000000..0513a9fd6 --- /dev/null +++ b/crates/ide/src/syntax_highlighting/injector.rs @@ -0,0 +1,83 @@ +//! Extracts a subsequence of a text document, remembering the mapping of ranges +//! between original and extracted texts. +use std::ops::{self, Sub}; + +use stdx::equal_range_by; +use syntax::{TextRange, TextSize}; + +use super::highlights::ordering; + +#[derive(Default)] +pub(super) struct Injector { + buf: String, + ranges: Vec<(TextRange, Option>)>, +} + +impl Injector { + pub(super) fn add(&mut self, text: &str, source_range: TextRange) { + let len = TextSize::of(text); + assert_eq!(len, source_range.len()); + + let target_range = TextRange::at(TextSize::of(&self.buf), len); + self.ranges + .push((target_range, Some(Delta::new(target_range.start(), source_range.start())))); + self.buf.push_str(text); + } + pub(super) fn add_unmapped(&mut self, text: &str) { + let len = TextSize::of(text); + + let target_range = TextRange::at(TextSize::of(&self.buf), len); + self.ranges.push((target_range, None)); + self.buf.push_str(text); + } + + pub(super) fn text(&self) -> &str { + &self.buf + } + pub(super) fn map_range_up(&self, range: TextRange) -> impl Iterator + '_ { + let (start, len) = equal_range_by(&self.ranges, |&(r, _)| ordering(r, range)); + (start..start + len).filter_map(move |i| { + let (target_range, delta) = self.ranges[i]; + let intersection = target_range.intersect(range).unwrap(); + Some(intersection + delta?) + }) + } +} + +#[derive(Clone, Copy)] +enum Delta { + Add(T), + Sub(T), +} + +impl Delta { + fn new(from: T, to: T) -> Delta + where + T: Ord + Sub, + { + if to >= from { + Delta::Add(to - from) + } else { + Delta::Sub(from - to) + } + } +} + +impl ops::Add> for TextSize { + type Output = TextSize; + + fn add(self, rhs: Delta) -> TextSize { + match rhs { + Delta::Add(it) => self + it, + Delta::Sub(it) => self - it, + } + } +} + +impl ops::Add> for TextRange { + type Output = TextRange; + + fn add(self, rhs: Delta) -> TextRange { + TextRange::at(self.start() + rhs, self.len()) + } +} -- cgit v1.2.3