mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 21:35:20 +00:00
Teach the server about Semantic Tokens proposed LSP
This commit is contained in:
parent
558d263a0c
commit
9f0cfb7ad2
9 changed files with 234 additions and 35 deletions
|
@ -75,7 +75,7 @@ pub use crate::{
|
||||||
runnables::{Runnable, RunnableKind, TestId},
|
runnables::{Runnable, RunnableKind, TestId},
|
||||||
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
|
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
|
||||||
ssr::SsrError,
|
ssr::SsrError,
|
||||||
syntax_highlighting::HighlightedRange,
|
syntax_highlighting::{tags, HighlightedRange},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use hir::Documentation;
|
pub use hir::Documentation;
|
||||||
|
|
|
@ -17,32 +17,32 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod tags {
|
pub mod tags {
|
||||||
pub(crate) const FIELD: &str = "field";
|
pub const FIELD: &str = "field";
|
||||||
pub(crate) const FUNCTION: &str = "function";
|
pub const FUNCTION: &str = "function";
|
||||||
pub(crate) const MODULE: &str = "module";
|
pub const MODULE: &str = "module";
|
||||||
pub(crate) const CONSTANT: &str = "constant";
|
pub const CONSTANT: &str = "constant";
|
||||||
pub(crate) const MACRO: &str = "macro";
|
pub const MACRO: &str = "macro";
|
||||||
|
|
||||||
pub(crate) const VARIABLE: &str = "variable";
|
pub const VARIABLE: &str = "variable";
|
||||||
pub(crate) const VARIABLE_MUT: &str = "variable.mut";
|
pub const VARIABLE_MUT: &str = "variable.mut";
|
||||||
|
|
||||||
pub(crate) const TYPE: &str = "type";
|
pub const TYPE: &str = "type";
|
||||||
pub(crate) const TYPE_BUILTIN: &str = "type.builtin";
|
pub const TYPE_BUILTIN: &str = "type.builtin";
|
||||||
pub(crate) const TYPE_SELF: &str = "type.self";
|
pub const TYPE_SELF: &str = "type.self";
|
||||||
pub(crate) const TYPE_PARAM: &str = "type.param";
|
pub const TYPE_PARAM: &str = "type.param";
|
||||||
pub(crate) const TYPE_LIFETIME: &str = "type.lifetime";
|
pub const TYPE_LIFETIME: &str = "type.lifetime";
|
||||||
|
|
||||||
pub(crate) const LITERAL_BYTE: &str = "literal.byte";
|
pub const LITERAL_BYTE: &str = "literal.byte";
|
||||||
pub(crate) const LITERAL_NUMERIC: &str = "literal.numeric";
|
pub const LITERAL_NUMERIC: &str = "literal.numeric";
|
||||||
pub(crate) const LITERAL_CHAR: &str = "literal.char";
|
pub const LITERAL_CHAR: &str = "literal.char";
|
||||||
|
|
||||||
pub(crate) const LITERAL_COMMENT: &str = "comment";
|
pub const LITERAL_COMMENT: &str = "comment";
|
||||||
pub(crate) const LITERAL_STRING: &str = "string";
|
pub const LITERAL_STRING: &str = "string";
|
||||||
pub(crate) const LITERAL_ATTRIBUTE: &str = "attribute";
|
pub const LITERAL_ATTRIBUTE: &str = "attribute";
|
||||||
|
|
||||||
pub(crate) const KEYWORD: &str = "keyword";
|
pub const KEYWORD: &str = "keyword";
|
||||||
pub(crate) const KEYWORD_UNSAFE: &str = "keyword.unsafe";
|
pub const KEYWORD_UNSAFE: &str = "keyword.unsafe";
|
||||||
pub(crate) const KEYWORD_CONTROL: &str = "keyword.control";
|
pub const KEYWORD_CONTROL: &str = "keyword.control";
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
//! Advertizes the capabilities of the LSP Server.
|
//! Advertizes the capabilities of the LSP Server.
|
||||||
|
|
||||||
|
use crate::semantic_tokens;
|
||||||
|
|
||||||
use lsp_types::{
|
use lsp_types::{
|
||||||
CallHierarchyServerCapability, CodeActionProviderCapability, CodeLensOptions,
|
CallHierarchyServerCapability, CodeActionProviderCapability, CodeLensOptions,
|
||||||
CompletionOptions, DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability,
|
CompletionOptions, DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability,
|
||||||
ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions,
|
ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions,
|
||||||
SelectionRangeProviderCapability, ServerCapabilities, SignatureHelpOptions,
|
SelectionRangeProviderCapability, SemanticTokensDocumentProvider, SemanticTokensLegend,
|
||||||
TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions,
|
SemanticTokensOptions, SemanticTokensServerCapabilities, ServerCapabilities,
|
||||||
TypeDefinitionProviderCapability, WorkDoneProgressOptions,
|
SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
|
||||||
|
TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn server_capabilities() -> ServerCapabilities {
|
pub fn server_capabilities() -> ServerCapabilities {
|
||||||
|
@ -57,7 +60,20 @@ pub fn server_capabilities() -> ServerCapabilities {
|
||||||
execute_command_provider: None,
|
execute_command_provider: None,
|
||||||
workspace: None,
|
workspace: None,
|
||||||
call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
|
call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
|
||||||
semantic_tokens_provider: None,
|
semantic_tokens_provider: Some(SemanticTokensServerCapabilities::SemanticTokensOptions(
|
||||||
|
SemanticTokensOptions {
|
||||||
|
legend: SemanticTokensLegend {
|
||||||
|
token_types: semantic_tokens::supported_token_types().iter().cloned().collect(),
|
||||||
|
token_modifiers: semantic_tokens::supported_token_modifiers()
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
|
|
||||||
|
document_provider: Some(SemanticTokensDocumentProvider::Bool(true)),
|
||||||
|
..SemanticTokensOptions::default()
|
||||||
|
},
|
||||||
|
)),
|
||||||
experimental: Default::default(),
|
experimental: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
use lsp_types::{
|
use lsp_types::{
|
||||||
self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation,
|
self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation,
|
||||||
Location, LocationLink, MarkupContent, MarkupKind, Position, Range, RenameFile, ResourceOp,
|
Location, LocationLink, MarkupContent, MarkupKind, Position, Range, RenameFile, ResourceOp,
|
||||||
SymbolKind, TextDocumentEdit, TextDocumentIdentifier, TextDocumentItem,
|
SemanticTokenModifier, SemanticTokenType, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
|
||||||
TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, WorkspaceEdit,
|
TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier,
|
||||||
|
WorkspaceEdit,
|
||||||
};
|
};
|
||||||
use ra_ide::{
|
use ra_ide::{
|
||||||
translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition,
|
tags, translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition,
|
||||||
FileRange, FileSystemEdit, Fold, FoldKind, InsertTextFormat, LineCol, LineIndex,
|
FileRange, FileSystemEdit, Fold, FoldKind, InsertTextFormat, LineCol, LineIndex,
|
||||||
NavigationTarget, RangeInfo, ReferenceAccess, Severity, SourceChange, SourceFileEdit,
|
NavigationTarget, RangeInfo, ReferenceAccess, Severity, SourceChange, SourceFileEdit,
|
||||||
};
|
};
|
||||||
|
@ -16,7 +17,7 @@ use ra_syntax::{SyntaxKind, TextRange, TextUnit};
|
||||||
use ra_text_edit::{AtomTextEdit, TextEdit};
|
use ra_text_edit::{AtomTextEdit, TextEdit};
|
||||||
use ra_vfs::LineEndings;
|
use ra_vfs::LineEndings;
|
||||||
|
|
||||||
use crate::{req, world::WorldSnapshot, Result};
|
use crate::{req, semantic_tokens, world::WorldSnapshot, Result};
|
||||||
|
|
||||||
pub trait Conv {
|
pub trait Conv {
|
||||||
type Output;
|
type Output;
|
||||||
|
@ -302,6 +303,76 @@ impl ConvWith<&FoldConvCtx<'_>> for Fold {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Conv for &'static str {
|
||||||
|
type Output = (SemanticTokenType, Vec<SemanticTokenModifier>);
|
||||||
|
|
||||||
|
fn conv(self) -> (SemanticTokenType, Vec<SemanticTokenModifier>) {
|
||||||
|
let token_type: SemanticTokenType = match self {
|
||||||
|
tags::FIELD => SemanticTokenType::MEMBER,
|
||||||
|
tags::FUNCTION => SemanticTokenType::FUNCTION,
|
||||||
|
tags::MODULE => SemanticTokenType::NAMESPACE,
|
||||||
|
tags::CONSTANT => {
|
||||||
|
return (
|
||||||
|
SemanticTokenType::VARIABLE,
|
||||||
|
vec![SemanticTokenModifier::STATIC, SemanticTokenModifier::READONLY],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
tags::MACRO => SemanticTokenType::MACRO,
|
||||||
|
|
||||||
|
tags::VARIABLE => {
|
||||||
|
return (SemanticTokenType::VARIABLE, vec![SemanticTokenModifier::READONLY])
|
||||||
|
}
|
||||||
|
tags::VARIABLE_MUT => SemanticTokenType::VARIABLE,
|
||||||
|
|
||||||
|
tags::TYPE => SemanticTokenType::TYPE,
|
||||||
|
tags::TYPE_BUILTIN => SemanticTokenType::TYPE,
|
||||||
|
tags::TYPE_SELF => {
|
||||||
|
return (SemanticTokenType::TYPE, vec![SemanticTokenModifier::REFERENCE])
|
||||||
|
}
|
||||||
|
tags::TYPE_PARAM => SemanticTokenType::TYPE_PARAMETER,
|
||||||
|
tags::TYPE_LIFETIME => {
|
||||||
|
return (SemanticTokenType::LABEL, vec![SemanticTokenModifier::REFERENCE])
|
||||||
|
}
|
||||||
|
|
||||||
|
tags::LITERAL_BYTE => SemanticTokenType::NUMBER,
|
||||||
|
tags::LITERAL_NUMERIC => SemanticTokenType::NUMBER,
|
||||||
|
tags::LITERAL_CHAR => SemanticTokenType::NUMBER,
|
||||||
|
|
||||||
|
tags::LITERAL_COMMENT => {
|
||||||
|
return (SemanticTokenType::COMMENT, vec![SemanticTokenModifier::DOCUMENTATION])
|
||||||
|
}
|
||||||
|
|
||||||
|
tags::LITERAL_STRING => SemanticTokenType::STRING,
|
||||||
|
tags::LITERAL_ATTRIBUTE => SemanticTokenType::KEYWORD,
|
||||||
|
|
||||||
|
tags::KEYWORD => SemanticTokenType::KEYWORD,
|
||||||
|
tags::KEYWORD_UNSAFE => SemanticTokenType::KEYWORD,
|
||||||
|
tags::KEYWORD_CONTROL => SemanticTokenType::KEYWORD,
|
||||||
|
unknown => panic!("Unknown semantic token: {}", unknown),
|
||||||
|
};
|
||||||
|
|
||||||
|
(token_type, vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Conv for (SemanticTokenType, Vec<SemanticTokenModifier>) {
|
||||||
|
type Output = (u32, u32);
|
||||||
|
|
||||||
|
fn conv(self) -> Self::Output {
|
||||||
|
let token_index =
|
||||||
|
semantic_tokens::supported_token_types().iter().position(|it| *it == self.0).unwrap();
|
||||||
|
let mut token_modifier_bitset = 0;
|
||||||
|
for modifier in self.1.iter() {
|
||||||
|
token_modifier_bitset |= semantic_tokens::supported_token_modifiers()
|
||||||
|
.iter()
|
||||||
|
.position(|it| it == modifier)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
(token_index as u32, token_modifier_bitset as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ConvWith<CTX>, CTX> ConvWith<CTX> for Option<T> {
|
impl<T: ConvWith<CTX>, CTX> ConvWith<CTX> for Option<T> {
|
||||||
type Output = Option<T::Output>;
|
type Output = Option<T::Output>;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ pub mod req;
|
||||||
mod config;
|
mod config;
|
||||||
mod world;
|
mod world;
|
||||||
mod diagnostics;
|
mod diagnostics;
|
||||||
|
mod semantic_tokens;
|
||||||
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
|
|
|
@ -528,6 +528,7 @@ fn on_request(
|
||||||
.on::<req::CallHierarchyIncomingCalls>(handlers::handle_call_hierarchy_incoming)?
|
.on::<req::CallHierarchyIncomingCalls>(handlers::handle_call_hierarchy_incoming)?
|
||||||
.on::<req::CallHierarchyOutgoingCalls>(handlers::handle_call_hierarchy_outgoing)?
|
.on::<req::CallHierarchyOutgoingCalls>(handlers::handle_call_hierarchy_outgoing)?
|
||||||
.on::<req::Ssr>(handlers::handle_ssr)?
|
.on::<req::Ssr>(handlers::handle_ssr)?
|
||||||
|
.on::<req::SemanticTokensRequest>(handlers::handle_semantic_tokens)?
|
||||||
.finish();
|
.finish();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,9 @@ use lsp_types::{
|
||||||
CodeAction, CodeActionOrCommand, CodeActionResponse, CodeLens, Command, CompletionItem,
|
CodeAction, CodeActionOrCommand, CodeActionResponse, CodeLens, Command, CompletionItem,
|
||||||
Diagnostic, DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange,
|
Diagnostic, DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange,
|
||||||
FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind, Position,
|
FoldingRangeParams, Hover, HoverContents, Location, MarkupContent, MarkupKind, Position,
|
||||||
PrepareRenameResponse, Range, RenameParams, SymbolInformation, TextDocumentIdentifier,
|
PrepareRenameResponse, Range, RenameParams, SemanticTokenModifier, SemanticTokenType,
|
||||||
TextEdit, WorkspaceEdit,
|
SemanticTokens, SemanticTokensParams, SemanticTokensResult, SymbolInformation,
|
||||||
|
TextDocumentIdentifier, TextEdit, WorkspaceEdit,
|
||||||
};
|
};
|
||||||
use ra_ide::{
|
use ra_ide::{
|
||||||
AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind,
|
AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind,
|
||||||
|
@ -38,6 +39,7 @@ use crate::{
|
||||||
diagnostics::DiagnosticTask,
|
diagnostics::DiagnosticTask,
|
||||||
from_json,
|
from_json,
|
||||||
req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
|
req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
|
||||||
|
semantic_tokens::SemanticTokensBuilder,
|
||||||
world::WorldSnapshot,
|
world::WorldSnapshot,
|
||||||
LspError, Result,
|
LspError, Result,
|
||||||
};
|
};
|
||||||
|
@ -1068,3 +1070,25 @@ pub fn handle_call_hierarchy_outgoing(
|
||||||
|
|
||||||
Ok(Some(res))
|
Ok(Some(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_semantic_tokens(
|
||||||
|
world: WorldSnapshot,
|
||||||
|
params: SemanticTokensParams,
|
||||||
|
) -> Result<Option<SemanticTokensResult>> {
|
||||||
|
let _p = profile("handle_semantic_tokens");
|
||||||
|
|
||||||
|
let file_id = params.text_document.try_conv_with(&world)?;
|
||||||
|
let line_index = world.analysis().file_line_index(file_id)?;
|
||||||
|
|
||||||
|
let mut builder = SemanticTokensBuilder::default();
|
||||||
|
|
||||||
|
for h in world.analysis().highlight(file_id)?.into_iter() {
|
||||||
|
let type_and_modifiers: (SemanticTokenType, Vec<SemanticTokenModifier>) = h.tag.conv();
|
||||||
|
let (token_type, token_modifiers) = type_and_modifiers.conv();
|
||||||
|
builder.push(h.range.conv_with(&line_index), token_type, token_modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tokens = SemanticTokens { data: builder.build(), ..Default::default() };
|
||||||
|
|
||||||
|
Ok(Some(tokens.into()))
|
||||||
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@ pub use lsp_types::{
|
||||||
DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType,
|
DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType,
|
||||||
PartialResultParams, ProgressParams, ProgressParamsValue, ProgressToken,
|
PartialResultParams, ProgressParams, ProgressParamsValue, ProgressToken,
|
||||||
PublishDiagnosticsParams, ReferenceParams, Registration, RegistrationParams, SelectionRange,
|
PublishDiagnosticsParams, ReferenceParams, Registration, RegistrationParams, SelectionRange,
|
||||||
SelectionRangeParams, ServerCapabilities, ShowMessageParams, SignatureHelp, SymbolKind,
|
SelectionRangeParams, SemanticTokensParams, SemanticTokensResult, ServerCapabilities,
|
||||||
TextDocumentEdit, TextDocumentPositionParams, TextEdit, WorkDoneProgressParams, WorkspaceEdit,
|
ShowMessageParams, SignatureHelp, SymbolKind, TextDocumentEdit, TextDocumentPositionParams,
|
||||||
WorkspaceSymbolParams,
|
TextEdit, WorkDoneProgressParams, WorkspaceEdit, WorkspaceSymbolParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum AnalyzerStatus {}
|
pub enum AnalyzerStatus {}
|
||||||
|
|
86
crates/rust-analyzer/src/semantic_tokens.rs
Normal file
86
crates/rust-analyzer/src/semantic_tokens.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
use lsp_types::{Range, SemanticToken, SemanticTokenModifier, SemanticTokenType};
|
||||||
|
|
||||||
|
const SUPPORTED_TYPES: &[SemanticTokenType] = &[
|
||||||
|
SemanticTokenType::COMMENT,
|
||||||
|
SemanticTokenType::KEYWORD,
|
||||||
|
SemanticTokenType::STRING,
|
||||||
|
SemanticTokenType::NUMBER,
|
||||||
|
SemanticTokenType::REGEXP,
|
||||||
|
SemanticTokenType::OPERATOR,
|
||||||
|
SemanticTokenType::NAMESPACE,
|
||||||
|
SemanticTokenType::TYPE,
|
||||||
|
SemanticTokenType::STRUCT,
|
||||||
|
SemanticTokenType::CLASS,
|
||||||
|
SemanticTokenType::INTERFACE,
|
||||||
|
SemanticTokenType::ENUM,
|
||||||
|
SemanticTokenType::TYPE_PARAMETER,
|
||||||
|
SemanticTokenType::FUNCTION,
|
||||||
|
SemanticTokenType::MEMBER,
|
||||||
|
SemanticTokenType::PROPERTY,
|
||||||
|
SemanticTokenType::MACRO,
|
||||||
|
SemanticTokenType::VARIABLE,
|
||||||
|
SemanticTokenType::PARAMETER,
|
||||||
|
SemanticTokenType::LABEL,
|
||||||
|
];
|
||||||
|
|
||||||
|
const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
|
||||||
|
SemanticTokenModifier::DOCUMENTATION,
|
||||||
|
SemanticTokenModifier::DECLARATION,
|
||||||
|
SemanticTokenModifier::DEFINITION,
|
||||||
|
SemanticTokenModifier::REFERENCE,
|
||||||
|
SemanticTokenModifier::STATIC,
|
||||||
|
SemanticTokenModifier::ABSTRACT,
|
||||||
|
SemanticTokenModifier::DEPRECATED,
|
||||||
|
SemanticTokenModifier::ASYNC,
|
||||||
|
SemanticTokenModifier::VOLATILE,
|
||||||
|
SemanticTokenModifier::READONLY,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub(crate) fn supported_token_types() -> &'static [SemanticTokenType] {
|
||||||
|
SUPPORTED_TYPES
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn supported_token_modifiers() -> &'static [SemanticTokenModifier] {
|
||||||
|
SUPPORTED_MODIFIERS
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub(crate) struct SemanticTokensBuilder {
|
||||||
|
prev_line: u32,
|
||||||
|
prev_char: u32,
|
||||||
|
data: Vec<SemanticToken>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SemanticTokensBuilder {
|
||||||
|
pub fn push(&mut self, range: Range, token_index: u32, modifier_bitset: u32) {
|
||||||
|
let mut push_line = range.start.line as u32;
|
||||||
|
let mut push_char = range.start.character as u32;
|
||||||
|
|
||||||
|
if !self.data.is_empty() {
|
||||||
|
push_line -= self.prev_line;
|
||||||
|
if push_line == 0 {
|
||||||
|
push_char -= self.prev_char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A token cannot be multiline
|
||||||
|
let token_len = range.end.character - range.start.character;
|
||||||
|
|
||||||
|
let token = SemanticToken {
|
||||||
|
delta_line: push_line,
|
||||||
|
delta_start: push_char,
|
||||||
|
length: token_len as u32,
|
||||||
|
token_type: token_index,
|
||||||
|
token_modifiers_bitset: modifier_bitset,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.data.push(token);
|
||||||
|
|
||||||
|
self.prev_line = range.start.line as u32;
|
||||||
|
self.prev_char = range.start.character as u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Vec<SemanticToken> {
|
||||||
|
self.data
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue