5643: Add new consuming modifier, apply consuming and mutable to methods r=matklad a=Nashenas88

This adds a new `consuming` semantic modifier for syntax highlighters.

This also emits `mutable` and `consuming` in two cases:

- When a method takes `&mut self`, then it now has `function.mutable` emitted.
- When a method takes `self`, and the type of `Self` is not `Copy`, then `function.consuming` is emitted.

CC @flodiebold 

Co-authored-by: Paul Daniel Faria <Nashenas88@users.noreply.github.com>
This commit is contained in:
bors[bot] 2020-08-19 11:27:02 +00:00 committed by GitHub
commit 529ca7e5e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 220 additions and 49 deletions

View file

@ -670,6 +670,21 @@ impl Function {
db.function_data(self.id).has_self_param db.function_data(self.id).has_self_param
} }
pub fn mutability_of_self_param(self, db: &dyn HirDatabase) -> Option<Mutability> {
let func_data = db.function_data(self.id);
if !func_data.has_self_param {
return None;
}
func_data.params.first().and_then(|param| {
if let TypeRef::Reference(_, mutability) = param {
Some(*mutability)
} else {
None
}
})
}
pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> { pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> {
db.function_data(self.id).params.clone() db.function_data(self.id).params.clone()
} }

View file

@ -38,7 +38,7 @@ pub use crate::{
Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
}, },
has_source::HasSource, has_source::HasSource,
semantics::{original_range, PathResolution, Semantics, SemanticsScope}, semantics::{original_range, PathResolution, SelfKind, Semantics, SemanticsScope},
}; };
pub use hir_def::{ pub use hir_def::{

View file

@ -6,8 +6,10 @@ use std::{cell::RefCell, fmt, iter::successors};
use base_db::{FileId, FileRange}; use base_db::{FileId, FileRange};
use hir_def::{ use hir_def::{
lang_item::LangItemTarget,
resolver::{self, HasResolver, Resolver, TypeNs}, resolver::{self, HasResolver, Resolver, TypeNs},
AsMacroCall, FunctionId, TraitId, VariantId, src::HasSource,
AsMacroCall, FunctionId, Lookup, TraitId, VariantId,
}; };
use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
use hir_ty::associated_type_shorthand_candidates; use hir_ty::associated_type_shorthand_candidates;
@ -15,7 +17,7 @@ use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use syntax::{ use syntax::{
algo::{find_node_at_offset, skip_trivia_token}, algo::{find_node_at_offset, skip_trivia_token},
ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextSize, ast, AstNode, Direction, SmolStr, SyntaxNode, SyntaxToken, TextRange, TextSize,
}; };
use crate::{ use crate::{
@ -79,6 +81,13 @@ impl PathResolution {
} }
} }
pub enum SelfKind {
Shared,
Mutable,
Consuming,
Copied,
}
/// Primary API to get semantic information, like types, from syntax trees. /// Primary API to get semantic information, like types, from syntax trees.
pub struct Semantics<'db, DB> { pub struct Semantics<'db, DB> {
pub db: &'db DB, pub db: &'db DB,
@ -188,6 +197,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.type_of_self(param) self.imp.type_of_self(param)
} }
pub fn method_reciever_kind(&self, call: &ast::MethodCallExpr) -> Option<SelfKind> {
self.imp.method_receiver_kind(call)
}
pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
self.imp.resolve_method_call(call).map(Function::from) self.imp.resolve_method_call(call).map(Function::from)
} }
@ -267,7 +280,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.assert_contains_node(node) self.imp.assert_contains_node(node)
} }
pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool {
self.imp.is_unsafe_method_call(method_call_expr) self.imp.is_unsafe_method_call(method_call_expr)
} }
@ -410,6 +423,35 @@ impl<'db> SemanticsImpl<'db> {
self.analyze(param.syntax()).type_of_self(self.db, &param) self.analyze(param.syntax()).type_of_self(self.db, &param)
} }
fn method_receiver_kind(&self, call: &ast::MethodCallExpr) -> Option<SelfKind> {
self.resolve_method_call(call).and_then(|func| {
let lookup = func.lookup(self.db.upcast());
let src = lookup.source(self.db.upcast());
let param_list = src.value.param_list()?;
let self_param = param_list.self_param()?;
if self_param.amp_token().is_some() {
return Some(if self_param.mut_token().is_some() {
SelfKind::Mutable
} else {
SelfKind::Shared
});
}
let ty = self.type_of_expr(&call.expr()?)?;
let krate = Function::from(func).krate(self.db)?;
let lang_item = self.db.lang_item(krate.id, SmolStr::new("copy"));
let copy_trait = match lang_item? {
LangItemTarget::TraitId(copy_trait) => Trait::from(copy_trait),
_ => return None,
};
Some(if ty.impls_trait(self.db, copy_trait, &[]) {
SelfKind::Copied
} else {
SelfKind::Consuming
})
})
}
fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
self.analyze(call.syntax()).resolve_method_call(self.db, call) self.analyze(call.syntax()).resolve_method_call(self.db, call)
} }
@ -571,7 +613,7 @@ impl<'db> SemanticsImpl<'db> {
InFile::new(file_id, node) InFile::new(file_id, node)
} }
pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool { pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool {
method_call_expr method_call_expr
.expr() .expr()
.and_then(|expr| { .and_then(|expr| {

View file

@ -4,7 +4,7 @@ mod injection;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
use hir::{Name, Semantics, VariantDef}; use hir::{Mutability, Name, SelfKind, Semantics, VariantDef};
use ide_db::{ use ide_db::{
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
RootDatabase, RootDatabase,
@ -519,6 +519,7 @@ fn highlight_element(
} }
NAME_REF => { NAME_REF => {
let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| {
let possibly_unsafe = is_possibly_unsafe(&name_ref); let possibly_unsafe = is_possibly_unsafe(&name_ref);
match classify_name_ref(sema, &name_ref) { match classify_name_ref(sema, &name_ref) {
Some(name_kind) => match name_kind { Some(name_kind) => match name_kind {
@ -540,6 +541,7 @@ fn highlight_element(
} }
None => HighlightTag::UnresolvedReference.into(), None => HighlightTag::UnresolvedReference.into(),
} }
})
} }
// Simple token-based highlighting // Simple token-based highlighting
@ -700,6 +702,35 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool {
} }
} }
fn highlight_func_by_name_ref(
sema: &Semantics<RootDatabase>,
name_ref: &ast::NameRef,
) -> Option<Highlight> {
let parent = name_ref.syntax().parent()?;
let method_call = ast::MethodCallExpr::cast(parent)?;
highlight_method_call(sema, &method_call)
}
fn highlight_method_call(
sema: &Semantics<RootDatabase>,
method_call: &ast::MethodCallExpr,
) -> Option<Highlight> {
let func = sema.resolve_method_call(&method_call)?;
let mut h = HighlightTag::Function.into();
if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
h |= HighlightModifier::Unsafe;
}
sema.method_reciever_kind(&method_call)
.map(|self_kind| match self_kind {
SelfKind::Shared => h,
SelfKind::Mutable => h | HighlightModifier::Mutable,
SelfKind::Consuming => h | HighlightModifier::Consuming,
SelfKind::Copied => h,
})
.or_else(|| Some(h))
}
fn highlight_name( fn highlight_name(
sema: &Semantics<RootDatabase>, sema: &Semantics<RootDatabase>,
db: &RootDatabase, db: &RootDatabase,
@ -722,20 +753,26 @@ fn highlight_name(
Definition::ModuleDef(def) => match def { Definition::ModuleDef(def) => match def {
hir::ModuleDef::Module(_) => HighlightTag::Module, hir::ModuleDef::Module(_) => HighlightTag::Module,
hir::ModuleDef::Function(func) => { hir::ModuleDef::Function(func) => {
return name_ref
.and_then(|name_ref| highlight_func_by_name_ref(sema, &name_ref))
.unwrap_or_else(|| {
let mut h = HighlightTag::Function.into(); let mut h = HighlightTag::Function.into();
if func.is_unsafe(db) { if func.is_unsafe(db) {
h |= HighlightModifier::Unsafe; h |= HighlightModifier::Unsafe;
}
return if func.has_self_param(db) {
match func.mutability_of_self_param(db) {
Some(mutability) => match mutability {
Mutability::Mut => h | HighlightModifier::Mutable,
Mutability::Shared => h,
},
None => h,
}
} else { } else {
let is_unsafe = name_ref h
.and_then(|name_ref| name_ref.syntax().parent()) };
.and_then(ast::MethodCallExpr::cast) });
.map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr))
.unwrap_or(false);
if is_unsafe {
h |= HighlightModifier::Unsafe;
}
}
return h;
} }
hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct, hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct,
hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum, hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum,
@ -807,15 +844,9 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabas
match parent.kind() { match parent.kind() {
METHOD_CALL_EXPR => { METHOD_CALL_EXPR => {
let mut h = Highlight::new(HighlightTag::Function); return ast::MethodCallExpr::cast(parent)
let is_unsafe = ast::MethodCallExpr::cast(parent) .and_then(|method_call| highlight_method_call(sema, &method_call))
.map(|method_call_expr| sema.is_unsafe_method_call(method_call_expr)) .unwrap_or_else(|| HighlightTag::Function.into());
.unwrap_or(false);
if is_unsafe {
h |= HighlightModifier::Unsafe;
}
h
} }
FIELD_EXPR => { FIELD_EXPR => {
let h = HighlightTag::Field; let h = HighlightTag::Field;

View file

@ -62,6 +62,7 @@ pub enum HighlightModifier {
Documentation, Documentation,
Injected, Injected,
Mutable, Mutable,
Consuming,
Unsafe, Unsafe,
} }
@ -119,6 +120,7 @@ impl HighlightModifier {
HighlightModifier::Documentation, HighlightModifier::Documentation,
HighlightModifier::Injected, HighlightModifier::Injected,
HighlightModifier::Mutable, HighlightModifier::Mutable,
HighlightModifier::Consuming,
HighlightModifier::Unsafe, HighlightModifier::Unsafe,
]; ];
@ -130,6 +132,7 @@ impl HighlightModifier {
HighlightModifier::Documentation => "documentation", HighlightModifier::Documentation => "documentation",
HighlightModifier::Injected => "injected", HighlightModifier::Injected => "injected",
HighlightModifier::Mutable => "mutable", HighlightModifier::Mutable => "mutable",
HighlightModifier::Consuming => "consuming",
HighlightModifier::Unsafe => "unsafe", HighlightModifier::Unsafe => "unsafe",
} }
} }

View file

@ -12,6 +12,12 @@ fn test_highlighting() {
use inner::{self as inner_mod}; use inner::{self as inner_mod};
mod inner {} mod inner {}
// Needed for function consuming vs normal
pub mod marker {
#[lang = "copy"]
pub trait Copy {}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct Foo { struct Foo {
pub x: i32, pub x: i32,
@ -36,6 +42,29 @@ impl Foo {
fn qux(&mut self) { fn qux(&mut self) {
self.x = 0; self.x = 0;
} }
fn quop(&self) -> i32 {
self.x
}
}
#[derive(Copy, Clone)]
struct FooCopy {
x: u32,
}
impl FooCopy {
fn baz(self) -> u32 {
self.x
}
fn qux(&mut self) {
self.x = 0;
}
fn quop(&self) -> u32 {
self.x
}
} }
static mut STATIC_MUT: i32 = 0; static mut STATIC_MUT: i32 = 0;
@ -87,6 +116,16 @@ fn main() {
let Foo { x: z, y } = Foo { x: z, y }; let Foo { x: z, y } = Foo { x: z, y };
y; y;
let mut foo = Foo { x, y: x };
foo.quop();
foo.qux();
foo.baz();
let mut copy = FooCopy { x };
copy.quop();
copy.qux();
copy.baz();
} }
enum Option<T> { enum Option<T> {

View file

@ -38,6 +38,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="punctuation">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="punctuation">}</span><span class="punctuation">;</span> <pre><code><span class="keyword">use</span> <span class="module">inner</span><span class="operator">::</span><span class="punctuation">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="module declaration">inner_mod</span><span class="punctuation">}</span><span class="punctuation">;</span>
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="punctuation">{</span><span class="punctuation">}</span> <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="comment">// Needed for function consuming vs normal</span>
<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">marker</span> <span class="punctuation">{</span>
<span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">lang</span><span class="attribute"> </span><span class="operator">=</span><span class="attribute"> </span><span class="string_literal">"copy"</span><span class="attribute">]</span>
<span class="keyword">pub</span> <span class="keyword">trait</span> <span class="trait declaration">Copy</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Clone</span><span class="punctuation">,</span><span class="attribute"> Debug</span><span class="punctuation">)</span><span class="attribute">]</span> <span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Clone</span><span class="punctuation">,</span><span class="attribute"> Debug</span><span class="punctuation">)</span><span class="attribute">]</span>
<span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span> <span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span>
<span class="keyword">pub</span> <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span> <span class="keyword">pub</span> <span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">i32</span><span class="punctuation">,</span>
@ -59,9 +65,32 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span> <span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
<span class="punctuation">}</span> <span class="punctuation">}</span>
<span class="keyword">fn</span> <span class="function declaration">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span> <span class="keyword">fn</span> <span class="function declaration mutable">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
<span class="self_keyword mutable">self</span><span class="punctuation">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> <span class="self_keyword mutable">self</span><span class="punctuation">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
<span class="punctuation">}</span> <span class="punctuation">}</span>
<span class="keyword">fn</span> <span class="function declaration">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
<span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
<span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="attribute">#</span><span class="attribute">[</span><span class="function attribute">derive</span><span class="punctuation">(</span><span class="attribute">Copy</span><span class="punctuation">,</span><span class="attribute"> Clone</span><span class="punctuation">)</span><span class="attribute">]</span>
<span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="punctuation">{</span>
<span class="field declaration">x</span><span class="punctuation">:</span> <span class="builtin_type">u32</span><span class="punctuation">,</span>
<span class="punctuation">}</span>
<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span>
<span class="keyword">fn</span> <span class="function declaration">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
<span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
<span class="punctuation">}</span>
<span class="keyword">fn</span> <span class="function declaration mutable">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
<span class="self_keyword mutable">self</span><span class="punctuation">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
<span class="punctuation">}</span>
<span class="keyword">fn</span> <span class="function declaration">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
<span class="self_keyword">self</span><span class="punctuation">.</span><span class="field">x</span>
<span class="punctuation">}</span>
<span class="punctuation">}</span> <span class="punctuation">}</span>
<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">STATIC_MUT</span><span class="punctuation">:</span> <span class="builtin_type">i32</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span> <span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">STATIC_MUT</span><span class="punctuation">:</span> <span class="builtin_type">i32</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
@ -113,6 +142,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">let</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable declaration">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span><span class="punctuation">;</span> <span class="keyword">let</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable declaration">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">:</span> <span class="variable">z</span><span class="punctuation">,</span> <span class="field">y</span> <span class="punctuation">}</span><span class="punctuation">;</span>
<span class="variable">y</span><span class="punctuation">;</span> <span class="variable">y</span><span class="punctuation">;</span>
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
<span class="variable mutable">foo</span><span class="punctuation">.</span><span class="function">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="variable mutable">foo</span><span class="punctuation">.</span><span class="function mutable">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="variable mutable">foo</span><span class="punctuation">.</span><span class="function consuming">baz</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span> <span class="field">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
<span class="variable mutable">copy</span><span class="punctuation">.</span><span class="function">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="variable mutable">copy</span><span class="punctuation">.</span><span class="function mutable">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="variable mutable">copy</span><span class="punctuation">.</span><span class="function">baz</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="punctuation">}</span> <span class="punctuation">}</span>
<span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="punctuation">&lt;</span><span class="type_param declaration">T</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span> <span class="keyword">enum</span> <span class="enum declaration">Option</span><span class="punctuation">&lt;</span><span class="type_param declaration">T</span><span class="punctuation">&gt;</span> <span class="punctuation">{</span>

View file

@ -75,6 +75,7 @@ define_semantic_token_modifiers![
(CONTROL_FLOW, "controlFlow"), (CONTROL_FLOW, "controlFlow"),
(INJECTED, "injected"), (INJECTED, "injected"),
(MUTABLE, "mutable"), (MUTABLE, "mutable"),
(CONSUMING, "consuming"),
(UNSAFE, "unsafe"), (UNSAFE, "unsafe"),
(ATTRIBUTE_MODIFIER, "attribute"), (ATTRIBUTE_MODIFIER, "attribute"),
]; ];

View file

@ -400,6 +400,7 @@ fn semantic_token_type_and_modifiers(
HighlightModifier::Injected => semantic_tokens::INJECTED, HighlightModifier::Injected => semantic_tokens::INJECTED,
HighlightModifier::ControlFlow => semantic_tokens::CONTROL_FLOW, HighlightModifier::ControlFlow => semantic_tokens::CONTROL_FLOW,
HighlightModifier::Mutable => semantic_tokens::MUTABLE, HighlightModifier::Mutable => semantic_tokens::MUTABLE,
HighlightModifier::Consuming => semantic_tokens::CONSUMING,
HighlightModifier::Unsafe => semantic_tokens::UNSAFE, HighlightModifier::Unsafe => semantic_tokens::UNSAFE,
}; };
mods |= modifier; mods |= modifier;