From 8b7f853cc19d0940ec542e10bc23aa78455bbb3b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 10 Nov 2019 00:32:00 +0300 Subject: Add hir::Local --- crates/ra_hir/src/code_model.rs | 55 ++++++++++++++- crates/ra_hir/src/expr/scope.rs | 2 +- crates/ra_hir/src/from_source.rs | 30 +++++++- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/source_binder.rs | 20 +++--- crates/ra_ide_api/src/display/navigation_target.rs | 70 ++++++++----------- crates/ra_ide_api/src/goto_definition.rs | 3 +- crates/ra_ide_api/src/hover.rs | 2 +- crates/ra_ide_api/src/references.rs | 3 +- crates/ra_ide_api/src/references/classify.rs | 22 +++--- .../ra_ide_api/src/references/name_definition.rs | 38 +---------- crates/ra_ide_api/src/references/search_scope.rs | 6 +- .../src/snapshots/rainbow_highlighting.html | 12 ++-- crates/ra_ide_api/src/syntax_highlighting.rs | 79 ++++++---------------- 14 files changed, 171 insertions(+), 173 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e5bfad3ca..09c4e97fa 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -22,7 +22,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; use crate::{ adt::VariantDef, db::{AstDatabase, DefDatabase, HirDatabase}, - expr::{validation::ExprValidator, Body, BodySourceMap}, + expr::{validation::ExprValidator, BindingAnnotation, Body, BodySourceMap, Pat, PatId}, generics::HasGenericParams, ids::{ AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, @@ -32,7 +32,7 @@ use crate::{ resolve::{Resolver, Scope, TypeNs}, traits::TraitData, ty::{InferenceResult, Namespace, TraitRef}, - Either, HasSource, ImportId, Name, ScopeDef, Ty, + Either, HasSource, ImportId, Name, ScopeDef, Source, Ty, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -1070,3 +1070,54 @@ impl AssocItem { .expect("AssocItem without container") } } + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct Local { + pub(crate) parent: DefWithBody, + pub(crate) pat_id: PatId, +} + +impl Local { + pub fn name(self, db: &impl HirDatabase) -> Option { + let body = db.body_hir(self.parent); + match &body[self.pat_id] { + Pat::Bind { name, .. } => Some(name.clone()), + _ => None, + } + } + + pub fn is_self(self, db: &impl HirDatabase) -> bool { + self.name(db) == Some(name::SELF_PARAM) + } + + pub fn is_mut(self, db: &impl HirDatabase) -> bool { + let body = db.body_hir(self.parent); + match &body[self.pat_id] { + Pat::Bind { mode, .. } => match mode { + BindingAnnotation::Mutable | BindingAnnotation::RefMut => true, + _ => false, + }, + _ => false, + } + } + + pub fn parent(self, _db: &impl HirDatabase) -> DefWithBody { + self.parent + } + + pub fn module(self, db: &impl HirDatabase) -> Module { + self.parent.module(db) + } + + pub fn ty(self, db: &impl HirDatabase) -> Ty { + let infer = db.infer(self.parent); + infer[self.pat_id].clone() + } + + pub fn source(self, db: &impl HirDatabase) -> Source> { + let (_body, source_map) = db.body_with_source_map(self.parent); + let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm... + let root = src.file_syntax(db); + src.map(|ast| ast.map(|it| it.cast().unwrap().to_node(&root), |it| it.to_node(&root))) + } +} diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 5a1eade2c..daf8d8d07 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -17,7 +17,7 @@ impl_arena_id!(ScopeId); #[derive(Debug, PartialEq, Eq)] pub struct ExprScopes { - body: Arc, + pub(crate) body: Arc, scopes: Arena, scope_by_expr: FxHashMap, } diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index c95d2cdd0..2c441b0f4 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -2,13 +2,17 @@ use hir_def::{StructId, StructOrUnionId, UnionId}; use hir_expand::name::AsName; -use ra_syntax::ast::{self, AstNode, NameOwner}; +use ra_syntax::{ + ast::{self, AstNode, NameOwner}, + match_ast, +}; use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, ids::{AstItemDef, LocationCtx}, - AstId, Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module, - ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, + AstId, Const, Crate, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, + ImplBlock, Local, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, + Union, VariantDef, }; pub trait FromSource: Sized { @@ -126,6 +130,26 @@ impl FromSource for StructField { } } +impl Local { + pub fn from_source(db: &impl HirDatabase, src: Source) -> Option { + let file_id = src.file_id; + let parent: DefWithBody = src.ast.syntax().ancestors().find_map(|it| { + let res = match_ast! { + match it { + ast::ConstDef(ast) => { Const::from_source(db, Source { ast, file_id})?.into() }, + ast::StaticDef(ast) => { Static::from_source(db, Source { ast, file_id})?.into() }, + ast::FnDef(ast) => { Function::from_source(db, Source { ast, file_id})?.into() }, + _ => return None, + } + }; + Some(res) + })?; + let (_body, source_map) = db.body_with_source_map(parent); + let pat_id = source_map.node_pat(&src.ast.into())?; + Some(Local { parent, pat_id }) + } +} + impl Module { pub fn from_declaration(db: &impl HirDatabase, src: Source) -> Option { let src_parent = Source { diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 9dc8d139b..806f1daed 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -65,7 +65,7 @@ pub use crate::{ docs::{DocDef, Docs, Documentation}, src::{HasBodySource, HasSource}, Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, - EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef, + EnumVariant, FieldSource, FnData, Function, HasBody, Local, MacroDef, Module, ModuleDef, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, }, expr::ExprScopes, diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 66cb4b357..c5fdf3bab 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -28,7 +28,7 @@ use crate::{ ids::LocationCtx, resolve::{ScopeDef, TypeNs, ValueNs}, ty::method_resolution::{self, implements_trait}, - AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, + AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, Local, MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, }; @@ -94,6 +94,7 @@ fn def_with_body_from_child_node( #[derive(Debug)] pub struct SourceAnalyzer { resolver: Resolver, + body_owner: Option, body_source_map: Option>, infer: Option>, scopes: Option>, @@ -104,7 +105,7 @@ pub enum PathResolution { /// An item Def(crate::ModuleDef), /// A local binding (only value namespace) - LocalBinding(Either, AstPtr>), + Local(Local), /// A generic parameter GenericParam(u32), SelfType(crate::ImplBlock), @@ -152,6 +153,7 @@ impl SourceAnalyzer { let resolver = expr::resolver_for_scope(def.body(db), db, scope); SourceAnalyzer { resolver, + body_owner: Some(def), body_source_map: Some(source_map), infer: Some(def.infer(db)), scopes: Some(scopes), @@ -162,6 +164,7 @@ impl SourceAnalyzer { .ancestors() .find_map(|node| try_get_resolver_for_node(db, file_id, &node)) .unwrap_or_default(), + body_owner: None, body_source_map: None, infer: None, scopes: None, @@ -233,16 +236,9 @@ impl SourceAnalyzer { }); let values = self.resolver.resolve_path_in_value_ns_fully(db, &path).and_then(|val| { let res = match val { - ValueNs::LocalBinding(it) => { - // We get a `PatId` from resolver, but it actually can only - // point at `BindPat`, and not at the arbitrary pattern. - let pat_ptr = self - .body_source_map - .as_ref()? - .pat_syntax(it)? - .ast // FIXME: ignoring file_id here is definitelly wrong - .map_a(|ptr| ptr.cast::().unwrap()); - PathResolution::LocalBinding(pat_ptr) + ValueNs::LocalBinding(pat_id) => { + let var = Local { parent: self.body_owner?, pat_id }; + PathResolution::Local(var) } ValueNs::Function(it) => PathResolution::Def(it.into()), ValueNs::Const(it) => PathResolution::Def(it.into()), diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index 41d467564..f7ad08515 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs @@ -1,11 +1,11 @@ //! FIXME: write short doc here -use hir::{AssocItem, FieldSource, HasSource, ModuleSource}; +use hir::{AssocItem, Either, FieldSource, HasSource, ModuleSource}; use ra_db::{FileId, SourceDatabase}; use ra_syntax::{ - ast::{self, DocCommentsOwner}, - match_ast, AstNode, AstPtr, SmolStr, - SyntaxKind::{self, NAME}, + ast::{self, DocCommentsOwner, NameOwner}, + match_ast, AstNode, SmolStr, + SyntaxKind::{self, BIND_PAT}, SyntaxNode, TextRange, }; @@ -76,42 +76,6 @@ impl NavigationTarget { self.focus_range } - pub(crate) fn from_bind_pat( - db: &RootDatabase, - file_id: FileId, - pat: &ast::BindPat, - ) -> NavigationTarget { - NavigationTarget::from_named(db, file_id.into(), pat, None, None) - } - - pub(crate) fn from_pat( - db: &RootDatabase, - file_id: FileId, - pat: AstPtr, - ) -> NavigationTarget { - let parse = db.parse(file_id); - let pat = pat.to_node(parse.tree().syntax()); - NavigationTarget::from_bind_pat(db, file_id, &pat) - } - - pub(crate) fn from_self_param( - file_id: FileId, - par: AstPtr, - ) -> NavigationTarget { - let (name, full_range) = ("self".into(), par.syntax_node_ptr().range()); - - NavigationTarget { - file_id, - name, - full_range, - focus_range: None, - kind: NAME, - container_name: None, - description: None, //< No document node for SelfParam - docs: None, //< No document node for SelfParam - } - } - pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); if let Some(src) = module.declaration_source(db) { @@ -370,6 +334,32 @@ impl ToNav for hir::AssocItem { } } +impl ToNav for hir::Local { + fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { + let src = self.source(db); + let (full_range, focus_range) = match src.ast { + Either::A(it) => { + (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range())) + } + Either::B(it) => (it.syntax().text_range(), Some(it.self_kw_token().text_range())), + }; + let name = match self.name(db) { + Some(it) => it.to_string().into(), + None => "".into(), + }; + NavigationTarget { + file_id: src.file_id.original_file(db), + name, + kind: BIND_PAT, + full_range, + focus_range, + container_name: None, + description: None, + docs: None, + } + } +} + fn find_range_from_node( db: &RootDatabase, src: hir::HirFileId, diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 713b61d5e..6c8387f6c 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -68,8 +68,7 @@ pub(crate) fn reference_definition( return Exact(adt.to_nav(db)); } } - Some(Pat((_, pat))) => return Exact(NavigationTarget::from_pat(db, file_id, pat)), - Some(SelfParam(par)) => return Exact(NavigationTarget::from_self_param(file_id, par)), + Some(Local(local)) => return Exact(local.to_nav(db)), Some(GenericParam(_)) => { // FIXME: go to the generic param def } diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index cc41390b2..086e6dec3 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -143,7 +143,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option { + Some(Local(_)) => { // Hover for these shows type names no_fallback = true; } diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 0a76bf484..9cb9433e7 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs @@ -86,8 +86,7 @@ pub(crate) fn find_all_refs( Some((adt, _)) => adt.to_nav(db), None => return None, }, - NameKind::Pat((_, pat)) => NavigationTarget::from_pat(db, position.file_id, pat), - NameKind::SelfParam(par) => NavigationTarget::from_self_param(position.file_id, par), + NameKind::Local(local) => local.to_nav(db), NameKind::GenericParam(_) => return None, }; diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 153082d5b..217f9951e 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -1,13 +1,13 @@ //! Functions that are used to classify an element from its definition or reference. -use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; +use hir::{FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; use ra_db::FileId; use ra_prof::profile; -use ra_syntax::{ast, match_ast, AstNode, AstPtr}; +use ra_syntax::{ast, match_ast, AstNode}; use test_utils::tested_by; use super::{ - name_definition::{from_assoc_item, from_module_def, from_pat, from_struct_field}, + name_definition::{from_assoc_item, from_module_def, from_struct_field}, NameDefinition, NameKind, }; use crate::db::RootDatabase; @@ -25,7 +25,13 @@ pub(crate) fn classify_name( match_ast! { match parent { ast::BindPat(it) => { - from_pat(db, file_id, AstPtr::new(&it)) + let src = hir::Source { file_id, ast: it }; + let local = hir::Local::from_source(db, src)?; + Some(NameDefinition { + visibility: None, + container: local.module(db), + kind: NameKind::Local(local), + }) }, ast::RecordFieldDef(it) => { let ast = hir::FieldSource::Named(it); @@ -159,10 +165,10 @@ pub(crate) fn classify_name_ref( match resolved { Def(def) => Some(from_module_def(db, def, Some(container))), AssocItem(item) => Some(from_assoc_item(db, item)), - LocalBinding(Either::A(pat)) => from_pat(db, file_id, pat), - LocalBinding(Either::B(par)) => { - let kind = NameKind::SelfParam(par); - Some(NameDefinition { kind, container, visibility }) + Local(local) => { + let container = local.module(db); + let kind = NameKind::Local(local); + Some(NameDefinition { kind, container, visibility: None }) } GenericParam(par) => { // FIXME: get generic param def diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs index 4580bc789..450f7ea9b 100644 --- a/crates/ra_ide_api/src/references/name_definition.rs +++ b/crates/ra_ide_api/src/references/name_definition.rs @@ -4,10 +4,9 @@ //! Note that the reference search is possible for not all of the classified items. use hir::{ - db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef, - Module, ModuleDef, StructField, Ty, VariantDef, + Adt, AssocItem, HasSource, Local, MacroDef, Module, ModuleDef, StructField, Ty, VariantDef, }; -use ra_syntax::{ast, ast::VisibilityOwner, match_ast, AstNode, AstPtr}; +use ra_syntax::{ast, ast::VisibilityOwner}; use crate::db::RootDatabase; @@ -18,8 +17,7 @@ pub enum NameKind { AssocItem(AssocItem), Def(ModuleDef), SelfType(Ty), - Pat((DefWithBody, AstPtr)), - SelfParam(AstPtr), + Local(Local), GenericParam(u32), } @@ -30,36 +28,6 @@ pub(crate) struct NameDefinition { pub kind: NameKind, } -pub(super) fn from_pat( - db: &RootDatabase, - file_id: HirFileId, - pat: AstPtr, -) -> Option { - let root = db.parse_or_expand(file_id)?; - let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { - match_ast! { - match node { - ast::FnDef(it) => { - let src = hir::Source { file_id, ast: it }; - Some(hir::Function::from_source(db, src)?.into()) - }, - ast::ConstDef(it) => { - let src = hir::Source { file_id, ast: it }; - Some(hir::Const::from_source(db, src)?.into()) - }, - ast::StaticDef(it) => { - let src = hir::Source { file_id, ast: it }; - Some(hir::Static::from_source(db, src)?.into()) - }, - _ => None, - } - } - })?; - let kind = NameKind::Pat((def, pat)); - let container = def.module(db); - Some(NameDefinition { kind, container, visibility: None }) -} - pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition { let container = item.module(db); let visibility = match item { diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs index f2789e0b2..2907787c2 100644 --- a/crates/ra_ide_api/src/references/search_scope.rs +++ b/crates/ra_ide_api/src/references/search_scope.rs @@ -71,13 +71,13 @@ impl NameDefinition { let module_src = self.container.definition_source(db); let file_id = module_src.file_id.original_file(db); - if let NameKind::Pat((def, _)) = self.kind { - let mut res = FxHashMap::default(); - let range = match def { + if let NameKind::Local(var) = self.kind { + let range = match var.parent(db) { DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), }; + let mut res = FxHashMap::default(); res.insert(file_id, Some(range)); return SearchScope::new(res); } diff --git a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html index ed664817e..79f11ea80 100644 --- a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html @@ -20,14 +20,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .keyword\.control { color: #F0DFAF; font-weight: bold; }
fn main() {
-    let hello = "hello";
-    let x = hello.to_string();
-    let y = hello.to_string();
+    let hello = "hello";
+    let x = hello.to_string();
+    let y = hello.to_string();
 
-    let x = "other color please!";
-    let y = x.to_string();
+    let x = "other color please!";
+    let y = x.to_string();
 }
 
 fn bar() {
-    let mut hello = "hello";
+    let mut hello = "hello";
 }
\ No newline at end of file diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 1ee68abe2..d53a759ee 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -2,15 +2,10 @@ use rustc_hash::{FxHashMap, FxHashSet}; -use hir::{Mutability, Ty}; +use hir::{Mutability, Name}; use ra_db::SourceDatabase; use ra_prof::profile; -use ra_syntax::{ - ast::{self, NameOwner}, - AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind, - SyntaxKind::*, - SyntaxNode, TextRange, T, -}; +use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; use crate::{ db::RootDatabase, @@ -43,32 +38,12 @@ fn is_control_keyword(kind: SyntaxKind) -> bool { } } -fn is_variable_mutable( - db: &RootDatabase, - analyzer: &hir::SourceAnalyzer, - pat: ast::BindPat, -) -> bool { - if pat.is_mutable() { - return true; - } - - let ty = analyzer.type_of_pat(db, &pat.into()).unwrap_or(Ty::Unknown); - if let Some((_, mutability)) = ty.as_reference() { - match mutability { - Mutability::Shared => false, - Mutability::Mut => true, - } - } else { - false - } -} - pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { let _p = profile("highlight"); let parse = db.parse(file_id); let root = parse.tree().syntax().clone(); - fn calc_binding_hash(file_id: FileId, text: &SmolStr, shadow_count: u32) -> u64 { + fn calc_binding_hash(file_id: FileId, name: &Name, shadow_count: u32) -> u64 { fn hash(x: T) -> u64 { use std::{collections::hash_map::DefaultHasher, hash::Hasher}; @@ -77,13 +52,13 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec = FxHashSet::default(); - let mut bindings_shadow_count: FxHashMap = FxHashMap::default(); + let mut bindings_shadow_count: FxHashMap = FxHashMap::default(); let mut res = Vec::new(); for node in root.descendants_with_tokens() { @@ -107,34 +82,29 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap(); let name_kind = classify_name(db, file_id, &name).map(|d| d.kind); - if let Some(Pat((_, ptr))) = &name_kind { - let pat = ptr.to_node(&root); - if let Some(name) = pat.name() { - let text = name.text(); - let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); + if let Some(Local(local)) = &name_kind { + if let Some(name) = local.name(db) { + let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); *shadow_count += 1; - binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count)) + binding_hash = Some(calc_binding_hash(file_id, &name, *shadow_count)) } }; match name_kind { - Some(name_kind) => highlight_name(db, file_id, name.syntax(), &root, name_kind), + Some(name_kind) => highlight_name(db, name_kind), None => name.syntax().parent().map_or("function", |x| match x.kind() { TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => "type", RECORD_FIELD_DEF => "field", @@ -237,13 +207,7 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo buf } -fn highlight_name( - db: &RootDatabase, - file_id: FileId, - node: &SyntaxNode, - root: &SyntaxNode, - name_kind: NameKind, -) -> &'static str { +fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { match name_kind { Macro(_) => "macro", Field(_) => "field", @@ -260,14 +224,15 @@ fn highlight_name( Def(hir::ModuleDef::TypeAlias(_)) => "type", Def(hir::ModuleDef::BuiltinType(_)) => "type", SelfType(_) => "type", - SelfParam(_) => "type", GenericParam(_) => "type", - Pat((_, ptr)) => { - let analyzer = hir::SourceAnalyzer::new(db, file_id, node, None); - if is_variable_mutable(db, &analyzer, ptr.to_node(&root)) { + Local(local) => { + if local.is_mut(db) { "variable.mut" } else { - "variable" + match local.ty(db).as_reference() { + Some((_, Mutability::Mut)) => "variable.mut", + _ => "variable", + } } } } -- cgit v1.2.3