2216 lines · 75.2 KB · Rust
RawDownload
#[cfg(test)]mod syntax_map_tests; use crate::{    Grammar, InjectionConfig, Language, LanguageId, LanguageRegistry, QUERY_CURSORS, with_parser,};use collections::HashMap;use futures::FutureExt;use gpui::SharedString;use std::{    borrow::Cow,    cmp::{self, Ordering, Reverse},    collections::BinaryHeap,    fmt, iter,    ops::{ControlFlow, Deref, DerefMut, Range},    sync::{Arc, LazyLock},    time::{Duration, Instant},};use streaming_iterator::StreamingIterator;use sum_tree::{Bias, Dimensions, SeekTarget, SumTree};use text::{Anchor, BufferSnapshot, OffsetRangeExt, Point, Rope, ToOffset, ToPoint};use tree_sitter::{    Node, Query, QueryCapture, QueryCaptures, QueryCursor, QueryMatch, QueryMatches,    QueryPredicateArg,}; pub const MAX_BYTES_TO_QUERY: usize = 16 * 1024; pub struct SyntaxMap {    snapshot: SyntaxSnapshot,    language_registry: Option<Arc<LanguageRegistry>>,} #[derive(Clone)]pub struct SyntaxSnapshot {    layers: SumTree<SyntaxLayerEntry>,    parsed_version: clock::Global,    interpolated_version: clock::Global,    language_registry_version: usize,    update_count: usize,} // Dropping deep treesitter Trees can be quite slow due to deallocating lots of memory.// To avoid blocking the main thread, we offload the drop operation to a background thread.impl Drop for SyntaxSnapshot {    fn drop(&mut self) {        static DROP_TX: LazyLock<std::sync::mpsc::Sender<SumTree<SyntaxLayerEntry>>> =            LazyLock::new(|| {                let (tx, rx) = std::sync::mpsc::channel();                std::thread::Builder::new()                    .name("SyntaxSnapshot::drop".into())                    .spawn(move || while let Ok(_) = rx.recv() {})                    .expect("failed to spawn drop thread");                tx            });        // This does allocate a new Arc, but it's cheap and avoids blocking the main thread without needing to use an `Option` or `MaybeUninit`.        let _ = DROP_TX.send(std::mem::replace(            &mut self.layers,            SumTree::from_summary(Default::default()),        ));    }} #[derive(Default)]pub struct SyntaxMapCaptures<'a> {    layers: Vec<SyntaxMapCapturesLayer<'a>>,    active_layer_count: usize,    grammars: Vec<&'a Grammar>,} #[derive(Default)]pub struct SyntaxMapMatches<'a> {    layers: Vec<SyntaxMapMatchesLayer<'a>>,    active_layer_count: usize,    grammars: Vec<&'a Grammar>,} #[derive(Debug)]pub struct SyntaxMapCapture<'a> {    pub node: Node<'a>,    pub index: u32,    pub grammar_index: usize,} #[derive(Debug)]pub struct SyntaxMapMatch<'a> {    pub language: Arc<Language>,    pub depth: usize,    pub pattern_index: usize,    pub captures: &'a [QueryCapture<'a>],    pub grammar_index: usize,} struct SyntaxMapCapturesLayer<'a> {    depth: usize,    captures: QueryCaptures<'a, 'a, TextProvider<'a>, &'a [u8]>,    next_capture: Option<QueryCapture<'a>>,    grammar_index: usize,    _query_cursor: QueryCursorHandle,} struct SyntaxMapMatchesLayer<'a> {    language: Arc<Language>,    depth: usize,    next_pattern_index: usize,    next_captures: Vec<QueryCapture<'a>>,    has_next: bool,    matches: QueryMatches<'a, 'a, TextProvider<'a>, &'a [u8]>,    query: &'a Query,    grammar_index: usize,    _query_cursor: QueryCursorHandle,} #[derive(Clone)]struct SyntaxLayerEntry {    depth: usize,    range: Range<Anchor>,    content: SyntaxLayerContent,} #[derive(Clone)]enum SyntaxLayerContent {    Parsed {        tree: tree_sitter::Tree,        language: Arc<Language>,        included_sub_ranges: Option<Vec<Range<Anchor>>>,    },    Pending {        language_name: Arc<str>,    },} impl SyntaxLayerContent {    fn language_id(&self) -> Option<LanguageId> {        match self {            SyntaxLayerContent::Parsed { language, .. } => Some(language.id),            SyntaxLayerContent::Pending { .. } => None,        }    }     fn tree(&self) -> Option<&tree_sitter::Tree> {        match self {            SyntaxLayerContent::Parsed { tree, .. } => Some(tree),            SyntaxLayerContent::Pending { .. } => None,        }    }} /// A layer of syntax highlighting, corresponding to a single syntax/// tree in a particular language.#[derive(Debug)]pub struct SyntaxLayer<'a> {    /// The language for this layer.    pub language: &'a Arc<Language>,    pub included_sub_ranges: Option<&'a [Range<Anchor>]>,    pub(crate) depth: usize,    tree: &'a tree_sitter::Tree,    pub(crate) offset: (usize, tree_sitter::Point),} /// A layer of syntax highlighting. Like [SyntaxLayer], but holding/// owned data instead of references.#[derive(Clone)]pub struct OwnedSyntaxLayer {    /// The language for this layer.    pub language: Arc<Language>,    tree: tree_sitter::Tree,    pub offset: (usize, tree_sitter::Point),} #[derive(Debug, Clone)]struct SyntaxLayerSummary {    min_depth: usize,    max_depth: usize,    range: Range<Anchor>,    last_layer_range: Range<Anchor>,    last_layer_language: Option<LanguageId>,    contains_unknown_injections: bool,} #[derive(Clone, Debug)]struct SyntaxLayerPosition {    depth: usize,    range: Range<Anchor>,    language: Option<LanguageId>,} #[derive(Clone, Debug)]struct ChangeStartPosition {    depth: usize,    position: Anchor,} #[derive(Clone, Debug)]struct SyntaxLayerPositionBeforeChange {    position: SyntaxLayerPosition,    change: ChangeStartPosition,} struct ParseStep {    depth: usize,    language: ParseStepLanguage,    range: Range<Anchor>,    included_ranges: Vec<tree_sitter::Range>,    mode: ParseMode,} #[derive(Debug)]enum ParseStepLanguage {    Loaded { language: Arc<Language> },    Pending { name: Arc<str> },} impl ParseStepLanguage {    fn name(&self) -> SharedString {        match self {            ParseStepLanguage::Loaded { language } => language.name().0,            ParseStepLanguage::Pending { name } => name.into(),        }    }     fn id(&self) -> Option<LanguageId> {        match self {            ParseStepLanguage::Loaded { language } => Some(language.id),            ParseStepLanguage::Pending { .. } => None,        }    }} enum ParseMode {    Single,    Combined {        parent_layer_range: Range<usize>,        parent_layer_changed_ranges: Vec<Range<usize>>,    },} #[derive(Debug, PartialEq, Eq)]struct ChangedRegion {    depth: usize,    range: Range<Anchor>,} #[derive(Default)]struct ChangeRegionSet(Vec<ChangedRegion>); struct TextProvider<'a>(&'a Rope); struct ByteChunks<'a>(text::Chunks<'a>); pub(crate) struct QueryCursorHandle(Option<QueryCursor>); impl SyntaxMap {    pub fn new(text: &BufferSnapshot) -> Self {        Self {            snapshot: SyntaxSnapshot::new(text),            language_registry: None,        }    }     pub fn set_language_registry(&mut self, registry: Arc<LanguageRegistry>) {        self.language_registry = Some(registry);    }     pub fn snapshot(&self) -> SyntaxSnapshot {        self.snapshot.clone()    }     pub fn language_registry(&self) -> Option<Arc<LanguageRegistry>> {        self.language_registry.clone()    }     pub fn interpolate(&mut self, text: &BufferSnapshot) {        self.snapshot.interpolate(text);    }     #[cfg(test)]    pub fn reparse(&mut self, language: Arc<Language>, text: &BufferSnapshot) {        self.snapshot            .reparse(text, self.language_registry.clone(), language);    }     pub fn did_parse(&mut self, snapshot: SyntaxSnapshot) {        self.snapshot = snapshot;    }     pub fn clear(&mut self, text: &BufferSnapshot) {        let update_count = self.snapshot.update_count + 1;        self.snapshot = SyntaxSnapshot::new(text);        self.snapshot.update_count = update_count;    }} impl SyntaxSnapshot {    fn new(text: &BufferSnapshot) -> Self {        Self {            layers: SumTree::new(text),            parsed_version: clock::Global::default(),            interpolated_version: clock::Global::default(),            language_registry_version: 0,            update_count: 0,        }    }     pub fn is_empty(&self) -> bool {        self.layers.is_empty()    }     pub fn root_language(&self) -> Option<Arc<Language>> {        match &self.layers.first()?.content {            SyntaxLayerContent::Parsed { language, .. } => Some(language.clone()),            SyntaxLayerContent::Pending { .. } => None,        }    }     pub fn update_count(&self) -> usize {        self.update_count    }     #[ztracing::instrument(skip_all)]    pub fn interpolate(&mut self, text: &BufferSnapshot) {        let edits = text            .anchored_edits_since::<Dimensions<usize, Point>>(&self.interpolated_version)            .collect::<Vec<_>>();        self.interpolated_version = text.version().clone();         if edits.is_empty() {            return;        }         let mut layers = SumTree::new(text);        let mut first_edit_ix_for_depth = 0;        let mut prev_depth = 0;        let mut cursor = self.layers.cursor::<SyntaxLayerSummary>(text);        cursor.next();         'outer: loop {            let depth = cursor.end().max_depth;            if depth > prev_depth {                first_edit_ix_for_depth = 0;                prev_depth = depth;            }             // Preserve any layers at this depth that precede the first edit.            if let Some((_, edit_range)) = edits.get(first_edit_ix_for_depth) {                let target = ChangeStartPosition {                    depth,                    position: edit_range.start,                };                if target.cmp(cursor.start(), text).is_gt() {                    let slice = cursor.slice(&target, Bias::Left);                    layers.append(slice, text);                }            }            // If this layer follows all of the edits, then preserve it and any            // subsequent layers at this same depth.            else if cursor.item().is_some() {                let slice = cursor.slice(                    &SyntaxLayerPosition {                        depth: depth + 1,                        range: Anchor::min_max_range_for_buffer(text.remote_id()),                        language: None,                    },                    Bias::Left,                );                layers.append(slice, text);                continue;            };             let Some(layer) = cursor.item() else { break };            let Dimensions(start_byte, start_point, _) =                layer.range.start.summary::<Dimensions<usize, Point>>(text);             // Ignore edits that end before the start of this layer, and don't consider them            // for any subsequent layers at this same depth.            loop {                let Some((_, edit_range)) = edits.get(first_edit_ix_for_depth) else {                    continue 'outer;                };                if edit_range.end.cmp(&layer.range.start, text).is_le() {                    first_edit_ix_for_depth += 1;                } else {                    break;                }            }             let mut layer = layer.clone();            if let SyntaxLayerContent::Parsed { tree, .. } = &mut layer.content {                for (edit, edit_range) in &edits[first_edit_ix_for_depth..] {                    // Ignore any edits that follow this layer.                    if edit_range.start.cmp(&layer.range.end, text).is_ge() {                        break;                    }                     // Apply any edits that intersect this layer to the layer's syntax tree.                    let tree_edit = if edit_range.start.cmp(&layer.range.start, text).is_ge() {                        tree_sitter::InputEdit {                            start_byte: edit.new.start.0 - start_byte,                            old_end_byte: edit.new.start.0 - start_byte                                + (edit.old.end.0 - edit.old.start.0),                            new_end_byte: edit.new.end.0 - start_byte,                            start_position: (edit.new.start.1 - start_point).to_ts_point(),                            old_end_position: (edit.new.start.1 - start_point                                + (edit.old.end.1 - edit.old.start.1))                                .to_ts_point(),                            new_end_position: (edit.new.end.1 - start_point).to_ts_point(),                        }                    } else {                        let node = tree.root_node();                        tree_sitter::InputEdit {                            start_byte: 0,                            old_end_byte: node.end_byte(),                            new_end_byte: 0,                            start_position: Default::default(),                            old_end_position: node.end_position(),                            new_end_position: Default::default(),                        }                    };                     tree.edit(&tree_edit);                }                 debug_assert!(                    tree.root_node().end_byte() <= text.len(),                    "tree's size {}, is larger than text size {}",                    tree.root_node().end_byte(),                    text.len(),                );            }             layers.push(layer, text);            cursor.next();        }         layers.append(cursor.suffix(), text);        drop(cursor);        self.layers = layers;    }     #[ztracing::instrument(skip_all)]    pub fn reparse(        &mut self,        text: &BufferSnapshot,        registry: Option<Arc<LanguageRegistry>>,        root_language: Arc<Language>,    ) {        self.reparse_(text, registry, root_language, None).ok();    }     #[ztracing::instrument(skip_all)]    pub fn reparse_with_timeout(        &mut self,        text: &BufferSnapshot,        registry: Option<Arc<LanguageRegistry>>,        root_language: Arc<Language>,        budget: Duration,    ) -> Result<(), ParseTimeout> {        self.reparse_(text, registry, root_language, Some(budget))    }     #[ztracing::instrument(skip_all, fields(lang = root_language.config.name.0.as_str()))]    fn reparse_(        &mut self,        text: &BufferSnapshot,        registry: Option<Arc<LanguageRegistry>>,        root_language: Arc<Language>,        mut budget: Option<Duration>,    ) -> Result<(), ParseTimeout> {        let budget = &mut budget;        let edit_ranges = text            .edits_since::<usize>(&self.parsed_version)            .map(|edit| edit.new)            .collect::<Vec<_>>();        self.reparse_with_ranges(            text,            root_language.clone(),            edit_ranges,            registry.as_ref(),            budget,        )?;         if let Some(registry) = registry            && registry.version() != self.language_registry_version        {            let mut resolved_injection_ranges = Vec::new();            let mut cursor = self                .layers                .filter::<_, ()>(text, |summary| summary.contains_unknown_injections);            cursor.next();            while let Some(layer) = cursor.item() {                let SyntaxLayerContent::Pending { language_name } = &layer.content else {                    unreachable!()                };                if registry                    .language_for_name_or_extension(language_name)                    .now_or_never()                    .and_then(|language| language.ok())                    .is_some()                {                    let range = layer.range.to_offset(text);

Lines 1–500 of 2216.