From c3a4c4429de83450654795534e64e878a774a088 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 18 Feb 2020 18:35:10 +0100 Subject: Refactor primary IDE API This introduces the new type -- Semantics. Semantics maps SyntaxNodes to various semantic info, such as type, name resolution or macro expansions. To do so, Semantics maintains a HashMap which maps every node it saw to the file from which the node originated. This is enough to get all the necessary hir bits just from syntax. --- crates/ra_assists/src/assist_ctx.rs | 40 ++++--------- crates/ra_assists/src/ast_transform.rs | 65 ++++++++++------------ .../ra_assists/src/handlers/add_explicit_type.rs | 5 +- .../src/handlers/add_missing_impl_members.rs | 29 ++++------ crates/ra_assists/src/handlers/add_new.rs | 11 +--- crates/ra_assists/src/handlers/auto_import.rs | 42 +++++--------- crates/ra_assists/src/handlers/fill_match_arms.rs | 23 +++----- .../src/handlers/inline_local_variable.rs | 3 +- crates/ra_assists/src/lib.rs | 11 +++- crates/ra_assists/src/utils.rs | 24 ++++---- 10 files changed, 100 insertions(+), 153 deletions(-) (limited to 'crates/ra_assists') diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 5aab5fb8b..c25d2e323 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -1,6 +1,6 @@ //! This module defines `AssistCtx` -- the API surface that is exposed to assists. -use hir::{InFile, SourceAnalyzer, SourceBinder}; -use ra_db::{FileRange, SourceDatabase}; +use hir::Semantics; +use ra_db::FileRange; use ra_fmt::{leading_indent, reindent}; use ra_ide_db::RootDatabase; use ra_syntax::{ @@ -74,29 +74,23 @@ pub(crate) type AssistHandler = fn(AssistCtx) -> Option; /// Note, however, that we don't actually use such two-phase logic at the /// moment, because the LSP API is pretty awkward in this place, and it's much /// easier to just compute the edit eagerly :-) -#[derive(Debug)] +#[derive(Clone)] pub(crate) struct AssistCtx<'a> { + pub(crate) sema: &'a Semantics<'a, RootDatabase>, pub(crate) db: &'a RootDatabase, pub(crate) frange: FileRange, source_file: SourceFile, should_compute_edit: bool, } -impl Clone for AssistCtx<'_> { - fn clone(&self) -> Self { - AssistCtx { - db: self.db, - frange: self.frange, - source_file: self.source_file.clone(), - should_compute_edit: self.should_compute_edit, - } - } -} - impl<'a> AssistCtx<'a> { - pub fn new(db: &RootDatabase, frange: FileRange, should_compute_edit: bool) -> AssistCtx { - let parse = db.parse(frange.file_id); - AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit } + pub fn new( + sema: &'a Semantics<'a, RootDatabase>, + frange: FileRange, + should_compute_edit: bool, + ) -> AssistCtx<'a> { + let source_file = sema.parse(frange.file_id); + AssistCtx { sema, db: sema.db, frange, source_file, should_compute_edit } } pub(crate) fn add_assist( @@ -138,18 +132,6 @@ impl<'a> AssistCtx<'a> { pub(crate) fn covering_element(&self) -> SyntaxElement { find_covering_element(self.source_file.syntax(), self.frange.range) } - pub(crate) fn source_binder(&self) -> SourceBinder<'a, RootDatabase> { - SourceBinder::new(self.db) - } - pub(crate) fn source_analyzer( - &self, - node: &SyntaxNode, - offset: Option, - ) -> SourceAnalyzer { - let src = InFile::new(self.frange.file_id.into(), node); - self.source_binder().analyze(src, offset) - } - pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { find_covering_element(self.source_file.syntax(), range) } diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs index c6d15af5f..7846e9798 100644 --- a/crates/ra_assists/src/ast_transform.rs +++ b/crates/ra_assists/src/ast_transform.rs @@ -1,15 +1,12 @@ //! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined. use rustc_hash::FxHashMap; -use hir::{InFile, PathResolution}; +use hir::{PathResolution, SemanticsScope}; use ra_ide_db::RootDatabase; use ra_syntax::ast::{self, AstNode}; pub trait AstTransform<'a> { - fn get_substitution( - &self, - node: InFile<&ra_syntax::SyntaxNode>, - ) -> Option; + fn get_substitution(&self, node: &ra_syntax::SyntaxNode) -> Option; fn chain_before(self, other: Box + 'a>) -> Box + 'a>; fn or + 'a>(self, other: T) -> Box + 'a> @@ -23,10 +20,7 @@ pub trait AstTransform<'a> { struct NullTransformer; impl<'a> AstTransform<'a> for NullTransformer { - fn get_substitution( - &self, - _node: InFile<&ra_syntax::SyntaxNode>, - ) -> Option { + fn get_substitution(&self, _node: &ra_syntax::SyntaxNode) -> Option { None } fn chain_before(self, other: Box + 'a>) -> Box + 'a> { @@ -35,14 +29,16 @@ impl<'a> AstTransform<'a> for NullTransformer { } pub struct SubstituteTypeParams<'a> { - db: &'a RootDatabase, + source_scope: &'a SemanticsScope<'a, RootDatabase>, substs: FxHashMap, previous: Box + 'a>, } impl<'a> SubstituteTypeParams<'a> { pub fn for_trait_impl( + source_scope: &'a SemanticsScope<'a, RootDatabase>, db: &'a RootDatabase, + // FIXME: there's implicit invariant that `trait_` and `source_scope` match... trait_: hir::Trait, impl_block: ast::ImplBlock, ) -> SubstituteTypeParams<'a> { @@ -56,7 +52,7 @@ impl<'a> SubstituteTypeParams<'a> { .zip(substs.into_iter()) .collect(); return SubstituteTypeParams { - db, + source_scope, substs: substs_by_param, previous: Box::new(NullTransformer), }; @@ -80,15 +76,15 @@ impl<'a> SubstituteTypeParams<'a> { } fn get_substitution_inner( &self, - node: InFile<&ra_syntax::SyntaxNode>, + node: &ra_syntax::SyntaxNode, ) -> Option { - let type_ref = ast::TypeRef::cast(node.value.clone())?; + let type_ref = ast::TypeRef::cast(node.clone())?; let path = match &type_ref { ast::TypeRef::PathType(path_type) => path_type.path()?, _ => return None, }; - let analyzer = hir::SourceAnalyzer::new(self.db, node, None); - let resolution = analyzer.resolve_path(self.db, &path)?; + let path = hir::Path::from_ast(path)?; + let resolution = self.source_scope.resolve_hir_path(&path)?; match resolution { hir::PathResolution::TypeParam(tp) => Some(self.substs.get(&tp)?.syntax().clone()), _ => None, @@ -97,10 +93,7 @@ impl<'a> SubstituteTypeParams<'a> { } impl<'a> AstTransform<'a> for SubstituteTypeParams<'a> { - fn get_substitution( - &self, - node: InFile<&ra_syntax::SyntaxNode>, - ) -> Option { + fn get_substitution(&self, node: &ra_syntax::SyntaxNode) -> Option { self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node)) } fn chain_before(self, other: Box + 'a>) -> Box + 'a> { @@ -109,29 +102,34 @@ impl<'a> AstTransform<'a> for SubstituteTypeParams<'a> { } pub struct QualifyPaths<'a> { + target_scope: &'a SemanticsScope<'a, RootDatabase>, + source_scope: &'a SemanticsScope<'a, RootDatabase>, db: &'a RootDatabase, - from: Option, previous: Box + 'a>, } impl<'a> QualifyPaths<'a> { - pub fn new(db: &'a RootDatabase, from: Option) -> Self { - Self { db, from, previous: Box::new(NullTransformer) } + pub fn new( + target_scope: &'a SemanticsScope<'a, RootDatabase>, + source_scope: &'a SemanticsScope<'a, RootDatabase>, + db: &'a RootDatabase, + ) -> Self { + Self { target_scope, source_scope, db, previous: Box::new(NullTransformer) } } fn get_substitution_inner( &self, - node: InFile<&ra_syntax::SyntaxNode>, + node: &ra_syntax::SyntaxNode, ) -> Option { // FIXME handle value ns? - let from = self.from?; - let p = ast::Path::cast(node.value.clone())?; + let from = self.target_scope.module()?; + let p = ast::Path::cast(node.clone())?; if p.segment().and_then(|s| s.param_list()).is_some() { // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway return None; } - let analyzer = hir::SourceAnalyzer::new(self.db, node, None); - let resolution = analyzer.resolve_path(self.db, &p)?; + let hir_path = hir::Path::from_ast(p.clone()); + let resolution = self.source_scope.resolve_hir_path(&hir_path?)?; match resolution { PathResolution::Def(def) => { let found_path = from.find_use_path(self.db, def)?; @@ -140,7 +138,7 @@ impl<'a> QualifyPaths<'a> { let type_args = p .segment() .and_then(|s| s.type_arg_list()) - .map(|arg_list| apply(self, node.with_value(arg_list))); + .map(|arg_list| apply(self, arg_list)); if let Some(type_args) = type_args { let last_segment = path.segment().unwrap(); path = path.with_segment(last_segment.with_type_args(type_args)) @@ -157,11 +155,11 @@ impl<'a> QualifyPaths<'a> { } } -pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: InFile) -> N { - let syntax = node.value.syntax(); +pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N { + let syntax = node.syntax(); let result = ra_syntax::algo::replace_descendants(syntax, &|element| match element { ra_syntax::SyntaxElement::Node(n) => { - let replacement = transformer.get_substitution(node.with_value(&n))?; + let replacement = transformer.get_substitution(&n)?; Some(replacement.into()) } _ => None, @@ -170,10 +168,7 @@ pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: InFile } impl<'a> AstTransform<'a> for QualifyPaths<'a> { - fn get_substitution( - &self, - node: InFile<&ra_syntax::SyntaxNode>, - ) -> Option { + fn get_substitution(&self, node: &ra_syntax::SyntaxNode) -> Option { self.get_substitution_inner(node).or_else(|| self.previous.get_substitution(node)) } fn chain_before(self, other: Box + 'a>) -> Box + 'a> { diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index 2cb9d2f48..a63ef48b1 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs @@ -51,14 +51,13 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option { } } // Infer type - let db = ctx.db; - let analyzer = ctx.source_analyzer(stmt.syntax(), None); - let ty = analyzer.type_of(db, &expr)?; + let ty = ctx.sema.type_of_expr(&expr)?; // Assist not applicable if the type is unknown if ty.contains_unknown() { return None; } + let db = ctx.db; ctx.add_assist( AssistId("add_explicit_type"), format!("Insert explicit type '{}'", ty.display(db)), diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index ab21388c8..4005014bd 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs @@ -1,4 +1,4 @@ -use hir::{HasSource, InFile}; +use hir::HasSource; use ra_syntax::{ ast::{self, edit, make, AstNode, NameOwner}, SmolStr, @@ -104,9 +104,7 @@ fn add_missing_impl_members_inner( let impl_node = ctx.find_node_at_offset::()?; let impl_item_list = impl_node.item_list()?; - let analyzer = ctx.source_analyzer(impl_node.syntax(), None); - - let trait_ = resolve_target_trait(ctx.db, &analyzer, &impl_node)?; + let trait_ = resolve_target_trait(&ctx.sema, &impl_node)?; let def_name = |item: &ast::ImplItem| -> Option { match item { @@ -117,7 +115,7 @@ fn add_missing_impl_members_inner( .map(|it| it.text().clone()) }; - let missing_items = get_missing_impl_items(ctx.db, &analyzer, &impl_node) + let missing_items = get_missing_impl_items(&ctx.sema, &impl_node) .iter() .map(|i| match i { hir::AssocItem::Function(i) => ast::ImplItem::FnDef(i.source(ctx.db).value), @@ -138,23 +136,17 @@ fn add_missing_impl_members_inner( return None; } - let db = ctx.db; - let file_id = ctx.frange.file_id; - let trait_file_id = trait_.source(db).file_id; + let sema = ctx.sema; ctx.add_assist(AssistId(assist_id), label, |edit| { let n_existing_items = impl_item_list.impl_items().count(); - let module = hir::SourceAnalyzer::new( - db, - hir::InFile::new(file_id.into(), impl_node.syntax()), - None, - ) - .module(); - let ast_transform = QualifyPaths::new(db, module) - .or(SubstituteTypeParams::for_trait_impl(db, trait_, impl_node)); + let source_scope = sema.scope_for_def(trait_); + let target_scope = sema.scope(impl_item_list.syntax()); + let ast_transform = QualifyPaths::new(&target_scope, &source_scope, sema.db) + .or(SubstituteTypeParams::for_trait_impl(&source_scope, sema.db, trait_, impl_node)); let items = missing_items .into_iter() - .map(|it| ast_transform::apply(&*ast_transform, InFile::new(trait_file_id, it))) + .map(|it| ast_transform::apply(&*ast_transform, it)) .map(|it| match it { ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), _ => it, @@ -181,9 +173,10 @@ fn add_body(fn_def: ast::FnDef) -> ast::FnDef { #[cfg(test)] mod tests { - use super::*; use crate::helpers::{check_assist, check_assist_not_applicable}; + use super::*; + #[test] fn test_add_missing_impl_members() { check_assist( diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index dd070e8ec..166e907fb 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs @@ -1,5 +1,5 @@ use format_buf::format; -use hir::{Adt, InFile}; +use hir::Adt; use join_to_string::join; use ra_syntax::{ ast::{ @@ -133,16 +133,11 @@ fn find_struct_impl(ctx: &AssistCtx, strukt: &ast::StructDef) -> Option; impl S {}` // (we currently use the wrong type parameter) diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs index c4aea2a06..edf0cf6d0 100644 --- a/crates/ra_assists/src/handlers/auto_import.rs +++ b/crates/ra_assists/src/handlers/auto_import.rs @@ -3,8 +3,8 @@ use crate::{ insert_use_statement, AssistId, }; use hir::{ - db::HirDatabase, AsAssocItem, AssocItemContainer, ModPath, Module, ModuleDef, PathResolution, - SourceAnalyzer, Trait, Type, + AsAssocItem, AssocItemContainer, ModPath, Module, ModuleDef, PathResolution, Semantics, Trait, + Type, }; use ra_ide_db::{imports_locator::ImportsLocator, RootDatabase}; use ra_prof::profile; @@ -78,14 +78,9 @@ impl AutoImportAssets { fn for_method_call(method_call: ast::MethodCallExpr, ctx: &AssistCtx) -> Option { let syntax_under_caret = method_call.syntax().to_owned(); - let source_analyzer = ctx.source_analyzer(&syntax_under_caret, None); - let module_with_name_to_import = source_analyzer.module()?; + let module_with_name_to_import = ctx.sema.scope(&syntax_under_caret).module()?; Some(Self { - import_candidate: ImportCandidate::for_method_call( - &method_call, - &source_analyzer, - ctx.db, - )?, + import_candidate: ImportCandidate::for_method_call(&ctx.sema, &method_call)?, module_with_name_to_import, syntax_under_caret, }) @@ -97,14 +92,9 @@ impl AutoImportAssets { return None; } - let source_analyzer = ctx.source_analyzer(&syntax_under_caret, None); - let module_with_name_to_import = source_analyzer.module()?; + let module_with_name_to_import = ctx.sema.scope(&syntax_under_caret).module()?; Some(Self { - import_candidate: ImportCandidate::for_regular_path( - &path_under_caret, - &source_analyzer, - ctx.db, - )?, + import_candidate: ImportCandidate::for_regular_path(&ctx.sema, &path_under_caret)?, module_with_name_to_import, syntax_under_caret, }) @@ -229,25 +219,23 @@ enum ImportCandidate { impl ImportCandidate { fn for_method_call( + sema: &Semantics, method_call: &ast::MethodCallExpr, - source_analyzer: &SourceAnalyzer, - db: &impl HirDatabase, ) -> Option { - if source_analyzer.resolve_method_call(method_call).is_some() { + if sema.resolve_method_call(method_call).is_some() { return None; } Some(Self::TraitMethod( - source_analyzer.type_of(db, &method_call.expr()?)?, + sema.type_of_expr(&method_call.expr()?)?, method_call.name_ref()?.syntax().to_string(), )) } fn for_regular_path( + sema: &Semantics, path_under_caret: &ast::Path, - source_analyzer: &SourceAnalyzer, - db: &impl HirDatabase, ) -> Option { - if source_analyzer.resolve_path(db, path_under_caret).is_some() { + if sema.resolve_path(path_under_caret).is_some() { return None; } @@ -256,17 +244,15 @@ impl ImportCandidate { let qualifier_start = qualifier.syntax().descendants().find_map(ast::NameRef::cast)?; let qualifier_start_path = qualifier_start.syntax().ancestors().find_map(ast::Path::cast)?; - if let Some(qualifier_start_resolution) = - source_analyzer.resolve_path(db, &qualifier_start_path) - { + if let Some(qualifier_start_resolution) = sema.resolve_path(&qualifier_start_path) { let qualifier_resolution = if qualifier_start_path == qualifier { qualifier_start_resolution } else { - source_analyzer.resolve_path(db, &qualifier)? + sema.resolve_path(&qualifier)? }; if let PathResolution::Def(ModuleDef::Adt(assoc_item_path)) = qualifier_resolution { Some(ImportCandidate::TraitAssocItem( - assoc_item_path.ty(db), + assoc_item_path.ty(sema.db), segment.syntax().to_string(), )) } else { diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs index ae2437ed3..e5d8c639d 100644 --- a/crates/ra_assists/src/handlers/fill_match_arms.rs +++ b/crates/ra_assists/src/handlers/fill_match_arms.rs @@ -2,10 +2,11 @@ use std::iter; -use hir::{db::HirDatabase, Adt, HasSource}; +use hir::{db::HirDatabase, Adt, HasSource, Semantics}; use ra_syntax::ast::{self, edit::IndentLevel, make, AstNode, NameOwner}; use crate::{Assist, AssistCtx, AssistId}; +use ra_ide_db::RootDatabase; // Assist: fill_match_arms // @@ -46,10 +47,9 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option { }; let expr = match_expr.expr()?; - let (enum_def, module) = { - let analyzer = ctx.source_analyzer(expr.syntax(), None); - (resolve_enum_def(ctx.db, &analyzer, &expr)?, analyzer.module()?) - }; + let enum_def = resolve_enum_def(&ctx.sema, &expr)?; + let module = ctx.sema.scope(expr.syntax()).module()?; + let variants = enum_def.variants(ctx.db); if variants.is_empty() { return None; @@ -81,18 +81,11 @@ fn is_trivial(arm: &ast::MatchArm) -> bool { } } -fn resolve_enum_def( - db: &impl HirDatabase, - analyzer: &hir::SourceAnalyzer, - expr: &ast::Expr, -) -> Option { - let expr_ty = analyzer.type_of(db, &expr)?; - - let result = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() { +fn resolve_enum_def(sema: &Semantics, expr: &ast::Expr) -> Option { + sema.type_of_expr(&expr)?.autoderef(sema.db).find_map(|ty| match ty.as_adt() { Some(Adt::Enum(e)) => Some(e), _ => None, - }); - result + }) } fn build_pat( diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index 91b588243..53a72309b 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs @@ -44,8 +44,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option { } else { let_stmt.syntax().text_range() }; - let analyzer = ctx.source_analyzer(bind_pat.syntax(), None); - let refs = analyzer.find_all_refs(&bind_pat); + let refs = ctx.sema.find_all_refs(&bind_pat); if refs.is_empty() { return None; }; diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 79fe43aa4..c28a9b92b 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -19,6 +19,7 @@ use ra_text_edit::TextEdit; pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler}; pub use crate::handlers::replace_qualified_name_with_use::insert_use_statement; +use hir::Semantics; /// Unique identifier of the assist, should not be shown to the user /// directly. @@ -63,7 +64,8 @@ pub struct ResolvedAssist { /// Assists are returned in the "unresolved" state, that is only labels are /// returned, without actual edits. pub fn unresolved_assists(db: &RootDatabase, range: FileRange) -> Vec { - let ctx = AssistCtx::new(db, range, false); + let sema = Semantics::new(db); + let ctx = AssistCtx::new(&sema, range, false); handlers::all() .iter() .filter_map(|f| f(ctx.clone())) @@ -77,7 +79,8 @@ pub fn unresolved_assists(db: &RootDatabase, range: FileRange) -> Vec Vec { - let ctx = AssistCtx::new(db, range, true); + let sema = Semantics::new(db); + let ctx = AssistCtx::new(&sema, range, true); let mut a = handlers::all() .iter() .filter_map(|f| f(ctx.clone())) @@ -165,6 +168,7 @@ mod helpers { use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset}; use crate::{AssistCtx, AssistHandler}; + use hir::Semantics; pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { let (mut db, file_id) = RootDatabase::with_single_file(text); @@ -202,7 +206,8 @@ mod helpers { let (db, file_id) = with_single_file(&before); let frange = FileRange { file_id, range }; - let assist_ctx = AssistCtx::new(&db, frange, true); + let sema = Semantics::new(&db); + let assist_ctx = AssistCtx::new(&sema, frange, true); match (assist(assist_ctx), expected) { (Some(assist), ExpectedResult::After(after)) => { diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index 6ff44c95c..92d3ed471 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs @@ -1,16 +1,15 @@ //! Assorted functions shared by several assists. +use hir::Semantics; +use ra_ide_db::RootDatabase; use ra_syntax::{ ast::{self, make, NameOwner}, AstNode, T, }; - -use hir::db::HirDatabase; use rustc_hash::FxHashSet; pub fn get_missing_impl_items( - db: &impl HirDatabase, - analyzer: &hir::SourceAnalyzer, + sema: &Semantics, impl_block: &ast::ImplBlock, ) -> Vec { // Names must be unique between constants and functions. However, type aliases @@ -42,15 +41,17 @@ pub fn get_missing_impl_items( } } - resolve_target_trait(db, analyzer, impl_block).map_or(vec![], |target_trait| { + resolve_target_trait(sema, impl_block).map_or(vec![], |target_trait| { target_trait - .items(db) + .items(sema.db) .iter() .filter(|i| match i { - hir::AssocItem::Function(f) => !impl_fns_consts.contains(&f.name(db).to_string()), - hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(db).to_string()), + hir::AssocItem::Function(f) => { + !impl_fns_consts.contains(&f.name(sema.db).to_string()) + } + hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(sema.db).to_string()), hir::AssocItem::Const(c) => c - .name(db) + .name(sema.db) .map(|n| !impl_fns_consts.contains(&n.to_string())) .unwrap_or_default(), }) @@ -60,8 +61,7 @@ pub fn get_missing_impl_items( } pub(crate) fn resolve_target_trait( - db: &impl HirDatabase, - analyzer: &hir::SourceAnalyzer, + sema: &Semantics, impl_block: &ast::ImplBlock, ) -> Option { let ast_path = impl_block @@ -70,7 +70,7 @@ pub(crate) fn resolve_target_trait( .and_then(ast::PathType::cast)? .path()?; - match analyzer.resolve_path(db, &ast_path) { + match sema.resolve_path(&ast_path) { Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def), _ => None, } -- cgit v1.2.3