editor/language: hoist out non-generic parts of edit functions. (#3130)
This reduces LLVM IR size of editor (that's one of the heaviest crates to build) by almost 5%. LLVM IR size of `editor` before this PR: 3280386 LLVM IR size with `editor::edit` changed: 3227092 LLVM IR size with `editor::edit` and `language::edit` changed: 3146807 Release Notes: - N/A
This commit is contained in:
parent
6f4008ebab
commit
cc335db9e0
2 changed files with 158 additions and 131 deletions
|
@ -1448,82 +1448,95 @@ impl Buffer {
|
|||
return None;
|
||||
}
|
||||
|
||||
self.start_transaction();
|
||||
self.pending_autoindent.take();
|
||||
let autoindent_request = autoindent_mode
|
||||
.and_then(|mode| self.language.as_ref().map(|_| (self.snapshot(), mode)));
|
||||
// Non-generic part hoisted out to reduce LLVM IR size.
|
||||
fn tail(
|
||||
this: &mut Buffer,
|
||||
edits: Vec<(Range<usize>, Arc<str>)>,
|
||||
autoindent_mode: Option<AutoindentMode>,
|
||||
cx: &mut ModelContext<Buffer>,
|
||||
) -> Option<clock::Lamport> {
|
||||
this.start_transaction();
|
||||
this.pending_autoindent.take();
|
||||
let autoindent_request = autoindent_mode
|
||||
.and_then(|mode| this.language.as_ref().map(|_| (this.snapshot(), mode)));
|
||||
|
||||
let edit_operation = self.text.edit(edits.iter().cloned());
|
||||
let edit_id = edit_operation.timestamp();
|
||||
let edit_operation = this.text.edit(edits.iter().cloned());
|
||||
let edit_id = edit_operation.timestamp();
|
||||
|
||||
if let Some((before_edit, mode)) = autoindent_request {
|
||||
let mut delta = 0isize;
|
||||
let entries = edits
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.zip(&edit_operation.as_edit().unwrap().new_text)
|
||||
.map(|((ix, (range, _)), new_text)| {
|
||||
let new_text_length = new_text.len();
|
||||
let old_start = range.start.to_point(&before_edit);
|
||||
let new_start = (delta + range.start as isize) as usize;
|
||||
delta += new_text_length as isize - (range.end as isize - range.start as isize);
|
||||
if let Some((before_edit, mode)) = autoindent_request {
|
||||
let mut delta = 0isize;
|
||||
let entries = edits
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.zip(&edit_operation.as_edit().unwrap().new_text)
|
||||
.map(|((ix, (range, _)), new_text)| {
|
||||
let new_text_length = new_text.len();
|
||||
let old_start = range.start.to_point(&before_edit);
|
||||
let new_start = (delta + range.start as isize) as usize;
|
||||
delta +=
|
||||
new_text_length as isize - (range.end as isize - range.start as isize);
|
||||
|
||||
let mut range_of_insertion_to_indent = 0..new_text_length;
|
||||
let mut first_line_is_new = false;
|
||||
let mut original_indent_column = None;
|
||||
let mut range_of_insertion_to_indent = 0..new_text_length;
|
||||
let mut first_line_is_new = false;
|
||||
let mut original_indent_column = None;
|
||||
|
||||
// When inserting an entire line at the beginning of an existing line,
|
||||
// treat the insertion as new.
|
||||
if new_text.contains('\n')
|
||||
&& old_start.column <= before_edit.indent_size_for_line(old_start.row).len
|
||||
{
|
||||
first_line_is_new = true;
|
||||
}
|
||||
|
||||
// When inserting text starting with a newline, avoid auto-indenting the
|
||||
// previous line.
|
||||
if new_text.starts_with('\n') {
|
||||
range_of_insertion_to_indent.start += 1;
|
||||
first_line_is_new = true;
|
||||
}
|
||||
|
||||
// Avoid auto-indenting after the insertion.
|
||||
if let AutoindentMode::Block {
|
||||
original_indent_columns,
|
||||
} = &mode
|
||||
{
|
||||
original_indent_column =
|
||||
Some(original_indent_columns.get(ix).copied().unwrap_or_else(|| {
|
||||
indent_size_for_text(
|
||||
new_text[range_of_insertion_to_indent.clone()].chars(),
|
||||
)
|
||||
.len
|
||||
}));
|
||||
if new_text[range_of_insertion_to_indent.clone()].ends_with('\n') {
|
||||
range_of_insertion_to_indent.end -= 1;
|
||||
// When inserting an entire line at the beginning of an existing line,
|
||||
// treat the insertion as new.
|
||||
if new_text.contains('\n')
|
||||
&& old_start.column
|
||||
<= before_edit.indent_size_for_line(old_start.row).len
|
||||
{
|
||||
first_line_is_new = true;
|
||||
}
|
||||
}
|
||||
|
||||
AutoindentRequestEntry {
|
||||
first_line_is_new,
|
||||
original_indent_column,
|
||||
indent_size: before_edit.language_indent_size_at(range.start, cx),
|
||||
range: self.anchor_before(new_start + range_of_insertion_to_indent.start)
|
||||
..self.anchor_after(new_start + range_of_insertion_to_indent.end),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
// When inserting text starting with a newline, avoid auto-indenting the
|
||||
// previous line.
|
||||
if new_text.starts_with('\n') {
|
||||
range_of_insertion_to_indent.start += 1;
|
||||
first_line_is_new = true;
|
||||
}
|
||||
|
||||
self.autoindent_requests.push(Arc::new(AutoindentRequest {
|
||||
before_edit,
|
||||
entries,
|
||||
is_block_mode: matches!(mode, AutoindentMode::Block { .. }),
|
||||
}));
|
||||
// Avoid auto-indenting after the insertion.
|
||||
if let AutoindentMode::Block {
|
||||
original_indent_columns,
|
||||
} = &mode
|
||||
{
|
||||
original_indent_column = Some(
|
||||
original_indent_columns.get(ix).copied().unwrap_or_else(|| {
|
||||
indent_size_for_text(
|
||||
new_text[range_of_insertion_to_indent.clone()].chars(),
|
||||
)
|
||||
.len
|
||||
}),
|
||||
);
|
||||
if new_text[range_of_insertion_to_indent.clone()].ends_with('\n') {
|
||||
range_of_insertion_to_indent.end -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
AutoindentRequestEntry {
|
||||
first_line_is_new,
|
||||
original_indent_column,
|
||||
indent_size: before_edit.language_indent_size_at(range.start, cx),
|
||||
range: this
|
||||
.anchor_before(new_start + range_of_insertion_to_indent.start)
|
||||
..this.anchor_after(new_start + range_of_insertion_to_indent.end),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
this.autoindent_requests.push(Arc::new(AutoindentRequest {
|
||||
before_edit,
|
||||
entries,
|
||||
is_block_mode: matches!(mode, AutoindentMode::Block { .. }),
|
||||
}));
|
||||
}
|
||||
|
||||
this.end_transaction(cx);
|
||||
this.send_operation(Operation::Buffer(edit_operation), cx);
|
||||
Some(edit_id)
|
||||
}
|
||||
|
||||
self.end_transaction(cx);
|
||||
self.send_operation(Operation::Buffer(edit_operation), cx);
|
||||
Some(edit_id)
|
||||
tail(self, edits, autoindent_mode, cx)
|
||||
}
|
||||
|
||||
fn did_edit(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue