@konomanoasa/tree-sitter-gitattributes 0.2.0 → 0.4.0

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-gitattributes"
3
- version = "0.2.0"
3
+ version = "0.4.0"
4
4
  edition = "2024"
5
5
  description = "Tree-sitter grammar for gitattributes."
6
6
  readme = "README.md"
package/README.md CHANGED
@@ -15,7 +15,7 @@ npm install @konomanoasa/tree-sitter-gitattributes
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
@@ -28,6 +28,10 @@ npm test
28
28
  - [Git 2.55.0 gitattributes manual](https://git-scm.com/docs/gitattributes/2.55.0)
29
29
  - [Git 2.55.0 gitignore manual](https://git-scm.com/docs/gitignore/2.55.0)
30
30
 
31
+ ## Used By
32
+
33
+ [gitfile-ts-mode](https://github.com/konomanoasa/gitfile-ts-mode): Emacs major mode.
34
+
31
35
  ## License
32
36
 
33
37
  [MIT](LICENSE)
package/grammar.js CHANGED
@@ -1,46 +1,71 @@
1
+ const missingKinds = (name) => [
2
+ [`missing_${name}`, "invalid_syntax", `missing_${name}`],
3
+ [`incomplete_${name}`, "incomplete_syntax", `missing_${name}`],
4
+ ];
1
5
  const issueKinds = [
2
- ["missing_set_close", "invalid_syntax", "missing_set_close"],
3
- ["incomplete_set_close", "incomplete_syntax", "missing_set_close"],
6
+ ...missingKinds("set_close"),
4
7
  ["invalid_encoding", "invalid_syntax", "invalid_encoding"],
5
8
  ["negative_pattern", "invalid_syntax", "negative_pattern"],
6
- ["invalid_escape", "invalid_syntax", "incomplete_escape"],
9
+ ["ended_escape", "invalid_syntax", "incomplete_escape"],
7
10
  ["incomplete_escape", "incomplete_syntax", "incomplete_escape"],
8
11
  ["invalid_quoted_escape", "invalid_syntax", "invalid_quoted_escape"],
9
12
  ["ended_quoted_escape", "invalid_syntax", "incomplete_quoted_escape"],
10
13
  ["incomplete_quoted_escape", "incomplete_syntax", "incomplete_quoted_escape"],
11
- ["missing_quote", "invalid_syntax", "missing_quote_close"],
12
- ["incomplete_quote", "incomplete_syntax", "missing_quote_close"],
13
- ["missing_separator", "invalid_syntax", "missing_attribute_separator"],
14
- ["missing_name", "invalid_syntax", "missing_attribute_name"],
15
- ["incomplete_name", "incomplete_syntax", "missing_attribute_name"],
14
+ ...missingKinds("quote_close"),
15
+ [
16
+ "missing_attribute_separator",
17
+ "invalid_syntax",
18
+ "missing_attribute_separator",
19
+ ],
20
+ ...missingKinds("attribute_name"),
16
21
  ["invalid_name_character", "invalid_syntax", "invalid_name_character"],
22
+ ["incomplete_name_character", "incomplete_syntax", "invalid_name_character"],
23
+ [
24
+ "invalid_name_escape",
25
+ "invalid_syntax",
26
+ "invalid_name_character",
27
+ "quoted_escape",
28
+ ],
29
+ ];
30
+ const quotedEscapeIssues = [
31
+ "invalid_quoted_escape",
32
+ "ended_quoted_escape",
33
+ "incomplete_quoted_escape",
17
34
  ];
35
+
18
36
  const issueRules = Object.fromEntries(
19
- issueKinds.flatMap(([token, outcome, reason]) => [
20
- [`_${token}_outcome`, ($) => alias($[`_${token}`], $[reason])],
37
+ issueKinds.flatMap(([token, outcome, reason, child]) => [
38
+ ...(child
39
+ ? [[`_${token}_reason`, ($) => alias($[`_${token}`], $[child])]]
40
+ : []),
41
+ [
42
+ `_${token}_outcome`,
43
+ ($) => alias($[child ? `_${token}_reason` : `_${token}`], $[reason]),
44
+ ],
21
45
  [`_${token}_issue`, ($) => alias($[`_${token}_outcome`], $[outcome])],
22
46
  ]),
23
47
  );
24
48
  const issue = ($, name) =>
25
49
  field("issue", alias($[`_${name}_issue`], $.syntax_issue));
26
50
  const issues = ($, ...names) => names.map((name) => issue($, name));
27
- // A backslash held by the owner before the issue of the unit it cannot escape.
51
+ const missing = ($, name) =>
52
+ choice(issue($, `missing_${name}`), issue($, `incomplete_${name}`));
28
53
  const heldPrefix = ($, ...names) =>
29
54
  seq($._escape_prefix, choice(...issues($, ...names)));
30
- const quotedEscapeIssues = [
31
- "invalid_quoted_escape",
32
- "ended_quoted_escape",
33
- "incomplete_quoted_escape",
34
- ];
35
- const missingName = ($) =>
36
- choice(...issues($, "missing_name", "incomplete_name"));
37
55
  const quoteClose = ($) =>
38
- optional(
39
- choice(
40
- field("closing", $.quote_close),
41
- ...issues($, "missing_quote", "incomplete_quote"),
42
- ),
43
- );
56
+ optional(choice(field("closing", $.quote_close), missing($, "quote_close")));
57
+ const attributeName = ($) =>
58
+ choice(field("name", $.attribute_name), missing($, "attribute_name"));
59
+ const globIssues = ($) => [
60
+ ...issues(
61
+ $,
62
+ "invalid_encoding",
63
+ "ended_escape",
64
+ "incomplete_escape",
65
+ ...quotedEscapeIssues,
66
+ ),
67
+ heldPrefix($, "invalid_encoding", ...quotedEscapeIssues),
68
+ ];
44
69
 
45
70
  export default grammar({
46
71
  name: "gitattributes",
@@ -51,7 +76,6 @@ export default grammar({
51
76
  $._rule_start,
52
77
  $._macro_start,
53
78
  $._eof,
54
- $.line_ending,
55
79
  $._layout,
56
80
  $._separator,
57
81
  $._attribute_start,
@@ -105,6 +129,7 @@ export default grammar({
105
129
  choice($.blank_line, $.comment, $.attribute_rule, $.macro_definition),
106
130
  ),
107
131
  ),
132
+ line_ending: () => /\r?\n/,
108
133
  _end: ($) => seq(optional($._layout), choice($.line_ending, $._eof)),
109
134
  blank_line: ($) => seq($._blank_start, $._end),
110
135
  comment: ($) =>
@@ -126,14 +151,17 @@ export default grammar({
126
151
  $._macro_start,
127
152
  optional(field("opening", $.quote_open)),
128
153
  field("marker", $.macro_marker),
129
- choice(field("name", $.attribute_name), missingName($)),
154
+ attributeName($),
130
155
  quoteClose($),
131
156
  optional($._attributes),
132
157
  $._end,
133
158
  ),
134
159
  _attributes: ($) =>
135
160
  repeat1(
136
- seq(choice($._separator, issue($, "missing_separator")), $.attribute),
161
+ seq(
162
+ choice($._separator, issue($, "missing_attribute_separator")),
163
+ $.attribute,
164
+ ),
137
165
  ),
138
166
  attribute: ($) =>
139
167
  seq(
@@ -141,7 +169,7 @@ export default grammar({
141
169
  optional(
142
170
  field("modifier", choice($.unset_marker, $.unspecified_marker)),
143
171
  ),
144
- choice(field("name", $.attribute_name), missingName($)),
172
+ attributeName($),
145
173
  optional(
146
174
  seq(
147
175
  field("operator", $.assignment_operator),
@@ -161,6 +189,8 @@ export default grammar({
161
189
  $,
162
190
  "invalid_encoding",
163
191
  "invalid_name_character",
192
+ "incomplete_name_character",
193
+ "invalid_name_escape",
164
194
  ...quotedEscapeIssues,
165
195
  ),
166
196
  heldPrefix($, "invalid_encoding"),
@@ -190,15 +220,8 @@ export default grammar({
190
220
  $.escape,
191
221
  $.quoted_escape,
192
222
  $.character_set,
193
- ...issues(
194
- $,
195
- "invalid_encoding",
196
- "negative_pattern",
197
- "invalid_escape",
198
- "incomplete_escape",
199
- ...quotedEscapeIssues,
200
- ),
201
- heldPrefix($, "invalid_encoding", ...quotedEscapeIssues),
223
+ issue($, "negative_pattern"),
224
+ ...globIssues($),
202
225
  ),
203
226
  ),
204
227
  ),
@@ -220,21 +243,11 @@ export default grammar({
220
243
  $.quoted_escape,
221
244
  $.character_range,
222
245
  $.character_class,
223
- ...issues(
224
- $,
225
- "invalid_encoding",
226
- "invalid_escape",
227
- "incomplete_escape",
228
- ...quotedEscapeIssues,
229
- ),
230
- heldPrefix($, "invalid_encoding", ...quotedEscapeIssues),
246
+ ...globIssues($),
231
247
  ),
232
248
  ),
233
249
  ),
234
- choice(
235
- field("closing", $.set_close),
236
- ...issues($, "missing_set_close", "incomplete_set_close"),
237
- ),
250
+ choice(field("closing", $.set_close), missing($, "set_close")),
238
251
  ),
239
252
  character_range: ($) =>
240
253
  seq(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konomanoasa/tree-sitter-gitattributes",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "Tree-sitter grammar for gitattributes.",
6
6
  "license": "MIT",
@@ -21,15 +21,15 @@
21
21
  },
22
22
  "scripts": {
23
23
  "build": "npm run tree-sitter -- build-all",
24
- "check": "biome check . && node scripts/check-c.js && node scripts/check-generated.js && npm test",
25
- "format": "biome check --write . && node scripts/check-c.js --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
  "test:sanitize": "node scripts/check-c.js --sanitize",
34
34
  "test:scanner": "node scripts/check-c.js",
35
35
  "tree-sitter": "node scripts/tree-sitter.js"
@@ -37,7 +37,8 @@
37
37
  "devDependencies": {
38
38
  "@biomejs/biome": "2.5.14",
39
39
  "@types/node": "26.5.1",
40
- "tree-sitter-cli": "0.27.0"
40
+ "tree-sitter-cli": "0.27.0",
41
+ "typescript": "7.0.2"
41
42
  },
42
43
  "allowScripts": {
43
44
  "tree-sitter-cli": true