@konomanoasa/tree-sitter-query 0.2.0 → 0.3.1

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,180 +215,112 @@ 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
- "\"a\0b\0\0c\"",
273
- vec![("\"", 0..1), ("string_content", 1..7), ("\"", 7..8)],
274
- ),
275
- (
276
- "\"\0\"",
277
- vec![("\"", 0..1), ("string_content", 1..2), ("\"", 2..3)],
278
- ),
279
- (
280
- "\"a\\\0b\"",
281
- vec![
282
- ("\"", 0..1),
283
- ("string_content", 1..2),
284
- ("escape_sequence", 2..4),
285
- ("string_content", 4..5),
286
- ("\"", 5..6),
287
- ],
288
- ),
289
- (
290
- "\"\\\0\"",
291
- vec![("\"", 0..1), ("escape_sequence", 1..3), ("\"", 3..4)],
292
- ),
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\"",
293
284
  ] {
294
285
  assert!(Query::new(&language, &format!("(#custom? {source})")).is_ok());
295
- let tree = parser.parse(source, None).unwrap();
296
- assert!(!tree.root_node().has_error(), "{source:?}");
297
- let string = tree
298
- .root_node()
299
- .named_child(0)
300
- .unwrap()
301
- .child_by_field_name("body")
302
- .unwrap();
303
- let mut cursor = string.walk();
304
- let actual: Vec<_> = string
305
- .children(&mut cursor)
306
- .map(|node| {
307
- assert_eq!(node.child_count(), 0);
308
- (node.kind(), node.byte_range())
309
- })
310
- .collect();
311
- assert_eq!(actual, expected, "{source:?}");
312
- }
313
- for source in ["\"a\0", "\"\\\0", "\"a\\", "\"\0\n\""] {
314
286
  assert!(
315
- parser.parse(source, None).unwrap().root_node().has_error(),
287
+ !parser.parse(source, None).unwrap().root_node().has_error(),
316
288
  "{source:?}"
317
289
  );
318
290
  }
319
291
  }
320
292
 
321
293
  #[test]
322
- fn carriage_returns_inside_comments_preserve_the_following_pattern() {
294
+ fn string_newlines_cannot_skip_comments_before_nul() {
323
295
  let language = grammar::LANGUAGE.into();
324
296
  let mut parser = parser();
325
- let source = ";a\rb\r\n(_)";
326
- assert!(Query::new(&language, source).is_ok());
327
- let tree = parser.parse(source, None).unwrap();
328
- let root = tree.root_node();
329
- assert!(!root.has_error());
330
- assert_eq!(
331
- root.to_sexp(),
332
- "(query (comment) (pattern body: (node_pattern node: (wildcard))))"
333
- );
334
- assert_eq!(root.named_child(0).unwrap().byte_range(), 0..4);
335
- assert_eq!(root.named_child(1).unwrap().byte_range(), 6..9);
297
+ for (source, api_error) in [
298
+ ("\"\n;x\0\"", QueryErrorKind::Syntax),
299
+ ("(#custom? \"\n;x\0\")", QueryErrorKind::Syntax),
300
+ ("(#custom! \"\n;x\0\")", QueryErrorKind::Syntax),
301
+ ("(identifier/\"\n;x\0\")", QueryErrorKind::Structure),
302
+ ] {
303
+ assert_eq!(
304
+ Query::new(&language, source).unwrap_err().kind,
305
+ api_error,
306
+ "{source:?}"
307
+ );
308
+ let tree = parser.parse(source, None).unwrap();
309
+ assert!(tree.root_node().has_error(), "{source:?}");
310
+ assert_eq!(tree.root_node().byte_range(), 0..source.len());
311
+ }
312
+ }
313
+
314
+ #[test]
315
+ fn comments_with_carriage_returns_follow_public_query_api_syntax() {
316
+ let language = grammar::LANGUAGE.into();
317
+ let mut parser = parser();
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
+ }
336
324
  }
337
325
 
338
326
  #[test]
@@ -391,96 +379,8 @@ fn highlight_captures_use_leaf_ranges_even_during_recovery() {
391
379
  }
392
380
 
393
381
  #[test]
394
- fn public_children_preserve_fields_delimiters_and_source_order() {
395
- let source = "(node . child: (_)+ @x !absent)";
396
- let tree = parser().parse(source, None).unwrap();
397
- assert!(!tree.root_node().has_error());
398
- let mut cursor = tree.walk();
399
- let mut depth = 0;
400
- let mut actual = Vec::new();
401
- 'walk: loop {
402
- let node = cursor.node();
403
- actual.push((
404
- depth,
405
- node.kind(),
406
- cursor.field_name(),
407
- node.is_named(),
408
- node.byte_range(),
409
- ));
410
- assert_eq!(
411
- node.start_position(),
412
- Point {
413
- row: 0,
414
- column: node.start_byte()
415
- }
416
- );
417
- assert_eq!(
418
- node.end_position(),
419
- Point {
420
- row: 0,
421
- column: node.end_byte()
422
- }
423
- );
424
- if cursor.goto_first_child() {
425
- depth += 1;
426
- continue;
427
- }
428
- while !cursor.goto_next_sibling() {
429
- if !cursor.goto_parent() {
430
- break 'walk;
431
- }
432
- depth -= 1;
433
- }
434
- }
435
- assert_eq!(
436
- actual,
437
- vec![
438
- (0, "query", None, true, 0..31),
439
- (1, "pattern", None, true, 0..31),
440
- (2, "node_pattern", Some("body"), true, 0..31),
441
- (3, "(", None, false, 0..1),
442
- (3, "identifier", Some("node"), true, 1..5),
443
- (3, "anchor", None, true, 6..7),
444
- (3, "field_constraint", None, true, 8..22),
445
- (4, "identifier", Some("name"), true, 8..13),
446
- (4, ":", None, false, 13..14),
447
- (4, "pattern", Some("pattern"), true, 15..22),
448
- (5, "node_pattern", Some("body"), true, 15..18),
449
- (6, "(", None, false, 15..16),
450
- (6, "wildcard", Some("node"), true, 16..17),
451
- (6, ")", None, false, 17..18),
452
- (5, "quantifier", Some("quantifier"), true, 18..19),
453
- (5, "capture", Some("capture"), true, 20..22),
454
- (6, "@", None, false, 20..21),
455
- (6, "identifier", Some("name"), true, 21..22),
456
- (3, "negated_field", None, true, 23..30),
457
- (4, "!", None, false, 23..24),
458
- (4, "identifier", Some("name"), true, 24..30),
459
- (3, ")", None, false, 30..31),
460
- ]
461
- );
462
- }
463
-
464
- #[test]
465
- fn bom_is_ignored_only_once_at_source_byte_zero() {
382
+ fn bom_at_an_included_range_start_is_not_a_source_bom() {
466
383
  let mut parser = parser();
467
- let source = "\u{feff}(node)\r\n";
468
- let tree = parser.parse(source, None).unwrap();
469
- assert!(!tree.root_node().has_error());
470
- let pattern = tree.root_node().named_child(0).unwrap();
471
- assert_eq!(pattern.byte_range(), 3..9);
472
- assert_eq!(pattern.start_position(), Point { row: 0, column: 3 });
473
- assert_eq!(tree.root_node().end_position(), Point { row: 1, column: 0 });
474
- for invalid in [
475
- " \u{feff}(node)",
476
- "\u{feff}\u{feff}(node)",
477
- "(node)\u{feff}",
478
- ] {
479
- assert!(
480
- parser.parse(invalid, None).unwrap().root_node().has_error(),
481
- "{invalid:?}"
482
- );
483
- }
484
384
  let embedded = "x\u{feff}(node)";
485
385
  parser
486
386
  .set_included_ranges(&[Range {
@@ -501,18 +401,3 @@ fn bom_is_ignored_only_once_at_source_byte_zero() {
501
401
  .has_error()
502
402
  );
503
403
  }
504
-
505
- #[test]
506
- fn crlf_and_multibyte_comment_ranges_keep_source_coordinates() {
507
- let mut parser = parser();
508
- let source = "; 日\r\n(node)";
509
- let tree = parser.parse(source, None).unwrap();
510
- let root = tree.root_node();
511
- assert!(!root.has_error());
512
- let comment = root.named_child(0).unwrap();
513
- assert_eq!(comment.byte_range(), 0..5);
514
- assert_eq!(comment.end_position(), Point { row: 0, column: 5 });
515
- let pattern = root.named_child(1).unwrap();
516
- assert_eq!(pattern.byte_range(), 7..13);
517
- assert_eq!(pattern.start_position(), Point { row: 1, column: 0 });
518
- }
package/tree-sitter.json CHANGED
@@ -12,7 +12,7 @@
12
12
  }
13
13
  ],
14
14
  "metadata": {
15
- "version": "0.2.0",
15
+ "version": "0.3.1",
16
16
  "license": "MIT",
17
17
  "description": "Tree-sitter grammar for Tree-sitter Query.",
18
18
  "links": {