From 10d66d63d716a10ba7a5a8d1b69c9066249caf69 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 10 Apr 2019 11:15:55 +0300 Subject: introduce SourceAnalyzer --- crates/ra_hir/src/code_model_api.rs | 10 ++-- crates/ra_hir/src/expr.rs | 16 +++--- crates/ra_hir/src/expr/scope.rs | 2 +- crates/ra_hir/src/lib.rs | 1 + crates/ra_hir/src/source_binder.rs | 100 +++++++++++++++++++++++++++++++++++- 5 files changed, 109 insertions(+), 20 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index f13a6b37a..660edf006 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -450,10 +450,6 @@ impl DefWithBody { db.infer(*self) } - pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc { - db.body_with_source_map(*self).1 - } - pub fn body(&self, db: &impl HirDatabase) -> Arc { db.body_hir(*self) } @@ -523,7 +519,7 @@ impl Function { self.signature(db).name.clone() } - pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc { + pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc { db.body_with_source_map((*self).into()).1 } @@ -606,7 +602,7 @@ impl Const { db.infer((*self).into()) } - pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc { + pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc { db.body_with_source_map((*self).into()).1 } @@ -679,7 +675,7 @@ impl Static { db.infer((*self).into()) } - pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc { + pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc { db.body_with_source_map((*self).into()).1 } } diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index a8e115e47..3806a3605 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -117,31 +117,27 @@ impl Index for Body { } impl BodySourceMap { - pub fn expr_syntax(&self, expr: ExprId) -> Option { + pub(crate) fn expr_syntax(&self, expr: ExprId) -> Option { self.expr_map_back.get(expr).cloned() } - pub fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option { + pub(crate) fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option { self.expr_map.get(&ptr).cloned() } - pub fn node_expr(&self, node: &ast::Expr) -> Option { + pub(crate) fn node_expr(&self, node: &ast::Expr) -> Option { self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned() } - pub fn pat_syntax(&self, pat: PatId) -> Option { + pub(crate) fn pat_syntax(&self, pat: PatId) -> Option { self.pat_map_back.get(pat).cloned() } - pub fn syntax_pat(&self, ptr: PatPtr) -> Option { - self.pat_map.get(&ptr).cloned() - } - - pub fn node_pat(&self, node: &ast::Pat) -> Option { + pub(crate) fn node_pat(&self, node: &ast::Pat) -> Option { self.pat_map.get(&Either::A(AstPtr::new(node))).cloned() } - pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr { + pub(crate) fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr { self.field_map[&(expr, field)].clone() } } diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 725b6c00e..404c979eb 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -109,7 +109,7 @@ impl ExprScopes { #[derive(Debug, Clone, PartialEq, Eq)] pub struct ScopesWithSourceMap { - pub source_map: Arc, + pub(crate) source_map: Arc, pub scopes: Arc, } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 0881939a2..59b402c57 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -66,6 +66,7 @@ pub use self::{ adt::AdtDef, expr::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}, resolve::{Resolver, Resolution}, + source_binder::{SourceAnalyser, PathResolution}, }; pub use self::code_model_api::{ diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 182ed4c91..79e304383 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -5,15 +5,17 @@ /// /// So, this modules should not be used during hir construction, it exists /// purely for "IDE needs". +use std::sync::Arc; + use ra_db::{FileId, FilePosition}; use ra_syntax::{ - SyntaxNode, + SyntaxNode, AstPtr, ast::{self, AstNode, NameOwner}, algo::{find_node_at_offset, find_token_at_offset}, }; use crate::{ - HirDatabase, Function, Struct, Enum,Const,Static, + HirDatabase, Function, Struct, Enum, Const, Static, Either, AsName, Module, HirFileId, Crate, Trait, Resolver, ids::LocationCtx, expr, AstId @@ -258,3 +260,97 @@ fn try_get_resolver_for_node( None } } + +// Name is bad, don't use inside HIR +#[derive(Debug)] +pub struct SourceAnalyser { + resolver: Resolver, + body_source_map: Option>, + infer: Option>, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum PathResolution { + /// An item + Def(crate::ModuleDef), + /// A local binding (only value namespace) + LocalBinding(crate::expr::PatId), + /// A generic parameter + GenericParam(u32), + SelfType(crate::ImplBlock), + AssocItem(crate::ImplItem), +} + +impl SourceAnalyser { + pub fn new(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> SourceAnalyser { + let resolver = resolver_for_node(db, file_id, node); + let function = function_from_child_node(db, file_id, node); + if let Some(function) = function { + SourceAnalyser { + resolver, + body_source_map: Some(function.body_source_map(db)), + infer: Some(function.infer(db)), + } + } else { + SourceAnalyser { resolver, body_source_map: None, infer: None } + } + } + + pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option { + let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?; + Some(self.infer.as_ref()?[expr_id].clone()) + } + + pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option { + let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?; + Some(self.infer.as_ref()?[pat_id].clone()) + } + + pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { + let expr_id = self.body_source_map.as_ref()?.node_expr(call.into())?; + self.infer.as_ref()?.method_resolution(expr_id) + } + + pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option { + let expr_id = self.body_source_map.as_ref()?.node_expr(field.into())?; + self.infer.as_ref()?.field_resolution(expr_id) + } + + pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option { + if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { + let expr_id = self.body_source_map.as_ref()?.node_expr(path_expr.into())?; + if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { + return Some(PathResolution::AssocItem(assoc)); + } + } + if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { + let pat_id = self.body_source_map.as_ref()?.node_pat(path_pat.into())?; + if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { + return Some(PathResolution::AssocItem(assoc)); + } + } + let hir_path = crate::Path::from_ast(path)?; + let res = self.resolver.resolve_path(db, &hir_path); + let res = res.clone().take_types().or_else(|| res.take_values())?; + Some(res.into()) + } + + pub fn pat_syntax( + &self, + _db: &impl HirDatabase, + pat: crate::expr::PatId, + ) -> Option, AstPtr>> { + self.body_source_map.as_ref()?.pat_syntax(pat) + } +} + +impl From for PathResolution { + fn from(res: crate::Resolution) -> PathResolution { + match res { + crate::Resolution::Def(it) => PathResolution::Def(it), + crate::Resolution::LocalBinding(it) => PathResolution::LocalBinding(it), + crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it), + crate::Resolution::SelfType(it) => PathResolution::SelfType(it), + } + } +} -- cgit v1.2.3 From 505acc973b3b865195d7d0aeb47c419c35f6bbbc Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 11 Apr 2019 15:34:13 +0300 Subject: Make call info to use real name resolution --- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/ty.rs | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 59b402c57..8702c6222 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -60,7 +60,7 @@ pub use self::{ source_id::{AstIdMap, ErasedFileAstId}, ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc}, nameres::{PerNs, Namespace, ImportId}, - ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay}, + ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay, CallableDef}, impl_block::{ImplBlock, ImplItem}, docs::{Docs, Documentation}, adt::AdtDef, diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 20e55d92d..ecf13fbc3 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -15,10 +15,11 @@ use std::sync::Arc; use std::{fmt, mem}; use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait}; +use display::{HirDisplay, HirFormatter}; -pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig}; +pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig}; pub(crate) use infer::{infer, InferenceResult, InferTy}; -use display::{HirDisplay, HirFormatter}; +pub use lower::CallableDef; /// A type constructor or type name: this might be something like the primitive /// type `bool`, a struct like `Vec`, or things like function pointers or @@ -288,6 +289,15 @@ impl Ty { } } + pub fn as_callable(&self) -> Option<(CallableDef, &Substs)> { + match self { + Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(callable_def), parameters }) => { + Some((*callable_def, parameters)) + } + _ => None, + } + } + fn builtin_deref(&self) -> Option { match self { Ty::Apply(a_ty) => match a_ty.ctor { -- cgit v1.2.3 From b6809b6695f9c4cec82ff98d73f7ff24f96cbecf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 11 Apr 2019 15:51:02 +0300 Subject: rename --- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/source_binder.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 8702c6222..3ca810a8b 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -66,7 +66,7 @@ pub use self::{ adt::AdtDef, expr::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}, resolve::{Resolver, Resolution}, - source_binder::{SourceAnalyser, PathResolution}, + source_binder::{SourceAnalyzer, PathResolution}, }; pub use self::code_model_api::{ diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 79e304383..309e33ca9 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -261,9 +261,9 @@ fn try_get_resolver_for_node( } } -// Name is bad, don't use inside HIR +/// `SourceAnalyzer` #[derive(Debug)] -pub struct SourceAnalyser { +pub struct SourceAnalyzer { resolver: Resolver, body_source_map: Option>, infer: Option>, @@ -281,18 +281,18 @@ pub enum PathResolution { AssocItem(crate::ImplItem), } -impl SourceAnalyser { - pub fn new(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> SourceAnalyser { +impl SourceAnalyzer { + pub fn new(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> SourceAnalyzer { let resolver = resolver_for_node(db, file_id, node); let function = function_from_child_node(db, file_id, node); if let Some(function) = function { - SourceAnalyser { + SourceAnalyzer { resolver, body_source_map: Some(function.body_source_map(db)), infer: Some(function.infer(db)), } } else { - SourceAnalyser { resolver, body_source_map: None, infer: None } + SourceAnalyzer { resolver, body_source_map: None, infer: None } } } -- cgit v1.2.3 From 07cc047b4ffe3049dfe95fc5cd59383336976e2d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 11 Apr 2019 15:58:00 +0300 Subject: minimize the API --- crates/ra_hir/src/source_binder.rs | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 309e33ca9..ec9af035f 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -261,7 +261,8 @@ fn try_get_resolver_for_node( } } -/// `SourceAnalyzer` +/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of +/// original source files. It should not be used inside the HIR itself. #[derive(Debug)] pub struct SourceAnalyzer { resolver: Resolver, @@ -274,7 +275,7 @@ pub enum PathResolution { /// An item Def(crate::ModuleDef), /// A local binding (only value namespace) - LocalBinding(crate::expr::PatId), + LocalBinding(Either, AstPtr>), /// A generic parameter GenericParam(u32), SelfType(crate::ImplBlock), @@ -332,25 +333,14 @@ impl SourceAnalyzer { let hir_path = crate::Path::from_ast(path)?; let res = self.resolver.resolve_path(db, &hir_path); let res = res.clone().take_types().or_else(|| res.take_values())?; - Some(res.into()) - } - - pub fn pat_syntax( - &self, - _db: &impl HirDatabase, - pat: crate::expr::PatId, - ) -> Option, AstPtr>> { - self.body_source_map.as_ref()?.pat_syntax(pat) - } -} - -impl From for PathResolution { - fn from(res: crate::Resolution) -> PathResolution { - match res { + let res = match res { crate::Resolution::Def(it) => PathResolution::Def(it), - crate::Resolution::LocalBinding(it) => PathResolution::LocalBinding(it), + crate::Resolution::LocalBinding(it) => { + PathResolution::LocalBinding(self.body_source_map.as_ref()?.pat_syntax(it)?) + } crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it), crate::Resolution::SelfType(it) => PathResolution::SelfType(it), - } + }; + Some(res) } } -- cgit v1.2.3 From 5471c1ef4b2fda2fbaa63f7d8404abf04a3e9da4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 11 Apr 2019 16:22:10 +0300 Subject: generalize SourceAnalyzer to handle all defs with bodies --- crates/ra_hir/src/code_model_api.rs | 8 ++++++++ crates/ra_hir/src/source_binder.rs | 30 +++++++++++++++++++----------- 2 files changed, 27 insertions(+), 11 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 660edf006..40bfd5faf 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -454,6 +454,14 @@ impl DefWithBody { db.body_hir(*self) } + pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc { + match *self { + DefWithBody::Const(ref c) => c.body_source_map(db), + DefWithBody::Function(ref f) => f.body_source_map(db), + DefWithBody::Static(ref s) => s.body_source_map(db), + } + } + /// Builds a resolver for code inside this item. pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { match *self { diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index ec9af035f..dc9d614c0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -15,7 +15,7 @@ use ra_syntax::{ }; use crate::{ - HirDatabase, Function, Struct, Enum, Const, Static, Either, + HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, AsName, Module, HirFileId, Crate, Trait, Resolver, ids::LocationCtx, expr, AstId @@ -219,7 +219,7 @@ pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> R .unwrap_or_default() } -pub fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> Resolver { +fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> Resolver { node.ancestors() .find_map(|node| { if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { @@ -284,16 +284,24 @@ pub enum PathResolution { impl SourceAnalyzer { pub fn new(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> SourceAnalyzer { - let resolver = resolver_for_node(db, file_id, node); - let function = function_from_child_node(db, file_id, node); - if let Some(function) = function { - SourceAnalyzer { - resolver, - body_source_map: Some(function.body_source_map(db)), - infer: Some(function.infer(db)), + let def_with_body = node.ancestors().find_map(|node| { + if let Some(src) = ast::FnDef::cast(node) { + return function_from_source(db, file_id, src).map(DefWithBody::from); } - } else { - SourceAnalyzer { resolver, body_source_map: None, infer: None } + if let Some(src) = ast::StaticDef::cast(node) { + return static_from_source(db, file_id, src).map(DefWithBody::from); + } + if let Some(src) = ast::ConstDef::cast(node) { + return const_from_source(db, file_id, src).map(DefWithBody::from); + } + None + }); + SourceAnalyzer { + resolver: def_with_body + .map(|it| it.resolver(db)) + .unwrap_or_else(|| resolver_for_node(db, file_id, node)), + body_source_map: def_with_body.map(|it| it.body_source_map(db)), + infer: def_with_body.map(|it| it.infer(db)), } } -- cgit v1.2.3 From 3c9f2d0e372cff6490dcd30411cb6cc1f691fde7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 11 Apr 2019 16:39:56 +0300 Subject: simplify --- crates/ra_hir/src/code_model_api.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 40bfd5faf..3c1f7cd65 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -455,11 +455,7 @@ impl DefWithBody { } pub fn body_source_map(&self, db: &impl HirDatabase) -> Arc { - match *self { - DefWithBody::Const(ref c) => c.body_source_map(db), - DefWithBody::Function(ref f) => f.body_source_map(db), - DefWithBody::Static(ref s) => s.body_source_map(db), - } + db.body_with_source_map(*self).1 } /// Builds a resolver for code inside this item. @@ -610,6 +606,7 @@ impl Const { db.infer((*self).into()) } + #[cfg(test)] pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc { db.body_with_source_map((*self).into()).1 } @@ -683,6 +680,7 @@ impl Static { db.infer((*self).into()) } + #[cfg(test)] pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc { db.body_with_source_map((*self).into()).1 } -- cgit v1.2.3 From ebb0c377f0ab99a0f5e6d0c776cb9b026b62b0e4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 11 Apr 2019 16:49:35 +0300 Subject: remove resolver from CompletonContext --- crates/ra_hir/src/source_binder.rs | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index dc9d614c0..560b48303 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -11,7 +11,7 @@ use ra_db::{FileId, FilePosition}; use ra_syntax::{ SyntaxNode, AstPtr, ast::{self, AstNode, NameOwner}, - algo::{find_node_at_offset, find_token_at_offset}, + algo::find_node_at_offset, }; use crate::{ @@ -196,29 +196,6 @@ pub fn trait_from_module( Trait { id: ctx.to_def(trait_def) } } -pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver { - let file_id = position.file_id; - let file = db.parse(file_id); - find_token_at_offset(file.syntax(), position.offset) - .find_map(|token| { - token.parent().ancestors().find_map(|node| { - if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { - if let Some(func) = function_from_child_node(db, file_id, node) { - let scopes = func.scopes(db); - let scope = scopes.scope_for_offset(position.offset); - Some(expr::resolver_for_scope(func.body(db), db, scope)) - } else { - // FIXME const/static/array length - None - } - } else { - try_get_resolver_for_node(db, file_id, node) - } - }) - }) - .unwrap_or_default() -} - fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> Resolver { node.ancestors() .find_map(|node| { @@ -305,6 +282,10 @@ impl SourceAnalyzer { } } + pub fn resolver(&self) -> &Resolver { + &self.resolver + } + pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option { let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?; Some(self.infer.as_ref()?[expr_id].clone()) -- cgit v1.2.3 From a347208bb283963cacb75439d1cf474d1f064f02 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 11 Apr 2019 16:51:30 +0300 Subject: use correct resolver for expressions --- crates/ra_hir/src/source_binder.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 560b48303..a764c54c0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -274,9 +274,7 @@ impl SourceAnalyzer { None }); SourceAnalyzer { - resolver: def_with_body - .map(|it| it.resolver(db)) - .unwrap_or_else(|| resolver_for_node(db, file_id, node)), + resolver: resolver_for_node(db, file_id, node), body_source_map: def_with_body.map(|it| it.body_source_map(db)), infer: def_with_body.map(|it| it.infer(db)), } -- cgit v1.2.3 From cf2ba2791d57123248141a3066071180f4255b1c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 11 Apr 2019 17:14:41 +0300 Subject: add todo --- crates/ra_hir/src/source_binder.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index a764c54c0..182bc36ff 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -274,6 +274,7 @@ impl SourceAnalyzer { None }); SourceAnalyzer { + //TODO: use scope_for_offset here to get correct scope for completion resolver: resolver_for_node(db, file_id, node), body_source_map: def_with_body.map(|it| it.body_source_map(db)), infer: def_with_body.map(|it| it.infer(db)), -- cgit v1.2.3 From 0fd93bc14a2d0ce2edd682d26c18979c13f181c5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 00:44:47 +0300 Subject: use really correct resolver for expressions --- crates/ra_hir/src/source_binder.rs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 182bc36ff..846394212 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use ra_db::{FileId, FilePosition}; use ra_syntax::{ - SyntaxNode, AstPtr, + SyntaxNode, AstPtr, TextUnit, ast::{self, AstNode, NameOwner}, algo::find_node_at_offset, }; @@ -196,13 +196,21 @@ pub fn trait_from_module( Trait { id: ctx.to_def(trait_def) } } -fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> Resolver { +fn resolver_for_node( + db: &impl HirDatabase, + file_id: FileId, + node: &SyntaxNode, + offset: Option, +) -> Resolver { node.ancestors() .find_map(|node| { if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { if let Some(func) = function_from_child_node(db, file_id, node) { let scopes = func.scopes(db); - let scope = scopes.scope_for(&node); + let scope = match offset { + None => scopes.scope_for(&node), + Some(offset) => scopes.scope_for_offset(offset), + }; Some(expr::resolver_for_scope(func.body(db), db, scope)) } else { // FIXME const/static/array length @@ -260,7 +268,12 @@ pub enum PathResolution { } impl SourceAnalyzer { - pub fn new(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> SourceAnalyzer { + pub fn new( + db: &impl HirDatabase, + file_id: FileId, + node: &SyntaxNode, + offset: Option, + ) -> SourceAnalyzer { let def_with_body = node.ancestors().find_map(|node| { if let Some(src) = ast::FnDef::cast(node) { return function_from_source(db, file_id, src).map(DefWithBody::from); @@ -274,8 +287,7 @@ impl SourceAnalyzer { None }); SourceAnalyzer { - //TODO: use scope_for_offset here to get correct scope for completion - resolver: resolver_for_node(db, file_id, node), + resolver: resolver_for_node(db, file_id, node, offset), body_source_map: def_with_body.map(|it| it.body_source_map(db)), infer: def_with_body.map(|it| it.infer(db)), } -- cgit v1.2.3 From 7c13e223345e4ff14cc884fc5b785c925f0e0b61 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 00:56:57 +0300 Subject: simplify tests --- crates/ra_hir/src/code_model_api.rs | 10 ---------- crates/ra_hir/src/source_binder.rs | 10 ++++++++++ crates/ra_hir/src/ty/tests.rs | 39 +++++++++++++------------------------ 3 files changed, 23 insertions(+), 36 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 3c1f7cd65..5179f719d 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -606,11 +606,6 @@ impl Const { db.infer((*self).into()) } - #[cfg(test)] - pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc { - db.body_with_source_map((*self).into()).1 - } - /// The containing impl block, if this is a method. pub fn impl_block(&self, db: &impl DefDatabase) -> Option { let module_impls = db.impls_in_module(self.module(db)); @@ -679,11 +674,6 @@ impl Static { pub fn infer(&self, db: &impl HirDatabase) -> Arc { db.infer((*self).into()) } - - #[cfg(test)] - pub(crate) fn body_source_map(&self, db: &impl HirDatabase) -> Arc { - db.body_with_source_map((*self).into()).1 - } } impl Docs for Static { diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 846394212..c3cb17882 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -343,4 +343,14 @@ impl SourceAnalyzer { }; Some(res) } + + #[cfg(test)] + pub(crate) fn body_source_map(&self) -> Arc { + self.body_source_map.clone().unwrap() + } + + #[cfg(test)] + pub(crate) fn inference_result(&self) -> Arc { + self.infer.clone().unwrap() + } } diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index ecc63f376..87d6bcaec 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -4,7 +4,7 @@ use std::fmt::Write; use insta::assert_snapshot_matches; use ra_db::{SourceDatabase, salsa::Database, FilePosition}; -use ra_syntax::{algo, ast::{self, AstNode}}; +use ra_syntax::{algo, ast::{self, AstNode}, SyntaxKind::*}; use test_utils::covers; use crate::{ @@ -12,7 +12,8 @@ use crate::{ mock::MockDatabase, ty::display::HirDisplay, ty::InferenceResult, - expr::BodySourceMap + expr::BodySourceMap, + SourceAnalyzer, }; // These tests compare the inference results for all expressions in a file @@ -1862,14 +1863,14 @@ fn test() { @r###" [49; 50) '0': u32 [80; 83) '101': u32 -[126; 128) '99': u32 [95; 213) '{ ...NST; }': () [138; 139) 'x': {unknown} [142; 153) 'LOCAL_CONST': {unknown} [163; 164) 'z': u32 [167; 179) 'GLOBAL_CONST': u32 [189; 191) 'id': u32 -[194; 210) 'Foo::A..._CONST': u32"### +[194; 210) 'Foo::A..._CONST': u32 +[126; 128) '99': u32"### ); } @@ -1891,8 +1892,6 @@ fn test() { @r###" [29; 32) '101': u32 [70; 73) '101': u32 -[118; 120) '99': u32 -[161; 163) '99': u32 [85; 280) '{ ...MUT; }': () [173; 174) 'x': {unknown} [177; 189) 'LOCAL_STATIC': {unknown} @@ -1901,7 +1900,9 @@ fn test() { [229; 230) 'z': u32 [233; 246) 'GLOBAL_STATIC': u32 [256; 257) 'w': u32 -[260; 277) 'GLOBAL...IC_MUT': u32"### +[260; 277) 'GLOBAL...IC_MUT': u32 +[118; 120) '99': u32 +[161; 163) '99': u32"### ); } @@ -2350,25 +2351,11 @@ fn infer(content: &str) -> String { } }; - for const_def in source_file.syntax().descendants().filter_map(ast::ConstDef::cast) { - let konst = source_binder::const_from_source(&db, file_id, const_def).unwrap(); - let inference_result = konst.infer(&db); - let body_source_map = konst.body_source_map(&db); - infer_def(inference_result, body_source_map) - } - - for static_def in source_file.syntax().descendants().filter_map(ast::StaticDef::cast) { - let static_ = source_binder::static_from_source(&db, file_id, static_def).unwrap(); - let inference_result = static_.infer(&db); - let body_source_map = static_.body_source_map(&db); - infer_def(inference_result, body_source_map) - } - - for fn_def in source_file.syntax().descendants().filter_map(ast::FnDef::cast) { - let func = source_binder::function_from_source(&db, file_id, fn_def).unwrap(); - let inference_result = func.infer(&db); - let body_source_map = func.body_source_map(&db); - infer_def(inference_result, body_source_map) + for node in source_file.syntax().descendants() { + if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { + let analyzer = SourceAnalyzer::new(&db, file_id, node, None); + infer_def(analyzer.inference_result(), analyzer.body_source_map()); + } } acc.truncate(acc.trim_end().len()); -- cgit v1.2.3 From 81e91980dd87f62bdd9013f99101f6599f067e3b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 01:05:18 +0300 Subject: simplify --- crates/ra_hir/src/source_binder.rs | 76 +++++++++++--------------------------- 1 file changed, 22 insertions(+), 54 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c3cb17882..476cf117f 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -89,27 +89,6 @@ fn module_from_source( ) } -pub fn const_from_source( - db: &impl HirDatabase, - file_id: FileId, - const_def: &ast::ConstDef, -) -> Option { - let module = module_from_child_node(db, file_id, const_def.syntax())?; - let res = const_from_module(db, module, const_def); - Some(res) -} - -pub fn const_from_module( - db: &impl HirDatabase, - module: Module, - const_def: &ast::ConstDef, -) -> Const { - let (file_id, _) = module.definition_source(db); - let file_id = file_id.into(); - let ctx = LocationCtx::new(db, module, file_id); - Const { id: ctx.to_def(const_def) } -} - pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option { let file = db.parse(position.file_id); let fn_def = find_node_at_offset::(file.syntax(), position.offset)?; @@ -157,27 +136,6 @@ pub fn struct_from_module( Struct { id: ctx.to_def(struct_def) } } -pub fn static_from_source( - db: &impl HirDatabase, - file_id: FileId, - static_def: &ast::StaticDef, -) -> Option { - let module = module_from_child_node(db, file_id, static_def.syntax())?; - let res = static_from_module(db, module, static_def); - Some(res) -} - -pub fn static_from_module( - db: &impl HirDatabase, - module: Module, - static_def: &ast::StaticDef, -) -> Static { - let (file_id, _) = module.definition_source(db); - let file_id = file_id.into(); - let ctx = LocationCtx::new(db, module, file_id); - Static { id: ctx.to_def(static_def) } -} - pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum { let (file_id, _) = module.definition_source(db); let file_id = file_id.into(); @@ -246,6 +204,27 @@ fn try_get_resolver_for_node( } } +pub fn def_with_body_from_child_node( + db: &impl HirDatabase, + file_id: FileId, + node: &SyntaxNode, +) -> Option { + let module = module_from_child_node(db, file_id, node)?; + let ctx = LocationCtx::new(db, module, file_id.into()); + node.ancestors().find_map(|node| { + if let Some(def) = ast::FnDef::cast(node) { + return Some(Function { id: ctx.to_def(def) }.into()); + } + if let Some(def) = ast::ConstDef::cast(node) { + return Some(Const { id: ctx.to_def(def) }.into()); + } + if let Some(def) = ast::StaticDef::cast(node) { + return Some(Static { id: ctx.to_def(def) }.into()); + } + None + }) +} + /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of /// original source files. It should not be used inside the HIR itself. #[derive(Debug)] @@ -274,18 +253,7 @@ impl SourceAnalyzer { node: &SyntaxNode, offset: Option, ) -> SourceAnalyzer { - let def_with_body = node.ancestors().find_map(|node| { - if let Some(src) = ast::FnDef::cast(node) { - return function_from_source(db, file_id, src).map(DefWithBody::from); - } - if let Some(src) = ast::StaticDef::cast(node) { - return static_from_source(db, file_id, src).map(DefWithBody::from); - } - if let Some(src) = ast::ConstDef::cast(node) { - return const_from_source(db, file_id, src).map(DefWithBody::from); - } - None - }); + let def_with_body = def_with_body_from_child_node(db, file_id, node); SourceAnalyzer { resolver: resolver_for_node(db, file_id, node, offset), body_source_map: def_with_body.map(|it| it.body_source_map(db)), -- cgit v1.2.3 From b0d8f9ff5d2a64f93189543385485c5b48fb8d76 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 01:07:24 +0300 Subject: make stuff private --- crates/ra_hir/src/source_binder.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 476cf117f..8e1f29019 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -95,7 +95,7 @@ pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> function_from_source(db, position.file_id, fn_def) } -pub fn function_from_source( +fn function_from_source( db: &impl HirDatabase, file_id: FileId, fn_def: &ast::FnDef, @@ -105,11 +105,7 @@ pub fn function_from_source( Some(res) } -pub fn function_from_module( - db: &impl HirDatabase, - module: Module, - fn_def: &ast::FnDef, -) -> Function { +fn function_from_module(db: &impl HirDatabase, module: Module, fn_def: &ast::FnDef) -> Function { let (file_id, _) = module.definition_source(db); let file_id = file_id.into(); let ctx = LocationCtx::new(db, module, file_id); -- cgit v1.2.3 From 58fe5598e70eef6edf109865cb87b806b22536fb Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 01:32:43 +0300 Subject: simplify --- crates/ra_hir/src/source_binder.rs | 6 ------ crates/ra_hir/src/ty/tests.rs | 23 ++++++++++++----------- 2 files changed, 12 insertions(+), 17 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 8e1f29019..0d2746ac0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -89,12 +89,6 @@ fn module_from_source( ) } -pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option { - let file = db.parse(position.file_id); - let fn_def = find_node_at_offset::(file.syntax(), position.offset)?; - function_from_source(db, position.file_id, fn_def) -} - fn function_from_source( db: &impl HirDatabase, file_id: FileId, diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 87d6bcaec..d7c2ca132 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -8,7 +8,6 @@ use ra_syntax::{algo, ast::{self, AstNode}, SyntaxKind::*}; use test_utils::covers; use crate::{ - source_binder, mock::MockDatabase, ty::display::HirDisplay, ty::InferenceResult, @@ -2303,13 +2302,10 @@ fn test() -> u64 { } fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { - let func = source_binder::function_from_position(db, pos).unwrap(); - let body_source_map = func.body_source_map(db); - let inference_result = func.infer(db); - let (_, syntax) = func.source(db); - let node = algo::find_node_at_offset::(syntax.syntax(), pos.offset).unwrap(); - let expr = body_source_map.node_expr(node).unwrap(); - let ty = &inference_result[expr]; + let file = db.parse(pos.file_id); + let expr = algo::find_node_at_offset::(file.syntax(), pos.offset).unwrap(); + let analyzer = SourceAnalyzer::new(db, pos.file_id, expr.syntax(), Some(pos.offset)); + let ty = analyzer.type_of(db, expr).unwrap(); ty.display(db).to_string() } @@ -2390,10 +2386,12 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() { } ", ); - let func = source_binder::function_from_position(&db, pos).unwrap(); { + let file = db.parse(pos.file_id); + let node = + algo::find_token_at_offset(file.syntax(), pos.offset).right_biased().unwrap().parent(); let events = db.log_executed(|| { - func.infer(&db); + SourceAnalyzer::new(&db, pos.file_id, node, None); }); assert!(format!("{:?}", events).contains("infer")) } @@ -2410,8 +2408,11 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() { db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text)); { + let file = db.parse(pos.file_id); + let node = + algo::find_token_at_offset(file.syntax(), pos.offset).right_biased().unwrap().parent(); let events = db.log_executed(|| { - func.infer(&db); + SourceAnalyzer::new(&db, pos.file_id, node, None); }); assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) } -- cgit v1.2.3 From 3aae223d938e5a36d997c45a0f86cfcabf83b570 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:31:03 +0300 Subject: hide some scopes --- crates/ra_hir/src/expr/scope.rs | 7 +++++-- crates/ra_hir/src/source_binder.rs | 11 +++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 404c979eb..a9be9fbdb 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -173,7 +173,10 @@ impl ScopesWithSourceMap { .unwrap_or(original_scope) } - pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { + pub(crate) fn resolve_local_name( + &self, + name_ref: &ast::NameRef, + ) -> Option { let mut shadowed = FxHashSet::default(); let name = name_ref.as_name(); let ret = self @@ -190,7 +193,7 @@ impl ScopesWithSourceMap { }) } - pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { + pub(crate) fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); let ptr = Either::A(AstPtr::new(pat.into())); fn_def diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 0d2746ac0..bdb300311 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -17,6 +17,7 @@ use ra_syntax::{ use crate::{ HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, AsName, Module, HirFileId, Crate, Trait, Resolver, + expr::scope::{ReferenceDescriptor, ScopeEntryWithSyntax}, ids::LocationCtx, expr, AstId }; @@ -222,6 +223,7 @@ pub struct SourceAnalyzer { resolver: Resolver, body_source_map: Option>, infer: Option>, + scopes: Option, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -248,6 +250,7 @@ impl SourceAnalyzer { resolver: resolver_for_node(db, file_id, node, offset), body_source_map: def_with_body.map(|it| it.body_source_map(db)), infer: def_with_body.map(|it| it.infer(db)), + scopes: def_with_body.map(|it| it.scopes(db)), } } @@ -302,6 +305,14 @@ impl SourceAnalyzer { Some(res) } + pub fn find_all_refs(&self, pat: &ast::BindPat) -> Option> { + self.scopes.as_ref().map(|it| it.find_all_refs(pat)) + } + + pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { + self.scopes.as_ref()?.resolve_local_name(name_ref) + } + #[cfg(test)] pub(crate) fn body_source_map(&self) -> Arc { self.body_source_map.clone().unwrap() -- cgit v1.2.3 From 9ead801a9cc8a98e44cde96ed860da8db99576e6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:32:25 +0300 Subject: make private --- crates/ra_hir/src/source_binder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index bdb300311..bb638bcb6 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -107,7 +107,7 @@ fn function_from_module(db: &impl HirDatabase, module: Module, fn_def: &ast::FnD Function { id: ctx.to_def(fn_def) } } -pub fn function_from_child_node( +fn function_from_child_node( db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode, -- cgit v1.2.3 From 65b00736535255c089cfef58c7b4eb13d4d8dbad Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:33:34 +0300 Subject: simplify --- crates/ra_hir/src/source_binder.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index bb638bcb6..880596615 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -96,15 +96,9 @@ fn function_from_source( fn_def: &ast::FnDef, ) -> Option { let module = module_from_child_node(db, file_id, fn_def.syntax())?; - let res = function_from_module(db, module, fn_def); - Some(res) -} - -fn function_from_module(db: &impl HirDatabase, module: Module, fn_def: &ast::FnDef) -> Function { - let (file_id, _) = module.definition_source(db); let file_id = file_id.into(); let ctx = LocationCtx::new(db, module, file_id); - Function { id: ctx.to_def(fn_def) } + Some(Function { id: ctx.to_def(fn_def) }) } fn function_from_child_node( -- cgit v1.2.3 From 17a0e228833de16ed7e8718ba177dceeec4abfb2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:36:28 +0300 Subject: simplify --- crates/ra_hir/src/source_binder.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 880596615..649c5b684 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -101,15 +101,6 @@ fn function_from_source( Some(Function { id: ctx.to_def(fn_def) }) } -fn function_from_child_node( - db: &impl HirDatabase, - file_id: FileId, - node: &SyntaxNode, -) -> Option { - let fn_def = node.ancestors().find_map(ast::FnDef::cast)?; - function_from_source(db, file_id, fn_def) -} - pub fn struct_from_module( db: &impl HirDatabase, module: Module, @@ -148,7 +139,11 @@ fn resolver_for_node( node.ancestors() .find_map(|node| { if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { - if let Some(func) = function_from_child_node(db, file_id, node) { + if let Some(func) = node + .ancestors() + .find_map(ast::FnDef::cast) + .and_then(|it| function_from_source(db, file_id, it)) + { let scopes = func.scopes(db); let scope = match offset { None => scopes.scope_for(&node), -- cgit v1.2.3 From d88269bc2d36d163eef5173912c40d5b6eee3847 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:38:37 +0300 Subject: generalize --- crates/ra_hir/src/source_binder.rs | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 649c5b684..5bb6d64ff 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -139,21 +139,13 @@ fn resolver_for_node( node.ancestors() .find_map(|node| { if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { - if let Some(func) = node - .ancestors() - .find_map(ast::FnDef::cast) - .and_then(|it| function_from_source(db, file_id, it)) - { - let scopes = func.scopes(db); - let scope = match offset { - None => scopes.scope_for(&node), - Some(offset) => scopes.scope_for_offset(offset), - }; - Some(expr::resolver_for_scope(func.body(db), db, scope)) - } else { - // FIXME const/static/array length - None - } + let def = def_with_body_from_child_node(db, file_id, node)?; + let scopes = def.scopes(db); + let scope = match offset { + None => scopes.scope_for(&node), + Some(offset) => scopes.scope_for_offset(offset), + }; + Some(expr::resolver_for_scope(def.body(db), db, scope)) } else { try_get_resolver_for_node(db, file_id, node) } -- cgit v1.2.3 From d4043a8dbafe6de9517dee760967dd0218bf28b7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:45:52 +0300 Subject: only def-with-body remains --- crates/ra_hir/src/source_binder.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 5bb6d64ff..67bf2de89 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -12,6 +12,7 @@ use ra_syntax::{ SyntaxNode, AstPtr, TextUnit, ast::{self, AstNode, NameOwner}, algo::find_node_at_offset, + SyntaxKind::*, }; use crate::{ @@ -90,17 +91,6 @@ fn module_from_source( ) } -fn function_from_source( - db: &impl HirDatabase, - file_id: FileId, - fn_def: &ast::FnDef, -) -> Option { - let module = module_from_child_node(db, file_id, fn_def.syntax())?; - let file_id = file_id.into(); - let ctx = LocationCtx::new(db, module, file_id); - Some(Function { id: ctx.to_def(fn_def) }) -} - pub fn struct_from_module( db: &impl HirDatabase, module: Module, @@ -168,8 +158,8 @@ fn try_get_resolver_for_node( } else if let Some(e) = ast::EnumDef::cast(node) { let module = module_from_child_node(db, file_id, e.syntax())?; Some(enum_from_module(db, module, e).resolver(db)) - } else if let Some(f) = ast::FnDef::cast(node) { - function_from_source(db, file_id, f).map(|f| f.resolver(db)) + } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { + Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db)) } else { // FIXME add missing cases None -- cgit v1.2.3 From 1e8569dce9a7259208503a6819d0a93618ddcc45 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:46:39 +0300 Subject: make private --- crates/ra_hir/src/source_binder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 67bf2de89..1c9e9320d 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -166,7 +166,7 @@ fn try_get_resolver_for_node( } } -pub fn def_with_body_from_child_node( +fn def_with_body_from_child_node( db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode, -- cgit v1.2.3 From 30481808fbfea109f324dfaf93daaaebacc75333 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 09:53:02 +0300 Subject: make stuff private --- crates/ra_hir/src/expr/scope.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index a9be9fbdb..dcec51a10 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -110,7 +110,7 @@ impl ExprScopes { #[derive(Debug, Clone, PartialEq, Eq)] pub struct ScopesWithSourceMap { pub(crate) source_map: Arc, - pub scopes: Arc, + pub(crate) scopes: Arc, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -134,7 +134,7 @@ impl ScopesWithSourceMap { generate(self.scope_for(node), move |&scope| self.scopes.scopes[scope].parent) } - pub fn scope_for_offset(&self, offset: TextUnit) -> Option { + pub(crate) fn scope_for_offset(&self, offset: TextUnit) -> Option { self.scopes .scope_for .iter() @@ -211,7 +211,7 @@ impl ScopesWithSourceMap { .collect() } - pub fn scope_for(&self, node: &SyntaxNode) -> Option { + pub(crate) fn scope_for(&self, node: &SyntaxNode) -> Option { node.ancestors() .map(SyntaxNodePtr::new) .filter_map(|ptr| self.source_map.syntax_expr(ptr)) -- cgit v1.2.3 From f4a94e74bcd6c8f9275a57a775e64314af1878da Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 10:49:01 +0300 Subject: fold ScopeWithSyntax into SourceAnalyzer --- crates/ra_hir/src/code_model_api.rs | 14 +-- crates/ra_hir/src/expr.rs | 4 +- crates/ra_hir/src/expr/scope.rs | 166 ++++++------------------------------ crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/source_binder.rs | 162 +++++++++++++++++++++++++++-------- 5 files changed, 157 insertions(+), 191 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 5179f719d..882208ec1 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -4,7 +4,7 @@ use ra_db::{CrateId, SourceRootId, Edition}; use ra_syntax::{ast::self, TreeArc}; use crate::{ - Name, ScopesWithSourceMap, Ty, HirFileId, Either, + Name, Ty, HirFileId, Either, HirDatabase, DefDatabase, type_ref::TypeRef, nameres::{ModuleScope, Namespace, ImportId, CrateModuleId}, @@ -466,12 +466,6 @@ impl DefWithBody { DefWithBody::Static(ref s) => s.resolver(db), } } - - pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap { - let scopes = db.expr_scopes(*self); - let source_map = db.body_with_source_map(*self).1; - ScopesWithSourceMap { scopes, source_map } - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -535,12 +529,6 @@ impl Function { db.type_for_def((*self).into(), Namespace::Values) } - pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSourceMap { - let scopes = db.expr_scopes((*self).into()); - let source_map = db.body_with_source_map((*self).into()).1; - ScopesWithSourceMap { scopes, source_map } - } - pub fn signature(&self, db: &impl HirDatabase) -> Arc { db.fn_signature(*self) } diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 3806a3605..038a25a97 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -16,7 +16,7 @@ use crate::{ }; use crate::{ path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}}; -pub use self::scope::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}; +pub use self::scope::{ExprScopes, ScopeEntryWithSyntax}; pub(crate) mod scope; @@ -93,7 +93,7 @@ pub fn resolver_for_scope( ) -> Resolver { let mut r = body.owner.resolver(db); let scopes = db.expr_scopes(body.owner); - let scope_chain = scopes.scope_chain_for(scope_id).collect::>(); + let scope_chain = scopes.scope_chain(scope_id).collect::>(); for scope in scope_chain.into_iter().rev() { r = r.push_expr_scope(Arc::clone(&scopes), scope); } diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index dcec51a10..476385a2f 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -1,17 +1,16 @@ use std::sync::Arc; -use rustc_hash::{FxHashMap, FxHashSet}; - +use rustc_hash::{FxHashMap}; use ra_syntax::{ - AstNode, SyntaxNode, TextUnit, TextRange, SyntaxNodePtr, AstPtr, + TextRange, AstPtr, algo::generate, ast, }; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - Name, AsName,DefWithBody, Either, - expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySourceMap}, + Name, DefWithBody, Either, + expr::{PatId, ExprId, Pat, Expr, Body, Statement}, HirDatabase, }; @@ -23,7 +22,7 @@ impl_arena_id!(ScopeId); pub struct ExprScopes { body: Arc, scopes: Arena, - scope_for: FxHashMap, + pub(crate) scope_for: FxHashMap, } #[derive(Debug, PartialEq, Eq)] @@ -66,10 +65,7 @@ impl ExprScopes { &self.scopes[scope].entries } - pub fn scope_chain_for<'a>( - &'a self, - scope: Option, - ) -> impl Iterator + 'a { + pub fn scope_chain<'a>(&'a self, scope: Option) -> impl Iterator + 'a { generate(scope, move |&scope| self.scopes[scope].parent) } @@ -107,16 +103,10 @@ impl ExprScopes { } } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ScopesWithSourceMap { - pub(crate) source_map: Arc, - pub(crate) scopes: Arc, -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct ScopeEntryWithSyntax { - name: Name, - ptr: Either, AstPtr>, + pub(crate) name: Name, + pub(crate) ptr: Either, AstPtr>, } impl ScopeEntryWithSyntax { @@ -129,96 +119,6 @@ impl ScopeEntryWithSyntax { } } -impl ScopesWithSourceMap { - fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator + 'a { - generate(self.scope_for(node), move |&scope| self.scopes.scopes[scope].parent) - } - - pub(crate) fn scope_for_offset(&self, offset: TextUnit) -> Option { - self.scopes - .scope_for - .iter() - .filter_map(|(id, scope)| Some((self.source_map.expr_syntax(*id)?, scope))) - // find containing scope - .min_by_key(|(ptr, _scope)| { - (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) - }) - .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)) - } - - // XXX: during completion, cursor might be outside of any particular - // expression. Try to figure out the correct scope... - // FIXME: move this to source binder? - fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { - let r = ptr.range(); - let child_scopes = self - .scopes - .scope_for - .iter() - .filter_map(|(id, scope)| Some((self.source_map.expr_syntax(*id)?, scope))) - .map(|(ptr, scope)| (ptr.range(), scope)) - .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r); - - child_scopes - .max_by(|(r1, _), (r2, _)| { - if r2.is_subrange(&r1) { - std::cmp::Ordering::Greater - } else if r1.is_subrange(&r2) { - std::cmp::Ordering::Less - } else { - r1.start().cmp(&r2.start()) - } - }) - .map(|(_ptr, scope)| *scope) - .unwrap_or(original_scope) - } - - pub(crate) fn resolve_local_name( - &self, - name_ref: &ast::NameRef, - ) -> Option { - let mut shadowed = FxHashSet::default(); - let name = name_ref.as_name(); - let ret = self - .scope_chain(name_ref.syntax()) - .flat_map(|scope| self.scopes.entries(scope).iter()) - .filter(|entry| shadowed.insert(entry.name())) - .filter(|entry| entry.name() == &name) - .nth(0); - ret.and_then(|entry| { - Some(ScopeEntryWithSyntax { - name: entry.name().clone(), - ptr: self.source_map.pat_syntax(entry.pat())?, - }) - }) - } - - pub(crate) fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { - let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); - let ptr = Either::A(AstPtr::new(pat.into())); - fn_def - .syntax() - .descendants() - .filter_map(ast::NameRef::cast) - .filter(|name_ref| match self.resolve_local_name(*name_ref) { - None => false, - Some(entry) => entry.ptr() == ptr, - }) - .map(|name_ref| ReferenceDescriptor { - name: name_ref.syntax().text().to_string(), - range: name_ref.syntax().range(), - }) - .collect() - } - - pub(crate) fn scope_for(&self, node: &SyntaxNode) -> Option { - node.ancestors() - .map(SyntaxNodePtr::new) - .filter_map(|ptr| self.source_map.syntax_expr(ptr)) - .find_map(|it| self.scopes.scope_for(it)) - } -} - impl ScopeEntry { pub fn name(&self) -> &Name { &self.name @@ -297,12 +197,11 @@ pub struct ReferenceDescriptor { #[cfg(test)] mod tests { - use ra_db::salsa::InternKey; - use ra_syntax::{SourceFile, algo::find_node_at_offset}; + use ra_db::SourceDatabase; + use ra_syntax::{algo::find_node_at_offset, AstNode, SyntaxNodePtr}; use test_utils::{extract_offset, assert_eq_text}; - use crate::Function; - use crate::expr::{ExprCollector}; + use crate::{source_binder::SourceAnalyzer, mock::MockDatabase}; use super::*; @@ -316,18 +215,20 @@ mod tests { buf.push_str(&code[off..]); buf }; - let file = SourceFile::parse(&code); + + let (db, _source_root, file_id) = MockDatabase::with_single_file(&code); + let file = db.parse(file_id); let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); - let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); - let irrelevant_function = - Function { id: crate::ids::FunctionId::from_intern_id(0u32.into()) }; - let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def); - let scopes = ExprScopes::new(Arc::new(body)); - let scopes = - ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) }; + let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); + + let scopes = analyzer.scopes(); + let expr_id = + analyzer.body_source_map().syntax_expr(SyntaxNodePtr::new(marker.syntax())).unwrap(); + let scope = scopes.scope_for(expr_id); + let actual = scopes - .scope_chain(marker.syntax()) - .flat_map(|scope| scopes.scopes.entries(scope)) + .scope_chain(scope) + .flat_map(|scope| scopes.entries(scope)) .map(|it| it.name().to_string()) .collect::>() .join("\n"); @@ -410,28 +311,17 @@ mod tests { ); } - fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> (Body, BodySourceMap) { - let mut collector = ExprCollector::new(DefWithBody::Function(function)); - collector.collect_fn_body(node); - collector.finish() - } - fn do_check_local_name(code: &str, expected_offset: u32) { let (off, code) = extract_offset(code); - let file = SourceFile::parse(&code); + + let (db, _source_root, file_id) = MockDatabase::with_single_file(&code); + let file = db.parse(file_id); let expected_name = find_node_at_offset::(file.syntax(), expected_offset.into()) .expect("failed to find a name at the target offset"); - - let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); + let analyzer = SourceAnalyzer::new(&db, file_id, name_ref.syntax(), None); - let irrelevant_function = - Function { id: crate::ids::FunctionId::from_intern_id(0u32.into()) }; - let (body, source_map) = collect_fn_body_syntax(irrelevant_function, fn_def); - let scopes = ExprScopes::new(Arc::new(body)); - let scopes = - ScopesWithSourceMap { scopes: Arc::new(scopes), source_map: Arc::new(source_map) }; - let local_name_entry = scopes.resolve_local_name(name_ref).unwrap(); + let local_name_entry = analyzer.resolve_local_name(name_ref).unwrap(); let local_name = local_name_entry.ptr().either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); assert_eq!(local_name.range(), expected_name.syntax().range()); diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 3ca810a8b..eb2aa0e6c 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -64,7 +64,7 @@ pub use self::{ impl_block::{ImplBlock, ImplItem}, docs::{Docs, Documentation}, adt::AdtDef, - expr::{ExprScopes, ScopesWithSourceMap, ScopeEntryWithSyntax}, + expr::{ExprScopes, ScopeEntryWithSyntax}, resolve::{Resolver, Resolution}, source_binder::{SourceAnalyzer, PathResolution}, }; diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 1c9e9320d..d87f8ff34 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -7,9 +7,10 @@ /// purely for "IDE needs". use std::sync::Arc; +use rustc_hash::FxHashSet; use ra_db::{FileId, FilePosition}; use ra_syntax::{ - SyntaxNode, AstPtr, TextUnit, + SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, ast::{self, AstNode, NameOwner}, algo::find_node_at_offset, SyntaxKind::*, @@ -18,7 +19,7 @@ use ra_syntax::{ use crate::{ HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, AsName, Module, HirFileId, Crate, Trait, Resolver, - expr::scope::{ReferenceDescriptor, ScopeEntryWithSyntax}, + expr::{BodySourceMap, scope::{ReferenceDescriptor, ScopeEntryWithSyntax, ScopeId, ExprScopes}}, ids::LocationCtx, expr, AstId }; @@ -120,29 +121,6 @@ pub fn trait_from_module( Trait { id: ctx.to_def(trait_def) } } -fn resolver_for_node( - db: &impl HirDatabase, - file_id: FileId, - node: &SyntaxNode, - offset: Option, -) -> Resolver { - node.ancestors() - .find_map(|node| { - if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { - let def = def_with_body_from_child_node(db, file_id, node)?; - let scopes = def.scopes(db); - let scope = match offset { - None => scopes.scope_for(&node), - Some(offset) => scopes.scope_for_offset(offset), - }; - Some(expr::resolver_for_scope(def.body(db), db, scope)) - } else { - try_get_resolver_for_node(db, file_id, node) - } - }) - .unwrap_or_default() -} - fn try_get_resolver_for_node( db: &impl HirDatabase, file_id: FileId, @@ -192,9 +170,9 @@ fn def_with_body_from_child_node( #[derive(Debug)] pub struct SourceAnalyzer { resolver: Resolver, - body_source_map: Option>, + body_source_map: Option>, infer: Option>, - scopes: Option, + scopes: Option>, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -217,11 +195,30 @@ impl SourceAnalyzer { offset: Option, ) -> SourceAnalyzer { let def_with_body = def_with_body_from_child_node(db, file_id, node); - SourceAnalyzer { - resolver: resolver_for_node(db, file_id, node, offset), - body_source_map: def_with_body.map(|it| it.body_source_map(db)), - infer: def_with_body.map(|it| it.infer(db)), - scopes: def_with_body.map(|it| it.scopes(db)), + if let Some(def) = def_with_body { + let source_map = def.body_source_map(db); + let scopes = db.expr_scopes(def); + let scope = match offset { + None => scope_for(&scopes, &source_map, &node), + Some(offset) => scope_for_offset(&scopes, &source_map, offset), + }; + let resolver = expr::resolver_for_scope(def.body(db), db, scope); + SourceAnalyzer { + resolver, + body_source_map: Some(source_map), + infer: Some(def.infer(db)), + scopes: Some(scopes), + } + } else { + SourceAnalyzer { + resolver: node + .ancestors() + .find_map(|node| try_get_resolver_for_node(db, file_id, node)) + .unwrap_or_default(), + body_source_map: None, + infer: None, + scopes: None, + } } } @@ -276,16 +273,46 @@ impl SourceAnalyzer { Some(res) } - pub fn find_all_refs(&self, pat: &ast::BindPat) -> Option> { - self.scopes.as_ref().map(|it| it.find_all_refs(pat)) + pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { + let mut shadowed = FxHashSet::default(); + let name = name_ref.as_name(); + let source_map = self.body_source_map.as_ref()?; + let scopes = self.scopes.as_ref()?; + let scope = scope_for(scopes, source_map, name_ref.syntax()); + let ret = scopes + .scope_chain(scope) + .flat_map(|scope| scopes.entries(scope).iter()) + .filter(|entry| shadowed.insert(entry.name())) + .filter(|entry| entry.name() == &name) + .nth(0); + ret.and_then(|entry| { + Some(ScopeEntryWithSyntax { + name: entry.name().clone(), + ptr: source_map.pat_syntax(entry.pat())?, + }) + }) } - pub fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { - self.scopes.as_ref()?.resolve_local_name(name_ref) + pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { + let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); + let ptr = Either::A(AstPtr::new(pat.into())); + fn_def + .syntax() + .descendants() + .filter_map(ast::NameRef::cast) + .filter(|name_ref| match self.resolve_local_name(*name_ref) { + None => false, + Some(entry) => entry.ptr() == ptr, + }) + .map(|name_ref| ReferenceDescriptor { + name: name_ref.syntax().text().to_string(), + range: name_ref.syntax().range(), + }) + .collect() } #[cfg(test)] - pub(crate) fn body_source_map(&self) -> Arc { + pub(crate) fn body_source_map(&self) -> Arc { self.body_source_map.clone().unwrap() } @@ -293,4 +320,65 @@ impl SourceAnalyzer { pub(crate) fn inference_result(&self) -> Arc { self.infer.clone().unwrap() } + + #[cfg(test)] + pub(crate) fn scopes(&self) -> Arc { + self.scopes.clone().unwrap() + } +} + +fn scope_for( + scopes: &ExprScopes, + source_map: &BodySourceMap, + node: &SyntaxNode, +) -> Option { + node.ancestors() + .map(SyntaxNodePtr::new) + .filter_map(|ptr| source_map.syntax_expr(ptr)) + .find_map(|it| scopes.scope_for(it)) +} + +fn scope_for_offset( + scopes: &ExprScopes, + source_map: &BodySourceMap, + offset: TextUnit, +) -> Option { + scopes + .scope_for + .iter() + .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope))) + // find containing scope + .min_by_key(|(ptr, _scope)| { + (!(ptr.range().start() <= offset && offset <= ptr.range().end()), ptr.range().len()) + }) + .map(|(ptr, scope)| adjust(scopes, source_map, ptr, offset).unwrap_or(*scope)) +} + +// XXX: during completion, cursor might be outside of any particular +// expression. Try to figure out the correct scope... +fn adjust( + scopes: &ExprScopes, + source_map: &BodySourceMap, + ptr: SyntaxNodePtr, + offset: TextUnit, +) -> Option { + let r = ptr.range(); + let child_scopes = scopes + .scope_for + .iter() + .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope))) + .map(|(ptr, scope)| (ptr.range(), scope)) + .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r); + + child_scopes + .max_by(|(r1, _), (r2, _)| { + if r2.is_subrange(&r1) { + std::cmp::Ordering::Greater + } else if r1.is_subrange(&r2) { + std::cmp::Ordering::Less + } else { + r1.start().cmp(&r2.start()) + } + }) + .map(|(_ptr, scope)| *scope) } -- cgit v1.2.3 From 62d01dd4dfc8feb52c006b84f9d1a1a7142cc060 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:00:15 +0300 Subject: hide resolver --- crates/ra_hir/src/source_binder.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index d87f8ff34..b5e2f86be 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -7,7 +7,7 @@ /// purely for "IDE needs". use std::sync::Arc; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashSet, FxHashMap}; use ra_db::{FileId, FilePosition}; use ra_syntax::{ SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, @@ -17,7 +17,7 @@ use ra_syntax::{ }; use crate::{ - HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, + HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name, AsName, Module, HirFileId, Crate, Trait, Resolver, expr::{BodySourceMap, scope::{ReferenceDescriptor, ScopeEntryWithSyntax, ScopeId, ExprScopes}}, ids::LocationCtx, @@ -222,10 +222,6 @@ impl SourceAnalyzer { } } - pub fn resolver(&self) -> &Resolver { - &self.resolver - } - pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option { let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?; Some(self.infer.as_ref()?[expr_id].clone()) @@ -246,6 +242,18 @@ impl SourceAnalyzer { self.infer.as_ref()?.field_resolution(expr_id) } + pub fn resolve_hir_path( + &self, + db: &impl HirDatabase, + path: &crate::Path, + ) -> PerNs { + self.resolver.resolve_path(db, path) + } + + pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap> { + self.resolver.all_names(db) + } + pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option { if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { let expr_id = self.body_source_map.as_ref()?.node_expr(path_expr.into())?; -- cgit v1.2.3 From a2cc76ce63c3449d33d4a2261392e452df1d31b1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:02:23 +0300 Subject: make resolver private --- crates/ra_hir/src/code_model_api.rs | 16 ++++++++-------- crates/ra_hir/src/expr.rs | 8 ++++++-- crates/ra_hir/src/impl_block.rs | 2 +- crates/ra_hir/src/lib.rs | 3 ++- crates/ra_hir/src/resolve.rs | 18 +++++------------- crates/ra_hir/src/ty/method_resolution.rs | 2 +- 6 files changed, 23 insertions(+), 26 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 882208ec1..5d8cf57b6 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -189,7 +189,7 @@ impl Module { } } - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { let def_map = db.crate_def_map(self.krate); Resolver::default().push_module_scope(def_map, self.module_id) } @@ -313,7 +313,7 @@ impl Struct { // FIXME move to a more general type /// Builds a resolver for type references inside this struct. - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { // take the outer scope... let r = self.module(db).resolver(db); // ...and add generic params, if present @@ -373,7 +373,7 @@ impl Enum { // FIXME: move to a more general type /// Builds a resolver for type references inside this struct. - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { // take the outer scope... let r = self.module(db).resolver(db); // ...and add generic params, if present @@ -459,7 +459,7 @@ impl DefWithBody { } /// Builds a resolver for code inside this item. - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { match *self { DefWithBody::Const(ref c) => c.resolver(db), DefWithBody::Function(ref f) => f.resolver(db), @@ -549,7 +549,7 @@ impl Function { // FIXME: move to a more general type for 'body-having' items /// Builds a resolver for code inside this item. - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { // take the outer scope... let r = self .impl_block(db) @@ -602,7 +602,7 @@ impl Const { // FIXME: move to a more general type for 'body-having' items /// Builds a resolver for code inside this item. - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { // take the outer scope... let r = self .impl_block(db) @@ -654,7 +654,7 @@ impl Static { } /// Builds a resolver for code inside this item. - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { // take the outer scope... self.module(db).resolver(db) } @@ -736,7 +736,7 @@ impl TypeAlias { } /// Builds a resolver for the type references in this type alias. - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { // take the outer scope... let r = self .impl_block(db) diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 038a25a97..239874792 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -81,12 +81,16 @@ impl Body { } // needs arbitrary_self_types to be a method... or maybe move to the def? -pub fn resolver_for_expr(body: Arc, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { +pub(crate) fn resolver_for_expr( + body: Arc, + db: &impl HirDatabase, + expr_id: ExprId, +) -> Resolver { let scopes = db.expr_scopes(body.owner); resolver_for_scope(body, db, scopes.scope_for(expr_id)) } -pub fn resolver_for_scope( +pub(crate) fn resolver_for_scope( body: Arc, db: &impl HirDatabase, scope_id: Option, diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 40d368cd9..b306874cc 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -105,7 +105,7 @@ impl ImplBlock { db.generic_params((*self).into()) } - pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { + pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { let r = self.module().resolver(db); // add generic params, if present let p = self.generic_params(db); diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index eb2aa0e6c..5eb2f32bd 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -51,6 +51,7 @@ use crate::{ db::{HirDatabase, DefDatabase}, name::{AsName, KnownName}, source_id::{FileAstId, AstId}, + resolve::Resolver, }; pub use self::{ @@ -65,7 +66,7 @@ pub use self::{ docs::{Docs, Documentation}, adt::AdtDef, expr::{ExprScopes, ScopeEntryWithSyntax}, - resolve::{Resolver, Resolution}, + resolve::Resolution, source_binder::{SourceAnalyzer, PathResolution}, }; diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 2609585b1..685f4b8b1 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs @@ -9,13 +9,13 @@ use crate::{ name::{Name, KnownName}, nameres::{PerNs, CrateDefMap, CrateModuleId}, generics::GenericParams, - expr::{scope::{ExprScopes, ScopeId}, PatId, Body}, + expr::{scope::{ExprScopes, ScopeId}, PatId}, impl_block::ImplBlock, path::Path, Trait }; #[derive(Debug, Clone, Default)] -pub struct Resolver { +pub(crate) struct Resolver { scopes: Vec, } @@ -117,7 +117,7 @@ pub enum Resolution { } impl Resolver { - pub fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs { + pub(crate) fn resolve_name(&self, db: &impl HirDatabase, name: &Name) -> PerNs { let mut resolution = PerNs::none(); for scope in self.scopes.iter().rev() { resolution = resolution.or(scope.resolve_name(db, name)); @@ -154,12 +154,12 @@ impl Resolver { /// Returns the fully resolved path if we were able to resolve it. /// otherwise returns `PerNs::none` - pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs { + pub(crate) fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs { // into_fully_resolved() returns the fully resolved path or PerNs::none() otherwise self.resolve_path_segments(db, path).into_fully_resolved() } - pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap> { + pub(crate) fn all_names(&self, db: &impl HirDatabase) -> FxHashMap> { let mut names = FxHashMap::default(); for scope in self.scopes.iter().rev() { scope.collect_names(db, &mut |name, res| { @@ -197,14 +197,6 @@ impl Resolver { _ => None, }) } - - /// The body from which any `LocalBinding` resolutions in this resolver come. - pub fn body(&self) -> Option> { - self.scopes.iter().rev().find_map(|scope| match scope { - Scope::ExprScope(expr_scope) => Some(expr_scope.expr_scopes.body()), - _ => None, - }) - } } impl Resolver { diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 3ac8dc46b..bb23246a6 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -135,7 +135,7 @@ fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option { impl Ty { /// Look up the method with the given name, returning the actual autoderefed /// receiver type (but without autoref applied yet). - pub fn lookup_method( + pub(crate) fn lookup_method( self, db: &impl HirDatabase, name: &Name, -- cgit v1.2.3 From 4f8dc1b9f0fd544b0565dc95bb3f14478aa467bf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:06:53 +0300 Subject: make expr scope stuff private --- crates/ra_hir/src/expr/scope.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 476385a2f..4ac797eb7 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use rustc_hash::{FxHashMap}; use ra_syntax::{ TextRange, AstPtr, - algo::generate, ast, }; use ra_arena::{Arena, RawId, impl_arena_id}; @@ -26,13 +25,13 @@ pub struct ExprScopes { } #[derive(Debug, PartialEq, Eq)] -pub struct ScopeEntry { +pub(crate) struct ScopeEntry { name: Name, pat: PatId, } #[derive(Debug, PartialEq, Eq)] -pub struct ScopeData { +pub(crate) struct ScopeData { parent: Option, entries: Vec, } @@ -57,16 +56,15 @@ impl ExprScopes { scopes } - pub fn body(&self) -> Arc { - self.body.clone() - } - - pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { + pub(crate) fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { &self.scopes[scope].entries } - pub fn scope_chain<'a>(&'a self, scope: Option) -> impl Iterator + 'a { - generate(scope, move |&scope| self.scopes[scope].parent) + pub(crate) fn scope_chain<'a>( + &'a self, + scope: Option, + ) -> impl Iterator + 'a { + std::iter::successors(scope, move |&scope| self.scopes[scope].parent) } fn root_scope(&mut self) -> ScopeId { @@ -98,7 +96,7 @@ impl ExprScopes { self.scope_for.insert(node, scope); } - pub fn scope_for(&self, expr: ExprId) -> Option { + pub(crate) fn scope_for(&self, expr: ExprId) -> Option { self.scope_for.get(&expr).map(|&scope| scope) } } -- cgit v1.2.3 From d387bdccba2b5bb681e5b6c84cc1b0efe5c1a79a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:21:32 +0300 Subject: drop obsolete fixme --- crates/ra_hir/src/expr/scope.rs | 1 - crates/ra_hir/src/source_binder.rs | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 4ac797eb7..6a6de5772 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -37,7 +37,6 @@ pub(crate) struct ScopeData { } impl ExprScopes { - // FIXME: This should take something more general than Function pub(crate) fn expr_scopes_query(db: &impl HirDatabase, def: DefWithBody) -> Arc { let body = db.body_hir(def); let res = ExprScopes::new(body); diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index b5e2f86be..a50287339 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -250,10 +250,6 @@ impl SourceAnalyzer { self.resolver.resolve_path(db, path) } - pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap> { - self.resolver.all_names(db) - } - pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option { if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { let expr_id = self.body_source_map.as_ref()?.node_expr(path_expr.into())?; @@ -301,6 +297,10 @@ impl SourceAnalyzer { }) } + pub fn all_names(&self, db: &impl HirDatabase) -> FxHashMap> { + self.resolver.all_names(db) + } + pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); let ptr = Either::A(AstPtr::new(pat.into())); -- cgit v1.2.3 From f9e825d95624129b66c34f25904f6ae46b9d5760 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:24:09 +0300 Subject: move ScopeEntryWithSyntax --- crates/ra_hir/src/expr.rs | 4 ++-- crates/ra_hir/src/expr/scope.rs | 45 +++++++++++--------------------------- crates/ra_hir/src/lib.rs | 4 ++-- crates/ra_hir/src/source_binder.rs | 18 ++++++++++++++- 4 files changed, 34 insertions(+), 37 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 239874792..817e660f9 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -14,9 +14,9 @@ use crate::{ name::AsName, type_ref::{Mutability, TypeRef}, }; -use crate::{ path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}}; +use crate::{path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}}; -pub use self::scope::{ExprScopes, ScopeEntryWithSyntax}; +pub use self::scope::ExprScopes; pub(crate) mod scope; diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 6a6de5772..090343d12 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -1,14 +1,11 @@ use std::sync::Arc; -use rustc_hash::{FxHashMap}; -use ra_syntax::{ - TextRange, AstPtr, - ast, -}; +use rustc_hash::FxHashMap; +use ra_syntax::TextRange; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - Name, DefWithBody, Either, + Name, DefWithBody, expr::{PatId, ExprId, Pat, Expr, Body, Statement}, HirDatabase, }; @@ -30,6 +27,16 @@ pub(crate) struct ScopeEntry { pat: PatId, } +impl ScopeEntry { + pub(crate) fn name(&self) -> &Name { + &self.name + } + + pub(crate) fn pat(&self) -> PatId { + self.pat + } +} + #[derive(Debug, PartialEq, Eq)] pub(crate) struct ScopeData { parent: Option, @@ -100,32 +107,6 @@ impl ExprScopes { } } -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ScopeEntryWithSyntax { - pub(crate) name: Name, - pub(crate) ptr: Either, AstPtr>, -} - -impl ScopeEntryWithSyntax { - pub fn name(&self) -> &Name { - &self.name - } - - pub fn ptr(&self) -> Either, AstPtr> { - self.ptr - } -} - -impl ScopeEntry { - pub fn name(&self) -> &Name { - &self.name - } - - pub fn pat(&self) -> PatId { - self.pat - } -} - fn compute_block_scopes( statements: &[Statement], tail: Option, diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 5eb2f32bd..a9db23060 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -65,9 +65,9 @@ pub use self::{ impl_block::{ImplBlock, ImplItem}, docs::{Docs, Documentation}, adt::AdtDef, - expr::{ExprScopes, ScopeEntryWithSyntax}, + expr::ExprScopes, resolve::Resolution, - source_binder::{SourceAnalyzer, PathResolution}, + source_binder::{SourceAnalyzer, PathResolution, ScopeEntryWithSyntax}, }; pub use self::code_model_api::{ diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index a50287339..34a00a300 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -19,7 +19,7 @@ use ra_syntax::{ use crate::{ HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name, AsName, Module, HirFileId, Crate, Trait, Resolver, - expr::{BodySourceMap, scope::{ReferenceDescriptor, ScopeEntryWithSyntax, ScopeId, ExprScopes}}, + expr::{BodySourceMap, scope::{ReferenceDescriptor, ScopeId, ExprScopes}}, ids::LocationCtx, expr, AstId }; @@ -187,6 +187,22 @@ pub enum PathResolution { AssocItem(crate::ImplItem), } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ScopeEntryWithSyntax { + pub(crate) name: Name, + pub(crate) ptr: Either, AstPtr>, +} + +impl ScopeEntryWithSyntax { + pub fn name(&self) -> &Name { + &self.name + } + + pub fn ptr(&self) -> Either, AstPtr> { + self.ptr + } +} + impl SourceAnalyzer { pub fn new( db: &impl HirDatabase, -- cgit v1.2.3 From b260641e0caa3938151afe66fa3bf5691b8c3caa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:29:47 +0300 Subject: slight encapsulation --- crates/ra_hir/src/expr/scope.rs | 18 +++++++++++------- crates/ra_hir/src/source_binder.rs | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 090343d12..7f53f23aa 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -18,7 +18,7 @@ impl_arena_id!(ScopeId); pub struct ExprScopes { body: Arc, scopes: Arena, - pub(crate) scope_for: FxHashMap, + scope_by_expr: FxHashMap, } #[derive(Debug, PartialEq, Eq)] @@ -54,7 +54,7 @@ impl ExprScopes { let mut scopes = ExprScopes { body: body.clone(), scopes: Arena::default(), - scope_for: FxHashMap::default(), + scope_by_expr: FxHashMap::default(), }; let root = scopes.root_scope(); scopes.add_params_bindings(root, body.params()); @@ -73,6 +73,14 @@ impl ExprScopes { std::iter::successors(scope, move |&scope| self.scopes[scope].parent) } + pub(crate) fn scope_for(&self, expr: ExprId) -> Option { + self.scope_by_expr.get(&expr).map(|&scope| scope) + } + + pub(crate) fn scope_by_expr(&self) -> &FxHashMap { + &self.scope_by_expr + } + fn root_scope(&mut self) -> ScopeId { self.scopes.alloc(ScopeData { parent: None, entries: vec![] }) } @@ -99,11 +107,7 @@ impl ExprScopes { } fn set_scope(&mut self, node: ExprId, scope: ScopeId) { - self.scope_for.insert(node, scope); - } - - pub(crate) fn scope_for(&self, expr: ExprId) -> Option { - self.scope_for.get(&expr).map(|&scope| scope) + self.scope_by_expr.insert(node, scope); } } diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 34a00a300..8d53079c6 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -368,7 +368,7 @@ fn scope_for_offset( offset: TextUnit, ) -> Option { scopes - .scope_for + .scope_by_expr() .iter() .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope))) // find containing scope @@ -388,7 +388,7 @@ fn adjust( ) -> Option { let r = ptr.range(); let child_scopes = scopes - .scope_for + .scope_by_expr() .iter() .filter_map(|(id, scope)| Some((source_map.expr_syntax(*id)?, scope))) .map(|(ptr, scope)| (ptr.range(), scope)) -- cgit v1.2.3 From 2facb5e061971afbf6bd2fabe3966d5de9d46489 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 13 Apr 2019 11:32:58 +0300 Subject: cleanups --- crates/ra_hir/src/expr/scope.rs | 11 +---------- crates/ra_hir/src/source_binder.rs | 14 +++++++++++--- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index 7f53f23aa..58f365128 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs @@ -1,7 +1,6 @@ use std::sync::Arc; use rustc_hash::FxHashMap; -use ra_syntax::TextRange; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ @@ -171,22 +170,14 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope }; } -#[derive(Debug)] -pub struct ReferenceDescriptor { - pub range: TextRange, - pub name: String, -} - #[cfg(test)] mod tests { use ra_db::SourceDatabase; - use ra_syntax::{algo::find_node_at_offset, AstNode, SyntaxNodePtr}; + use ra_syntax::{algo::find_node_at_offset, AstNode, SyntaxNodePtr, ast}; use test_utils::{extract_offset, assert_eq_text}; use crate::{source_binder::SourceAnalyzer, mock::MockDatabase}; - use super::*; - fn do_check(code: &str, expected: &[&str]) { let (off, code) = extract_offset(code); let code = { diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 8d53079c6..bd035ced9 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use rustc_hash::{FxHashSet, FxHashMap}; use ra_db::{FileId, FilePosition}; use ra_syntax::{ - SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, + SyntaxNode, AstPtr, TextUnit, SyntaxNodePtr, TextRange, ast::{self, AstNode, NameOwner}, algo::find_node_at_offset, SyntaxKind::*, @@ -19,7 +19,7 @@ use ra_syntax::{ use crate::{ HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name, AsName, Module, HirFileId, Crate, Trait, Resolver, - expr::{BodySourceMap, scope::{ReferenceDescriptor, ScopeId, ExprScopes}}, + expr::{BodySourceMap, scope::{ScopeId, ExprScopes}}, ids::LocationCtx, expr, AstId }; @@ -203,6 +203,12 @@ impl ScopeEntryWithSyntax { } } +#[derive(Debug)] +pub struct ReferenceDescriptor { + pub range: TextRange, + pub name: String, +} + impl SourceAnalyzer { pub fn new( db: &impl HirDatabase, @@ -318,6 +324,8 @@ impl SourceAnalyzer { } pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { + // FIXME: at least, this should work with any DefWithBody, but ideally + // this should be hir-based altogether let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); let ptr = Either::A(AstPtr::new(pat.into())); fn_def @@ -329,7 +337,7 @@ impl SourceAnalyzer { Some(entry) => entry.ptr() == ptr, }) .map(|name_ref| ReferenceDescriptor { - name: name_ref.syntax().text().to_string(), + name: name_ref.text().to_string(), range: name_ref.syntax().range(), }) .collect() -- cgit v1.2.3