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 ++++++-------- 5 files changed, 90 insertions(+), 19 deletions(-) (limited to 'crates/ra_hir') 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()), -- cgit v1.2.3