feat: semantic tokens for inherits:, format-ignore (#171)
Some checks are pending
CI / Lint (push) Waiting to run
CI / Format (push) Waiting to run
CI / Test (push) Waiting to run
CI / Corpus test (push) Waiting to run
CI / Generate schema (push) Waiting to run

This commit is contained in:
Riley Bruins 2025-07-05 16:59:22 -07:00 committed by GitHub
parent 1ef27e6421
commit 04dc2ffb87
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 61 additions and 9 deletions

View file

@ -1,5 +1,6 @@
use std::sync::LazyLock;
use regex::Regex;
use tower_lsp::{
jsonrpc::Result,
lsp_types::{
@ -15,13 +16,14 @@ use crate::{
util::{INHERITS_REGEX, NodeUtil, TextProviderRope, ToTsPoint},
};
static FORMAT_IGNORE_REGEX: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^;+\s*(format-ignore)").unwrap());
static SEM_TOK_QUERY: LazyLock<Query> = LazyLock::new(|| {
Query::new(
&QUERY_LANGUAGE,
r#"(named_node (identifier) @ident)
(missing_node (identifier) @ident)
(program
. (comment) @comment)
(comment) @comment
"#,
)
.unwrap()
@ -120,19 +122,48 @@ async fn get_semantic_tokens(
prev_col = start_col;
}
}
// Highlight imported modules
// Highlight special comments (inherits, format ignore)
"comment" => {
if let Some(fmt_ignore) = FORMAT_IGNORE_REGEX
.captures(&node_text)
.and_then(|c| c.get(1))
{
const FMT_IGNORE_LEN: u32 = 13;
let offset = fmt_ignore.start() as u32;
tokens.push(SemanticToken {
delta_line,
delta_start: delta_start + offset,
length: FMT_IGNORE_LEN,
token_type: 3,
token_modifiers_bitset: 0,
});
prev_line = start_row;
prev_col = start_col + offset;
continue;
};
if start_row != 0 {
continue;
}
let Some(pre_text) = INHERITS_REGEX.captures(&node_text).and_then(|c| c.get(1))
let Some(mods) = INHERITS_REGEX.captures(&node_text).and_then(|c| c.get(1))
else {
continue;
};
let mods = pre_text.as_str().split(',');
let len = pre_text.start() as u32;
let mut delta_start = delta_start + len;
let mut start_col = start_col + len;
let offset = mods.start() as u32;
let mods = mods.as_str().split(',');
// Add a token for `inherits:`
const INHERITS_LEN: u32 = 9;
let mut delta_start = delta_start + offset - INHERITS_LEN - 1;
tokens.push(SemanticToken {
delta_line: 0,
delta_start,
length: INHERITS_LEN,
token_type: 3,
token_modifiers_bitset: 0,
});
delta_start = INHERITS_LEN + 1;
let mut start_col = start_col + offset;
let mut delta_line = delta_line;
for module in mods {
// We assert that modules are valid ASCII characters, so we can index them
@ -191,6 +222,9 @@ mod test {
(MISSING ERROR) @missingerror
(MISSING supertype) @missingsupertype
;;;format-ignore
(foo)
";
let mut service = initialize_server(
&[(
@ -228,9 +262,17 @@ mod test {
let actual = Some(SemanticTokensResult::Tokens(SemanticTokens {
result_id: None,
data: vec![
// ; inherits:
SemanticToken {
delta_line: 0,
delta_start: 12,
delta_start: 2,
length: 9,
token_type: 3,
token_modifiers_bitset: 0,
},
SemanticToken {
delta_line: 0,
delta_start: 10,
length: 1,
token_type: 2,
token_modifiers_bitset: 0,
@ -242,6 +284,7 @@ mod test {
token_type: 2,
token_modifiers_bitset: 0,
},
// ERROR, Supertypes
SemanticToken {
delta_line: 2,
delta_start: 1,
@ -284,6 +327,14 @@ mod test {
token_type: 0,
token_modifiers_bitset: 0,
},
// format-ignore
SemanticToken {
delta_line: 2,
delta_start: 3,
length: 13,
token_type: 3,
token_modifiers_bitset: 0,
},
],
}));
assert_eq!(

View file

@ -81,6 +81,7 @@ static SERVER_CAPABILITIES: LazyLock<ServerCapabilities> = LazyLock::new(|| Serv
SemanticTokenType::INTERFACE,
SemanticTokenType::VARIABLE,
SemanticTokenType::NAMESPACE,
SemanticTokenType::KEYWORD,
],
token_modifiers: vec![SemanticTokenModifier::DEFAULT_LIBRARY],
},