diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-04-29 14:03:40 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-04-29 14:03:40 +0100 |
commit | 12aae7771dc220a62d1323ac6a30ddf215fe2b92 (patch) | |
tree | 429968c8f7e4da8c54673b645f5d1de072bc7e1d /crates/ra_assists/src/utils.rs | |
parent | 69cf9fcc0aa452f144a565760d161dde523abe08 (diff) | |
parent | b4dd4752570d5f1ba24f7ffda69be4b1c935cd04 (diff) |
Merge #4208
4208: More principled approach for finding From trait r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_assists/src/utils.rs')
-rw-r--r-- | crates/ra_assists/src/utils.rs | 60 |
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 | ||
4 | use std::iter; | 4 | use std::iter; |
5 | 5 | ||
6 | use hir::{Adt, Semantics, Type}; | 6 | use hir::{Adt, Crate, Semantics, Trait, Type}; |
7 | use ra_ide_db::RootDatabase; | 7 | use ra_ide_db::RootDatabase; |
8 | use ra_syntax::{ | 8 | use 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. | ||
157 | pub(crate) struct FamousDefs<'a, 'b>(pub(crate) &'a Semantics<'b, RootDatabase>, pub(crate) Crate); | ||
158 | |||
159 | #[allow(non_snake_case)] | ||
160 | impl FamousDefs<'_, '_> { | ||
161 | #[cfg(test)] | ||
162 | pub(crate) const FIXTURE: &'static str = r#" | ||
163 | //- /libcore.rs crate:core | ||
164 | pub mod convert{ | ||
165 | pub trait From<T> { | ||
166 | fn from(T) -> Self; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | pub mod prelude { pub use crate::convert::From } | ||
171 | #[prelude_import] | ||
172 | pub 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 | } | ||