@konomanoasa/tree-sitter-query 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,22 +25,12 @@ fn parses_valid_source() {
25
25
  }
26
26
 
27
27
  #[test]
28
- fn preserves_comment_text() {
29
- let mut parser = parser();
30
- let source = "; query\n";
31
- let tree = parser.parse(source, None).unwrap();
32
- let root = tree.root_node();
33
- assert!(!root.has_error());
34
- assert_eq!(root.kind(), "query");
35
- assert_eq!(root.to_sexp(), "(query (comment))");
36
- assert_eq!(root.named_child(0).unwrap().byte_range(), 0..7);
37
- }
38
-
39
- #[test]
40
- fn missing_node_forms_follow_public_query_api_syntax() {
28
+ fn node_designators_follow_public_query_api_syntax() {
41
29
  let language = grammar::LANGUAGE.into();
42
30
  let mut parser = parser();
43
31
  for (source, valid) in [
32
+ ("(_ @x)", false),
33
+ ("(_+ _)", false),
44
34
  ("(MISSING)", true),
45
35
  ("(MISSING ; comment\n)", true),
46
36
  ("(MISSING identifier)", true),
@@ -68,6 +58,72 @@ fn missing_node_forms_follow_public_query_api_syntax() {
68
58
  }
69
59
  }
70
60
 
61
+ #[test]
62
+ fn call_placement_and_arguments_follow_public_query_api_syntax() {
63
+ let language = grammar::LANGUAGE.into();
64
+ let mut parser = parser();
65
+ for (source, valid) in [
66
+ ("(#custom?)", true),
67
+ ("[(#custom?)]", true),
68
+ ("((#custom?))", true),
69
+ ("(node_pattern (#custom?))", true),
70
+ ("(#custom? 42 -1 0.5 _ MISSING)", true),
71
+ ("(#_call? _arg)", true),
72
+ ("(_) @_cap (#_call? _arg @_cap)", true),
73
+ ("(#custom)", false),
74
+ ("(#custom?) @capture", false),
75
+ ("(#custom!)?", false),
76
+ ("(# custom?)", false),
77
+ ("(#custom ?)", false),
78
+ ("(identifier) @ name", false),
79
+ ] {
80
+ match Query::new(&language, source) {
81
+ Ok(_) => assert!(valid, "{source:?}"),
82
+ Err(error) => {
83
+ assert!(!valid, "{source:?}: {error:?}");
84
+ assert_eq!(error.kind, QueryErrorKind::Syntax, "{source:?}");
85
+ }
86
+ }
87
+ assert_eq!(
88
+ parser.parse(source, None).unwrap().root_node().has_error(),
89
+ !valid,
90
+ "{source:?}"
91
+ );
92
+ }
93
+ }
94
+
95
+ #[test]
96
+ fn documented_call_prefix_overrides_the_public_query_api_extension() {
97
+ let language = grammar::LANGUAGE.into();
98
+ let mut parser = parser();
99
+ for (source, valid) in [
100
+ ("(#custom?)", true),
101
+ ("(#custom! key value)", true),
102
+ ("(.custom?)", false),
103
+ ("(.custom! key value)", false),
104
+ ] {
105
+ assert!(Query::new(&language, source).is_ok(), "{source:?}");
106
+ assert_eq!(
107
+ parser.parse(source, None).unwrap().root_node().has_error(),
108
+ !valid,
109
+ "{source:?}"
110
+ );
111
+ }
112
+ }
113
+
114
+ #[test]
115
+ fn postfix_order_and_repetition_follow_public_query_api_syntax() {
116
+ let language = grammar::LANGUAGE.into();
117
+ let mut parser = parser();
118
+ for source in ["(identifier) @x? @y+", "(identifier) +*?"] {
119
+ let query = Query::new(&language, source).unwrap();
120
+ assert_eq!(query.pattern_count(), 1, "{source:?}");
121
+ let tree = parser.parse(source, None).unwrap();
122
+ assert!(!tree.root_node().has_error(), "{source:?}");
123
+ assert_eq!(tree.root_node().named_child_count(), 1, "{source:?}");
124
+ }
125
+ }
126
+
71
127
  #[test]
72
128
  fn field_constraints_and_call_anchors_follow_public_query_api_syntax() {
73
129
  let language = grammar::LANGUAGE.into();
@@ -159,173 +215,76 @@ fn adjacent_bare_wildcards_follow_public_query_api_pattern_and_capture_counts()
159
215
  }
160
216
 
161
217
  #[test]
162
- fn bare_wildcards_split_field_prefixes_but_identifier_contexts_preserve_ranges()
163
- {
218
+ fn underscored_names_reach_semantic_validation_without_wildcard_splitting() {
164
219
  let language = grammar::LANGUAGE.into();
165
- let query = Query::new(&language, "[(wildcard) (identifier)] @leaf").unwrap();
166
220
  let mut parser = parser();
167
- for (source, expected) in [
168
- (
169
- "__ @x",
170
- vec![("wildcard", 0..1), ("wildcard", 1..2), ("identifier", 4..5)],
171
- ),
172
- (
173
- "_field: (x)",
174
- vec![
175
- ("wildcard", 0..1),
176
- ("identifier", 1..6),
177
- ("identifier", 9..10),
178
- ],
179
- ),
180
- (
181
- "(_x !_field) @_cap",
182
- vec![
183
- ("identifier", 1..3),
184
- ("identifier", 5..11),
185
- ("identifier", 14..18),
186
- ],
187
- ),
188
- (
189
- "(#_call? _arg @_cap)",
190
- vec![
191
- ("identifier", 2..7),
192
- ("identifier", 9..13),
193
- ("identifier", 15..19),
194
- ],
195
- ),
196
- (
197
- "(MISSING _type) (_super/_sub)",
198
- vec![
199
- ("identifier", 9..14),
200
- ("identifier", 17..23),
201
- ("identifier", 24..28),
202
- ],
203
- ),
221
+ for (source, error) in [
222
+ ("(_x)", QueryErrorKind::NodeType),
223
+ ("(_ !_x)", QueryErrorKind::Field),
224
+ ("(node_pattern !_)", QueryErrorKind::Field),
204
225
  ] {
226
+ assert_eq!(
227
+ Query::new(&language, source).unwrap_err().kind,
228
+ error,
229
+ "{source:?}"
230
+ );
205
231
  let tree = parser.parse(source, None).unwrap();
206
232
  assert!(!tree.root_node().has_error(), "{source:?}");
207
- let mut cursor = QueryCursor::new();
208
- let mut matches =
209
- cursor.matches(&query, tree.root_node(), source.as_bytes());
210
- let mut actual = Vec::new();
211
- while let Some(item) = matches.next() {
212
- let node = item.captures()[0].node;
213
- assert_eq!(node.child_count(), 0);
214
- actual.push((node.kind(), node.byte_range()));
215
- }
216
- assert_eq!(actual, expected, "{source:?}");
233
+ assert_eq!(tree.root_node().byte_range(), 0..source.len());
217
234
  }
218
235
  }
219
236
 
220
237
  #[test]
221
- fn chained_fields_preserve_names_separators_and_postfix_ranges() {
222
- let tree = parser().parse("left: right: (_)+ @x", None).unwrap();
223
- let root = tree.root_node();
224
- assert!(!root.has_error());
225
- assert_eq!(root.named_child_count(), 1);
226
- let mut target = root.named_child(0).unwrap();
227
- for (range, name_range, separator_range) in
228
- [(0..20, 0..4, 4..5), (6..20, 6..11, 11..12)]
229
- {
230
- assert_eq!(target.kind(), "field_constraint");
231
- assert_eq!(target.byte_range(), range);
232
- assert_eq!(target.child_count(), 3);
233
- assert_eq!(
234
- target.child_by_field_name("name").unwrap().byte_range(),
235
- name_range
236
- );
237
- let separator = target.child(1).unwrap();
238
- assert_eq!(separator.kind(), ":");
239
- assert!(!separator.is_named());
240
- assert_eq!(separator.byte_range(), separator_range);
241
- target = target.child_by_field_name("pattern").unwrap();
242
- }
243
- assert_eq!(target.kind(), "pattern");
244
- assert_eq!(target.byte_range(), 13..20);
245
- for (field, kind, range) in [
246
- ("body", "node_pattern", 13..16),
247
- ("quantifier", "quantifier", 16..17),
248
- ("capture", "capture", 18..20),
249
- ] {
250
- let child = target.child_by_field_name(field).unwrap();
251
- assert_eq!(child.kind(), kind);
252
- assert_eq!(child.byte_range(), range);
238
+ fn field_lookup_matches_cursor_ownership() {
239
+ let mut parser = parser();
240
+ for source in ["left: right: (_)+ @x", "(node . child: (_)+ @x !absent)"] {
241
+ let tree = parser.parse(source, None).unwrap();
242
+ let mut pending = vec![tree.root_node()];
243
+ let mut fields = 0;
244
+ while let Some(owner) = pending.pop() {
245
+ let mut cursor = owner.walk();
246
+ if !cursor.goto_first_child() {
247
+ continue;
248
+ }
249
+ loop {
250
+ let child = cursor.node();
251
+ if let Some(field) = cursor.field_name() {
252
+ assert_eq!(
253
+ owner.child_by_field_name(field),
254
+ Some(child),
255
+ "{source:?}: {field}"
256
+ );
257
+ assert_eq!(child.parent(), Some(owner));
258
+ fields += 1;
259
+ }
260
+ pending.push(child);
261
+ if !cursor.goto_next_sibling() {
262
+ break;
263
+ }
264
+ }
265
+ }
266
+ assert!(fields > 0, "{source:?}: no fields");
253
267
  }
254
268
  }
255
269
 
256
270
  #[test]
257
- fn string_leaves_preserve_literal_bytes_and_escape_spelling() {
271
+ fn string_arguments_follow_public_query_api_syntax() {
258
272
  let language = grammar::LANGUAGE.into();
259
273
  let mut parser = parser();
260
- for (source, expected) in [
261
- (
262
- "\"日\\\"本\"",
263
- vec![
264
- ("\"", 0..1),
265
- ("string_content", 1..4),
266
- ("escape_sequence", 4..6),
267
- ("string_content", 6..9),
268
- ("\"", 9..10),
269
- ],
270
- ),
271
- (
272
- "\";x\0\"",
273
- vec![("\"", 0..1), ("string_content", 1..4), ("\"", 4..5)],
274
- ),
275
- (
276
- "\"\\\n;x\0\"",
277
- vec![
278
- ("\"", 0..1),
279
- ("escape_sequence", 1..3),
280
- ("string_content", 3..6),
281
- ("\"", 6..7),
282
- ],
283
- ),
284
- (
285
- "\"a\0b\0\0c\"",
286
- vec![("\"", 0..1), ("string_content", 1..7), ("\"", 7..8)],
287
- ),
288
- (
289
- "\"\0\"",
290
- vec![("\"", 0..1), ("string_content", 1..2), ("\"", 2..3)],
291
- ),
292
- (
293
- "\"a\\\0b\"",
294
- vec![
295
- ("\"", 0..1),
296
- ("string_content", 1..2),
297
- ("escape_sequence", 2..4),
298
- ("string_content", 4..5),
299
- ("\"", 5..6),
300
- ],
301
- ),
302
- (
303
- "\"\\\0\"",
304
- vec![("\"", 0..1), ("escape_sequence", 1..3), ("\"", 3..4)],
305
- ),
274
+ for source in [
275
+ "\"日\\\"本\"",
276
+ "\";x\0\"",
277
+ "\"\\\n;x\0\"",
278
+ "\"a\0b\0\0c\"",
279
+ "\"\0\"",
280
+ "\"a\\\0b\"",
281
+ "\"\\\0\"",
282
+ r#""\q""#,
283
+ "\"\r\"",
306
284
  ] {
307
285
  assert!(Query::new(&language, &format!("(#custom? {source})")).is_ok());
308
- let tree = parser.parse(source, None).unwrap();
309
- assert!(!tree.root_node().has_error(), "{source:?}");
310
- let string = tree
311
- .root_node()
312
- .named_child(0)
313
- .unwrap()
314
- .child_by_field_name("body")
315
- .unwrap();
316
- let mut cursor = string.walk();
317
- let actual: Vec<_> = string
318
- .children(&mut cursor)
319
- .map(|node| {
320
- assert_eq!(node.child_count(), 0);
321
- (node.kind(), node.byte_range())
322
- })
323
- .collect();
324
- assert_eq!(actual, expected, "{source:?}");
325
- }
326
- for source in ["\"a\0", "\"\\\0", "\"a\\", "\"\0\n\""] {
327
286
  assert!(
328
- parser.parse(source, None).unwrap().root_node().has_error(),
287
+ !parser.parse(source, None).unwrap().root_node().has_error(),
329
288
  "{source:?}"
330
289
  );
331
290
  }
@@ -353,20 +312,15 @@ fn string_newlines_cannot_skip_comments_before_nul() {
353
312
  }
354
313
 
355
314
  #[test]
356
- fn carriage_returns_inside_comments_preserve_the_following_pattern() {
315
+ fn comments_with_carriage_returns_follow_public_query_api_syntax() {
357
316
  let language = grammar::LANGUAGE.into();
358
317
  let mut parser = parser();
359
- let source = ";a\rb\r\n(_)";
360
- assert!(Query::new(&language, source).is_ok());
361
- let tree = parser.parse(source, None).unwrap();
362
- let root = tree.root_node();
363
- assert!(!root.has_error());
364
- assert_eq!(
365
- root.to_sexp(),
366
- "(query (comment) (pattern body: (node_pattern node: (wildcard))))"
367
- );
368
- assert_eq!(root.named_child(0).unwrap().byte_range(), 0..4);
369
- assert_eq!(root.named_child(1).unwrap().byte_range(), 6..9);
318
+ for (source, patterns) in [(";a\rb\r\n(_)", 1), (";x\r(_)", 0)] {
319
+ let query = Query::new(&language, source).unwrap();
320
+ assert_eq!(query.pattern_count(), patterns, "{source:?}");
321
+ let tree = parser.parse(source, None).unwrap();
322
+ assert!(!tree.root_node().has_error(), "{source:?}");
323
+ }
370
324
  }
371
325
 
372
326
  #[test]
@@ -425,96 +379,8 @@ fn highlight_captures_use_leaf_ranges_even_during_recovery() {
425
379
  }
426
380
 
427
381
  #[test]
428
- fn public_children_preserve_fields_delimiters_and_source_order() {
429
- let source = "(node . child: (_)+ @x !absent)";
430
- let tree = parser().parse(source, None).unwrap();
431
- assert!(!tree.root_node().has_error());
432
- let mut cursor = tree.walk();
433
- let mut depth = 0;
434
- let mut actual = Vec::new();
435
- 'walk: loop {
436
- let node = cursor.node();
437
- actual.push((
438
- depth,
439
- node.kind(),
440
- cursor.field_name(),
441
- node.is_named(),
442
- node.byte_range(),
443
- ));
444
- assert_eq!(
445
- node.start_position(),
446
- Point {
447
- row: 0,
448
- column: node.start_byte()
449
- }
450
- );
451
- assert_eq!(
452
- node.end_position(),
453
- Point {
454
- row: 0,
455
- column: node.end_byte()
456
- }
457
- );
458
- if cursor.goto_first_child() {
459
- depth += 1;
460
- continue;
461
- }
462
- while !cursor.goto_next_sibling() {
463
- if !cursor.goto_parent() {
464
- break 'walk;
465
- }
466
- depth -= 1;
467
- }
468
- }
469
- assert_eq!(
470
- actual,
471
- vec![
472
- (0, "query", None, true, 0..31),
473
- (1, "pattern", None, true, 0..31),
474
- (2, "node_pattern", Some("body"), true, 0..31),
475
- (3, "(", None, false, 0..1),
476
- (3, "identifier", Some("node"), true, 1..5),
477
- (3, "anchor", None, true, 6..7),
478
- (3, "field_constraint", None, true, 8..22),
479
- (4, "identifier", Some("name"), true, 8..13),
480
- (4, ":", None, false, 13..14),
481
- (4, "pattern", Some("pattern"), true, 15..22),
482
- (5, "node_pattern", Some("body"), true, 15..18),
483
- (6, "(", None, false, 15..16),
484
- (6, "wildcard", Some("node"), true, 16..17),
485
- (6, ")", None, false, 17..18),
486
- (5, "quantifier", Some("quantifier"), true, 18..19),
487
- (5, "capture", Some("capture"), true, 20..22),
488
- (6, "@", None, false, 20..21),
489
- (6, "identifier", Some("name"), true, 21..22),
490
- (3, "negated_field", None, true, 23..30),
491
- (4, "!", None, false, 23..24),
492
- (4, "identifier", Some("name"), true, 24..30),
493
- (3, ")", None, false, 30..31),
494
- ]
495
- );
496
- }
497
-
498
- #[test]
499
- fn bom_is_ignored_only_once_at_source_byte_zero() {
382
+ fn bom_at_an_included_range_start_is_not_a_source_bom() {
500
383
  let mut parser = parser();
501
- let source = "\u{feff}(node)\r\n";
502
- let tree = parser.parse(source, None).unwrap();
503
- assert!(!tree.root_node().has_error());
504
- let pattern = tree.root_node().named_child(0).unwrap();
505
- assert_eq!(pattern.byte_range(), 3..9);
506
- assert_eq!(pattern.start_position(), Point { row: 0, column: 3 });
507
- assert_eq!(tree.root_node().end_position(), Point { row: 1, column: 0 });
508
- for invalid in [
509
- " \u{feff}(node)",
510
- "\u{feff}\u{feff}(node)",
511
- "(node)\u{feff}",
512
- ] {
513
- assert!(
514
- parser.parse(invalid, None).unwrap().root_node().has_error(),
515
- "{invalid:?}"
516
- );
517
- }
518
384
  let embedded = "x\u{feff}(node)";
519
385
  parser
520
386
  .set_included_ranges(&[Range {
@@ -535,18 +401,3 @@ fn bom_is_ignored_only_once_at_source_byte_zero() {
535
401
  .has_error()
536
402
  );
537
403
  }
538
-
539
- #[test]
540
- fn crlf_and_multibyte_comment_ranges_keep_source_coordinates() {
541
- let mut parser = parser();
542
- let source = "; 日\r\n(node)";
543
- let tree = parser.parse(source, None).unwrap();
544
- let root = tree.root_node();
545
- assert!(!root.has_error());
546
- let comment = root.named_child(0).unwrap();
547
- assert_eq!(comment.byte_range(), 0..5);
548
- assert_eq!(comment.end_position(), Point { row: 0, column: 5 });
549
- let pattern = root.named_child(1).unwrap();
550
- assert_eq!(pattern.byte_range(), 7..13);
551
- assert_eq!(pattern.start_position(), Point { row: 1, column: 0 });
552
- }
package/tree-sitter.json CHANGED
@@ -12,7 +12,7 @@
12
12
  }
13
13
  ],
14
14
  "metadata": {
15
- "version": "0.3.0",
15
+ "version": "0.3.2",
16
16
  "license": "MIT",
17
17
  "description": "Tree-sitter grammar for Tree-sitter Query.",
18
18
  "links": {