From a21d355ade9ab381f7d55710b98ece547eab4997 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 22 Jul 2019 11:00:57 -0700 Subject: [PATCH] Fix handling of potentially overlapping selectors in property sheets --- cli/src/generate/properties.rs | 72 +++++++++++++++++++++++++------- cli/src/tests/properties_test.rs | 13 +++--- 2 files changed, 65 insertions(+), 20 deletions(-) diff --git a/cli/src/generate/properties.rs b/cli/src/generate/properties.rs index bd4a5a08..77fa29e1 100644 --- a/cli/src/generate/properties.rs +++ b/cli/src/generate/properties.rs @@ -407,24 +407,68 @@ impl<'a> Builder<'a> { left: &PropertyTransitionJSON, right: &PropertyTransitionJSON, ) -> Option { - // If one transition is based on the node's type and the other - // is based on its field name, then create a combined transition - // wiht *both* criteria. - if let (Some(left_field), None) = (&left.field, &left.kind) { - if right.field.is_none() { - let mut result = right.clone(); - result.field = Some(left_field.clone()); - return Some(result); + let mut left_contributes = false; + let mut right_contributes = false; + let mut result = left.clone(); + + if let Some(left_kind) = &left.kind { + if let Some(right_kind) = &right.kind { + if left_kind != right_kind || left.named != right.named { + return None; + } + } else { + left_contributes = true; } + } else if let Some(right_kind) = &right.kind { + result.kind = Some(right_kind.clone()); + result.named = right.named; + right_contributes = true; } - if let (Some(right_field), None) = (&right.field, &right.kind) { - if left.field.is_none() { - let mut result = left.clone(); - result.field = Some(right_field.clone()); - return Some(result); + + if let Some(left_field) = &left.field { + if let Some(right_field) = &right.field { + if left_field != right_field { + return None; + } + } else { + left_contributes = true; } + } else if let Some(right_field) = &right.field { + result.field = Some(right_field.clone()); + right_contributes = true; + } + + if let Some(left_text) = &left.text { + if let Some(right_text) = &right.text { + if left_text != right_text { + return None; + } + } else { + left_contributes = true; + } + } else if let Some(right_text) = &right.text { + result.text = Some(right_text.clone()); + right_contributes = true; + } + + if let Some(left_index) = &left.index { + if let Some(right_index) = &right.index { + if left_index != right_index { + return None; + } + } else { + left_contributes = true; + } + } else if let Some(right_index) = &right.index { + result.index = Some(right_index.clone()); + right_contributes = true; + } + + if left_contributes && right_contributes { + Some(result) + } else { + None } - return None; } fn remove_duplicate_states(&mut self) { diff --git a/cli/src/tests/properties_test.rs b/cli/src/tests/properties_test.rs index 7c67a4df..51f0e820 100644 --- a/cli/src/tests/properties_test.rs +++ b/cli/src/tests/properties_test.rs @@ -2,9 +2,9 @@ use super::helpers::fixtures::get_language; use crate::generate::properties; use serde_derive::Deserialize; use serde_json; -use tree_sitter::{Parser, PropertySheet}; -use std::collections::HashSet; +use std::collections::HashSet; +use tree_sitter::{Parser, PropertySheet}; #[derive(Debug, Default, Deserialize, PartialEq, Eq)] struct Properties { a: Option, @@ -31,7 +31,7 @@ fn test_walk_with_properties_with_nth_child() { a: z; } ", - ) + ), ) .unwrap(); @@ -106,7 +106,7 @@ fn test_walk_with_properties_with_regexes() { a: x; } ", - ) + ), ) .unwrap(); @@ -195,7 +195,7 @@ fn test_walk_with_properties_based_on_fields() { a: w; } ", - ) + ), ) .unwrap(); @@ -260,5 +260,6 @@ fn test_walk_with_properties_based_on_fields() { } fn generate_property_sheet_string(path: &str, css: &str) -> String { - serde_json::to_string(&properties::generate_property_sheet(path, css, &HashSet::new()).unwrap()).unwrap() + serde_json::to_string(&properties::generate_property_sheet(path, css, &HashSet::new()).unwrap()) + .unwrap() }