]> git.lizzy.rs Git - rust.git/blob - crates/ide_db/src/helpers.rs
Align config's API with usage
[rust.git] / crates / ide_db / src / helpers.rs
1 //! A module with ide helpers for high-level ide features.
2 pub mod insert_use;
3
4 use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait};
5 use syntax::ast::{self, make};
6
7 use crate::RootDatabase;
8
9 /// Converts the mod path struct into its ast representation.
10 pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
11     let _p = profile::span("mod_path_to_ast");
12
13     let mut segments = Vec::new();
14     let mut is_abs = false;
15     match path.kind {
16         hir::PathKind::Plain => {}
17         hir::PathKind::Super(0) => segments.push(make::path_segment_self()),
18         hir::PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
19         hir::PathKind::DollarCrate(_) | hir::PathKind::Crate => {
20             segments.push(make::path_segment_crate())
21         }
22         hir::PathKind::Abs => is_abs = true,
23     }
24
25     segments.extend(
26         path.segments
27             .iter()
28             .map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
29     );
30     make::path_from_segments(segments, is_abs)
31 }
32
33 /// Helps with finding well-know things inside the standard library. This is
34 /// somewhat similar to the known paths infra inside hir, but it different; We
35 /// want to make sure that IDE specific paths don't become interesting inside
36 /// the compiler itself as well.
37 pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>);
38
39 #[allow(non_snake_case)]
40 impl FamousDefs<'_, '_> {
41     pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core
42 pub mod convert {
43     pub trait From<T> {
44         fn from(t: T) -> Self;
45     }
46 }
47
48 pub mod default {
49     pub trait Default {
50        fn default() -> Self;
51     }
52 }
53
54 pub mod iter {
55     pub use self::traits::{collect::IntoIterator, iterator::Iterator};
56     mod traits {
57         pub(crate) mod iterator {
58             use crate::option::Option;
59             pub trait Iterator {
60                 type Item;
61                 fn next(&mut self) -> Option<Self::Item>;
62                 fn by_ref(&mut self) -> &mut Self {
63                     self
64                 }
65                 fn take(self, n: usize) -> crate::iter::Take<Self> {
66                     crate::iter::Take { inner: self }
67                 }
68             }
69
70             impl<I: Iterator> Iterator for &mut I {
71                 type Item = I::Item;
72                 fn next(&mut self) -> Option<I::Item> {
73                     (**self).next()
74                 }
75             }
76         }
77         pub(crate) mod collect {
78             pub trait IntoIterator {
79                 type Item;
80             }
81         }
82     }
83
84     pub use self::sources::*;
85     pub(crate) mod sources {
86         use super::Iterator;
87         use crate::option::Option::{self, *};
88         pub struct Repeat<A> {
89             element: A,
90         }
91
92         pub fn repeat<T>(elt: T) -> Repeat<T> {
93             Repeat { element: elt }
94         }
95
96         impl<A> Iterator for Repeat<A> {
97             type Item = A;
98
99             fn next(&mut self) -> Option<A> {
100                 None
101             }
102         }
103     }
104
105     pub use self::adapters::*;
106     pub(crate) mod adapters {
107         use super::Iterator;
108         use crate::option::Option::{self, *};
109         pub struct Take<I> { pub(crate) inner: I }
110         impl<I> Iterator for Take<I> where I: Iterator {
111             type Item = <I as Iterator>::Item;
112             fn next(&mut self) -> Option<<I as Iterator>::Item> {
113                 None
114             }
115         }
116     }
117 }
118
119 pub mod option {
120     pub enum Option<T> { None, Some(T)}
121 }
122
123 pub mod prelude {
124     pub use crate::{convert::From, iter::{IntoIterator, Iterator}, option::Option::{self, *}, default::Default};
125 }
126 #[prelude_import]
127 pub use prelude::*;
128 "#;
129
130     pub fn core(&self) -> Option<Crate> {
131         self.find_crate("core")
132     }
133
134     pub fn core_convert_From(&self) -> Option<Trait> {
135         self.find_trait("core:convert:From")
136     }
137
138     pub fn core_option_Option(&self) -> Option<Enum> {
139         self.find_enum("core:option:Option")
140     }
141
142     pub fn core_default_Default(&self) -> Option<Trait> {
143         self.find_trait("core:default:Default")
144     }
145
146     pub fn core_iter_Iterator(&self) -> Option<Trait> {
147         self.find_trait("core:iter:traits:iterator:Iterator")
148     }
149
150     pub fn core_iter(&self) -> Option<Module> {
151         self.find_module("core:iter")
152     }
153
154     fn find_trait(&self, path: &str) -> Option<Trait> {
155         match self.find_def(path)? {
156             hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
157             _ => None,
158         }
159     }
160
161     fn find_enum(&self, path: &str) -> Option<Enum> {
162         match self.find_def(path)? {
163             hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it),
164             _ => None,
165         }
166     }
167
168     fn find_module(&self, path: &str) -> Option<Module> {
169         match self.find_def(path)? {
170             hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(it)) => Some(it),
171             _ => None,
172         }
173     }
174
175     fn find_crate(&self, name: &str) -> Option<Crate> {
176         let krate = self.1?;
177         let db = self.0.db;
178         let res =
179             krate.dependencies(db).into_iter().find(|dep| dep.name.to_string() == name)?.krate;
180         Some(res)
181     }
182
183     fn find_def(&self, path: &str) -> Option<ScopeDef> {
184         let db = self.0.db;
185         let mut path = path.split(':');
186         let trait_ = path.next_back()?;
187         let std_crate = path.next()?;
188         let std_crate = self.find_crate(std_crate)?;
189         let mut module = std_crate.root_module(db);
190         for segment in path {
191             module = module.children(db).find_map(|child| {
192                 let name = child.name(db)?;
193                 if name.to_string() == segment {
194                     Some(child)
195                 } else {
196                     None
197                 }
198             })?;
199         }
200         let def =
201             module.scope(db, None).into_iter().find(|(name, _def)| name.to_string() == trait_)?.1;
202         Some(def)
203     }
204 }
205
206 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
207 pub struct SnippetCap {
208     _private: (),
209 }
210
211 impl SnippetCap {
212     pub const fn new(allow_snippets: bool) -> Option<SnippetCap> {
213         if allow_snippets {
214             Some(SnippetCap { _private: () })
215         } else {
216             None
217         }
218     }
219 }