tree-sitter-ucode 0.5.0 → 0.6.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/README.md +64 -19
- package/markup/queries/injections.scm +6 -0
- package/markup/src/parser.c +2 -2
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/tree-sitter-ucode.node +0 -0
- package/prebuilds/linux-arm64/tree-sitter-ucode.node +0 -0
- package/prebuilds/linux-x64/tree-sitter-ucode.node +0 -0
- package/prebuilds/win32-x64/tree-sitter-ucode.node +0 -0
- package/queries/injections.scm +5 -0
- package/src/parser.c +2 -2
- package/src/scanner_impl.h +1 -3
- package/tree-sitter-ucode.wasm +0 -0
- package/tree-sitter-ucode_markup.wasm +0 -0
- package/tree-sitter.json +13 -1
- package/ucdocs/grammar.js +41 -12
- package/ucdocs/queries/highlights.scm +63 -4
- package/ucdocs/src/grammar.json +185 -79
- package/ucdocs/src/node-types.json +308 -4
- package/ucdocs/src/parser.c +4031 -2804
package/README.md
CHANGED
|
@@ -2,17 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
Tree-sitter grammar for [ucode](https://github.com/jow-/ucode), the ECMAScript-like scripting language used in OpenWrt.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Three grammars are provided:
|
|
6
6
|
|
|
7
|
-
| Grammar | Scope | File types |
|
|
8
|
-
|
|
9
|
-
| `ucode` | `source.uc` | `.uc`, `.ucode`, `.ut` |
|
|
10
|
-
| `ucode_markup` | `source.ucode.markup` | `.uc`, `.ucode`, `.ut
|
|
7
|
+
| Grammar | Scope | File types | Purpose |
|
|
8
|
+
|---------|-------|------------|---------|
|
|
9
|
+
| `ucode` | `source.uc` | `.uc`, `.ucode`, `.ut` | Plain ucode source files |
|
|
10
|
+
| `ucode_markup` | `source.ucode.markup` | `.uc`, `.ucode`, `.ut` (template files — detected by content) | Ucode template files mixing raw text and code tags |
|
|
11
|
+
| `ucdocs` | — | injected | JSDoc-style `/** */` doc comment blocks |
|
|
12
|
+
|
|
13
|
+
`ucode` and `ucode_markup` share file extensions. Template files are distinguished from plain
|
|
14
|
+
code files by content: any file containing a tag opener (`{%`, `{{`, or `{#`) at the start
|
|
15
|
+
of a line (with optional leading whitespace) is automatically parsed by `ucode_markup`. Plain
|
|
16
|
+
code files fall back to `ucode`. See [File-type detection](#file-type-detection) below.
|
|
11
17
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
`ucdocs` is not a standalone file grammar — it is automatically injected by the `ucode` and
|
|
19
|
+
`ucode_markup` grammars into every `/** */` doc comment block. Tools that load grammars
|
|
20
|
+
directly from `tree-sitter.json` (including the tree-sitter CLI) handle this automatically.
|
|
21
|
+
Editor plugins may require registering the `ucdocs` grammar separately — see the editor
|
|
22
|
+
sections below.
|
|
16
23
|
|
|
17
24
|
## Ucode vs JavaScript
|
|
18
25
|
|
|
@@ -29,6 +36,34 @@ Ucode is an ECMAScript subset with OpenWrt-specific extensions. Key differences:
|
|
|
29
36
|
| Regex flags | `g`, `i`, `s` only | Full set |
|
|
30
37
|
| Module system | Static `import`/`export` only; no `from` on re-exports | Full ES modules |
|
|
31
38
|
|
|
39
|
+
## Doc comment grammar (ucdocs)
|
|
40
|
+
|
|
41
|
+
`/** */` blocks are parsed by the `ucdocs` grammar and injected into the host parse tree.
|
|
42
|
+
The grammar understands the following tags:
|
|
43
|
+
|
|
44
|
+
| Tag | Syntax |
|
|
45
|
+
|-----|--------|
|
|
46
|
+
| `@param` | `@param {Type} name description` |
|
|
47
|
+
| `@returns` / `@return` | `@returns {Type} description` |
|
|
48
|
+
| `@throws` / `@throw` | `@throws {Type} description` |
|
|
49
|
+
| `@type` | `@type {Type}` |
|
|
50
|
+
| `@typedef` | `@typedef {Type} TypeName` |
|
|
51
|
+
| `@template` | `@template T, U` |
|
|
52
|
+
| `@function` | `@function module:path#member` |
|
|
53
|
+
| `@module` | `@module name` |
|
|
54
|
+
| `@deprecated` | `@deprecated description` |
|
|
55
|
+
| `@since` | `@since version` |
|
|
56
|
+
| `@see` | `@see reference` |
|
|
57
|
+
| `@example` | `@example code` |
|
|
58
|
+
| `@default` | `@default value` |
|
|
59
|
+
|
|
60
|
+
Type expressions support: primitives (`int`, `float`, `string`, `boolean`, `null`, `void`,
|
|
61
|
+
`function`), `*`/`any`, `list<T>`, `dict<T>`, record types (`{field: T}`), named types
|
|
62
|
+
(`TypeName`, `TypeName<T, U>`), cross-module refs (`module:path.To.Type`), named function
|
|
63
|
+
types `(name: T) => U`, anonymous function types `function(T): U`, union `T | U`, nullable
|
|
64
|
+
`?T`, and array postfix `T[]`. Inline `{@link ...}` tags and optional params `[name=default]`
|
|
65
|
+
are also supported.
|
|
66
|
+
|
|
32
67
|
## Requirements
|
|
33
68
|
|
|
34
69
|
- [tree-sitter CLI](https://github.com/tree-sitter/tree-sitter) ≥ 0.24
|
|
@@ -38,10 +73,10 @@ Ucode is an ECMAScript subset with OpenWrt-specific extensions. Key differences:
|
|
|
38
73
|
|
|
39
74
|
```sh
|
|
40
75
|
npm install
|
|
41
|
-
npm run build # generate + compile Node.js bindings
|
|
76
|
+
npm run build # generate + compile Node.js bindings (ucode and ucode_markup only)
|
|
42
77
|
```
|
|
43
78
|
|
|
44
|
-
To regenerate parsers after editing a grammar file:
|
|
79
|
+
To regenerate parsers after editing a grammar file (run from the repo root):
|
|
45
80
|
|
|
46
81
|
```sh
|
|
47
82
|
# ucode grammar
|
|
@@ -49,27 +84,33 @@ npx tree-sitter generate
|
|
|
49
84
|
|
|
50
85
|
# ucode_markup grammar (generated from grammar.js — do not edit markup/grammar.js directly)
|
|
51
86
|
node scripts/generate-markup-grammar.js
|
|
52
|
-
|
|
87
|
+
npx tree-sitter generate markup/grammar.js --output markup/src
|
|
88
|
+
|
|
89
|
+
# ucdocs grammar (not included in npm run build — must be regenerated manually)
|
|
90
|
+
npx tree-sitter generate ucdocs/grammar.js --output ucdocs/src
|
|
53
91
|
```
|
|
54
92
|
|
|
55
93
|
## Test
|
|
56
94
|
|
|
57
95
|
```sh
|
|
58
|
-
npm test #
|
|
96
|
+
npm test # builds and tests all three grammars (ucode, ucode_markup, ucdocs)
|
|
59
97
|
```
|
|
60
98
|
|
|
61
|
-
To filter by corpus file name:
|
|
99
|
+
To filter by corpus file name (run from the repo root):
|
|
62
100
|
|
|
63
101
|
```sh
|
|
64
102
|
npx tree-sitter test --file-name control_flow
|
|
65
|
-
cd markup && npx tree-sitter test --file-name markup
|
|
103
|
+
(cd markup && npx tree-sitter test --file-name markup)
|
|
104
|
+
(cd ucdocs && npx tree-sitter test --file-name tags)
|
|
105
|
+
(cd ucdocs && npx tree-sitter test --file-name types)
|
|
66
106
|
```
|
|
67
107
|
|
|
68
108
|
## File-type detection
|
|
69
109
|
|
|
70
|
-
Both
|
|
110
|
+
Both `ucode` and `ucode_markup` claim the same file extensions. Tools that respect `content-regex` in
|
|
71
111
|
`tree-sitter.json` (including the tree-sitter CLI ≥ 0.24) automatically route
|
|
72
|
-
template files to `ucode_markup` when a tag opener
|
|
112
|
+
template files to `ucode_markup` when a tag opener (`{%`, `{{`, or `{#`) appears at
|
|
113
|
+
the start of a line (with optional leading whitespace).
|
|
73
114
|
Editors that manage their own filetype dispatch (Neovim, Helix) need an explicit
|
|
74
115
|
rule — see the editor sections below.
|
|
75
116
|
|
|
@@ -102,11 +143,15 @@ grammar = "ucode_markup"
|
|
|
102
143
|
|
|
103
144
|
[[grammar]]
|
|
104
145
|
name = "ucode"
|
|
105
|
-
source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "v0.
|
|
146
|
+
source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "v0.6.0" }
|
|
106
147
|
|
|
107
148
|
[[grammar]]
|
|
108
149
|
name = "ucode_markup"
|
|
109
|
-
source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "v0.
|
|
150
|
+
source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "v0.6.0", subpath = "markup" }
|
|
151
|
+
|
|
152
|
+
[[grammar]]
|
|
153
|
+
name = "ucdocs"
|
|
154
|
+
source = { git = "https://github.com/m00qek/tree-sitter-ucode", rev = "v0.6.0", subpath = "ucdocs" }
|
|
110
155
|
```
|
|
111
156
|
|
|
112
157
|
Helix does not support content-based filetype detection for shared extensions. For
|
|
@@ -38,3 +38,9 @@
|
|
|
38
38
|
(for_alt_statement open: (_) increment: (_) @injection.content (#set! injection.language "ucode"))
|
|
39
39
|
|
|
40
40
|
(for_in_alt_statement open: (_) right: (_) @injection.content (#set! injection.language "ucode"))
|
|
41
|
+
|
|
42
|
+
; Inject ucdocs into JSDoc block comments (/** ... */).
|
|
43
|
+
; The [^*/] guard excludes /*** section dividers (≥3 stars) and /**/ (empty, non-JSDoc).
|
|
44
|
+
((comment) @injection.content
|
|
45
|
+
(#match? @injection.content "^/\\*\\*[^*/]")
|
|
46
|
+
(#set! injection.language "ucdocs"))
|
package/markup/src/parser.c
CHANGED
|
@@ -134501,8 +134501,8 @@ TS_PUBLIC const TSLanguage *tree_sitter_ucode_markup(void) {
|
|
|
134501
134501
|
.max_reserved_word_set_size = 28,
|
|
134502
134502
|
.metadata = {
|
|
134503
134503
|
.major_version = 0,
|
|
134504
|
-
.minor_version =
|
|
134505
|
-
.patch_version =
|
|
134504
|
+
.minor_version = 6,
|
|
134505
|
+
.patch_version = 1,
|
|
134506
134506
|
},
|
|
134507
134507
|
};
|
|
134508
134508
|
return &language;
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/parser.c
CHANGED
|
@@ -113826,8 +113826,8 @@ TS_PUBLIC const TSLanguage *tree_sitter_ucode(void) {
|
|
|
113826
113826
|
.max_reserved_word_set_size = 28,
|
|
113827
113827
|
.metadata = {
|
|
113828
113828
|
.major_version = 0,
|
|
113829
|
-
.minor_version =
|
|
113830
|
-
.patch_version =
|
|
113829
|
+
.minor_version = 6,
|
|
113830
|
+
.patch_version = 1,
|
|
113831
113831
|
},
|
|
113832
113832
|
};
|
|
113833
113833
|
return &language;
|
package/src/scanner_impl.h
CHANGED
|
@@ -400,9 +400,7 @@ static bool scan_automatic_semicolon(TSLexer *lexer) {
|
|
|
400
400
|
}
|
|
401
401
|
|
|
402
402
|
static bool scan_ternary_qmark(TSLexer *lexer) {
|
|
403
|
-
while (lexer->lookahead
|
|
404
|
-
lexer->lookahead != 0x2028 && lexer->lookahead != 0x2029 &&
|
|
405
|
-
iswspace(lexer->lookahead))
|
|
403
|
+
while (iswspace(lexer->lookahead))
|
|
406
404
|
skip(lexer);
|
|
407
405
|
|
|
408
406
|
if (lexer->lookahead != '?') return false;
|
package/tree-sitter-ucode.wasm
CHANGED
|
Binary file
|
|
Binary file
|
package/tree-sitter.json
CHANGED
|
@@ -14,9 +14,21 @@
|
|
|
14
14
|
"locals": [
|
|
15
15
|
"queries/locals.scm"
|
|
16
16
|
],
|
|
17
|
+
"injections": [
|
|
18
|
+
"queries/injections.scm"
|
|
19
|
+
],
|
|
17
20
|
"tags": [
|
|
18
21
|
"queries/tags.scm"
|
|
19
22
|
],
|
|
23
|
+
"folds": [
|
|
24
|
+
"queries/folds.scm"
|
|
25
|
+
],
|
|
26
|
+
"indents": [
|
|
27
|
+
"queries/indents.scm"
|
|
28
|
+
],
|
|
29
|
+
"textobjects": [
|
|
30
|
+
"queries/textobjects.scm"
|
|
31
|
+
],
|
|
20
32
|
"injection-regex": "^ucode$"
|
|
21
33
|
},
|
|
22
34
|
{
|
|
@@ -66,7 +78,7 @@
|
|
|
66
78
|
}
|
|
67
79
|
],
|
|
68
80
|
"metadata": {
|
|
69
|
-
"version": "0.
|
|
81
|
+
"version": "0.6.1",
|
|
70
82
|
"license": "MIT",
|
|
71
83
|
"description": "Ucode grammar for tree-sitter",
|
|
72
84
|
"links": {
|
package/ucdocs/grammar.js
CHANGED
|
@@ -33,28 +33,24 @@ module.exports = grammar({
|
|
|
33
33
|
$.see_tag,
|
|
34
34
|
$.example_tag,
|
|
35
35
|
$.default_tag,
|
|
36
|
+
$.function_tag,
|
|
37
|
+
$.module_tag,
|
|
36
38
|
$.unknown_tag,
|
|
37
39
|
)),
|
|
38
40
|
$._end,
|
|
39
41
|
),
|
|
40
42
|
|
|
41
|
-
_begin: _ => seq('/',
|
|
42
|
-
_end: _ => '/',
|
|
43
|
+
_begin: _ => token(seq('/', /\*+/)),
|
|
44
|
+
_end: _ => token(seq(/\*+/, '/')),
|
|
43
45
|
|
|
44
46
|
// Used after a type_expression/rest_type_expression has already claimed `{` at
|
|
45
47
|
// this position (param_tag, returns_tag, throws_tag) — excludes _brace_text so
|
|
46
48
|
// it never competes with a legitimate {type} for the leading `{`.
|
|
47
|
-
_typed_description: $ =>
|
|
48
|
-
choice($._text, $.inline_tag),
|
|
49
|
-
repeat(choice($._text, $.inline_tag)),
|
|
50
|
-
)),
|
|
49
|
+
_typed_description: $ => repeat1(choice($._text, $.inline_tag)),
|
|
51
50
|
|
|
52
51
|
// Used wherever no type_expression can appear at the same position, so a bare
|
|
53
52
|
// `{` can only be an inline tag or arbitrary brace-text (e.g. @example code).
|
|
54
|
-
_free_description: $ =>
|
|
55
|
-
choice($._text, $.inline_tag, $._brace_text),
|
|
56
|
-
repeat(choice($._text, $.inline_tag, $._brace_text)),
|
|
57
|
-
)),
|
|
53
|
+
_free_description: $ => repeat1(choice($._text, $.inline_tag, $._brace_text)),
|
|
58
54
|
|
|
59
55
|
// {@link target text} and similar inline JSDoc tags embedded in description text.
|
|
60
56
|
inline_tag: $ => seq(
|
|
@@ -159,6 +155,29 @@ module.exports = grammar({
|
|
|
159
155
|
optional(field('description', alias($._free_description, $.description))),
|
|
160
156
|
),
|
|
161
157
|
|
|
158
|
+
// @function module:X.Y#Z — identifies the qualified name of the documented function.
|
|
159
|
+
function_tag: $ => seq(
|
|
160
|
+
'@function',
|
|
161
|
+
optional(field('namepath', $.namepath)),
|
|
162
|
+
),
|
|
163
|
+
|
|
164
|
+
// @module name — identifies the module this file documents.
|
|
165
|
+
module_tag: $ => seq(
|
|
166
|
+
'@module',
|
|
167
|
+
field('name', $.member_name),
|
|
168
|
+
),
|
|
169
|
+
|
|
170
|
+
// module:X.Y#Z — a namepath referencing a specific member within a module.
|
|
171
|
+
// The #member suffix distinguishes instance methods from the module path itself.
|
|
172
|
+
namepath: $ => seq(
|
|
173
|
+
'module:',
|
|
174
|
+
field('path', $.module_path),
|
|
175
|
+
optional(seq('#', field('member', $.member_name))),
|
|
176
|
+
),
|
|
177
|
+
|
|
178
|
+
// Member names cover lowercase (error), uppercase (ERR), and underscored (ulog_open).
|
|
179
|
+
member_name: _ => /[a-zA-Z_$][a-zA-Z0-9_$]*/,
|
|
180
|
+
|
|
162
181
|
unknown_tag: $ => seq(
|
|
163
182
|
$.tag_name,
|
|
164
183
|
optional(field('description', alias($._free_description, $.description))),
|
|
@@ -185,9 +204,11 @@ module.exports = grammar({
|
|
|
185
204
|
$.union_type,
|
|
186
205
|
$.nullable_type,
|
|
187
206
|
$.any_type,
|
|
207
|
+
$.parenthesized_type,
|
|
208
|
+
$.array_type,
|
|
188
209
|
),
|
|
189
210
|
|
|
190
|
-
primitive_type: _ => choice('int', 'float', 'string', 'boolean', 'null', 'void'),
|
|
211
|
+
primitive_type: _ => choice('int', 'float', 'string', 'boolean', 'null', 'void', 'function'),
|
|
191
212
|
|
|
192
213
|
any_type: _ => choice('*', 'any'),
|
|
193
214
|
|
|
@@ -259,6 +280,14 @@ module.exports = grammar({
|
|
|
259
280
|
optional(seq(':', field('return', $._type))),
|
|
260
281
|
),
|
|
261
282
|
|
|
283
|
+
// Explicit grouping: (T|U) to override default union associativity or
|
|
284
|
+
// for clarity in complex expressions like ?(T|U).
|
|
285
|
+
parenthesized_type: $ => seq('(', $._type, ')'),
|
|
286
|
+
|
|
287
|
+
// T[] postfix array notation. Precedence 3 > nullable (2) > union (1)
|
|
288
|
+
// so ?T[] == ?(T[]) and T[]|U[] == (T[])|(U[]).
|
|
289
|
+
array_type: $ => prec(3, seq($._type, '[]')),
|
|
290
|
+
|
|
262
291
|
// Left-associative so T | U | V parses as (T | U) | V.
|
|
263
292
|
union_type: $ => prec.left(1, seq($._type, '|', $._type)),
|
|
264
293
|
|
|
@@ -271,7 +300,7 @@ module.exports = grammar({
|
|
|
271
300
|
// Lowercase-starting names: parameter names and function param names.
|
|
272
301
|
identifier: _ => /[a-z_$][a-zA-Z_$0-9]*/,
|
|
273
302
|
|
|
274
|
-
_text: _ => token(prec(-1, /[^*{}@\s][^*{}@\n]*/)),
|
|
303
|
+
_text: _ => token(prec(-1, /[^*{}@\s][^*{}@\n\r]*/)),
|
|
275
304
|
},
|
|
276
305
|
});
|
|
277
306
|
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
; ── Tag keywords ──────────────────────────────────────────────────────────────
|
|
2
|
+
|
|
1
3
|
(tag_name) @keyword
|
|
4
|
+
|
|
2
5
|
(param_tag "@param" @keyword)
|
|
3
6
|
(returns_tag ["@returns" "@return"] @keyword)
|
|
4
7
|
(template_tag "@template" @keyword)
|
|
@@ -10,16 +13,72 @@
|
|
|
10
13
|
(see_tag "@see" @keyword)
|
|
11
14
|
(example_tag "@example" @keyword)
|
|
12
15
|
(default_tag "@default" @keyword)
|
|
16
|
+
(function_tag "@function" @keyword)
|
|
17
|
+
(module_tag "@module" @keyword)
|
|
18
|
+
|
|
19
|
+
; ── Names ──────────────────────────────────────────────────────────────────
|
|
13
20
|
|
|
14
21
|
(type_param) @type.parameter
|
|
15
22
|
(type_identifier) @type
|
|
16
23
|
(primitive_type) @type.builtin
|
|
17
24
|
(any_type) @type.builtin
|
|
18
|
-
(module_type "module:" @module)
|
|
19
|
-
(module_path) @module
|
|
20
25
|
|
|
21
26
|
(identifier) @variable.parameter
|
|
27
|
+
(record_field name: (identifier) @variable.member)
|
|
28
|
+
(member_name) @variable.member
|
|
29
|
+
|
|
22
30
|
(default_value) @constant
|
|
23
|
-
|
|
31
|
+
|
|
32
|
+
; ── Module paths ────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
(module_type "module:" @module)
|
|
35
|
+
(module_type path: (module_path) @module)
|
|
36
|
+
(namepath "module:" @module)
|
|
37
|
+
(namepath path: (module_path) @module)
|
|
38
|
+
|
|
39
|
+
; ── Operators ───────────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
(union_type "|" @operator)
|
|
42
|
+
(nullable_type "?" @operator)
|
|
43
|
+
(function_type "=>" @operator)
|
|
44
|
+
(optional_param "=" @operator)
|
|
45
|
+
|
|
46
|
+
; ── Punctuation: brackets ────────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
(type_expression "{" @punctuation.bracket "}" @punctuation.bracket)
|
|
49
|
+
(rest_type_expression "{" @punctuation.bracket "}" @punctuation.bracket)
|
|
50
|
+
(record_type "{" @punctuation.bracket "}" @punctuation.bracket)
|
|
51
|
+
(parenthesized_type "(" @punctuation.bracket ")" @punctuation.bracket)
|
|
52
|
+
(function_type "(" @punctuation.bracket ")" @punctuation.bracket)
|
|
53
|
+
(anon_function_type "(" @punctuation.bracket ")" @punctuation.bracket)
|
|
54
|
+
(named_type "<" @punctuation.bracket ">" @punctuation.bracket)
|
|
55
|
+
(list_type "<" @punctuation.bracket ">" @punctuation.bracket)
|
|
56
|
+
(dict_type "<" @punctuation.bracket ">" @punctuation.bracket)
|
|
57
|
+
(optional_param "[" @punctuation.bracket "]" @punctuation.bracket)
|
|
58
|
+
(array_type "[]" @punctuation.bracket)
|
|
24
59
|
(inline_tag "{" @punctuation.bracket "}" @punctuation.bracket)
|
|
25
|
-
|
|
60
|
+
|
|
61
|
+
; ── Punctuation: delimiters ──────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
(record_type "," @punctuation.delimiter)
|
|
64
|
+
(record_field ":" @punctuation.delimiter)
|
|
65
|
+
(function_param ":" @punctuation.delimiter)
|
|
66
|
+
(anon_function_type ":" @punctuation.delimiter)
|
|
67
|
+
(namepath "#" @punctuation.delimiter)
|
|
68
|
+
|
|
69
|
+
; ── Punctuation: special ─────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
(rest_type_expression "..." @punctuation.special)
|
|
72
|
+
|
|
73
|
+
; ── Descriptions ─────────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
(description) @comment
|
|
76
|
+
|
|
77
|
+
; @spell only on prose-bearing tags; @example descriptions contain code.
|
|
78
|
+
(document (description) @spell)
|
|
79
|
+
(param_tag description: (description) @spell)
|
|
80
|
+
(returns_tag description: (description) @spell)
|
|
81
|
+
(throws_tag description: (description) @spell)
|
|
82
|
+
(deprecated_tag description: (description) @spell)
|
|
83
|
+
(since_tag description: (description) @spell)
|
|
84
|
+
(see_tag description: (description) @spell)
|