Auto merge of #16217 - hurryabit:simplify-apply-change, r=lnicola

internal: Simplify implementation of apply_document_changes

While reading through the code base, I stumbled across a piece of code that I found hard to read despite its simple purpose. This is my attempt at making the code easier to understand for future readers.

I won't be offended if this is too minor and not worth your time.
This commit is contained in:
bors 2023-12-30 19:43:04 +00:00
commit e872f5085c

View File

@ -171,30 +171,19 @@ pub(crate) fn apply_document_changes(
file_contents: impl FnOnce() -> String,
mut content_changes: Vec<lsp_types::TextDocumentContentChangeEvent>,
) -> String {
// Skip to the last full document change, as it invalidates all previous changes anyways.
let mut start = content_changes
.iter()
.rev()
.position(|change| change.range.is_none())
.map(|idx| content_changes.len() - idx - 1)
.unwrap_or(0);
let mut text: String = match content_changes.get_mut(start) {
// peek at the first content change as an optimization
Some(lsp_types::TextDocumentContentChangeEvent { range: None, text, .. }) => {
let text = mem::take(text);
start += 1;
// The only change is a full document update
if start == content_changes.len() {
return text;
// If at least one of the changes is a full document change, use the last
// of them as the starting point and ignore all previous changes.
let (mut text, content_changes) =
match content_changes.iter().rposition(|change| change.range.is_none()) {
Some(idx) => {
let text = mem::take(&mut content_changes[idx].text);
(text, &content_changes[idx + 1..])
}
text
}
Some(_) => file_contents(),
// we received no content changes
None => return file_contents(),
};
None => (file_contents(), &content_changes[..]),
};
if content_changes.is_empty() {
return text;
}
let mut line_index = LineIndex {
// the index will be overwritten in the bottom loop's first iteration