From 20072e18d5cafdb2690c57ec1ce6bcde433f104e Mon Sep 17 00:00:00 2001 From: Keith Hall Date: Sun, 26 Jan 2025 22:11:09 +0200 Subject: [PATCH] wip track original match pattern regular expression patterns so can do a re-replacement of the variable references against the new extended syntax's variables --- src/parsing/syntax_definition.rs | 4 ++ src/parsing/yaml_load.rs | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/parsing/syntax_definition.rs b/src/parsing/syntax_definition.rs index 856c42e5..97c80f41 100644 --- a/src/parsing/syntax_definition.rs +++ b/src/parsing/syntax_definition.rs @@ -117,6 +117,7 @@ pub struct MatchIter<'a> { #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct MatchPattern { pub has_captures: bool, + pub raw_regex_str: String, pub regex: Regex, pub scope: Vec, pub captures: Option, @@ -268,6 +269,7 @@ where impl MatchPattern { pub fn new( has_captures: bool, + raw_regex_str: String, regex_str: String, scope: Vec, captures: Option, @@ -276,6 +278,7 @@ impl MatchPattern { ) -> MatchPattern { MatchPattern { has_captures, + raw_regex_str, regex: Regex::new(regex_str), scope, captures, @@ -318,6 +321,7 @@ mod tests { fn can_compile_refs() { let pat = MatchPattern { has_captures: true, + raw_regex_str: "ignored here".into(), regex: Regex::new(r"lol \\ \2 \1 '\9' \wz".into()), scope: vec![], captures: None, diff --git a/src/parsing/yaml_load.rs b/src/parsing/yaml_load.rs index 6a4733f4..5c1d0854 100644 --- a/src/parsing/yaml_load.rs +++ b/src/parsing/yaml_load.rs @@ -205,6 +205,9 @@ impl SyntaxDefinition { state: &mut ParserState<'_>, ) -> Result, ParseSyntaxError> { // FIXME: contexts need to be re-evaluated with the new values of the variables + // we now store raw_regex_str on MatchPattern for this purpose + // - perhaps we only need to do so when it actually contains a variable reference + // - otherwise it is an unnecessary waste let mut contexts = extends.cloned().unwrap_or_default(); for (key, value) in map.iter() { if let (Some(name), Some(val_vec)) = (key.as_str(), value.as_vec()) { @@ -460,6 +463,7 @@ impl SyntaxDefinition { let pattern = MatchPattern::new( has_captures, + raw_regex.to_string(), regex_str, scope, captures, @@ -1086,6 +1090,79 @@ mod tests { } } + #[test] + fn can_parse_extends_with_overwritten_variables() { + let defn: SyntaxDefinition = SyntaxDefinition::load_from_str( + " + name: base syntax + scope: source.base + variables: + a: 'abc' + b: '{{a}}def' + contexts: + main: + - match: '{{b}}' + scope: testing + ", + false, + None, + ) + .unwrap(); + assert_eq!(defn.name, "base syntax"); + + let defn2: SyntaxDefinition = SyntaxDefinition::load_from_str_extended( + " + name: derived syntax + scope: source.derived + extends: base-syntax.sublime-syntax + variables: + a: 'ghi' + contexts: + main: + - meta_append: true + - match: '{{a}}' + scope: foobar + ", + Some(&defn), + false, + None + ) + .unwrap(); + assert_eq!(defn2.name, "derived syntax"); + + let main = &defn2.contexts["main"]; + + let first_pattern: &Pattern = &main.patterns[0]; + match *first_pattern { + Pattern::Match(ref match_pat) => { + assert_eq!( + match_pat.scope, + vec![ + Scope::new("testing").unwrap(), + ] + ); + + assert_eq!("ghidef", match_pat.regex.regex_str()); + } + _ => unreachable!(), + } + + let second_pattern: &Pattern = &main.patterns[1]; + match *second_pattern { + Pattern::Match(ref match_pat) => { + assert_eq!( + match_pat.scope, + vec![ + Scope::new("foobar").unwrap(), + ] + ); + + assert_eq!("ghi", match_pat.regex.regex_str()); + } + _ => unreachable!(), + } + } + #[test] fn can_parse_embed_as_with_prototypes() { let old_def = SyntaxDefinition::load_from_str(r#"