Skip to content

Commit 5a97979

Browse files
committed
test: validate pre-conversion nesting in flatten tests
Ensure that nested structures exist before conversion by adding assert_direct_nested_kind checks to all no_nested_* tests. This prevents false positives where tests pass on already-flat structures.
1 parent 13a4f5e commit 5a97979

File tree

2 files changed

+79
-19
lines changed

2 files changed

+79
-19
lines changed

crates/postgresql-cst-parser/src/tree_sitter/assert_util.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,26 @@ pub fn assert_no_direct_nested_kind(root: &ResolvedNode, kind: SyntaxKind) {
4545
}
4646
}
4747

48+
/// Asserts that there is at least one directly nested node of the specified `SyntaxKind`.
49+
/// In other words, there must be a node of `kind` that has another `kind` node as its immediate child.
50+
pub fn assert_direct_nested_kind(root: &ResolvedNode, kind: SyntaxKind) {
51+
let has_direct_nesting = root
52+
.descendants()
53+
.filter(|node| node.kind() == kind)
54+
.any(|node| {
55+
if let Some(parent) = node.parent() {
56+
node.kind() == kind && parent.kind() == kind
57+
} else {
58+
false
59+
}
60+
});
61+
62+
assert!(
63+
has_direct_nesting,
64+
"Expected at least one directly nested {kind:?} node, but none was found."
65+
);
66+
}
67+
4868
#[cfg(test)]
4969
mod tests {
5070
use super::*;
@@ -118,4 +138,23 @@ mod tests {
118138

119139
assert_no_direct_nested_kind(&root, SyntaxKind::target_list);
120140
}
141+
142+
#[test]
143+
fn test_direct_nested_kind_passes() {
144+
let input = "select a,b,c;";
145+
let root = cst::parse(input).unwrap();
146+
147+
assert_direct_nested_kind(&root, SyntaxKind::target_list);
148+
}
149+
150+
#[test]
151+
#[should_panic(
152+
expected = "Expected at least one directly nested SelectStmt node, but none was found."
153+
)]
154+
fn test_direct_nested_kind_fails() {
155+
let input = "select a;";
156+
let root = cst::parse(input).unwrap();
157+
158+
assert_direct_nested_kind(&root, SyntaxKind::SelectStmt);
159+
}
121160
}

crates/postgresql-cst-parser/src/tree_sitter/convert.rs

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,9 @@ FROM
326326
cst,
327327
syntax_kind::SyntaxKind,
328328
tree_sitter::{
329-
assert_util::{assert_no_direct_nested_kind, assert_node_count},
329+
assert_util::{
330+
assert_direct_nested_kind, assert_no_direct_nested_kind, assert_node_count,
331+
},
330332
convert::get_ts_tree_and_range_map,
331333
},
332334
};
@@ -337,6 +339,7 @@ FROM
337339

338340
let root = cst::parse(input).unwrap();
339341
assert_node_count(&root, SyntaxKind::target_list, 3);
342+
assert_direct_nested_kind(&root, SyntaxKind::target_list);
340343

341344
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
342345
assert_node_count(&new_root, SyntaxKind::target_list, 1);
@@ -347,17 +350,19 @@ FROM
347350
fn no_nested_stmtmulti() {
348351
let input = "select a,b,c;\nselect d,e from t;";
349352
let root = cst::parse(input).unwrap();
350-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
353+
assert_direct_nested_kind(&root, SyntaxKind::stmtmulti);
351354

355+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
352356
assert_no_direct_nested_kind(&new_root, SyntaxKind::stmtmulti);
353357
}
354358

355359
#[test]
356360
fn no_nested_from_list() {
357361
let input = "select * from t1, t2;";
358362
let root = cst::parse(input).unwrap();
359-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
363+
assert_direct_nested_kind(&root, SyntaxKind::from_list);
360364

365+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
361366
assert_no_direct_nested_kind(&new_root, SyntaxKind::from_list);
362367
}
363368

@@ -366,143 +371,159 @@ FROM
366371
let input =
367372
"select t.a, t.b.c, t1.*, a[1], a[4][5], a[2:5], a[3].b, a[3][4].b, a[3:5].b;";
368373
let root = cst::parse(input).unwrap();
369-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
374+
assert_direct_nested_kind(&root, SyntaxKind::indirection);
370375

376+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
371377
assert_no_direct_nested_kind(&new_root, SyntaxKind::indirection);
372378
}
373379

374380
#[test]
375381
fn no_nested_expr_list() {
376382
let input = "select a from t where a in (1,2,3);";
377383
let root = cst::parse(input).unwrap();
378-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
384+
assert_direct_nested_kind(&root, SyntaxKind::expr_list);
379385

386+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
380387
assert_no_direct_nested_kind(&new_root, SyntaxKind::expr_list);
381388
}
382389

383390
#[test]
384391
fn no_nested_func_arg_list() {
385392
let input = "select func(1, 2, func2(3, 4), 5);";
386393
let root = cst::parse(input).unwrap();
387-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
394+
assert_direct_nested_kind(&root, SyntaxKind::func_arg_list);
388395

396+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
389397
assert_no_direct_nested_kind(&new_root, SyntaxKind::func_arg_list);
390398
}
391399

392400
#[test]
393401
fn no_nested_when_clause_list() {
394402
let input = "select case when a then b when c then d when e then f else g end;";
395403
let root = cst::parse(input).unwrap();
396-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
404+
assert_direct_nested_kind(&root, SyntaxKind::when_clause_list);
397405

406+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
398407
assert_no_direct_nested_kind(&new_root, SyntaxKind::when_clause_list);
399408
}
400409

401410
#[test]
402411
fn no_nested_sortby_list() {
403412
let input = "select * from t order by a, b, c;";
404413
let root = cst::parse(input).unwrap();
405-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
414+
assert_direct_nested_kind(&root, SyntaxKind::sortby_list);
406415

416+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
407417
assert_no_direct_nested_kind(&new_root, SyntaxKind::sortby_list);
408418
}
409419

410420
#[test]
411421
fn no_nested_groupby_list() {
412422
let input = "select a, b, c from t group by a, b, c;";
413423
let root = cst::parse(input).unwrap();
414-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
424+
assert_direct_nested_kind(&root, SyntaxKind::group_by_list);
415425

426+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
416427
assert_no_direct_nested_kind(&new_root, SyntaxKind::group_by_list);
417428
}
418429

419430
#[test]
420431
fn no_nested_for_locking_items() {
421432
let input = "select * from t1, t2 for update of t1 for update of t2;";
422433
let root = cst::parse(input).unwrap();
423-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
434+
assert_direct_nested_kind(&root, SyntaxKind::for_locking_items);
424435

436+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
425437
assert_no_direct_nested_kind(&new_root, SyntaxKind::for_locking_items);
426438
}
427439

428440
#[test]
429441
fn no_nested_qualified_name_list() {
430442
let input = "select a from t for update of t.a, t.b;";
431443
let root = cst::parse(input).unwrap();
432-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
444+
assert_direct_nested_kind(&root, SyntaxKind::qualified_name_list);
433445

446+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
434447
assert_no_direct_nested_kind(&new_root, SyntaxKind::qualified_name_list);
435448
}
436449

437450
#[test]
438451
fn no_nested_cte_list() {
439452
let input = "with a as (select 1), b as (select 2) select * from a, b;";
440453
let root = cst::parse(input).unwrap();
441-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
454+
assert_direct_nested_kind(&root, SyntaxKind::cte_list);
442455

456+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
443457
assert_no_direct_nested_kind(&new_root, SyntaxKind::cte_list);
444458
}
445459

446460
#[test]
447461
fn no_nested_name_list() {
448462
let input = "with t (a, b) as (select 1) select * from t;";
449463
let root = cst::parse(input).unwrap();
450-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
464+
assert_direct_nested_kind(&root, SyntaxKind::name_list);
451465

466+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
452467
assert_no_direct_nested_kind(&new_root, SyntaxKind::name_list);
453468
}
454469

455470
#[test]
456471
fn no_nested_set_clause_list() {
457472
let input = "update t set a = 1, b = 2, c = 3;";
458473
let root = cst::parse(input).unwrap();
459-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
474+
assert_direct_nested_kind(&root, SyntaxKind::set_clause_list);
460475

476+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
461477
assert_no_direct_nested_kind(&new_root, SyntaxKind::set_clause_list);
462478
}
463479

464480
#[test]
465481
fn no_nested_set_target_list() {
466482
let input = "update t set (a, b, c) = (1, 2, 3) where id = 1;";
467483
let root = cst::parse(input).unwrap();
468-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
484+
assert_direct_nested_kind(&root, SyntaxKind::set_target_list);
469485

486+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
470487
assert_no_direct_nested_kind(&new_root, SyntaxKind::set_target_list);
471488
}
472489

473490
#[test]
474491
fn no_nested_insert_column_list() {
475492
let input = "insert into t (a, b, c) values (1, 2, 3);";
476493
let root = cst::parse(input).unwrap();
477-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
494+
assert_direct_nested_kind(&root, SyntaxKind::insert_column_list);
478495

496+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
479497
assert_no_direct_nested_kind(&new_root, SyntaxKind::insert_column_list);
480498
}
481499

482500
#[test]
483501
fn no_nested_index_params() {
484502
let input = "insert into t (a, b, c) values (1, 2, 3) on conflict (a, b) do nothing;";
485503
let root = cst::parse(input).unwrap();
486-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
504+
assert_direct_nested_kind(&root, SyntaxKind::index_params);
487505

506+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
488507
assert_no_direct_nested_kind(&new_root, SyntaxKind::index_params);
489508
}
490509

491510
#[test]
492511
fn no_nested_values_clause() {
493512
let input = "values (1,2,3), (4,5,6), (7,8,9);";
494513
let root = cst::parse(input).unwrap();
495-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
514+
assert_direct_nested_kind(&root, SyntaxKind::values_clause);
496515

516+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
497517
assert_no_direct_nested_kind(&new_root, SyntaxKind::values_clause);
498518
}
499519

500520
#[test]
501521
fn no_nested_table_func_element_list() {
502522
let input = "select * from unnest(a) as (x int, y text);";
503523
let root = cst::parse(input).unwrap();
504-
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
524+
assert_direct_nested_kind(&root, SyntaxKind::TableFuncElementList);
505525

526+
let (new_root, _) = get_ts_tree_and_range_map(input, &root);
506527
assert_no_direct_nested_kind(&new_root, SyntaxKind::TableFuncElementList);
507528
}
508529
}

0 commit comments

Comments
 (0)