2020-02-24 21:17:20 -05:00
//! Semantic Tokens helpers
2020-02-26 19:39:32 +01:00
use std ::ops ;
2020-03-30 12:07:27 -04:00
use lsp_types ::{ Range , SemanticToken , SemanticTokenModifier , SemanticTokenType , SemanticTokens } ;
2020-02-14 17:56:28 -05:00
2020-02-26 19:39:32 +01:00
pub ( crate ) const ATTRIBUTE : SemanticTokenType = SemanticTokenType ::new ( " attribute " ) ;
2020-02-28 12:06:54 +01:00
pub ( crate ) const BUILTIN_TYPE : SemanticTokenType = SemanticTokenType ::new ( " builtinType " ) ;
pub ( crate ) const ENUM_MEMBER : SemanticTokenType = SemanticTokenType ::new ( " enumMember " ) ;
pub ( crate ) const LIFETIME : SemanticTokenType = SemanticTokenType ::new ( " lifetime " ) ;
pub ( crate ) const TYPE_ALIAS : SemanticTokenType = SemanticTokenType ::new ( " typeAlias " ) ;
pub ( crate ) const UNION : SemanticTokenType = SemanticTokenType ::new ( " union " ) ;
2020-02-26 19:39:32 +01:00
2020-02-28 12:06:54 +01:00
pub ( crate ) const CONSTANT : SemanticTokenModifier = SemanticTokenModifier ::new ( " constant " ) ;
2020-04-05 14:46:07 +02:00
pub ( crate ) const CONTROL_FLOW : SemanticTokenModifier = SemanticTokenModifier ::new ( " controlFlow " ) ;
2020-02-26 19:39:32 +01:00
pub ( crate ) const MUTABLE : SemanticTokenModifier = SemanticTokenModifier ::new ( " mutable " ) ;
pub ( crate ) const UNSAFE : SemanticTokenModifier = SemanticTokenModifier ::new ( " unsafe " ) ;
pub ( crate ) const SUPPORTED_TYPES : & [ SemanticTokenType ] = & [
2020-02-14 17:56:28 -05:00
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 ,
2020-02-26 19:39:32 +01:00
ATTRIBUTE ,
2020-02-28 12:06:54 +01:00
BUILTIN_TYPE ,
ENUM_MEMBER ,
LIFETIME ,
TYPE_ALIAS ,
UNION ,
2020-02-14 17:56:28 -05:00
] ;
2020-02-26 19:39:32 +01:00
pub ( crate ) const SUPPORTED_MODIFIERS : & [ SemanticTokenModifier ] = & [
2020-02-14 17:56:28 -05:00
SemanticTokenModifier ::DOCUMENTATION ,
SemanticTokenModifier ::DECLARATION ,
SemanticTokenModifier ::DEFINITION ,
SemanticTokenModifier ::STATIC ,
SemanticTokenModifier ::ABSTRACT ,
SemanticTokenModifier ::DEPRECATED ,
SemanticTokenModifier ::READONLY ,
2020-02-28 12:06:54 +01:00
CONSTANT ,
2020-02-26 19:39:32 +01:00
MUTABLE ,
UNSAFE ,
2020-04-05 14:46:07 +02:00
CONTROL_FLOW ,
2020-02-14 17:56:28 -05:00
] ;
2020-02-26 19:39:32 +01:00
#[ derive(Default) ]
pub ( crate ) struct ModifierSet ( pub ( crate ) u32 ) ;
2020-02-14 17:56:28 -05:00
2020-02-26 19:39:32 +01:00
impl ops ::BitOrAssign < SemanticTokenModifier > for ModifierSet {
fn bitor_assign ( & mut self , rhs : SemanticTokenModifier ) {
let idx = SUPPORTED_MODIFIERS . iter ( ) . position ( | it | it = = & rhs ) . unwrap ( ) ;
self . 0 | = 1 < < idx ;
}
2020-02-14 17:56:28 -05:00
}
2020-02-24 21:17:20 -05:00
/// Tokens are encoded relative to each other.
2020-02-25 12:42:44 +01:00
///
2020-02-24 21:17:20 -05:00
/// This is a direct port of https://github.com/microsoft/vscode-languageserver-node/blob/f425af9de46a0187adb78ec8a46b9b2ce80c5412/server/src/sematicTokens.proposed.ts#L45
2020-02-14 17:56:28 -05:00
#[ derive(Default) ]
pub ( crate ) struct SemanticTokensBuilder {
prev_line : u32 ,
prev_char : u32 ,
data : Vec < SemanticToken > ,
}
impl SemanticTokensBuilder {
2020-02-24 21:17:20 -05:00
/// Push a new token onto the builder
2020-02-14 17:56:28 -05:00
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 ;
}
2020-03-30 12:07:27 -04:00
pub fn build ( self ) -> SemanticTokens {
SemanticTokens { result_id : None , data : self . data }
2020-02-14 17:56:28 -05:00
}
}
2020-02-26 19:39:32 +01:00
pub fn type_index ( type_ : SemanticTokenType ) -> u32 {
SUPPORTED_TYPES . iter ( ) . position ( | it | * it = = type_ ) . unwrap ( ) as u32
}