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-04-28 17:14:05 +02:00
macro_rules ! define_semantic_token_types {
( $( ( $ident :ident , $string :literal ) ) , * $(, ) ? ) = > {
$( pub ( crate ) const $ident : SemanticTokenType = SemanticTokenType ::new ( $string ) ; ) *
2020-02-26 19:39:32 +01:00
2020-04-28 17:14:05 +02:00
pub ( crate ) 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 ,
$( $ident ) , *
] ;
} ;
}
2020-02-26 19:39:32 +01:00
2020-04-28 17:14:05 +02:00
define_semantic_token_types! [
( ATTRIBUTE , " attribute " ) ,
( BUILTIN_TYPE , " builtinType " ) ,
( ENUM_MEMBER , " enumMember " ) ,
( LIFETIME , " lifetime " ) ,
( TYPE_ALIAS , " typeAlias " ) ,
( UNION , " union " ) ,
( UNRESOLVED_REFERENCE , " unresolvedReference " ) ,
( FORMAT_SPECIFIER , " formatSpecifier " ) ,
2020-02-14 17:56:28 -05:00
] ;
2020-04-28 17:14:05 +02:00
macro_rules ! define_semantic_token_modifiers {
( $( ( $ident :ident , $string :literal ) ) , * $(, ) ? ) = > {
$( pub ( crate ) const $ident : SemanticTokenModifier = SemanticTokenModifier ::new ( $string ) ; ) *
pub ( crate ) const SUPPORTED_MODIFIERS : & [ SemanticTokenModifier ] = & [
SemanticTokenModifier ::DOCUMENTATION ,
SemanticTokenModifier ::DECLARATION ,
SemanticTokenModifier ::DEFINITION ,
SemanticTokenModifier ::STATIC ,
SemanticTokenModifier ::ABSTRACT ,
SemanticTokenModifier ::DEPRECATED ,
SemanticTokenModifier ::READONLY ,
$( $ident ) , *
] ;
} ;
}
define_semantic_token_modifiers! [
( CONSTANT , " constant " ) ,
( CONTROL_FLOW , " controlFlow " ) ,
( MUTABLE , " mutable " ) ,
( UNSAFE , " unsafe " ) ,
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
}