Skip to content

Commit

Permalink
fix: 394 yaml strings (#569)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-ley-scrub authored Oct 30, 2024
1 parent e12de3b commit 4d1380e
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 7 deletions.
6 changes: 6 additions & 0 deletions crates/cli_bin/fixtures/yaml_strings/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# https://github.com/actions/runner-images/blob/main/README.md#available-images
steps:
- "ubuntu-latest"
- 'ubuntu-latest'
- ubuntu-latest
- something random
33 changes: 33 additions & 0 deletions crates/cli_bin/tests/apply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3051,6 +3051,39 @@ fn apply_to_path_with_invalid_lang() -> Result<()> {
Ok(())
}

/// test that we can apply to a yaml file containing equivalent strings but with different formatting/representations
/// see https://github.com/getgrit/gritql/issues/394
#[test]
fn apply_to_yaml_with_multiple_equivalent_strings() -> Result<()> {
let (_temp_dir, fixture_dir) = get_fixture("yaml_strings", false)?;

let mut cmd = get_test_cmd()?;
cmd.arg("apply")
.arg("`'ubuntu-latest'` => `'ubuntu-22.04'`")
.arg("build.yml")
.arg("--lang=yaml")
.arg("--force")
.current_dir(&fixture_dir);

let result = cmd.output()?;

let stderr = String::from_utf8(result.stderr)?;
println!("stderr: {:?}", stderr);
let stdout = String::from_utf8(result.stdout)?;
println!("stdout: {:?}", stdout);

assert!(result.status.success(), "Command failed");
// Read back the build.yml file to ensure it was processed correctly
let target_file = fixture_dir.join("build.yml");
let content: String = fs_err::read_to_string(target_file)?;
assert_snapshot!(content);

// ensure all equivalent strings were replaced
assert!(stdout.contains("Processed 1 files and found 3 matches"));

Ok(())
}

/// Ban multiple stdin paths
#[test]
fn apply_stdin_two_paths() -> Result<()> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
source: crates/cli_bin/tests/apply.rs
expression: content
---
# https://github.com/actions/runner-images/blob/main/README.md#available-images
steps:
- 'ubuntu-22.04'
- 'ubuntu-22.04'
- 'ubuntu-22.04'
- something random
6 changes: 6 additions & 0 deletions crates/core/src/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ impl AstLeafNode {
text: text.to_owned(),
})
}
pub fn is_equivalent_class(&self, sort: SortId) -> bool {
if let Some(e) = &self.equivalence_class {
return e.contains(sort);
}
false
}
}

impl AstLeafNodePattern<MarzanoQueryContext> for AstLeafNode {
Expand Down
69 changes: 64 additions & 5 deletions crates/core/src/marzano_code_snippet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,70 @@ impl Matcher<MarzanoQueryContext> for MarzanoCodeSnippet {
return Ok(false);
};

if let Some((_, pattern)) = self
.patterns
.iter()
.find(|(id, _)| *id == node.node.kind_id())
{
if let Some((_, pattern)) = self.patterns.iter().find(|(id, p)| {
let kind_id = node.node.kind_id();
if *id == kind_id {
return true;
}
// use equivalence classes to match 'ubuntu-latest' and "ubuntu-latest" in yaml
// i.e. to match string_scalar, single_quote_scalar, and double_quote_scalar
// see https://github.com/getgrit/gritql/issues/394
match p {
Pattern::AstLeafNode(p) => p.is_equivalent_class(kind_id),
Pattern::AstNode(_) => false,
Pattern::Some(_) => false,
Pattern::Every(_) => false,
Pattern::List(_) => false,
Pattern::ListIndex(_) => false,
Pattern::Map(_) => false,
Pattern::Accessor(_) => false,
Pattern::Call(_) => false,
Pattern::Regex(_) => false,
Pattern::File(_) => false,
Pattern::Files(_) => false,
Pattern::Bubble(_) => false,
Pattern::Limit(_) => false,
Pattern::CallBuiltIn(_) => false,
Pattern::CallFunction(_) => false,
Pattern::CallForeignFunction(_) => false,
Pattern::CallbackPattern(_) => false,
Pattern::Assignment(_) => false,
Pattern::Accumulate(_) => false,
Pattern::StringConstant(_) => false,
Pattern::IntConstant(_) => false,
Pattern::FloatConstant(_) => false,
Pattern::BooleanConstant(_) => false,
Pattern::Variable(_) => false,
Pattern::Add(_) => false,
Pattern::Subtract(_) => false,
Pattern::Multiply(_) => false,
Pattern::Divide(_) => false,
Pattern::Modulo(_) => false,
Pattern::And(_) => false,
Pattern::Or(_) => false,
Pattern::Maybe(_) => false,
Pattern::Any(_) => false,
Pattern::CodeSnippet(_) => false,
Pattern::Rewrite(_) => false,
Pattern::Range(_) => false,
Pattern::Contains(_) => false,
Pattern::Includes(_) => false,
Pattern::Within(_) => false,
Pattern::After(_) => false,
Pattern::Before(_) => false,
Pattern::Where(_) => false,
Pattern::Undefined => false,
Pattern::Top => false,
Pattern::Underscore => false,
Pattern::Bottom => false,
Pattern::Not(_) => false,
Pattern::If(_) => false,
Pattern::Dots => false,
Pattern::Dynamic(_) => false,
Pattern::Sequential(_) => false,
Pattern::Like(_) => false,
}
}) {
pattern.execute(resolved, state, context, logs)
} else {
Ok(false)
Expand Down
7 changes: 7 additions & 0 deletions crates/language/src/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ impl LeafEquivalenceClass {
.is_some_and(|s| s == self.representative)
})
}
pub fn contains(&self, sort: SortId) -> bool {
self.class.iter().any(|c| c.sort == sort)
}
pub(crate) fn new(
representative: &str,
sort: SortId,
Expand Down Expand Up @@ -120,6 +123,10 @@ pub(crate) fn normalize_double_quote_string(s: &str) -> Option<&str> {
s.strip_prefix('"')?.strip_suffix('"')
}

pub(crate) fn normalize_single_quote_string(s: &str) -> Option<&str> {
s.strip_prefix('\'')?.strip_suffix('\'')
}

pub(crate) fn kind_and_field_id_for_field_map(
lang: &TSLanguage,
names: Vec<(&str, &str, FieldExpectationCondition)>,
Expand Down
21 changes: 19 additions & 2 deletions crates/language/src/yaml.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::language::{
fields_for_nodes, normalize_double_quote_string, normalize_identity, Field,
LeafEquivalenceClass, LeafNormalizer, MarzanoLanguage, NodeTypes, SortId, TSLanguage,
fields_for_nodes, normalize_double_quote_string, normalize_identity,
normalize_single_quote_string, Field, LeafEquivalenceClass, LeafNormalizer, MarzanoLanguage,
NodeTypes, SortId, TSLanguage,
};
use grit_util::Language;
use marzano_util::node_with_source::NodeWithSource;
Expand Down Expand Up @@ -45,6 +46,10 @@ impl Yaml {
language.id_for_node_kind("double_quote_scalar", true),
normalize_double_quote_string,
),
LeafNormalizer::new(
language.id_for_node_kind("single_quote_scalar", true),
normalize_single_quote_string,
),
]]
});
let metavariable_sort = language.id_for_node_kind("grit_metavariable", true);
Expand Down Expand Up @@ -154,6 +159,18 @@ mod tests {
assert!(!nodes.is_empty());
}

#[test]
fn simple_strings() {
let snippet = "steps:\n - runs_on: \"ubuntu-latest\"\n - runs_on: 'ubuntu-latest'\n - runs_on: ubuntu-latest";
let lang = Yaml::new(None);
let snippets = lang.parse_snippet_contexts(snippet);
let nodes = nodes_from_indices(&snippets);
for node in &nodes {
print_node(&node.node)
}
assert!(!nodes.is_empty());
}

#[test]
fn simple_yaml_metavariable() {
let snippet = "$list";
Expand Down

0 comments on commit 4d1380e

Please sign in to comment.