From a8a5e23e5e051ba823a98a0a697381d74afa0ebb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Feb 2019 10:15:18 -0800 Subject: [PATCH] Make TreePropertyCursor respect field selectors --- lib/binding/lib.rs | 147 +++++++++++++++++++++++++++------------------ 1 file changed, 88 insertions(+), 59 deletions(-) diff --git a/lib/binding/lib.rs b/lib/binding/lib.rs index 94001870..926f95b4 100644 --- a/lib/binding/lib.rs +++ b/lib/binding/lib.rs @@ -57,20 +57,15 @@ pub struct InputEdit { } struct PropertyTransition { - state_id: usize, - child_index: Option, - text_regex_index: Option, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -enum NodeId { - Kind(u16), - Field(u16), - KindAndField(u16, u16), + state_id: u16, + child_index: Option, + text_regex_index: Option, + node_kind_id: Option, } struct PropertyState { - transitions: HashMap>, + field_transitions: HashMap>, + kind_transitions: HashMap>, property_set_id: usize, default_next_state_id: usize, } @@ -260,7 +255,10 @@ impl Parser { pub fn parse(&mut self, input: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Option { let bytes = input.as_ref(); let len = bytes.len(); - self.parse_with(&mut |i, _| if i < len { &bytes[i..] } else { &[] }, old_tree) + self.parse_with( + &mut |i, _| if i < len { &bytes[i..] } else { &[] }, + old_tree, + ) } pub fn parse_utf16( @@ -270,7 +268,10 @@ impl Parser { ) -> Option { let code_points = input.as_ref(); let len = code_points.len(); - self.parse_utf16_with(&mut |i, _| if i < len { &code_points[i..] } else { &[] }, old_tree) + self.parse_utf16_with( + &mut |i, _| if i < len { &code_points[i..] } else { &[] }, + old_tree, + ) } pub fn parse_with<'a, T: FnMut(usize, Point) -> &'a [u8]>( @@ -753,41 +754,40 @@ impl<'a, P> TreePropertyCursor<'a, P> { node_field_id: Option, node_child_index: usize, ) -> usize { - let keys; - let key_count; - if let Some(node_field_id) = node_field_id { - key_count = 3; - keys = [ - NodeId::KindAndField(node_kind_id, node_field_id), - NodeId::Field(node_field_id), - NodeId::Kind(node_kind_id), - ]; + let transitions = if let Some(field_id) = node_field_id { + state.field_transitions.get(&field_id) } else { - key_count = 1; - keys = [NodeId::Kind(node_kind_id); 3]; - } + state.kind_transitions.get(&node_kind_id) + }; - for key in &keys[0..key_count] { - if let Some(transitions) = state.transitions.get(key) { - for transition in transitions.iter() { - if let Some(text_regex_index) = transition.text_regex_index { - let node = self.cursor.node(); - let text = &self.source[node.start_byte()..node.end_byte()]; - if let Ok(text) = str::from_utf8(text) { - if !self.property_sheet.text_regexes[text_regex_index].is_match(text) { - continue; - } - } - } + if let Some(transitions) = transitions { + for transition in transitions.iter() { + if transition + .node_kind_id + .map_or(false, |id| id != node_kind_id) + { + continue; + } - if let Some(child_index) = transition.child_index { - if child_index != node_child_index { + if let Some(text_regex_index) = transition.text_regex_index { + let node = self.cursor.node(); + let text = &self.source[node.start_byte()..node.end_byte()]; + if let Ok(text) = str::from_utf8(text) { + if !self.property_sheet.text_regexes[text_regex_index as usize] + .is_match(text) + { continue; } } - - return transition.state_id; } + + if let Some(child_index) = transition.child_index { + if child_index != node_child_index as u16 { + continue; + } + } + + return transition.state_id as usize; } } @@ -876,20 +876,32 @@ impl

PropertySheet

{ let mut text_regex_patterns = Vec::new(); for state in input.states.iter() { - let mut transitions = HashMap::new(); let node_kind_count = language.node_kind_count(); + let mut kind_transitions = HashMap::new(); + let mut field_transitions = HashMap::new(); + + for transition in state.transitions.iter() { + let field_id = transition + .field + .as_ref() + .and_then(|field| language.field_id_for_name(&field)); + if let Some(field_id) = field_id { + field_transitions.entry(field_id).or_insert(Vec::new()); + } + } + for transition in state.transitions.iter() { let text_regex_index = if let Some(regex_pattern) = transition.text.as_ref() { if let Some(index) = text_regex_patterns.iter().position(|r| *r == regex_pattern) { - Some(index) + Some(index as u16) } else { text_regex_patterns.push(regex_pattern); text_regexes.push( Regex::new(®ex_pattern).map_err(PropertySheetError::InvalidRegex)?, ); - Some(text_regexes.len() - 1) + Some(text_regexes.len() as u16 - 1) } } else { None @@ -912,24 +924,41 @@ impl

PropertySheet

{ .as_ref() .and_then(|field| language.field_id_for_name(&field)); - let key = match (kind_id, field_id) { - (Some(kind_id), None) => NodeId::Kind(kind_id), - (None, Some(field_id)) => NodeId::Field(field_id), - (Some(kind_id), Some(field_id)) => NodeId::KindAndField(kind_id, field_id), - (None, None) => continue, - }; + if let Some(field_id) = field_id { + field_transitions + .entry(field_id) + .or_insert(Vec::new()) + .push(PropertyTransition { + node_kind_id: kind_id, + child_index: transition.index.map(|i| i as u16), + state_id: transition.state_id as u16, + text_regex_index, + }); + } else { + for (_, entries) in field_transitions.iter_mut() { + entries.push(PropertyTransition { + node_kind_id: kind_id, + child_index: transition.index.map(|i| i as u16), + state_id: transition.state_id as u16, + text_regex_index, + }); + } - transitions - .entry(key) - .or_insert(Vec::new()) - .push(PropertyTransition { - child_index: transition.index, - state_id: transition.state_id, - text_regex_index, - }); + if let Some(kind_id) = kind_id { + kind_transitions.entry(kind_id).or_insert(Vec::new()).push( + PropertyTransition { + node_kind_id: None, + child_index: transition.index.map(|i| i as u16), + state_id: transition.state_id as u16, + text_regex_index, + }, + ); + } + } } states.push(PropertyState { - transitions, + field_transitions, + kind_transitions, default_next_state_id: state.default_next_state_id, property_set_id: state.property_set_id, });