Introduce SourceCodeSlice to reduce the size of FormatElement (#4622)

Introduce `SourceCodeSlice` to reduce the size of `FormatElement`
This commit is contained in:
Micha Reiser 2023-05-24 17:04:52 +02:00 committed by GitHub
parent 6943beee66
commit 86ced3516b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 408 additions and 171 deletions

View file

@ -0,0 +1,81 @@
use ruff_text_size::TextRange;
use std::fmt::{Debug, Formatter};
/// The source code of a document that gets formatted
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default)]
pub struct SourceCode<'a> {
text: &'a str,
}
impl<'a> SourceCode<'a> {
pub fn new(text: &'a str) -> Self {
Self { text }
}
pub fn slice(self, range: TextRange) -> SourceCodeSlice {
assert!(
usize::from(range.end()) <= self.text.len(),
"Range end {:?} out of bounds {}.",
range.end(),
self.text.len()
);
assert!(
self.text.is_char_boundary(usize::from(range.start())),
"The range start position {:?} is not a char boundary.",
range.start()
);
assert!(
self.text.is_char_boundary(usize::from(range.end())),
"The range end position {:?} is not a char boundary.",
range.end()
);
SourceCodeSlice {
range,
#[cfg(debug_assertions)]
text: String::from(&self.text[range]).into_boxed_str(),
}
}
}
impl Debug for SourceCode<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("SourceCode").field(&self.text).finish()
}
}
/// A slice into the source text of a document.
///
/// It only stores the range in production builds for a more compact representation, but it
/// keeps the original text in debug builds for better developer experience.
#[derive(Clone, Eq, PartialEq)]
pub struct SourceCodeSlice {
range: TextRange,
#[cfg(debug_assertions)]
text: Box<str>,
}
impl SourceCodeSlice {
/// Returns the slice's text.
pub fn text<'a>(&self, code: SourceCode<'a>) -> &'a str {
assert!(usize::from(self.range.end()) <= code.text.len(), "The range of this slice is out of bounds. Did you provide the correct source code for this slice?");
&code.text[self.range]
}
pub fn range(&self) -> TextRange {
self.range
}
}
impl Debug for SourceCodeSlice {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut tuple = f.debug_tuple("SourceCodeSlice");
#[cfg(debug_assertions)]
tuple.field(&self.text);
tuple.field(&self.range).finish()
}
}