From 24ab3e80ca258a3db21bf263225c52d9995a2ea0 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 10 Feb 2020 00:22:12 +0200 Subject: Resolve methods and functions better --- crates/ra_hir/src/source_analyzer.rs | 60 ++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 6 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index bb9a35c5d..49e1a10e0 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs @@ -20,7 +20,10 @@ use hir_def::{ use hir_expand::{ hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, }; -use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; +use hir_ty::{ + method_resolution::{iterate_method_candidates, LookupMode}, + Canonical, InEnvironment, InferenceResult, TraitEnvironment, +}; use ra_syntax::{ ast::{self, AstNode}, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit, @@ -28,8 +31,8 @@ use ra_syntax::{ use rustc_hash::FxHashSet; use crate::{ - db::HirDatabase, Adt, Const, DefWithBody, EnumVariant, Function, Local, MacroDef, Name, Path, - ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, + db::HirDatabase, Adt, AssocItem, Const, DefWithBody, EnumVariant, Function, Local, MacroDef, + ModuleDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, }; /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of @@ -289,9 +292,11 @@ impl SourceAnalyzer { 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.expr_id(&path_expr.into())?; - if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { - return Some(PathResolution::AssocItem(assoc.into())); + let path_resolution = self + .resolve_as_full_path(path_expr.clone()) + .or_else(|| self.resolve_as_path_to_method(db, &path_expr)); + if path_resolution.is_some() { + return path_resolution; } } if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { @@ -305,6 +310,49 @@ impl SourceAnalyzer { self.resolve_hir_path(db, &hir_path) } + fn resolve_as_full_path(&self, path_expr: ast::PathExpr) -> Option { + let expr_id = self.expr_id(&path_expr.into())?; + self.infer + .as_ref()? + .assoc_resolutions_for_expr(expr_id) + .map(|assoc| PathResolution::AssocItem(assoc.into())) + } + + fn resolve_as_path_to_method( + &self, + db: &impl HirDatabase, + path_expr: &ast::PathExpr, + ) -> Option { + let full_path = path_expr.path()?; + let path_to_method = full_path.qualifier()?; + let method_name = full_path.segment()?.syntax().to_string(); + match self.resolve_path(db, &path_to_method)? { + PathResolution::Def(ModuleDef::Adt(adt)) => { + let ty = adt.ty(db); + iterate_method_candidates( + &Canonical { value: ty.ty.value, num_vars: 0 }, + db, + ty.ty.environment, + self.resolver.krate()?, + &self.resolver.traits_in_scope(db), + None, + LookupMode::Path, + |_, assoc_item_id| { + let assoc = assoc_item_id.into(); + if let AssocItem::Function(function) = assoc { + if function.name(db).to_string() == method_name { + return Some(assoc); + } + } + None + }, + ) + } + _ => None, + } + .map(PathResolution::AssocItem) + } + fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { let name = name_ref.as_name(); let source_map = self.body_source_map.as_ref()?; -- cgit v1.2.3 From 8f959f20ee0fecd644054ffed334c378f9ae20f5 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 11 Feb 2020 15:21:12 +0200 Subject: Trait location draft --- crates/ra_hir/src/code_model.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 4fb679f6d..73158b8bd 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -123,7 +123,7 @@ impl_froms!( ); pub use hir_def::{ - attr::Attrs, item_scope::ItemInNs, visibility::Visibility, AssocItemId, AssocItemLoc, + attr::Attrs, item_scope::ItemInNs, visibility::Visibility, AssocContainerId, AssocItemId, }; use rustc_hash::FxHashSet; @@ -696,16 +696,12 @@ impl AssocItem { AssocItem::TypeAlias(t) => t.module(db), } } - pub fn container(self, db: &impl DefDatabase) -> AssocItemContainer { - let container = match self { - AssocItem::Function(it) => it.id.lookup(db).container, - AssocItem::Const(it) => it.id.lookup(db).container, - AssocItem::TypeAlias(it) => it.id.lookup(db).container, - }; - match container { - AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()), - AssocContainerId::ImplId(id) => AssocItemContainer::ImplBlock(id.into()), - AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"), + + pub fn container(self, db: &impl DefDatabase) -> AssocContainerId { + match self { + AssocItem::Function(f) => f.id.lookup(db).container, + AssocItem::Const(c) => c.id.lookup(db).container, + AssocItem::TypeAlias(t) => t.id.lookup(db).container, } } } -- cgit v1.2.3 From d5c3808545e26d246d75e0754e81de803f9e53e6 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 11 Feb 2020 18:24:43 +0200 Subject: Support trait method call autoimports --- crates/ra_hir/src/code_model.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 73158b8bd..140b3a87f 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -548,6 +548,10 @@ impl Function { let mut validator = ExprValidator::new(self.id, infer, sink); validator.validate_body(db); } + + pub fn container(self, db: &impl DefDatabase) -> AssocContainerId { + self.id.lookup(db).container + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -699,7 +703,7 @@ impl AssocItem { pub fn container(self, db: &impl DefDatabase) -> AssocContainerId { match self { - AssocItem::Function(f) => f.id.lookup(db).container, + AssocItem::Function(f) => f.container(db), AssocItem::Const(c) => c.id.lookup(db).container, AssocItem::TypeAlias(t) => t.id.lookup(db).container, } -- cgit v1.2.3 From afc1d18ff3e060a4107d7a17623a5e84f6c6c86e Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 12 Feb 2020 17:18:29 +0200 Subject: Fix post-rebase issues --- crates/ra_hir/src/code_model.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 140b3a87f..cf3b04511 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -123,7 +123,7 @@ impl_froms!( ); pub use hir_def::{ - attr::Attrs, item_scope::ItemInNs, visibility::Visibility, AssocContainerId, AssocItemId, + attr::Attrs, item_scope::ItemInNs, visibility::Visibility, AssocItemId, AssocItemLoc, }; use rustc_hash::FxHashSet; @@ -548,10 +548,6 @@ impl Function { let mut validator = ExprValidator::new(self.id, infer, sink); validator.validate_body(db); } - - pub fn container(self, db: &impl DefDatabase) -> AssocContainerId { - self.id.lookup(db).container - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -701,11 +697,16 @@ impl AssocItem { } } - pub fn container(self, db: &impl DefDatabase) -> AssocContainerId { - match self { - AssocItem::Function(f) => f.container(db), - AssocItem::Const(c) => c.id.lookup(db).container, - AssocItem::TypeAlias(t) => t.id.lookup(db).container, + pub fn container(self, db: &impl DefDatabase) -> AssocItemContainer { + let container = match self { + AssocItem::Function(it) => it.id.lookup(db).container, + AssocItem::Const(it) => it.id.lookup(db).container, + AssocItem::TypeAlias(it) => it.id.lookup(db).container, + }; + match container { + AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()), + AssocContainerId::ImplId(id) => AssocItemContainer::ImplBlock(id.into()), + AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"), } } } @@ -818,7 +819,7 @@ impl TypeParam { } } -// FIXME: rename to `ImplBlock` +// FIXME: rename from `ImplBlock` to `Impl` #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ImplBlock { pub(crate) id: ImplId, -- cgit v1.2.3 From f65daf23dfb14677d6b23557e4356aec6fdee065 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 12 Feb 2020 17:34:17 +0200 Subject: Revert source_analyzer changes --- crates/ra_hir/src/code_model.rs | 1 - crates/ra_hir/src/source_analyzer.rs | 60 ++++-------------------------------- 2 files changed, 6 insertions(+), 55 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index cf3b04511..a56b8ab04 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -696,7 +696,6 @@ impl AssocItem { AssocItem::TypeAlias(t) => t.module(db), } } - pub fn container(self, db: &impl DefDatabase) -> AssocItemContainer { let container = match self { AssocItem::Function(it) => it.id.lookup(db).container, diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 49e1a10e0..bb9a35c5d 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs @@ -20,10 +20,7 @@ use hir_def::{ use hir_expand::{ hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, }; -use hir_ty::{ - method_resolution::{iterate_method_candidates, LookupMode}, - Canonical, InEnvironment, InferenceResult, TraitEnvironment, -}; +use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; use ra_syntax::{ ast::{self, AstNode}, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit, @@ -31,8 +28,8 @@ use ra_syntax::{ use rustc_hash::FxHashSet; use crate::{ - db::HirDatabase, Adt, AssocItem, Const, DefWithBody, EnumVariant, Function, Local, MacroDef, - ModuleDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, + db::HirDatabase, Adt, Const, DefWithBody, EnumVariant, Function, Local, MacroDef, Name, Path, + ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, }; /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of @@ -292,11 +289,9 @@ impl SourceAnalyzer { 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 path_resolution = self - .resolve_as_full_path(path_expr.clone()) - .or_else(|| self.resolve_as_path_to_method(db, &path_expr)); - if path_resolution.is_some() { - return path_resolution; + let expr_id = self.expr_id(&path_expr.into())?; + if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { + return Some(PathResolution::AssocItem(assoc.into())); } } if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { @@ -310,49 +305,6 @@ impl SourceAnalyzer { self.resolve_hir_path(db, &hir_path) } - fn resolve_as_full_path(&self, path_expr: ast::PathExpr) -> Option { - let expr_id = self.expr_id(&path_expr.into())?; - self.infer - .as_ref()? - .assoc_resolutions_for_expr(expr_id) - .map(|assoc| PathResolution::AssocItem(assoc.into())) - } - - fn resolve_as_path_to_method( - &self, - db: &impl HirDatabase, - path_expr: &ast::PathExpr, - ) -> Option { - let full_path = path_expr.path()?; - let path_to_method = full_path.qualifier()?; - let method_name = full_path.segment()?.syntax().to_string(); - match self.resolve_path(db, &path_to_method)? { - PathResolution::Def(ModuleDef::Adt(adt)) => { - let ty = adt.ty(db); - iterate_method_candidates( - &Canonical { value: ty.ty.value, num_vars: 0 }, - db, - ty.ty.environment, - self.resolver.krate()?, - &self.resolver.traits_in_scope(db), - None, - LookupMode::Path, - |_, assoc_item_id| { - let assoc = assoc_item_id.into(); - if let AssocItem::Function(function) = assoc { - if function.name(db).to_string() == method_name { - return Some(assoc); - } - } - None - }, - ) - } - _ => None, - } - .map(PathResolution::AssocItem) - } - fn resolve_local_name(&self, name_ref: &ast::NameRef) -> Option { let name = name_ref.as_name(); let source_map = self.body_source_map.as_ref()?; -- cgit v1.2.3