Skip to content

Commit 4d87469

Browse files
authored
Bug fix in contains clause in concrete syntax (#775)
Concrete syntax contains was passing the wrong node for the checker, and was matching with nodes it shouldn't. It was a very subtle bug. This PR should fix it.
1 parent d05fe5a commit 4d87469

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

crates/concrete-syntax/src/models/concrete_syntax/constraint_checker.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use super::interpreter::get_all_matches_for_concrete_syntax;
1717
use super::tree_sitter_adapter::{Node, SyntaxNode};
1818
use crate::models::concrete_syntax::parser::CsConstraint;
1919
use crate::models::matches::CapturedNode;
20+
use crate::tree_sitter_adapter::SyntaxCursor;
2021

2122
/// Simple context for contains constraint checking
2223
pub struct ConstraintContext<'a> {
@@ -64,13 +65,12 @@ fn check_contains_recursive(
6465
) -> bool {
6566
// Run the resolved pattern against the entire AST
6667
let matches = get_all_matches_for_concrete_syntax(
67-
context.ast_root,
68+
&context.ast_root.walk().node(),
6869
context.source_code,
6970
resolved_pattern,
7071
true, // recursive
7172
None, // replace_node
7273
);
73-
7474
// If we found any matches, the contains constraint is satisfied
7575
!matches.is_empty()
7676
}

crates/concrete-syntax/src/models/concrete_syntax/interpreter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ fn try_match_node_range(
394394
let constraint_context = ConstraintContext {
395395
captured_node: &captured,
396396
source_code: ctx.source_code,
397-
ast_root: ctx.top_node,
397+
ast_root: &ctx.cursor.node(),
398398
};
399399
if satisfies_constraints(&captured, constraints, Some(&constraint_context)) {
400400
let mut sub_ctx = MatchingContext {

crates/concrete-syntax/src/models/concrete_syntax/unit_tests/interpreter_test.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,3 +484,61 @@ fn test_not_contains_constraint() {
484484
GO,
485485
);
486486
}
487+
488+
#[test]
489+
fn test_contains_constraint_bug_minimal() {
490+
// Minimal anonymized test for contains constraint bug
491+
run_test(
492+
r#"func TestSomething(t *testing.T) {
493+
for _, tc := range[] struct {
494+
fieldA string
495+
fieldB int
496+
flag1 bool
497+
flag2 bool
498+
flag3 bool
499+
} {
500+
{
501+
fieldA: "a",
502+
flag2: false,
503+
flag3: false,
504+
},
505+
{
506+
fieldA: "b",
507+
flag2: true,
508+
flag3: false,
509+
},
510+
{
511+
fieldA: "c",
512+
flag2: true,
513+
flag3: true,
514+
},
515+
}
516+
}"#,
517+
r#"{
518+
:[before*]
519+
:[to_delete]
520+
:[after*]
521+
}
522+
|>
523+
:[to_delete].node_type in ["keyed_element"],
524+
:[to_delete] contains /flag3: true/"#,
525+
2,
526+
vec![
527+
vec![
528+
("to_delete", "flag3: true"),
529+
(
530+
"*",
531+
"{\n fieldA: \"c\",\n flag2: true,\n flag3: true,\n }",
532+
),
533+
],
534+
vec![
535+
("to_delete", "flag3: true"),
536+
(
537+
"*",
538+
"{\n fieldA: \"c\",\n flag2: true,\n flag3: true,\n }",
539+
),
540+
],
541+
],
542+
GO,
543+
);
544+
}

0 commit comments

Comments
 (0)