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