use anyhow::{ensure, Result}; use tree_sitter::Query; use code_blocks::{get_query_subtrees, Block}; #[path = "../test_utils.rs"] mod test_utils; use test_utils::{build_tree, copy_item_above}; fn preserve_scope(s: &Block, d: &Block) -> Result<()> { ensure!( s.head().parent() == d.head().parent(), "Blocks have different parents" ); Ok(()) } fn rust_queries() -> [Query; 4] { [ Query::new( tree_sitter_rust::language(), "(([(attribute_item) (line_comment)] @header . [(attribute_item) (line_comment)]* @header)? . (function_item) @item)", ) .unwrap(), Query::new( tree_sitter_rust::language(), "(([(attribute_item) (line_comment)] @header . [(attribute_item) (line_comment)]* @header)? . (mod_item) @item)", ) .unwrap(), Query::new( tree_sitter_rust::language(), "(([(attribute_item) (line_comment)] @header . [(attribute_item) (line_comment)]* @header)? . (struct_item) @item)", ) .unwrap(), Query::new( tree_sitter_rust::language(), "(([(attribute_item) (line_comment)] @header . [(attribute_item) (line_comment)]* @header)? . (impl_item) @item)", ) .unwrap(), ] } #[test] fn test_get_query_subtrees() { let text = r#" mod stuff { #[derive(Debug)] /// struct doc struct A { } /// docs pub fn foo() { } } #[cfg(test)] mod tests { use super::*; /// test foo #[test] /// very long test #[ignore] fn test_foo() { stuff::foo(); } } "#; let tree = build_tree(text, tree_sitter_rust::language()); let subtrees = get_query_subtrees(&rust_queries(), &tree, text); for t in &subtrees { dbg!(text[t.block.byte_range()].to_string()); } insta::assert_debug_snapshot!(subtrees); } snapshot! { test_move_block, tree_sitter_rust::language(), rust_queries(), r#" fn foo() { /* ^src */ fn in_foo() { bar(); } } fn bar() {} /* ^dst */ "# } snapshot!( test_move_block_in_module, tree_sitter_rust::language(), rust_queries(), r#" mod m { fn foo() { /* ^src */ fn in_foo() { bar(); } } fn bar() {} /* ^dst */ } fn baz() {} "# ); snapshot!( test_move_block_in_module2, tree_sitter_rust::language(), rust_queries(), r#" mod m { fn foo() {} /* ^src */ fn bar() {}} /* ^dst */ fn baz() {} "# ); snapshot!( test_move_block_outside_scope_fails, tree_sitter_rust::language(), rust_queries(), preserve_scope, r#" mod m { fn foo() {} /* ^src */ } fn baz() {} /* ^fail */ "# ); snapshot!( test_move_block_outside_scope_fails2, tree_sitter_rust::language(), rust_queries(), preserve_scope, r#" mod m { /* ^fail */ fn foo() {} /* ^src */ } fn baz() {} "# ); snapshot!( test_move_block_up, tree_sitter_rust::language(), rust_queries(), r#" fn foo() {} /* ^dst */ fn bar() {} fn baz() {} /* ^src */ "# ); snapshot!( test_move_block_down, tree_sitter_rust::language(), rust_queries(), r#" mod m1 { /* ^src */ fn foo() {} } mod m2 { fn bar() {} } mod m3 { /* ^dst */ fn baz() {} } "# ); snapshot!( test_move_block_up2, tree_sitter_rust::language(), rust_queries(), r#" mod m1 { /* ^dst */ fn foo() {} } mod m2 { fn bar() {} } mod m3 { /* ^src */ fn baz() {} } "# ); snapshot!( test_move_block_into_scope_fails, tree_sitter_rust::language(), rust_queries(), preserve_scope, r#" mod m1 { fn foo() {} } mod m2 { fn bar() {} /* ^fail */ } mod m3 { /* ^src */ fn baz() {} } "# ); snapshot!( test_move_block_with_attributes, tree_sitter_rust::language(), rust_queries(), r#" #[test] fn foo() {} /* ^src */ fn bar() {} /* ^dst */ "# );