Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide_db/src/helpers.rs')
| -rw-r--r-- | crates/ide_db/src/helpers.rs | 127 |
1 files changed, 7 insertions, 120 deletions
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index 2433d8e918..c92893716f 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs @@ -1,15 +1,17 @@ //! A module with ide helpers for high-level ide features. +pub mod famous_defs; +pub mod generated_lints; pub mod import_assets; pub mod insert_use; pub mod merge_imports; +pub mod node_ext; pub mod rust_doc; -pub mod generated_lints; use std::collections::VecDeque; use base_db::FileId; use either::Either; -use hir::{Crate, Enum, ItemInNs, MacroDef, Module, ModuleDef, Name, ScopeDef, Semantics, Trait}; +use hir::{ItemInNs, MacroDef, ModuleDef, Name, Semantics}; use syntax::{ ast::{self, make, LoopBodyOwner}, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxToken, TokenAtOffset, WalkEvent, T, @@ -17,6 +19,8 @@ use syntax::{ use crate::RootDatabase; +pub use self::famous_defs::FamousDefs; + pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> { match item { ItemInNs::Types(module_def_id) => ModuleDef::from(module_def_id).name(db), @@ -27,7 +31,7 @@ pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> { /// Resolves the path at the cursor token as a derive macro if it inside a token tree of a derive attribute. pub fn try_resolve_derive_input_at( - sema: &Semantics<RootDatabase>, + sema: &hir::Semantics<RootDatabase>, derive_attr: &ast::Attr, cursor: &SyntaxToken, ) -> Option<MacroDef> { @@ -113,123 +117,6 @@ pub fn visit_file_defs( module.impl_defs(db).into_iter().for_each(|impl_| cb(Either::Right(impl_))); } -/// Helps with finding well-know things inside the standard library. This is -/// somewhat similar to the known paths infra inside hir, but it different; We -/// want to make sure that IDE specific paths don't become interesting inside -/// the compiler itself as well. -/// -/// Note that, by default, rust-analyzer tests **do not** include core or std -/// libraries. If you are writing tests for functionality using [`FamousDefs`], -/// you'd want to include minicore (see `test_utils::MiniCore`) declaration at -/// the start of your tests: -/// -/// ``` -/// //- minicore: iterator, ord, derive -/// ``` -pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>); - -#[allow(non_snake_case)] -impl FamousDefs<'_, '_> { - pub fn std(&self) -> Option<Crate> { - self.find_crate("std") - } - - pub fn core(&self) -> Option<Crate> { - self.find_crate("core") - } - - pub fn core_cmp_Ord(&self) -> Option<Trait> { - self.find_trait("core:cmp:Ord") - } - - pub fn core_convert_From(&self) -> Option<Trait> { - self.find_trait("core:convert:From") - } - - pub fn core_convert_Into(&self) -> Option<Trait> { - self.find_trait("core:convert:Into") - } - - pub fn core_option_Option(&self) -> Option<Enum> { - self.find_enum("core:option:Option") - } - - pub fn core_result_Result(&self) -> Option<Enum> { - self.find_enum("core:result:Result") - } - - pub fn core_default_Default(&self) -> Option<Trait> { - self.find_trait("core:default:Default") - } - - pub fn core_iter_Iterator(&self) -> Option<Trait> { - self.find_trait("core:iter:traits:iterator:Iterator") - } - - pub fn core_iter_IntoIterator(&self) -> Option<Trait> { - self.find_trait("core:iter:traits:collect:IntoIterator") - } - - pub fn core_iter(&self) -> Option<Module> { - self.find_module("core:iter") - } - - pub fn core_ops_Deref(&self) -> Option<Trait> { - self.find_trait("core:ops:Deref") - } - - fn find_trait(&self, path: &str) -> Option<Trait> { - match self.find_def(path)? { - hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it), - _ => None, - } - } - - fn find_enum(&self, path: &str) -> Option<Enum> { - match self.find_def(path)? { - hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it), - _ => None, - } - } - - fn find_module(&self, path: &str) -> Option<Module> { - match self.find_def(path)? { - hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(it)) => Some(it), - _ => None, - } - } - - fn find_crate(&self, name: &str) -> Option<Crate> { - let krate = self.1?; - let db = self.0.db; - let res = - krate.dependencies(db).into_iter().find(|dep| dep.name.to_string() == name)?.krate; - Some(res) - } - - fn find_def(&self, path: &str) -> Option<ScopeDef> { - let db = self.0.db; - let mut path = path.split(':'); - let trait_ = path.next_back()?; - let std_crate = path.next()?; - let std_crate = self.find_crate(std_crate)?; - let mut module = std_crate.root_module(db); - for segment in path { - module = module.children(db).find_map(|child| { - let name = child.name(db)?; - if name.to_string() == segment { - Some(child) - } else { - None - } - })?; - } - let def = - module.scope(db, None).into_iter().find(|(name, _def)| name.to_string() == trait_)?.1; - Some(def) - } -} - #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct SnippetCap { _private: (), |