@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.
package/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "konomanoasa-tree-sitter-query"
3
- version = "0.2.0"
3
+ version = "0.3.1"
4
4
  edition = "2024"
5
5
  description = "Tree-sitter grammar for Tree-sitter Query."
6
6
  readme = "README.md"
package/README.md CHANGED
@@ -15,7 +15,7 @@ npm install @konomanoasa/tree-sitter-query
15
15
 
16
16
  ## Development
17
17
 
18
- Development uses Node.js 24 or later.
18
+ Development uses Node.js 24.21.0 or later.
19
19
 
20
20
  ```sh
21
21
  npm install
@@ -29,6 +29,10 @@ npm test
29
29
  - [Tree-sitter query operators](https://tree-sitter.github.io/tree-sitter/using-parsers/queries/2-operators.html)
30
30
  - [Tree-sitter query predicates and directives](https://tree-sitter.github.io/tree-sitter/using-parsers/queries/3-predicates-and-directives.html)
31
31
 
32
+ ## Used By
33
+
34
+ [query-ts-mode](https://github.com/konomanoasa/query-ts-mode): Emacs major mode.
35
+
32
36
  ## License
33
37
 
34
38
  [MIT](LICENSE)
package/grammar.js CHANGED
@@ -1,5 +1,5 @@
1
- const name = /[A-Za-z0-9_-][A-Za-z0-9_.-]*/;
2
- const stringContent = /[^"\\\n]+/;
1
+ const namePattern = /[A-Za-z0-9_-][A-Za-z0-9_.-]*/;
2
+ const fieldNamePattern = /[A-Za-z0-9-][A-Za-z0-9_.-]*/;
3
3
 
4
4
  const postfixed = ($, body) =>
5
5
  seq(
@@ -24,10 +24,9 @@ const fieldConstraint = ($, target) =>
24
24
  field("pattern", target),
25
25
  );
26
26
 
27
- // The Query API accepts no layout or comment around the subtype separator.
28
- const subtyped = ($, name) =>
27
+ const subtyped = ($, supertype) =>
29
28
  seq(
30
- field("supertype", name),
29
+ field("supertype", supertype),
31
30
  token.immediate("/"),
32
31
  field(
33
32
  "subtype",
@@ -38,6 +37,9 @@ const subtyped = ($, name) =>
38
37
  ),
39
38
  );
40
39
 
40
+ const callOnlyGroupMembers = ($) =>
41
+ seq($._call_only_group_start, repeat(anchored($, $._call_only_member)));
42
+
41
43
  const call = ($, marker) =>
42
44
  seq(
43
45
  "(",
@@ -52,10 +54,12 @@ export default grammar({
52
54
  name: "query",
53
55
  extras: ($) => [/[ \t\r\n\v\f]/, $.comment],
54
56
  rules: {
55
- query: ($) => repeat($._member),
56
- _member: ($) => choice($._child_pattern, $._call),
57
- _call_only_member: ($) => choice($._call_only_child_pattern, $._call),
57
+ query: ($) => optional($._members),
58
+ _members: ($) => seq($._member, optional($._members)),
59
+ _member: ($) => choice($._matching_child_pattern, $._call_only_member),
58
60
  _call: ($) => choice($.predicate, $.directive),
61
+ _call_only_member: ($) => choice($._call_only_child_pattern, $._call),
62
+
59
63
  pattern: ($) => postfixed($, choice($._delimited, $.string, $.wildcard)),
60
64
  _call_only_pattern: ($) =>
61
65
  postfixed(
@@ -65,9 +69,14 @@ export default grammar({
65
69
  alias($._call_only_alternation, $.alternation),
66
70
  ),
67
71
  ),
68
- // "(_" always opens a node pattern, so a group never starts with a bare wildcard.
69
- _group_pattern: ($) => postfixed($, choice($._delimited, $.string)),
70
72
  _delimited: ($) => choice($.node_pattern, $.group, $.alternation),
73
+ _matching_child_pattern: ($) => choice($.pattern, $.field_constraint),
74
+ _call_only_child_pattern: ($) =>
75
+ choice(
76
+ alias($._call_only_pattern, $.pattern),
77
+ alias($._call_only_field_constraint, $.field_constraint),
78
+ ),
79
+
71
80
  node_pattern: ($) =>
72
81
  seq(
73
82
  "(",
@@ -78,13 +87,13 @@ export default grammar({
78
87
  "node",
79
88
  choice($.identifier, $.wildcard, $.supertype, $.missing_node),
80
89
  ),
81
- repeat($._node_annotation),
90
+ repeat($._non_matching_child),
82
91
  optional(
83
92
  seq(
84
93
  anchored($, $._matching_child_pattern),
85
94
  repeat(
86
95
  choice(
87
- $._node_annotation,
96
+ $._non_matching_child,
88
97
  anchored($, $._matching_child_pattern),
89
98
  ),
90
99
  ),
@@ -95,20 +104,14 @@ export default grammar({
95
104
  ),
96
105
  ")",
97
106
  ),
98
- _child_pattern: ($) =>
99
- choice($._matching_child_pattern, $._call_only_child_pattern),
100
- _matching_child_pattern: ($) => choice($.pattern, $.field_constraint),
101
- _call_only_child_pattern: ($) =>
102
- choice(
103
- alias($._call_only_pattern, $.pattern),
104
- alias($._call_only_field_constraint, $.field_constraint),
105
- ),
106
- _node_annotation: ($) =>
107
+ _non_matching_child: ($) =>
107
108
  choice(anchored($, $._call_only_member), $.negated_field),
109
+
108
110
  field_constraint: ($) => fieldConstraint($, $._matching_child_pattern),
109
111
  _call_only_field_constraint: ($) =>
110
112
  fieldConstraint($, $._call_only_child_pattern),
111
113
  negated_field: ($) => seq("!", field("name", $._name)),
114
+
112
115
  supertype: ($) =>
113
116
  subtyped($, choice($.identifier, alias($.wildcard, $.identifier))),
114
117
  _untyped_missing_node: () => "MISSING",
@@ -121,29 +124,22 @@ export default grammar({
121
124
  ),
122
125
  ),
123
126
  _missing_supertype: ($) => subtyped($, $._name),
127
+
124
128
  group: ($) =>
125
129
  seq(
126
130
  "(",
127
131
  choice(
128
- alias($._group_pattern, $.pattern),
129
- seq(
130
- $._call_only_group_start,
131
- repeat(anchored($, $._call_only_member)),
132
- anchored($, $._matching_child_pattern),
133
- ),
132
+ alias($._group_start_pattern, $.pattern),
133
+ seq(callOnlyGroupMembers($), anchored($, $._matching_child_pattern)),
134
134
  ),
135
135
  repeat(anchored($, $._member)),
136
136
  ")",
137
137
  ),
138
- _call_only_group: ($) =>
139
- seq(
140
- "(",
141
- $._call_only_group_start,
142
- repeat(anchored($, $._call_only_member)),
143
- ")",
144
- ),
138
+ _group_start_pattern: ($) => postfixed($, choice($._delimited, $.string)),
139
+ _call_only_group: ($) => seq("(", callOnlyGroupMembers($), ")"),
145
140
  _call_only_group_start: ($) =>
146
141
  choice($._call, alias($._call_only_pattern, $.pattern)),
142
+
147
143
  alternation: ($) =>
148
144
  seq(
149
145
  "[",
@@ -153,39 +149,41 @@ export default grammar({
153
149
  "]",
154
150
  ),
155
151
  _call_only_alternation: ($) => seq("[", repeat1($._call_only_member), "]"),
152
+
156
153
  quantifier: () => token(choice("+", "*", "?")),
157
154
  anchor: () => ".",
155
+ wildcard: () => "_",
158
156
  capture: ($) =>
159
157
  seq("@", field("name", alias($._immediate_identifier, $.identifier))),
158
+
160
159
  predicate: ($) => call($, "?"),
161
160
  directive: ($) => call($, "!"),
162
- identifier: () => name,
163
- _field_identifier: () => /[A-Za-z0-9-][A-Za-z0-9_.-]*/,
164
- _immediate_identifier: () => token.immediate(name),
161
+
162
+ identifier: () => namePattern,
163
+ _field_identifier: () => fieldNamePattern,
164
+ _immediate_identifier: () => token.immediate(namePattern),
165
165
  _name: ($) =>
166
166
  choice(
167
167
  $.identifier,
168
168
  alias($.wildcard, $.identifier),
169
169
  alias("MISSING", $.identifier),
170
170
  ),
171
- wildcard: () => "_",
171
+
172
172
  string: ($) => seq('"', $._string_tail),
173
173
  _immediate_string: ($) => seq(token.immediate('"'), $._string_tail),
174
174
  _string_tail: ($) =>
175
175
  seq(
176
176
  repeat(choice($.string_content, $.escape_sequence)),
177
- token.immediate('"'),
177
+ choice(token.immediate('"'), seq($._string_line_break, $._unmatchable)),
178
178
  ),
179
- // Content outranks the comment extra so that ; stays inside the string.
179
+ _string_line_break: () => token.immediate(/\n/),
180
+ _unmatchable: () => token(seq("\\", /[^\s\S]/)),
181
+ // Keep NUL distinct from EOF in the generated lexer.
180
182
  string_content: () =>
181
- token.immediate(
182
- prec(
183
- 1,
184
- repeat1(choice(stringContent, seq("\0", optional(stringContent)))),
185
- ),
186
- ),
187
- // Distinct NUL transitions prevent the generated lexer from treating it as EOF.
188
- escape_sequence: () => token.immediate(choice(/\\(.|\n)/, prec(1, "\\\0"))),
183
+ token.immediate(prec(1, repeat1(choice(/[^"\\\n]+/, "\0")))),
184
+ escape_sequence: () =>
185
+ token.immediate(seq("\\", choice(/.|\n/, prec(1, "\0")))),
186
+
189
187
  comment: () => /;[^\r\n]*(\r+[^\r\n]+)*/,
190
188
  },
191
189
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konomanoasa/tree-sitter-query",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "description": "Tree-sitter grammar for Tree-sitter Query.",
6
6
  "license": "MIT",
@@ -21,21 +21,22 @@
21
21
  },
22
22
  "scripts": {
23
23
  "build": "npm run tree-sitter -- build-all",
24
- "check": "biome check . && node scripts/check-generated.js && npm test",
25
- "format": "biome check --write .",
24
+ "check": "biome check . && tsc --noEmit",
25
+ "check:queries": "npm run tree-sitter -- check-queries",
26
+ "format": "biome format --write .",
26
27
  "generate": "npm run tree-sitter -- generate-all",
27
28
  "test": "npm run tree-sitter -- test-corpus --rebuild && node --test --test-concurrency=1 \"test/*.test.js\"",
28
- "test:bindings": "cargo test --locked",
29
29
  "test:fuzz": "node --test --test-name-pattern=\"fixed-seed generated histories\" test/incremental.test.js",
30
30
  "test:fuzz:corpus": "npm run tree-sitter -- fuzz-all --iterations 100 --edits 5",
31
31
  "test:highlights": "node --test test/highlight.test.js",
32
- "test:incremental": "node --test test/incremental.test.js",
32
+ "test:incremental": "node --test --test-concurrency=1 test/cst.test.js test/parser.test.js test/incremental.test.js",
33
33
  "tree-sitter": "node scripts/tree-sitter.js"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@biomejs/biome": "2.5.14",
37
37
  "@types/node": "26.5.1",
38
- "tree-sitter-cli": "0.27.0"
38
+ "tree-sitter-cli": "0.27.0",
39
+ "typescript": "7.0.2"
39
40
  },
40
41
  "allowScripts": {
41
42
  "tree-sitter-cli": true