diff options
Diffstat (limited to 'crates/ra_assists/src/utils.rs')
-rw-r--r-- | crates/ra_assists/src/utils.rs | 78 |
1 files changed, 69 insertions, 9 deletions
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs index f3fc92ebf..0038a9764 100644 --- a/crates/ra_assists/src/utils.rs +++ b/crates/ra_assists/src/utils.rs | |||
@@ -1,18 +1,57 @@ | |||
1 | //! Assorted functions shared by several assists. | 1 | //! Assorted functions shared by several assists. |
2 | pub(crate) mod insert_use; | 2 | pub(crate) mod insert_use; |
3 | 3 | ||
4 | use std::iter; | 4 | use std::{iter, ops}; |
5 | 5 | ||
6 | use hir::{Adt, Crate, Semantics, Trait, Type}; | 6 | use hir::{Adt, Crate, Enum, ScopeDef, 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}, |
10 | AstNode, T, | 10 | AstNode, SyntaxNode, T, |
11 | }; | 11 | }; |
12 | use rustc_hash::FxHashSet; | 12 | use rustc_hash::FxHashSet; |
13 | 13 | ||
14 | use crate::assist_config::SnippetCap; | ||
15 | |||
14 | pub(crate) use insert_use::insert_use_statement; | 16 | pub(crate) use insert_use::insert_use_statement; |
15 | 17 | ||
18 | #[derive(Clone, Copy, Debug)] | ||
19 | pub(crate) enum Cursor<'a> { | ||
20 | Replace(&'a SyntaxNode), | ||
21 | Before(&'a SyntaxNode), | ||
22 | } | ||
23 | |||
24 | impl<'a> Cursor<'a> { | ||
25 | fn node(self) -> &'a SyntaxNode { | ||
26 | match self { | ||
27 | Cursor::Replace(node) | Cursor::Before(node) => node, | ||
28 | } | ||
29 | } | ||
30 | } | ||
31 | |||
32 | pub(crate) fn render_snippet(_cap: SnippetCap, node: &SyntaxNode, cursor: Cursor) -> String { | ||
33 | assert!(cursor.node().ancestors().any(|it| it == *node)); | ||
34 | let range = cursor.node().text_range() - node.text_range().start(); | ||
35 | let range: ops::Range<usize> = range.into(); | ||
36 | |||
37 | let mut placeholder = cursor.node().to_string(); | ||
38 | escape(&mut placeholder); | ||
39 | let tab_stop = match cursor { | ||
40 | Cursor::Replace(placeholder) => format!("${{0:{}}}", placeholder), | ||
41 | Cursor::Before(placeholder) => format!("$0{}", placeholder), | ||
42 | }; | ||
43 | |||
44 | let mut buf = node.to_string(); | ||
45 | buf.replace_range(range, &tab_stop); | ||
46 | return buf; | ||
47 | |||
48 | fn escape(buf: &mut String) { | ||
49 | stdx::replace(buf, '{', r"\{"); | ||
50 | stdx::replace(buf, '}', r"\}"); | ||
51 | stdx::replace(buf, '$', r"\$"); | ||
52 | } | ||
53 | } | ||
54 | |||
16 | pub fn get_missing_assoc_items( | 55 | pub fn get_missing_assoc_items( |
17 | sema: &Semantics<RootDatabase>, | 56 | sema: &Semantics<RootDatabase>, |
18 | impl_def: &ast::ImplDef, | 57 | impl_def: &ast::ImplDef, |
@@ -161,13 +200,19 @@ impl FamousDefs<'_, '_> { | |||
161 | #[cfg(test)] | 200 | #[cfg(test)] |
162 | pub(crate) const FIXTURE: &'static str = r#" | 201 | pub(crate) const FIXTURE: &'static str = r#" |
163 | //- /libcore.rs crate:core | 202 | //- /libcore.rs crate:core |
164 | pub mod convert{ | 203 | pub mod convert { |
165 | pub trait From<T> { | 204 | pub trait From<T> { |
166 | fn from(T) -> Self; | 205 | fn from(T) -> Self; |
167 | } | 206 | } |
168 | } | 207 | } |
169 | 208 | ||
170 | pub mod prelude { pub use crate::convert::From } | 209 | pub mod option { |
210 | pub enum Option<T> { None, Some(T)} | ||
211 | } | ||
212 | |||
213 | pub mod prelude { | ||
214 | pub use crate::{convert::From, option::Option::{self, *}}; | ||
215 | } | ||
171 | #[prelude_import] | 216 | #[prelude_import] |
172 | pub use prelude::*; | 217 | pub use prelude::*; |
173 | "#; | 218 | "#; |
@@ -176,7 +221,25 @@ pub use prelude::*; | |||
176 | self.find_trait("core:convert:From") | 221 | self.find_trait("core:convert:From") |
177 | } | 222 | } |
178 | 223 | ||
224 | pub(crate) fn core_option_Option(&self) -> Option<Enum> { | ||
225 | self.find_enum("core:option:Option") | ||
226 | } | ||
227 | |||
179 | fn find_trait(&self, path: &str) -> Option<Trait> { | 228 | fn find_trait(&self, path: &str) -> Option<Trait> { |
229 | match self.find_def(path)? { | ||
230 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it), | ||
231 | _ => None, | ||
232 | } | ||
233 | } | ||
234 | |||
235 | fn find_enum(&self, path: &str) -> Option<Enum> { | ||
236 | match self.find_def(path)? { | ||
237 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it), | ||
238 | _ => None, | ||
239 | } | ||
240 | } | ||
241 | |||
242 | fn find_def(&self, path: &str) -> Option<ScopeDef> { | ||
180 | let db = self.0.db; | 243 | let db = self.0.db; |
181 | let mut path = path.split(':'); | 244 | let mut path = path.split(':'); |
182 | let trait_ = path.next_back()?; | 245 | let trait_ = path.next_back()?; |
@@ -201,9 +264,6 @@ pub use prelude::*; | |||
201 | } | 264 | } |
202 | let def = | 265 | let def = |
203 | module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1; | 266 | module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1; |
204 | match def { | 267 | Some(def) |
205 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it), | ||
206 | _ => None, | ||
207 | } | ||
208 | } | 268 | } |
209 | } | 269 | } |