Skip to main content

perl_parser/incremental/
mod.rs

1// Incremental parser internals are being split into private modules; facade
2// documentation stays on the exported types and entry points.
3#![allow(missing_docs)]
4
5mod checkpoint;
6mod diagnostics;
7mod edit;
8mod lex;
9mod reparse;
10mod state;
11mod strategy;
12
13use anyhow::Result;
14
15pub use perl_line_index::LineIndex;
16
17pub use checkpoint::{LexCheckpoint, ParseCheckpoint, ScopeSnapshot};
18pub use diagnostics::ReparseResult;
19pub use edit::Edit;
20use reparse::{apply_single_edit, apply_text_edit_to_state, full_reparse};
21pub use state::IncrementalState;
22pub use strategy::MAX_EDIT_SIZE;
23
24pub mod incremental_advanced_reuse;
25#[cfg(test)]
26mod incremental_boundary_regressions;
27pub mod incremental_checkpoint;
28pub mod incremental_document;
29pub mod incremental_edit;
30pub mod incremental_handler_v2;
31pub mod incremental_integration;
32pub mod incremental_simple;
33pub mod incremental_v2;
34
35/// Apply edits incrementally
36pub fn apply_edits(state: &mut IncrementalState, edits: &[Edit]) -> Result<ReparseResult> {
37    let mut sorted_edits = edits.to_vec();
38    sorted_edits.sort_by_key(|e| e.start_byte);
39    sorted_edits.reverse();
40
41    let total_changed = sorted_edits.iter().map(Edit::touched_bytes).sum::<usize>();
42
43    if total_changed > MAX_EDIT_SIZE {
44        return full_reparse(state);
45    }
46
47    if sorted_edits.len() == 1 {
48        let edit = &sorted_edits[0];
49
50        if edit.touched_bytes() > 1024 || edit.new_text.matches('\n').count() > 10 {
51            apply_text_edit_to_state(state, edit)?;
52            return full_reparse(state);
53        }
54
55        let reparse = match apply_single_edit(state, edit) {
56            Ok(reparse) => reparse,
57            Err(_) => return full_reparse(state),
58        };
59        let reparsed_bytes = reparse.range.end - reparse.range.start;
60
61        Ok(ReparseResult {
62            changed_ranges: vec![reparse.range],
63            diagnostics: vec![],
64            reparsed_bytes,
65            reused_tokens: reparse.reused_tokens,
66            token_count: reparse.token_count,
67        })
68    } else {
69        for edit in sorted_edits {
70            if apply_single_edit(state, &edit).is_err() {
71                return full_reparse(state);
72            }
73        }
74        full_reparse(state)
75    }
76}
77
78#[cfg(test)]
79mod tests;