Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/parsing/syntax_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Scope>,
pub captures: Option<CaptureMapping>,
Expand Down Expand Up @@ -268,6 +269,7 @@ where
impl MatchPattern {
pub fn new(
has_captures: bool,
raw_regex_str: String,
regex_str: String,
scope: Vec<Scope>,
captures: Option<CaptureMapping>,
Expand All @@ -276,6 +278,7 @@ impl MatchPattern {
) -> MatchPattern {
MatchPattern {
has_captures,
raw_regex_str,
regex: Regex::new(regex_str),
scope,
captures,
Expand Down Expand Up @@ -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,
Expand Down
77 changes: 77 additions & 0 deletions src/parsing/yaml_load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ impl SyntaxDefinition {
state: &mut ParserState<'_>,
) -> Result<HashMap<String, Context>, 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()) {
Expand Down Expand Up @@ -460,6 +463,7 @@ impl SyntaxDefinition {

let pattern = MatchPattern::new(
has_captures,
raw_regex.to_string(),
regex_str,
scope,
captures,
Expand Down Expand Up @@ -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#"
Expand Down