aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/utils.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/utils.rs')
-rw-r--r--crates/ra_assists/src/utils.rs60
1 files changed, 59 insertions, 1 deletions
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 61f8bd1dc..efd988697 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -3,7 +3,7 @@ pub(crate) mod insert_use;
3 3
4use std::iter; 4use std::iter;
5 5
6use hir::{Adt, Semantics, Type}; 6use hir::{Adt, Crate, Semantics, Trait, Type};
7use ra_ide_db::RootDatabase; 7use ra_ide_db::RootDatabase;
8use ra_syntax::{ 8use ra_syntax::{
9 ast::{self, make, NameOwner}, 9 ast::{self, make, NameOwner},
@@ -149,3 +149,61 @@ impl TryEnum {
149 } 149 }
150 } 150 }
151} 151}
152
153/// Helps with finding well-know things inside the standard library. This is
154/// somewhat similar to the known paths infra inside hir, but it different; We
155/// want to make sure that IDE specific paths don't become interesting inside
156/// the compiler itself as well.
157pub(crate) struct FamousDefs<'a, 'b>(pub(crate) &'a Semantics<'b, RootDatabase>, pub(crate) Crate);
158
159#[allow(non_snake_case)]
160impl FamousDefs<'_, '_> {
161 #[cfg(test)]
162 pub(crate) const FIXTURE: &'static str = r#"
163//- /libcore.rs crate:core
164pub mod convert{
165 pub trait From<T> {
166 fn from(T) -> Self;
167 }
168}
169
170pub mod prelude { pub use crate::convert::From }
171#[prelude_import]
172pub use prelude::*;
173"#;
174
175 pub(crate) fn core_convert_From(&self) -> Option<Trait> {
176 self.find_trait("core:convert:From")
177 }
178
179 fn find_trait(&self, path: &str) -> Option<Trait> {
180 let db = self.0.db;
181 let mut path = path.split(':');
182 let trait_ = path.next_back()?;
183 let std_crate = path.next()?;
184 let std_crate = self
185 .1
186 .dependencies(db)
187 .into_iter()
188 .find(|dep| &dep.name.to_string() == std_crate)?
189 .krate;
190
191 let mut module = std_crate.root_module(db)?;
192 for segment in path {
193 module = module.children(db).find_map(|child| {
194 let name = child.name(db)?;
195 if &name.to_string() == segment {
196 Some(child)
197 } else {
198 None
199 }
200 })?;
201 }
202 let def =
203 module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1;
204 match def {
205 hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
206 _ => None,
207 }
208 }
209}