@@ -1260,7 +1260,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
1260
1260
use std:: { iter, mem, ops, str, usize} ;
1261
1261
use tree_sitter:: {
1262
1262
Language as Grammar , Node , Parser , Point , Query , QueryCaptures , QueryCursor , QueryError ,
1263
- QueryMatch , Range , TextProvider , Tree ,
1263
+ QueryMatch , Range , TextProvider , Tree , TreeCursor ,
1264
1264
} ;
1265
1265
1266
1266
const CANCELLATION_CHECK_INTERVAL : usize = 100 ;
@@ -2130,57 +2130,68 @@ impl<I: Iterator<Item = HighlightEvent>> Iterator for Merge<I> {
2130
2130
}
2131
2131
}
2132
2132
2133
+ fn node_is_visible ( node : & Node ) -> bool {
2134
+ node. is_missing ( ) || ( node. is_named ( ) && node. language ( ) . node_kind_is_visible ( node. kind_id ( ) ) )
2135
+ }
2136
+
2133
2137
pub fn pretty_print_tree < W : fmt:: Write > ( fmt : & mut W , node : Node ) -> fmt:: Result {
2134
- pretty_print_tree_impl ( fmt, node, true , None , 0 )
2138
+ if node. child_count ( ) == 0 {
2139
+ if node_is_visible ( & node) {
2140
+ write ! ( fmt, "({})" , node. kind( ) )
2141
+ } else {
2142
+ write ! ( fmt, "\" {}\" " , node. kind( ) )
2143
+ }
2144
+ } else {
2145
+ pretty_print_tree_impl ( fmt, & mut node. walk ( ) , 0 )
2146
+ }
2135
2147
}
2136
2148
2137
2149
fn pretty_print_tree_impl < W : fmt:: Write > (
2138
2150
fmt : & mut W ,
2139
- node : Node ,
2140
- is_root : bool ,
2141
- field_name : Option < & str > ,
2151
+ cursor : & mut TreeCursor ,
2142
2152
depth : usize ,
2143
2153
) -> fmt:: Result {
2144
- fn is_visible ( node : Node ) -> bool {
2145
- node. is_missing ( )
2146
- || ( node. is_named ( ) && node. language ( ) . node_kind_is_visible ( node. kind_id ( ) ) )
2147
- }
2154
+ let node = cursor. node ( ) ;
2155
+ let visible = node_is_visible ( & node) ;
2148
2156
2149
- if is_visible ( node ) {
2157
+ if visible {
2150
2158
let indentation_columns = depth * 2 ;
2151
2159
write ! ( fmt, "{:indentation_columns$}" , "" ) ?;
2152
2160
2153
- if let Some ( field_name) = field_name {
2161
+ if let Some ( field_name) = cursor . field_name ( ) {
2154
2162
write ! ( fmt, "{}: " , field_name) ?;
2155
2163
}
2156
2164
2157
2165
write ! ( fmt, "({}" , node. kind( ) ) ?;
2158
- } else if is_root {
2159
- write ! ( fmt, "(\" {}\" )" , node. kind( ) ) ?;
2160
2166
}
2161
2167
2162
- for child_idx in 0 ..node. child_count ( ) {
2163
- if let Some ( child) = node. child ( child_idx) {
2164
- if is_visible ( child) {
2168
+ // Handle children.
2169
+ if cursor. goto_first_child ( ) {
2170
+ loop {
2171
+ if node_is_visible ( & cursor. node ( ) ) {
2165
2172
fmt. write_char ( '\n' ) ?;
2166
2173
}
2167
2174
2168
- pretty_print_tree_impl (
2169
- fmt,
2170
- child,
2171
- false ,
2172
- node. field_name_for_child ( child_idx as u32 ) ,
2173
- depth + 1 ,
2174
- ) ?;
2175
+ pretty_print_tree_impl ( fmt, cursor, depth + 1 ) ?;
2176
+
2177
+ if !cursor. goto_next_sibling ( ) {
2178
+ break ;
2179
+ }
2175
2180
}
2181
+
2182
+ let moved = cursor. goto_parent ( ) ;
2183
+ // The parent of the first child must exist, and must be `node`.
2184
+ debug_assert ! ( moved) ;
2185
+ debug_assert ! ( cursor. node( ) == node) ;
2176
2186
}
2177
2187
2178
- if is_visible ( node ) {
2179
- write ! ( fmt, ")" ) ?;
2188
+ if visible {
2189
+ fmt. write_char ( ')' ) ?;
2180
2190
}
2181
2191
2182
2192
Ok ( ( ) )
2183
2193
}
2194
+
2184
2195
#[ cfg( test) ]
2185
2196
mod test {
2186
2197
use super :: * ;
@@ -2353,11 +2364,17 @@ mod test {
2353
2364
}
2354
2365
2355
2366
#[ track_caller]
2356
- fn assert_pretty_print ( source : & str , expected : & str , start : usize , end : usize ) {
2367
+ fn assert_pretty_print (
2368
+ language_name : & str ,
2369
+ source : & str ,
2370
+ expected : & str ,
2371
+ start : usize ,
2372
+ end : usize ,
2373
+ ) {
2357
2374
let source = Rope :: from_str ( source) ;
2358
2375
2359
2376
let loader = Loader :: new ( Configuration { language : vec ! [ ] } ) ;
2360
- let language = get_language ( "rust" ) . unwrap ( ) ;
2377
+ let language = get_language ( language_name ) . unwrap ( ) ;
2361
2378
2362
2379
let config = HighlightConfiguration :: new ( language, "" , "" , "" ) . unwrap ( ) ;
2363
2380
let syntax = Syntax :: new ( & source, Arc :: new ( config) , Arc :: new ( loader) ) ;
@@ -2377,13 +2394,14 @@ mod test {
2377
2394
#[ test]
2378
2395
fn test_pretty_print ( ) {
2379
2396
let source = r#"/// Hello"# ;
2380
- assert_pretty_print ( source, "(line_comment)" , 0 , source. len ( ) ) ;
2397
+ assert_pretty_print ( "rust" , source, "(line_comment)" , 0 , source. len ( ) ) ;
2381
2398
2382
2399
// A large tree should be indented with fields:
2383
2400
let source = r#"fn main() {
2384
2401
println!("Hello, World!");
2385
2402
}"# ;
2386
2403
assert_pretty_print (
2404
+ "rust" ,
2387
2405
source,
2388
2406
concat ! (
2389
2407
"(function_item\n " ,
@@ -2402,11 +2420,34 @@ mod test {
2402
2420
2403
2421
// Selecting a token should print just that token:
2404
2422
let source = r#"fn main() {}"# ;
2405
- assert_pretty_print ( source, r#"( "fn") "# , 0 , 1 ) ;
2423
+ assert_pretty_print ( "rust" , source, r#""fn""# , 0 , 1 ) ;
2406
2424
2407
2425
// Error nodes are printed as errors:
2408
2426
let source = r#"}{"# ;
2409
- assert_pretty_print ( source, "(ERROR)" , 0 , source. len ( ) ) ;
2427
+ assert_pretty_print ( "rust" , source, "(ERROR)" , 0 , source. len ( ) ) ;
2428
+
2429
+ // Fields broken under unnamed nodes are determined correctly.
2430
+ // In the following source, `object` belongs to the `singleton_method`
2431
+ // rule but `name` and `body` belong to an unnamed helper `_method_rest`.
2432
+ // This can cause a bug with a pretty-printing implementation that
2433
+ // uses `Node::field_name_for_child` to determine field names but is
2434
+ // fixed when using `TreeCursor::field_name`.
2435
+ let source = "def self.method_name
2436
+ true
2437
+ end" ;
2438
+ assert_pretty_print (
2439
+ "ruby" ,
2440
+ source,
2441
+ concat ! (
2442
+ "(singleton_method\n " ,
2443
+ " object: (self)\n " ,
2444
+ " name: (identifier)\n " ,
2445
+ " body: (body_statement\n " ,
2446
+ " (true)))"
2447
+ ) ,
2448
+ 0 ,
2449
+ source. len ( ) ,
2450
+ ) ;
2410
2451
}
2411
2452
2412
2453
#[ test]
0 commit comments