From 6742f38e49d001359a7a9911becc0fcae4c67910 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 16 Jan 2021 19:33:36 +0200 Subject: Share import_assets and related entities --- crates/assists/src/utils/import_assets.rs | 265 ------------------------------ 1 file changed, 265 deletions(-) delete mode 100644 crates/assists/src/utils/import_assets.rs (limited to 'crates/assists/src/utils/import_assets.rs') diff --git a/crates/assists/src/utils/import_assets.rs b/crates/assists/src/utils/import_assets.rs deleted file mode 100644 index 4ce82c1ba..000000000 --- a/crates/assists/src/utils/import_assets.rs +++ /dev/null @@ -1,265 +0,0 @@ -//! Look up accessible paths for items. -use either::Either; -use hir::{AsAssocItem, AssocItemContainer, ModuleDef, Semantics}; -use ide_db::{imports_locator, RootDatabase}; -use rustc_hash::FxHashSet; -use syntax::{ast, AstNode, SyntaxNode}; - -use crate::assist_config::InsertUseConfig; - -#[derive(Debug)] -pub(crate) enum ImportCandidate { - /// Simple name like 'HashMap' - UnqualifiedName(PathImportCandidate), - /// First part of the qualified name. - /// For 'std::collections::HashMap', that will be 'std'. - QualifierStart(PathImportCandidate), - /// A trait associated function (with no self parameter) or associated constant. - /// For 'test_mod::TestEnum::test_function', `ty` is the `test_mod::TestEnum` expression type - /// and `name` is the `test_function` - TraitAssocItem(TraitImportCandidate), - /// A trait method with self parameter. - /// For 'test_enum.test_method()', `ty` is the `test_enum` expression type - /// and `name` is the `test_method` - TraitMethod(TraitImportCandidate), -} - -#[derive(Debug)] -pub(crate) struct TraitImportCandidate { - pub(crate) ty: hir::Type, - pub(crate) name: ast::NameRef, -} - -#[derive(Debug)] -pub(crate) struct PathImportCandidate { - pub(crate) name: ast::NameRef, -} - -#[derive(Debug)] -pub(crate) struct ImportAssets { - import_candidate: ImportCandidate, - module_with_name_to_import: hir::Module, - syntax_under_caret: SyntaxNode, -} - -impl ImportAssets { - pub(crate) fn for_method_call( - method_call: ast::MethodCallExpr, - sema: &Semantics, - ) -> Option { - let syntax_under_caret = method_call.syntax().to_owned(); - let module_with_name_to_import = sema.scope(&syntax_under_caret).module()?; - Some(Self { - import_candidate: ImportCandidate::for_method_call(sema, &method_call)?, - module_with_name_to_import, - syntax_under_caret, - }) - } - - pub(crate) fn for_regular_path( - path_under_caret: ast::Path, - sema: &Semantics, - ) -> Option { - let syntax_under_caret = path_under_caret.syntax().to_owned(); - if syntax_under_caret.ancestors().find_map(ast::Use::cast).is_some() { - return None; - } - - let module_with_name_to_import = sema.scope(&syntax_under_caret).module()?; - Some(Self { - import_candidate: ImportCandidate::for_regular_path(sema, &path_under_caret)?, - module_with_name_to_import, - syntax_under_caret, - }) - } - - pub(crate) fn syntax_under_caret(&self) -> &SyntaxNode { - &self.syntax_under_caret - } - - pub(crate) fn import_candidate(&self) -> &ImportCandidate { - &self.import_candidate - } - - fn get_search_query(&self) -> &str { - match &self.import_candidate { - ImportCandidate::UnqualifiedName(candidate) - | ImportCandidate::QualifierStart(candidate) => candidate.name.text(), - ImportCandidate::TraitAssocItem(candidate) - | ImportCandidate::TraitMethod(candidate) => candidate.name.text(), - } - } - - pub(crate) fn search_for_imports( - &self, - sema: &Semantics, - config: &InsertUseConfig, - ) -> Vec<(hir::ModPath, hir::ItemInNs)> { - let _p = profile::span("import_assists::search_for_imports"); - self.search_for(sema, Some(config.prefix_kind)) - } - - /// This may return non-absolute paths if a part of the returned path is already imported into scope. - #[allow(dead_code)] - pub(crate) fn search_for_relative_paths( - &self, - sema: &Semantics, - ) -> Vec<(hir::ModPath, hir::ItemInNs)> { - let _p = profile::span("import_assists::search_for_relative_paths"); - self.search_for(sema, None) - } - - fn search_for( - &self, - sema: &Semantics, - prefixed: Option, - ) -> Vec<(hir::ModPath, hir::ItemInNs)> { - let db = sema.db; - let mut trait_candidates = FxHashSet::default(); - let current_crate = self.module_with_name_to_import.krate(); - - let filter = |candidate: Either| { - trait_candidates.clear(); - match &self.import_candidate { - ImportCandidate::TraitAssocItem(trait_candidate) => { - let located_assoc_item = match candidate { - Either::Left(ModuleDef::Function(located_function)) => { - located_function.as_assoc_item(db) - } - Either::Left(ModuleDef::Const(located_const)) => { - located_const.as_assoc_item(db) - } - _ => None, - } - .map(|assoc| assoc.container(db)) - .and_then(Self::assoc_to_trait)?; - - trait_candidates.insert(located_assoc_item.into()); - - trait_candidate - .ty - .iterate_path_candidates( - db, - current_crate, - &trait_candidates, - None, - |_, assoc| Self::assoc_to_trait(assoc.container(db)), - ) - .map(ModuleDef::from) - .map(Either::Left) - } - ImportCandidate::TraitMethod(trait_candidate) => { - let located_assoc_item = - if let Either::Left(ModuleDef::Function(located_function)) = candidate { - located_function - .as_assoc_item(db) - .map(|assoc| assoc.container(db)) - .and_then(Self::assoc_to_trait) - } else { - None - }?; - - trait_candidates.insert(located_assoc_item.into()); - - trait_candidate - .ty - .iterate_method_candidates( - db, - current_crate, - &trait_candidates, - None, - |_, function| { - Self::assoc_to_trait(function.as_assoc_item(db)?.container(db)) - }, - ) - .map(ModuleDef::from) - .map(Either::Left) - } - _ => Some(candidate), - } - }; - - let mut res = imports_locator::find_exact_imports( - sema, - current_crate, - self.get_search_query().to_string(), - ) - .filter_map(filter) - .filter_map(|candidate| { - let item: hir::ItemInNs = candidate.either(Into::into, Into::into); - if let Some(prefix_kind) = prefixed { - self.module_with_name_to_import.find_use_path_prefixed(db, item, prefix_kind) - } else { - self.module_with_name_to_import.find_use_path(db, item) - } - .map(|path| (path, item)) - }) - .filter(|(use_path, _)| use_path.len() > 1) - .take(20) - .collect::>(); - res.sort_by_key(|(path, _)| path.clone()); - res - } - - fn assoc_to_trait(assoc: AssocItemContainer) -> Option { - if let AssocItemContainer::Trait(extracted_trait) = assoc { - Some(extracted_trait) - } else { - None - } - } -} - -impl ImportCandidate { - fn for_method_call( - sema: &Semantics, - method_call: &ast::MethodCallExpr, - ) -> Option { - match sema.resolve_method_call(method_call) { - Some(_) => None, - None => Some(Self::TraitMethod(TraitImportCandidate { - ty: sema.type_of_expr(&method_call.receiver()?)?, - name: method_call.name_ref()?, - })), - } - } - - fn for_regular_path( - sema: &Semantics, - path_under_caret: &ast::Path, - ) -> Option { - if sema.resolve_path(path_under_caret).is_some() { - return None; - } - - let segment = path_under_caret.segment()?; - let candidate = if let Some(qualifier) = path_under_caret.qualifier() { - 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) = sema.resolve_path(&qualifier_start_path) { - let qualifier_resolution = if qualifier_start_path == qualifier { - qualifier_start_resolution - } else { - sema.resolve_path(&qualifier)? - }; - match qualifier_resolution { - hir::PathResolution::Def(hir::ModuleDef::Adt(assoc_item_path)) => { - ImportCandidate::TraitAssocItem(TraitImportCandidate { - ty: assoc_item_path.ty(sema.db), - name: segment.name_ref()?, - }) - } - _ => return None, - } - } else { - ImportCandidate::QualifierStart(PathImportCandidate { name: qualifier_start }) - } - } else { - ImportCandidate::UnqualifiedName(PathImportCandidate { - name: segment.syntax().descendants().find_map(ast::NameRef::cast)?, - }) - }; - Some(candidate) - } -} -- cgit v1.2.3