1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use syntastica::theme::THEME_KEYS;
use tree_sitter::{Language, Query};
pub fn validate_query(lang: &Language, query: &str, kind: &str) {
match Query::new(lang, query) {
Ok(query) => {
for predicate in
(0..query.pattern_count()).flat_map(|idx| query.general_predicates(idx))
{
let predicate_name = predicate.operator.as_ref();
if ![
"set!",
"any-of?",
"not-any-of?",
"contains?",
"not-contains?",
"lua-match?",
"not-lua-match?",
"gsub!",
"replace!",
// TODO: check whether the following predicates are actually supported
"offset!",
"has-ancestor?",
"not-has-ancestor?",
"has-parent?",
"not-has-parent?",
]
.contains(&predicate_name)
{
panic!("{kind} queries use unsupported predicate '{predicate_name}'");
}
}
for name in query.capture_names() {
if !name.starts_with('_')
&& !THEME_KEYS.contains(name)
&& ![
"injection.content",
"injection.language",
"content",
"language",
"combined",
"local.scope",
"local.reference",
"local.definition",
"scope",
"reference",
"definition",
]
.contains(name)
&& !name.starts_with("local.definition.")
&& !name.starts_with("definition.")
{
panic!("{kind} queries use unsupported capture name '{name}'");
}
}
}
Err(err) => {
eprintln!("invalid {kind} queries: {err}");
eprintln!("\n{}", "-".repeat(50));
let context = query
.lines()
.enumerate()
.skip(err.row.saturating_sub(10))
.take(21);
for (row, line) in context {
match row == err.row {
true => eprintln!(
"--> {}\x1b[1;31m{}\x1b[0m{}",
&line[..err.column],
&line[err.column..(err.column + 10).min(line.len())],
&line[(err.column + 10).min(line.len())..]
),
false => eprintln!(" {line}"),
}
}
eprintln!("{}\n", "-".repeat(50));
panic!("invalid {kind} queries: {err}");
}
}
}