aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/assists/Cargo.toml2
-rw-r--r--crates/assists/src/assist_config.rs3
-rw-r--r--crates/assists/src/ast_transform.rs3
-rw-r--r--crates/assists/src/handlers/auto_import.rs5
-rw-r--r--crates/assists/src/handlers/extract_struct_from_enum_variant.rs16
-rw-r--r--crates/assists/src/handlers/fill_match_arms.rs9
-rw-r--r--crates/assists/src/handlers/generate_from_impl_for_enum.rs3
-rw-r--r--crates/assists/src/handlers/merge_imports.rs6
-rw-r--r--crates/assists/src/handlers/qualify_path.rs2
-rw-r--r--crates/assists/src/handlers/replace_derive_with_manual_impl.rs4
-rw-r--r--crates/assists/src/handlers/replace_qualified_name_with_use.rs6
-rw-r--r--crates/assists/src/utils.rs200
-rw-r--r--crates/completion/Cargo.toml1
-rw-r--r--crates/completion/src/completions/record.rs4
-rw-r--r--crates/completion/src/completions/unqualified_path.rs2
-rw-r--r--crates/completion/src/config.rs2
-rw-r--r--crates/completion/src/item.rs36
-rw-r--r--crates/completion/src/render.rs25
-rw-r--r--crates/completion/src/render/enum_variant.rs14
-rw-r--r--crates/completion/src/render/function.rs16
-rw-r--r--crates/completion/src/render/macro_.rs16
-rw-r--r--crates/ide/src/inlay_hints.rs4
-rw-r--r--crates/ide/src/lib.rs4
-rw-r--r--crates/ide_db/Cargo.toml3
-rw-r--r--crates/ide_db/src/helpers.rs203
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs (renamed from crates/assists/src/utils/insert_use.rs)8
-rw-r--r--crates/ide_db/src/lib.rs1
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/config.rs6
29 files changed, 304 insertions, 302 deletions
diff --git a/crates/assists/Cargo.toml b/crates/assists/Cargo.toml
index 108f656e9..3fd8327d6 100644
--- a/crates/assists/Cargo.toml
+++ b/crates/assists/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
12[dependencies] 12[dependencies]
13rustc-hash = "1.1.0" 13rustc-hash = "1.1.0"
14itertools = "0.9.0" 14itertools = "0.9.0"
15either = "1.5.3" 15either = "1.6.1"
16 16
17stdx = { path = "../stdx", version = "0.0.0" } 17stdx = { path = "../stdx", version = "0.0.0" }
18syntax = { path = "../syntax", version = "0.0.0" } 18syntax = { path = "../syntax", version = "0.0.0" }
diff --git a/crates/assists/src/assist_config.rs b/crates/assists/src/assist_config.rs
index b24527ec4..786224cfa 100644
--- a/crates/assists/src/assist_config.rs
+++ b/crates/assists/src/assist_config.rs
@@ -5,8 +5,9 @@
5//! assists if we are allowed to. 5//! assists if we are allowed to.
6 6
7use hir::PrefixKind; 7use hir::PrefixKind;
8use ide_db::helpers::insert_use::MergeBehaviour;
8 9
9use crate::{utils::MergeBehaviour, AssistKind}; 10use crate::AssistKind;
10 11
11#[derive(Clone, Debug, PartialEq, Eq)] 12#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct AssistConfig { 13pub struct AssistConfig {
diff --git a/crates/assists/src/ast_transform.rs b/crates/assists/src/ast_transform.rs
index ac72f3f02..66e4634b1 100644
--- a/crates/assists/src/ast_transform.rs
+++ b/crates/assists/src/ast_transform.rs
@@ -1,5 +1,6 @@
1//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined. 1//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
2use hir::{HirDisplay, PathResolution, SemanticsScope}; 2use hir::{HirDisplay, PathResolution, SemanticsScope};
3use ide_db::helpers::mod_path_to_ast;
3use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
4use syntax::{ 5use syntax::{
5 algo::SyntaxRewriter, 6 algo::SyntaxRewriter,
@@ -7,8 +8,6 @@ use syntax::{
7 SyntaxNode, 8 SyntaxNode,
8}; 9};
9 10
10use crate::utils::mod_path_to_ast;
11
12pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N { 11pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
13 SyntaxRewriter::from_fn(|element| match element { 12 SyntaxRewriter::from_fn(|element| match element {
14 syntax::SyntaxElement::Node(n) => { 13 syntax::SyntaxElement::Node(n) => {
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs
index d665837a2..bd5bba646 100644
--- a/crates/assists/src/handlers/auto_import.rs
+++ b/crates/assists/src/handlers/auto_import.rs
@@ -1,8 +1,11 @@
1use ide_db::helpers::{
2 insert_use::{insert_use, ImportScope},
3 mod_path_to_ast,
4};
1use syntax::ast; 5use syntax::ast;
2 6
3use crate::{ 7use crate::{
4 utils::import_assets::{ImportAssets, ImportCandidate}, 8 utils::import_assets::{ImportAssets, ImportCandidate},
5 utils::{insert_use, mod_path_to_ast, ImportScope},
6 AssistContext, AssistId, AssistKind, Assists, GroupLabel, 9 AssistContext, AssistId, AssistKind, Assists, GroupLabel,
7}; 10};
8 11
diff --git a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
index cac77c49b..d85767b4e 100644
--- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -2,6 +2,10 @@ use std::iter;
2 2
3use either::Either; 3use either::Either;
4use hir::{AsName, EnumVariant, Module, ModuleDef, Name}; 4use hir::{AsName, EnumVariant, Module, ModuleDef, Name};
5use ide_db::helpers::{
6 insert_use::{insert_use, ImportScope},
7 mod_path_to_ast,
8};
5use ide_db::{defs::Definition, search::Reference, RootDatabase}; 9use ide_db::{defs::Definition, search::Reference, RootDatabase};
6use rustc_hash::{FxHashMap, FxHashSet}; 10use rustc_hash::{FxHashMap, FxHashSet};
7use syntax::{ 11use syntax::{
@@ -10,10 +14,7 @@ use syntax::{
10 SourceFile, SyntaxElement, SyntaxNode, T, 14 SourceFile, SyntaxElement, SyntaxNode, T,
11}; 15};
12 16
13use crate::{ 17use crate::{AssistContext, AssistId, AssistKind, Assists};
14 utils::{insert_use, mod_path_to_ast, ImportScope},
15 AssistContext, AssistId, AssistKind, Assists,
16};
17 18
18// Assist: extract_struct_from_enum_variant 19// Assist: extract_struct_from_enum_variant
19// 20//
@@ -236,10 +237,9 @@ fn update_reference(
236 237
237#[cfg(test)] 238#[cfg(test)]
238mod tests { 239mod tests {
239 use crate::{ 240 use ide_db::helpers::FamousDefs;
240 tests::{check_assist, check_assist_not_applicable}, 241
241 utils::FamousDefs, 242 use crate::tests::{check_assist, check_assist_not_applicable};
242 };
243 243
244 use super::*; 244 use super::*;
245 245
diff --git a/crates/assists/src/handlers/fill_match_arms.rs b/crates/assists/src/handlers/fill_match_arms.rs
index eda45f5b3..ef12ef0cf 100644
--- a/crates/assists/src/handlers/fill_match_arms.rs
+++ b/crates/assists/src/handlers/fill_match_arms.rs
@@ -1,13 +1,14 @@
1use std::iter; 1use std::iter;
2 2
3use hir::{Adt, HasSource, ModuleDef, Semantics}; 3use hir::{Adt, HasSource, ModuleDef, Semantics};
4use ide_db::helpers::{mod_path_to_ast, FamousDefs};
4use ide_db::RootDatabase; 5use ide_db::RootDatabase;
5use itertools::Itertools; 6use itertools::Itertools;
6use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat}; 7use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat};
7use test_utils::mark; 8use test_utils::mark;
8 9
9use crate::{ 10use crate::{
10 utils::{mod_path_to_ast, render_snippet, Cursor, FamousDefs}, 11 utils::{render_snippet, Cursor},
11 AssistContext, AssistId, AssistKind, Assists, 12 AssistContext, AssistId, AssistKind, Assists,
12}; 13};
13 14
@@ -212,12 +213,10 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> O
212 213
213#[cfg(test)] 214#[cfg(test)]
214mod tests { 215mod tests {
216 use ide_db::helpers::FamousDefs;
215 use test_utils::mark; 217 use test_utils::mark;
216 218
217 use crate::{ 219 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
218 tests::{check_assist, check_assist_not_applicable, check_assist_target},
219 utils::FamousDefs,
220 };
221 220
222 use super::fill_match_arms; 221 use super::fill_match_arms;
223 222
diff --git a/crates/assists/src/handlers/generate_from_impl_for_enum.rs b/crates/assists/src/handlers/generate_from_impl_for_enum.rs
index 674e5a175..3c374e5d9 100644
--- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs
+++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs
@@ -1,8 +1,9 @@
1use ide_db::helpers::FamousDefs;
1use ide_db::RootDatabase; 2use ide_db::RootDatabase;
2use syntax::ast::{self, AstNode, NameOwner}; 3use syntax::ast::{self, AstNode, NameOwner};
3use test_utils::mark; 4use test_utils::mark;
4 5
5use crate::{utils::FamousDefs, AssistContext, AssistId, AssistKind, Assists}; 6use crate::{AssistContext, AssistId, AssistKind, Assists};
6 7
7// Assist: generate_from_impl_for_enum 8// Assist: generate_from_impl_for_enum
8// 9//
diff --git a/crates/assists/src/handlers/merge_imports.rs b/crates/assists/src/handlers/merge_imports.rs
index fd9c9e03c..b7e853994 100644
--- a/crates/assists/src/handlers/merge_imports.rs
+++ b/crates/assists/src/handlers/merge_imports.rs
@@ -1,3 +1,4 @@
1use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehaviour};
1use syntax::{ 2use syntax::{
2 algo::{neighbor, SyntaxRewriter}, 3 algo::{neighbor, SyntaxRewriter},
3 ast, AstNode, 4 ast, AstNode,
@@ -5,10 +6,7 @@ use syntax::{
5 6
6use crate::{ 7use crate::{
7 assist_context::{AssistContext, Assists}, 8 assist_context::{AssistContext, Assists},
8 utils::{ 9 utils::next_prev,
9 insert_use::{try_merge_imports, try_merge_trees},
10 next_prev, MergeBehaviour,
11 },
12 AssistId, AssistKind, 10 AssistId, AssistKind,
13}; 11};
14 12
diff --git a/crates/assists/src/handlers/qualify_path.rs b/crates/assists/src/handlers/qualify_path.rs
index d5bc4e574..6f9810fe8 100644
--- a/crates/assists/src/handlers/qualify_path.rs
+++ b/crates/assists/src/handlers/qualify_path.rs
@@ -1,6 +1,7 @@
1use std::iter; 1use std::iter;
2 2
3use hir::AsName; 3use hir::AsName;
4use ide_db::helpers::mod_path_to_ast;
4use ide_db::RootDatabase; 5use ide_db::RootDatabase;
5use syntax::{ 6use syntax::{
6 ast, 7 ast,
@@ -12,7 +13,6 @@ use test_utils::mark;
12use crate::{ 13use crate::{
13 assist_context::{AssistContext, Assists}, 14 assist_context::{AssistContext, Assists},
14 utils::import_assets::{ImportAssets, ImportCandidate}, 15 utils::import_assets::{ImportAssets, ImportCandidate},
15 utils::mod_path_to_ast,
16 AssistId, AssistKind, GroupLabel, 16 AssistId, AssistKind, GroupLabel,
17}; 17};
18 18
diff --git a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
index 453a6cebf..4d6a1956b 100644
--- a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -1,3 +1,4 @@
1use ide_db::helpers::mod_path_to_ast;
1use ide_db::imports_locator; 2use ide_db::imports_locator;
2use itertools::Itertools; 3use itertools::Itertools;
3use syntax::{ 4use syntax::{
@@ -10,8 +11,7 @@ use syntax::{
10use crate::{ 11use crate::{
11 assist_context::{AssistBuilder, AssistContext, Assists}, 12 assist_context::{AssistBuilder, AssistContext, Assists},
12 utils::{ 13 utils::{
13 add_trait_assoc_items_to_impl, filter_assoc_items, mod_path_to_ast, render_snippet, Cursor, 14 add_trait_assoc_items_to_impl, filter_assoc_items, render_snippet, Cursor, DefaultMethods,
14 DefaultMethods,
15 }, 15 },
16 AssistId, AssistKind, 16 AssistId, AssistKind,
17}; 17};
diff --git a/crates/assists/src/handlers/replace_qualified_name_with_use.rs b/crates/assists/src/handlers/replace_qualified_name_with_use.rs
index a66db9ae3..8bdf9eea5 100644
--- a/crates/assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/assists/src/handlers/replace_qualified_name_with_use.rs
@@ -1,10 +1,8 @@
1use ide_db::helpers::insert_use::{insert_use, ImportScope};
1use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode}; 2use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode};
2use test_utils::mark; 3use test_utils::mark;
3 4
4use crate::{ 5use crate::{AssistContext, AssistId, AssistKind, Assists};
5 utils::{insert_use, ImportScope},
6 AssistContext, AssistId, AssistKind, Assists,
7};
8 6
9// Assist: replace_qualified_name_with_use 7// Assist: replace_qualified_name_with_use
10// 8//
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs
index 048746587..01f5c291f 100644
--- a/crates/assists/src/utils.rs
+++ b/crates/assists/src/utils.rs
@@ -1,10 +1,9 @@
1//! Assorted functions shared by several assists. 1//! Assorted functions shared by several assists.
2pub(crate) mod insert_use;
3pub(crate) mod import_assets; 2pub(crate) mod import_assets;
4 3
5use std::ops; 4use std::ops;
6 5
7use hir::{Crate, Enum, HasSource, Module, ScopeDef, Semantics, Trait}; 6use hir::HasSource;
8use ide_db::RootDatabase; 7use ide_db::RootDatabase;
9use itertools::Itertools; 8use itertools::Itertools;
10use syntax::{ 9use syntax::{
@@ -22,30 +21,6 @@ use crate::{
22 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, 21 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
23}; 22};
24 23
25pub use insert_use::{insert_use, ImportScope, MergeBehaviour};
26
27pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
28 let _p = profile::span("mod_path_to_ast");
29 let mut segments = Vec::new();
30 let mut is_abs = false;
31 match path.kind {
32 hir::PathKind::Plain => {}
33 hir::PathKind::Super(0) => segments.push(make::path_segment_self()),
34 hir::PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
35 hir::PathKind::DollarCrate(_) | hir::PathKind::Crate => {
36 segments.push(make::path_segment_crate())
37 }
38 hir::PathKind::Abs => is_abs = true,
39 }
40
41 segments.extend(
42 path.segments
43 .iter()
44 .map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
45 );
46 make::path_from_segments(segments, is_abs)
47}
48
49pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { 24pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr {
50 extract_trivial_expression(&block) 25 extract_trivial_expression(&block)
51 .filter(|expr| !expr.syntax().text().contains_char('\n')) 26 .filter(|expr| !expr.syntax().text().contains_char('\n'))
@@ -260,179 +235,6 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
260 } 235 }
261} 236}
262 237
263/// Helps with finding well-know things inside the standard library. This is
264/// somewhat similar to the known paths infra inside hir, but it different; We
265/// want to make sure that IDE specific paths don't become interesting inside
266/// the compiler itself as well.
267pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>);
268
269#[allow(non_snake_case)]
270impl FamousDefs<'_, '_> {
271 pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core
272pub mod convert {
273 pub trait From<T> {
274 fn from(t: T) -> Self;
275 }
276}
277
278pub mod default {
279 pub trait Default {
280 fn default() -> Self;
281 }
282}
283
284pub mod iter {
285 pub use self::traits::{collect::IntoIterator, iterator::Iterator};
286 mod traits {
287 pub(crate) mod iterator {
288 use crate::option::Option;
289 pub trait Iterator {
290 type Item;
291 fn next(&mut self) -> Option<Self::Item>;
292 fn by_ref(&mut self) -> &mut Self {
293 self
294 }
295 fn take(self, n: usize) -> crate::iter::Take<Self> {
296 crate::iter::Take { inner: self }
297 }
298 }
299
300 impl<I: Iterator> Iterator for &mut I {
301 type Item = I::Item;
302 fn next(&mut self) -> Option<I::Item> {
303 (**self).next()
304 }
305 }
306 }
307 pub(crate) mod collect {
308 pub trait IntoIterator {
309 type Item;
310 }
311 }
312 }
313
314 pub use self::sources::*;
315 pub(crate) mod sources {
316 use super::Iterator;
317 use crate::option::Option::{self, *};
318 pub struct Repeat<A> {
319 element: A,
320 }
321
322 pub fn repeat<T>(elt: T) -> Repeat<T> {
323 Repeat { element: elt }
324 }
325
326 impl<A> Iterator for Repeat<A> {
327 type Item = A;
328
329 fn next(&mut self) -> Option<A> {
330 None
331 }
332 }
333 }
334
335 pub use self::adapters::*;
336 pub(crate) mod adapters {
337 use super::Iterator;
338 use crate::option::Option::{self, *};
339 pub struct Take<I> { pub(crate) inner: I }
340 impl<I> Iterator for Take<I> where I: Iterator {
341 type Item = <I as Iterator>::Item;
342 fn next(&mut self) -> Option<<I as Iterator>::Item> {
343 None
344 }
345 }
346 }
347}
348
349pub mod option {
350 pub enum Option<T> { None, Some(T)}
351}
352
353pub mod prelude {
354 pub use crate::{convert::From, iter::{IntoIterator, Iterator}, option::Option::{self, *}, default::Default};
355}
356#[prelude_import]
357pub use prelude::*;
358"#;
359
360 pub fn core(&self) -> Option<Crate> {
361 self.find_crate("core")
362 }
363
364 pub(crate) fn core_convert_From(&self) -> Option<Trait> {
365 self.find_trait("core:convert:From")
366 }
367
368 pub(crate) fn core_option_Option(&self) -> Option<Enum> {
369 self.find_enum("core:option:Option")
370 }
371
372 pub fn core_default_Default(&self) -> Option<Trait> {
373 self.find_trait("core:default:Default")
374 }
375
376 pub fn core_iter_Iterator(&self) -> Option<Trait> {
377 self.find_trait("core:iter:traits:iterator:Iterator")
378 }
379
380 pub fn core_iter(&self) -> Option<Module> {
381 self.find_module("core:iter")
382 }
383
384 fn find_trait(&self, path: &str) -> Option<Trait> {
385 match self.find_def(path)? {
386 hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
387 _ => None,
388 }
389 }
390
391 fn find_enum(&self, path: &str) -> Option<Enum> {
392 match self.find_def(path)? {
393 hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it),
394 _ => None,
395 }
396 }
397
398 fn find_module(&self, path: &str) -> Option<Module> {
399 match self.find_def(path)? {
400 hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(it)) => Some(it),
401 _ => None,
402 }
403 }
404
405 fn find_crate(&self, name: &str) -> Option<Crate> {
406 let krate = self.1?;
407 let db = self.0.db;
408 let res =
409 krate.dependencies(db).into_iter().find(|dep| dep.name.to_string() == name)?.krate;
410 Some(res)
411 }
412
413 fn find_def(&self, path: &str) -> Option<ScopeDef> {
414 let db = self.0.db;
415 let mut path = path.split(':');
416 let trait_ = path.next_back()?;
417 let std_crate = path.next()?;
418 let std_crate = self.find_crate(std_crate)?;
419 let mut module = std_crate.root_module(db);
420 for segment in path {
421 module = module.children(db).find_map(|child| {
422 let name = child.name(db)?;
423 if name.to_string() == segment {
424 Some(child)
425 } else {
426 None
427 }
428 })?;
429 }
430 let def =
431 module.scope(db, None).into_iter().find(|(name, _def)| name.to_string() == trait_)?.1;
432 Some(def)
433 }
434}
435
436pub(crate) fn next_prev() -> impl Iterator<Item = Direction> { 238pub(crate) fn next_prev() -> impl Iterator<Item = Direction> {
437 [Direction::Next, Direction::Prev].iter().copied() 239 [Direction::Next, Direction::Prev].iter().copied()
438} 240}
diff --git a/crates/completion/Cargo.toml b/crates/completion/Cargo.toml
index e7df9d955..35e169a28 100644
--- a/crates/completion/Cargo.toml
+++ b/crates/completion/Cargo.toml
@@ -15,7 +15,6 @@ log = "0.4.8"
15rustc-hash = "1.1.0" 15rustc-hash = "1.1.0"
16either = "1.6.1" 16either = "1.6.1"
17 17
18assists = { path = "../assists", version = "0.0.0" }
19stdx = { path = "../stdx", version = "0.0.0" } 18stdx = { path = "../stdx", version = "0.0.0" }
20syntax = { path = "../syntax", version = "0.0.0" } 19syntax = { path = "../syntax", version = "0.0.0" }
21text_edit = { path = "../text_edit", version = "0.0.0" } 20text_edit = { path = "../text_edit", version = "0.0.0" }
diff --git a/crates/completion/src/completions/record.rs b/crates/completion/src/completions/record.rs
index 2049b9d09..eaa44c97d 100644
--- a/crates/completion/src/completions/record.rs
+++ b/crates/completion/src/completions/record.rs
@@ -1,5 +1,5 @@
1//! Complete fields in record literals and patterns. 1//! Complete fields in record literals and patterns.
2use assists::utils::FamousDefs; 2use ide_db::helpers::FamousDefs;
3use syntax::ast::Expr; 3use syntax::ast::Expr;
4 4
5use crate::{ 5use crate::{
@@ -45,8 +45,8 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
45 45
46#[cfg(test)] 46#[cfg(test)]
47mod tests { 47mod tests {
48 use assists::utils::FamousDefs;
49 use expect_test::{expect, Expect}; 48 use expect_test::{expect, Expect};
49 use ide_db::helpers::FamousDefs;
50 50
51 use crate::{test_utils::completion_list, CompletionKind}; 51 use crate::{test_utils::completion_list, CompletionKind};
52 52
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index 3bd776905..81691cd7f 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -1,8 +1,8 @@
1//! Completion of names from the current scope, e.g. locals and imported items. 1//! Completion of names from the current scope, e.g. locals and imported items.
2 2
3use assists::utils::ImportScope;
4use either::Either; 3use either::Either;
5use hir::{Adt, ModuleDef, ScopeDef, Type}; 4use hir::{Adt, ModuleDef, ScopeDef, Type};
5use ide_db::helpers::insert_use::ImportScope;
6use ide_db::imports_locator; 6use ide_db::imports_locator;
7use syntax::AstNode; 7use syntax::AstNode;
8use test_utils::mark; 8use test_utils::mark;
diff --git a/crates/completion/src/config.rs b/crates/completion/src/config.rs
index f50735372..654a76f7b 100644
--- a/crates/completion/src/config.rs
+++ b/crates/completion/src/config.rs
@@ -4,7 +4,7 @@
4//! module, and we use to statically check that we only produce snippet 4//! module, and we use to statically check that we only produce snippet
5//! completions if we are allowed to. 5//! completions if we are allowed to.
6 6
7use assists::utils::MergeBehaviour; 7use ide_db::helpers::insert_use::MergeBehaviour;
8 8
9#[derive(Clone, Debug, PartialEq, Eq)] 9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct CompletionConfig { 10pub struct CompletionConfig {
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs
index 7b62c2c4e..e85549fef 100644
--- a/crates/completion/src/item.rs
+++ b/crates/completion/src/item.rs
@@ -2,8 +2,11 @@
2 2
3use std::fmt; 3use std::fmt;
4 4
5use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour};
6use hir::{Documentation, ModPath, Mutability}; 5use hir::{Documentation, ModPath, Mutability};
6use ide_db::helpers::{
7 insert_use::{self, ImportScope, MergeBehaviour},
8 mod_path_to_ast,
9};
7use syntax::{algo, TextRange}; 10use syntax::{algo, TextRange};
8use text_edit::TextEdit; 11use text_edit::TextEdit;
9 12
@@ -201,7 +204,7 @@ impl CompletionItem {
201 trigger_call_info: None, 204 trigger_call_info: None,
202 score: None, 205 score: None,
203 ref_match: None, 206 ref_match: None,
204 import_data: None, 207 import_to_add: None,
205 } 208 }
206 } 209 }
207 210
@@ -255,13 +258,21 @@ impl CompletionItem {
255 } 258 }
256} 259}
257 260
261/// An extra import to add after the completion is applied.
262#[derive(Clone)]
263pub(crate) struct ImportToAdd {
264 pub(crate) import_path: ModPath,
265 pub(crate) import_scope: ImportScope,
266 pub(crate) merge_behaviour: Option<MergeBehaviour>,
267}
268
258/// A helper to make `CompletionItem`s. 269/// A helper to make `CompletionItem`s.
259#[must_use] 270#[must_use]
260#[derive(Clone)] 271#[derive(Clone)]
261pub(crate) struct Builder { 272pub(crate) struct Builder {
262 source_range: TextRange, 273 source_range: TextRange,
263 completion_kind: CompletionKind, 274 completion_kind: CompletionKind,
264 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, 275 import_to_add: Option<ImportToAdd>,
265 label: String, 276 label: String,
266 insert_text: Option<String>, 277 insert_text: Option<String>,
267 insert_text_format: InsertTextFormat, 278 insert_text_format: InsertTextFormat,
@@ -285,9 +296,9 @@ impl Builder {
285 let mut insert_text = self.insert_text; 296 let mut insert_text = self.insert_text;
286 let mut text_edits = TextEdit::builder(); 297 let mut text_edits = TextEdit::builder();
287 298
288 if let Some((import_path, import_scope, merge_behaviour)) = self.import_data { 299 if let Some(import_data) = self.import_to_add {
289 let import = mod_path_to_ast(&import_path); 300 let import = mod_path_to_ast(&import_data.import_path);
290 let mut import_path_without_last_segment = import_path; 301 let mut import_path_without_last_segment = import_data.import_path;
291 let _ = import_path_without_last_segment.segments.pop(); 302 let _ = import_path_without_last_segment.segments.pop();
292 303
293 if !import_path_without_last_segment.segments.is_empty() { 304 if !import_path_without_last_segment.segments.is_empty() {
@@ -300,7 +311,11 @@ impl Builder {
300 label = format!("{}::{}", import_path_without_last_segment, label); 311 label = format!("{}::{}", import_path_without_last_segment, label);
301 } 312 }
302 313
303 let rewriter = insert_use(&import_scope, import, merge_behaviour); 314 let rewriter = insert_use::insert_use(
315 &import_data.import_scope,
316 import,
317 import_data.merge_behaviour,
318 );
304 if let Some(old_ast) = rewriter.rewrite_root() { 319 if let Some(old_ast) = rewriter.rewrite_root() {
305 algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut text_edits); 320 algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut text_edits);
306 } 321 }
@@ -392,11 +407,8 @@ impl Builder {
392 self.trigger_call_info = Some(true); 407 self.trigger_call_info = Some(true);
393 self 408 self
394 } 409 }
395 pub(crate) fn import_data( 410 pub(crate) fn add_import(mut self, import_to_add: Option<ImportToAdd>) -> Builder {
396 mut self, 411 self.import_to_add = import_to_add;
397 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
398 ) -> Builder {
399 self.import_data = import_data;
400 self 412 self
401 } 413 }
402 pub(crate) fn set_ref_match( 414 pub(crate) fn set_ref_match(
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index bce02f577..504757a6a 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -9,15 +9,15 @@ pub(crate) mod type_alias;
9 9
10mod builder_ext; 10mod builder_ext;
11 11
12use assists::utils::{ImportScope, MergeBehaviour};
13use hir::{Documentation, HasAttrs, HirDisplay, ModPath, Mutability, ScopeDef, Type}; 12use hir::{Documentation, HasAttrs, HirDisplay, ModPath, Mutability, ScopeDef, Type};
13use ide_db::helpers::insert_use::{ImportScope, MergeBehaviour};
14use ide_db::RootDatabase; 14use ide_db::RootDatabase;
15use syntax::TextRange; 15use syntax::TextRange;
16use test_utils::mark; 16use test_utils::mark;
17 17
18use crate::{ 18use crate::{
19 config::SnippetCap, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, 19 config::SnippetCap, item::ImportToAdd, CompletionContext, CompletionItem, CompletionItemKind,
20 CompletionScore, 20 CompletionKind, CompletionScore,
21}; 21};
22 22
23use crate::render::{enum_variant::render_enum_variant, function::render_fn, macro_::render_macro}; 23use crate::render::{enum_variant::render_enum_variant, function::render_fn, macro_::render_macro};
@@ -48,15 +48,15 @@ pub(crate) fn render_resolution<'a>(
48 48
49pub(crate) fn render_resolution_with_import<'a>( 49pub(crate) fn render_resolution_with_import<'a>(
50 ctx: RenderContext<'a>, 50 ctx: RenderContext<'a>,
51 import: ModPath, 51 import_path: ModPath,
52 import_scope: ImportScope, 52 import_scope: ImportScope,
53 merge_behaviour: Option<MergeBehaviour>, 53 merge_behaviour: Option<MergeBehaviour>,
54 resolution: &ScopeDef, 54 resolution: &ScopeDef,
55) -> Option<CompletionItem> { 55) -> Option<CompletionItem> {
56 let local_name = import.segments.last()?.to_string(); 56 let local_name = import_path.segments.last()?.to_string();
57 Render::new(ctx).render_resolution( 57 Render::new(ctx).render_resolution(
58 local_name, 58 local_name,
59 Some((import, import_scope, merge_behaviour)), 59 Some(ImportToAdd { import_path, import_scope, merge_behaviour }),
60 resolution, 60 resolution,
61 ) 61 )
62} 62}
@@ -147,7 +147,7 @@ impl<'a> Render<'a> {
147 fn render_resolution( 147 fn render_resolution(
148 self, 148 self,
149 local_name: String, 149 local_name: String,
150 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, 150 import_to_add: Option<ImportToAdd>,
151 resolution: &ScopeDef, 151 resolution: &ScopeDef,
152 ) -> Option<CompletionItem> { 152 ) -> Option<CompletionItem> {
153 let _p = profile::span("render_resolution"); 153 let _p = profile::span("render_resolution");
@@ -160,15 +160,16 @@ impl<'a> Render<'a> {
160 160
161 let kind = match resolution { 161 let kind = match resolution {
162 ScopeDef::ModuleDef(Function(func)) => { 162 ScopeDef::ModuleDef(Function(func)) => {
163 let item = render_fn(self.ctx, import_data, Some(local_name), *func); 163 let item = render_fn(self.ctx, import_to_add, Some(local_name), *func);
164 return Some(item); 164 return Some(item);
165 } 165 }
166 ScopeDef::ModuleDef(EnumVariant(var)) => { 166 ScopeDef::ModuleDef(EnumVariant(var)) => {
167 let item = render_enum_variant(self.ctx, import_data, Some(local_name), *var, None); 167 let item =
168 render_enum_variant(self.ctx, import_to_add, Some(local_name), *var, None);
168 return Some(item); 169 return Some(item);
169 } 170 }
170 ScopeDef::MacroDef(mac) => { 171 ScopeDef::MacroDef(mac) => {
171 let item = render_macro(self.ctx, import_data, local_name, *mac); 172 let item = render_macro(self.ctx, import_to_add, local_name, *mac);
172 return item; 173 return item;
173 } 174 }
174 175
@@ -193,7 +194,7 @@ impl<'a> Render<'a> {
193 local_name, 194 local_name,
194 ) 195 )
195 .kind(CompletionItemKind::UnresolvedReference) 196 .kind(CompletionItemKind::UnresolvedReference)
196 .import_data(import_data) 197 .add_import(import_to_add)
197 .build(); 198 .build();
198 return Some(item); 199 return Some(item);
199 } 200 }
@@ -248,7 +249,7 @@ impl<'a> Render<'a> {
248 249
249 let item = item 250 let item = item
250 .kind(kind) 251 .kind(kind)
251 .import_data(import_data) 252 .add_import(import_to_add)
252 .set_documentation(docs) 253 .set_documentation(docs)
253 .set_ref_match(ref_match) 254 .set_ref_match(ref_match)
254 .build(); 255 .build();
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs
index 64e742b77..f4bd02f25 100644
--- a/crates/completion/src/render/enum_variant.rs
+++ b/crates/completion/src/render/enum_variant.rs
@@ -1,24 +1,23 @@
1//! Renderer for `enum` variants. 1//! Renderer for `enum` variants.
2 2
3use assists::utils::{ImportScope, MergeBehaviour};
4use hir::{HasAttrs, HirDisplay, ModPath, StructKind}; 3use hir::{HasAttrs, HirDisplay, ModPath, StructKind};
5use itertools::Itertools; 4use itertools::Itertools;
6use test_utils::mark; 5use test_utils::mark;
7 6
8use crate::{ 7use crate::{
9 item::{CompletionItem, CompletionItemKind, CompletionKind}, 8 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportToAdd},
10 render::{builder_ext::Params, RenderContext}, 9 render::{builder_ext::Params, RenderContext},
11}; 10};
12 11
13pub(crate) fn render_enum_variant<'a>( 12pub(crate) fn render_enum_variant<'a>(
14 ctx: RenderContext<'a>, 13 ctx: RenderContext<'a>,
15 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, 14 import_to_add: Option<ImportToAdd>,
16 local_name: Option<String>, 15 local_name: Option<String>,
17 variant: hir::EnumVariant, 16 variant: hir::EnumVariant,
18 path: Option<ModPath>, 17 path: Option<ModPath>,
19) -> CompletionItem { 18) -> CompletionItem {
20 let _p = profile::span("render_enum_variant"); 19 let _p = profile::span("render_enum_variant");
21 EnumVariantRender::new(ctx, local_name, variant, path).render(import_data) 20 EnumVariantRender::new(ctx, local_name, variant, path).render(import_to_add)
22} 21}
23 22
24#[derive(Debug)] 23#[derive(Debug)]
@@ -63,10 +62,7 @@ impl<'a> EnumVariantRender<'a> {
63 } 62 }
64 } 63 }
65 64
66 fn render( 65 fn render(self, import_to_add: Option<ImportToAdd>) -> CompletionItem {
67 self,
68 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
69 ) -> CompletionItem {
70 let mut builder = CompletionItem::new( 66 let mut builder = CompletionItem::new(
71 CompletionKind::Reference, 67 CompletionKind::Reference,
72 self.ctx.source_range(), 68 self.ctx.source_range(),
@@ -75,7 +71,7 @@ impl<'a> EnumVariantRender<'a> {
75 .kind(CompletionItemKind::EnumVariant) 71 .kind(CompletionItemKind::EnumVariant)
76 .set_documentation(self.variant.docs(self.ctx.db())) 72 .set_documentation(self.variant.docs(self.ctx.db()))
77 .set_deprecated(self.ctx.is_deprecated(self.variant)) 73 .set_deprecated(self.ctx.is_deprecated(self.variant))
78 .import_data(import_data) 74 .add_import(import_to_add)
79 .detail(self.detail()); 75 .detail(self.detail());
80 76
81 if self.variant_kind == StructKind::Tuple { 77 if self.variant_kind == StructKind::Tuple {
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
index e8b726ad6..542383d7e 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -1,22 +1,21 @@
1//! Renderer for function calls. 1//! Renderer for function calls.
2 2
3use assists::utils::{ImportScope, MergeBehaviour}; 3use hir::{HasSource, Type};
4use hir::{HasSource, ModPath, Type};
5use syntax::{ast::Fn, display::function_declaration}; 4use syntax::{ast::Fn, display::function_declaration};
6 5
7use crate::{ 6use crate::{
8 item::{CompletionItem, CompletionItemKind, CompletionKind}, 7 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportToAdd},
9 render::{builder_ext::Params, RenderContext}, 8 render::{builder_ext::Params, RenderContext},
10}; 9};
11 10
12pub(crate) fn render_fn<'a>( 11pub(crate) fn render_fn<'a>(
13 ctx: RenderContext<'a>, 12 ctx: RenderContext<'a>,
14 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, 13 import_to_add: Option<ImportToAdd>,
15 local_name: Option<String>, 14 local_name: Option<String>,
16 fn_: hir::Function, 15 fn_: hir::Function,
17) -> CompletionItem { 16) -> CompletionItem {
18 let _p = profile::span("render_fn"); 17 let _p = profile::span("render_fn");
19 FunctionRender::new(ctx, local_name, fn_).render(import_data) 18 FunctionRender::new(ctx, local_name, fn_).render(import_to_add)
20} 19}
21 20
22#[derive(Debug)] 21#[derive(Debug)]
@@ -39,10 +38,7 @@ impl<'a> FunctionRender<'a> {
39 FunctionRender { ctx, name, fn_, ast_node } 38 FunctionRender { ctx, name, fn_, ast_node }
40 } 39 }
41 40
42 fn render( 41 fn render(self, import_to_add: Option<ImportToAdd>) -> CompletionItem {
43 self,
44 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
45 ) -> CompletionItem {
46 let params = self.params(); 42 let params = self.params();
47 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone()) 43 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone())
48 .kind(self.kind()) 44 .kind(self.kind())
@@ -50,7 +46,7 @@ impl<'a> FunctionRender<'a> {
50 .set_deprecated(self.ctx.is_deprecated(self.fn_)) 46 .set_deprecated(self.ctx.is_deprecated(self.fn_))
51 .detail(self.detail()) 47 .detail(self.detail())
52 .add_call_parens(self.ctx.completion, self.name, params) 48 .add_call_parens(self.ctx.completion, self.name, params)
53 .import_data(import_data) 49 .add_import(import_to_add)
54 .build() 50 .build()
55 } 51 }
56 52
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs
index 91055a296..b4ab32c6e 100644
--- a/crates/completion/src/render/macro_.rs
+++ b/crates/completion/src/render/macro_.rs
@@ -1,23 +1,22 @@
1//! Renderer for macro invocations. 1//! Renderer for macro invocations.
2 2
3use assists::utils::{ImportScope, MergeBehaviour}; 3use hir::{Documentation, HasSource};
4use hir::{Documentation, HasSource, ModPath};
5use syntax::display::macro_label; 4use syntax::display::macro_label;
6use test_utils::mark; 5use test_utils::mark;
7 6
8use crate::{ 7use crate::{
9 item::{CompletionItem, CompletionItemKind, CompletionKind}, 8 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportToAdd},
10 render::RenderContext, 9 render::RenderContext,
11}; 10};
12 11
13pub(crate) fn render_macro<'a>( 12pub(crate) fn render_macro<'a>(
14 ctx: RenderContext<'a>, 13 ctx: RenderContext<'a>,
15 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, 14 import_to_add: Option<ImportToAdd>,
16 name: String, 15 name: String,
17 macro_: hir::MacroDef, 16 macro_: hir::MacroDef,
18) -> Option<CompletionItem> { 17) -> Option<CompletionItem> {
19 let _p = profile::span("render_macro"); 18 let _p = profile::span("render_macro");
20 MacroRender::new(ctx, name, macro_).render(import_data) 19 MacroRender::new(ctx, name, macro_).render(import_to_add)
21} 20}
22 21
23#[derive(Debug)] 22#[derive(Debug)]
@@ -39,10 +38,7 @@ impl<'a> MacroRender<'a> {
39 MacroRender { ctx, name, macro_, docs, bra, ket } 38 MacroRender { ctx, name, macro_, docs, bra, ket }
40 } 39 }
41 40
42 fn render( 41 fn render(&self, import_to_add: Option<ImportToAdd>) -> Option<CompletionItem> {
43 &self,
44 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
45 ) -> Option<CompletionItem> {
46 // FIXME: Currently proc-macro do not have ast-node, 42 // FIXME: Currently proc-macro do not have ast-node,
47 // such that it does not have source 43 // such that it does not have source
48 if self.macro_.is_proc_macro() { 44 if self.macro_.is_proc_macro() {
@@ -54,7 +50,7 @@ impl<'a> MacroRender<'a> {
54 .kind(CompletionItemKind::Macro) 50 .kind(CompletionItemKind::Macro)
55 .set_documentation(self.docs.clone()) 51 .set_documentation(self.docs.clone())
56 .set_deprecated(self.ctx.is_deprecated(self.macro_)) 52 .set_deprecated(self.ctx.is_deprecated(self.macro_))
57 .import_data(import_data) 53 .add_import(import_to_add)
58 .detail(self.detail()); 54 .detail(self.detail());
59 55
60 let needs_bang = self.needs_bang(); 56 let needs_bang = self.needs_bang();
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 6cfb22e13..65df7979c 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -1,6 +1,6 @@
1use assists::utils::FamousDefs;
2use either::Either; 1use either::Either;
3use hir::{known, Callable, HirDisplay, Semantics}; 2use hir::{known, Callable, HirDisplay, Semantics};
3use ide_db::helpers::FamousDefs;
4use ide_db::RootDatabase; 4use ide_db::RootDatabase;
5use stdx::to_lower_snake_case; 5use stdx::to_lower_snake_case;
6use syntax::{ 6use syntax::{
@@ -427,8 +427,8 @@ fn get_callable(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<hir:
427 427
428#[cfg(test)] 428#[cfg(test)]
429mod tests { 429mod tests {
430 use assists::utils::FamousDefs;
431 use expect_test::{expect, Expect}; 430 use expect_test::{expect, Expect};
431 use ide_db::helpers::FamousDefs;
432 use test_utils::extract_annotations; 432 use test_utils::extract_annotations;
433 433
434 use crate::{fixture, inlay_hints::InlayHintsConfig}; 434 use crate::{fixture, inlay_hints::InlayHintsConfig};
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 6288f7ea7..5244bdd61 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -87,9 +87,7 @@ pub use ide_db::{
87 search::{Reference, ReferenceAccess, ReferenceKind}, 87 search::{Reference, ReferenceAccess, ReferenceKind},
88}; 88};
89 89
90pub use assists::{ 90pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
91 utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist,
92};
93pub use hir::{Documentation, Semantics}; 91pub use hir::{Documentation, Semantics};
94pub use ide_db::base_db::{ 92pub use ide_db::base_db::{
95 Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot, 93 Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,
diff --git a/crates/ide_db/Cargo.toml b/crates/ide_db/Cargo.toml
index 72a9212f1..0ad6e1000 100644
--- a/crates/ide_db/Cargo.toml
+++ b/crates/ide_db/Cargo.toml
@@ -18,7 +18,8 @@ rayon = "1.5.0"
18fst = { version = "0.4", default-features = false } 18fst = { version = "0.4", default-features = false }
19rustc-hash = "1.1.0" 19rustc-hash = "1.1.0"
20once_cell = "1.3.1" 20once_cell = "1.3.1"
21either = "1.5.3" 21either = "1.6.1"
22itertools = "0.9.0"
22 23
23stdx = { path = "../stdx", version = "0.0.0" } 24stdx = { path = "../stdx", version = "0.0.0" }
24syntax = { path = "../syntax", version = "0.0.0" } 25syntax = { path = "../syntax", version = "0.0.0" }
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
new file mode 100644
index 000000000..d988588ff
--- /dev/null
+++ b/crates/ide_db/src/helpers.rs
@@ -0,0 +1,203 @@
1//! A module with ide helpers for high-level ide features.
2use crate::RootDatabase;
3use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait};
4use syntax::ast::{self, make};
5
6pub mod insert_use;
7
8/// Converts the mod path struct into its ast representation.
9pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
10 let _p = profile::span("mod_path_to_ast");
11
12 let mut segments = Vec::new();
13 let mut is_abs = false;
14 match path.kind {
15 hir::PathKind::Plain => {}
16 hir::PathKind::Super(0) => segments.push(make::path_segment_self()),
17 hir::PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
18 hir::PathKind::DollarCrate(_) | hir::PathKind::Crate => {
19 segments.push(make::path_segment_crate())
20 }
21 hir::PathKind::Abs => is_abs = true,
22 }
23
24 segments.extend(
25 path.segments
26 .iter()
27 .map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
28 );
29 make::path_from_segments(segments, is_abs)
30}
31
32/// Helps with finding well-know things inside the standard library. This is
33/// somewhat similar to the known paths infra inside hir, but it different; We
34/// want to make sure that IDE specific paths don't become interesting inside
35/// the compiler itself as well.
36pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>);
37
38#[allow(non_snake_case)]
39impl FamousDefs<'_, '_> {
40 pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core
41pub mod convert {
42 pub trait From<T> {
43 fn from(t: T) -> Self;
44 }
45}
46
47pub mod default {
48 pub trait Default {
49 fn default() -> Self;
50 }
51}
52
53pub mod iter {
54 pub use self::traits::{collect::IntoIterator, iterator::Iterator};
55 mod traits {
56 pub(crate) mod iterator {
57 use crate::option::Option;
58 pub trait Iterator {
59 type Item;
60 fn next(&mut self) -> Option<Self::Item>;
61 fn by_ref(&mut self) -> &mut Self {
62 self
63 }
64 fn take(self, n: usize) -> crate::iter::Take<Self> {
65 crate::iter::Take { inner: self }
66 }
67 }
68
69 impl<I: Iterator> Iterator for &mut I {
70 type Item = I::Item;
71 fn next(&mut self) -> Option<I::Item> {
72 (**self).next()
73 }
74 }
75 }
76 pub(crate) mod collect {
77 pub trait IntoIterator {
78 type Item;
79 }
80 }
81 }
82
83 pub use self::sources::*;
84 pub(crate) mod sources {
85 use super::Iterator;
86 use crate::option::Option::{self, *};
87 pub struct Repeat<A> {
88 element: A,
89 }
90
91 pub fn repeat<T>(elt: T) -> Repeat<T> {
92 Repeat { element: elt }
93 }
94
95 impl<A> Iterator for Repeat<A> {
96 type Item = A;
97
98 fn next(&mut self) -> Option<A> {
99 None
100 }
101 }
102 }
103
104 pub use self::adapters::*;
105 pub(crate) mod adapters {
106 use super::Iterator;
107 use crate::option::Option::{self, *};
108 pub struct Take<I> { pub(crate) inner: I }
109 impl<I> Iterator for Take<I> where I: Iterator {
110 type Item = <I as Iterator>::Item;
111 fn next(&mut self) -> Option<<I as Iterator>::Item> {
112 None
113 }
114 }
115 }
116}
117
118pub mod option {
119 pub enum Option<T> { None, Some(T)}
120}
121
122pub mod prelude {
123 pub use crate::{convert::From, iter::{IntoIterator, Iterator}, option::Option::{self, *}, default::Default};
124}
125#[prelude_import]
126pub use prelude::*;
127"#;
128
129 pub fn core(&self) -> Option<Crate> {
130 self.find_crate("core")
131 }
132
133 pub fn core_convert_From(&self) -> Option<Trait> {
134 self.find_trait("core:convert:From")
135 }
136
137 pub fn core_option_Option(&self) -> Option<Enum> {
138 self.find_enum("core:option:Option")
139 }
140
141 pub fn core_default_Default(&self) -> Option<Trait> {
142 self.find_trait("core:default:Default")
143 }
144
145 pub fn core_iter_Iterator(&self) -> Option<Trait> {
146 self.find_trait("core:iter:traits:iterator:Iterator")
147 }
148
149 pub fn core_iter(&self) -> Option<Module> {
150 self.find_module("core:iter")
151 }
152
153 fn find_trait(&self, path: &str) -> Option<Trait> {
154 match self.find_def(path)? {
155 hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
156 _ => None,
157 }
158 }
159
160 fn find_enum(&self, path: &str) -> Option<Enum> {
161 match self.find_def(path)? {
162 hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it),
163 _ => None,
164 }
165 }
166
167 fn find_module(&self, path: &str) -> Option<Module> {
168 match self.find_def(path)? {
169 hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(it)) => Some(it),
170 _ => None,
171 }
172 }
173
174 fn find_crate(&self, name: &str) -> Option<Crate> {
175 let krate = self.1?;
176 let db = self.0.db;
177 let res =
178 krate.dependencies(db).into_iter().find(|dep| dep.name.to_string() == name)?.krate;
179 Some(res)
180 }
181
182 fn find_def(&self, path: &str) -> Option<ScopeDef> {
183 let db = self.0.db;
184 let mut path = path.split(':');
185 let trait_ = path.next_back()?;
186 let std_crate = path.next()?;
187 let std_crate = self.find_crate(std_crate)?;
188 let mut module = std_crate.root_module(db);
189 for segment in path {
190 module = module.children(db).find_map(|child| {
191 let name = child.name(db)?;
192 if name.to_string() == segment {
193 Some(child)
194 } else {
195 None
196 }
197 })?;
198 }
199 let def =
200 module.scope(db, None).into_iter().find(|(name, _def)| name.to_string() == trait_)?.1;
201 Some(def)
202 }
203}
diff --git a/crates/assists/src/utils/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs
index 304adb93d..67e800fad 100644
--- a/crates/assists/src/utils/insert_use.rs
+++ b/crates/ide_db/src/helpers/insert_use.rs
@@ -1,8 +1,8 @@
1//! Handle syntactic aspects of inserting a new `use`. 1//! Handle syntactic aspects of inserting a new `use`.
2use std::{cmp::Ordering, iter::successors}; 2use std::{cmp::Ordering, iter::successors};
3 3
4use crate::RootDatabase;
4use hir::Semantics; 5use hir::Semantics;
5use ide_db::RootDatabase;
6use itertools::{EitherOrBoth, Itertools}; 6use itertools::{EitherOrBoth, Itertools};
7use syntax::{ 7use syntax::{
8 algo::SyntaxRewriter, 8 algo::SyntaxRewriter,
@@ -22,7 +22,7 @@ pub enum ImportScope {
22} 22}
23 23
24impl ImportScope { 24impl ImportScope {
25 pub(crate) fn from(syntax: SyntaxNode) -> Option<Self> { 25 pub fn from(syntax: SyntaxNode) -> Option<Self> {
26 if let Some(module) = ast::Module::cast(syntax.clone()) { 26 if let Some(module) = ast::Module::cast(syntax.clone()) {
27 module.item_list().map(ImportScope::Module) 27 module.item_list().map(ImportScope::Module)
28 } else if let this @ Some(_) = ast::SourceFile::cast(syntax.clone()) { 28 } else if let this @ Some(_) = ast::SourceFile::cast(syntax.clone()) {
@@ -180,7 +180,7 @@ fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -
180 } 180 }
181} 181}
182 182
183pub(crate) fn try_merge_imports( 183pub fn try_merge_imports(
184 lhs: &ast::Use, 184 lhs: &ast::Use,
185 rhs: &ast::Use, 185 rhs: &ast::Use,
186 merge_behaviour: MergeBehaviour, 186 merge_behaviour: MergeBehaviour,
@@ -195,7 +195,7 @@ pub(crate) fn try_merge_imports(
195 Some(lhs.with_use_tree(merged)) 195 Some(lhs.with_use_tree(merged))
196} 196}
197 197
198pub(crate) fn try_merge_trees( 198pub fn try_merge_trees(
199 lhs: &ast::UseTree, 199 lhs: &ast::UseTree,
200 rhs: &ast::UseTree, 200 rhs: &ast::UseTree,
201 merge: MergeBehaviour, 201 merge: MergeBehaviour,
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs
index 05139a651..fceaa089a 100644
--- a/crates/ide_db/src/lib.rs
+++ b/crates/ide_db/src/lib.rs
@@ -13,6 +13,7 @@ pub mod source_change;
13pub mod ty_filter; 13pub mod ty_filter;
14pub mod traits; 14pub mod traits;
15pub mod call_info; 15pub mod call_info;
16pub mod helpers;
16 17
17use std::{fmt, sync::Arc}; 18use std::{fmt, sync::Arc};
18 19
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 436f5041b..08559b53a 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -39,6 +39,7 @@ tracing-tree = { version = "0.1.4" }
39stdx = { path = "../stdx", version = "0.0.0" } 39stdx = { path = "../stdx", version = "0.0.0" }
40flycheck = { path = "../flycheck", version = "0.0.0" } 40flycheck = { path = "../flycheck", version = "0.0.0" }
41ide = { path = "../ide", version = "0.0.0" } 41ide = { path = "../ide", version = "0.0.0" }
42ide_db = { path = "../ide_db", version = "0.0.0" }
42profile = { path = "../profile", version = "0.0.0" } 43profile = { path = "../profile", version = "0.0.0" }
43project_model = { path = "../project_model", version = "0.0.0" } 44project_model = { path = "../project_model", version = "0.0.0" }
44syntax = { path = "../syntax", version = "0.0.0" } 45syntax = { path = "../syntax", version = "0.0.0" }
@@ -49,7 +50,6 @@ cfg = { path = "../cfg", version = "0.0.0" }
49toolchain = { path = "../toolchain", version = "0.0.0" } 50toolchain = { path = "../toolchain", version = "0.0.0" }
50 51
51# This should only be used in CLI 52# This should only be used in CLI
52ide_db = { path = "../ide_db", version = "0.0.0" }
53ssr = { path = "../ssr", version = "0.0.0" } 53ssr = { path = "../ssr", version = "0.0.0" }
54hir = { path = "../hir", version = "0.0.0" } 54hir = { path = "../hir", version = "0.0.0" }
55hir_def = { path = "../hir_def", version = "0.0.0" } 55hir_def = { path = "../hir_def", version = "0.0.0" }
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index a334cdb11..30299a465 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -11,10 +11,8 @@ use std::{convert::TryFrom, ffi::OsString, path::PathBuf};
11 11
12use flycheck::FlycheckConfig; 12use flycheck::FlycheckConfig;
13use hir::PrefixKind; 13use hir::PrefixKind;
14use ide::{ 14use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig};
15 AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig, 15use ide_db::helpers::insert_use::MergeBehaviour;
16 MergeBehaviour,
17};
18use lsp_types::{ClientCapabilities, MarkupKind}; 16use lsp_types::{ClientCapabilities, MarkupKind};
19use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; 17use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
20use rustc_hash::FxHashSet; 18use rustc_hash::FxHashSet;