aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock18
-rw-r--r--crates/assists/Cargo.toml3
-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.rs8
-rw-r--r--crates/assists/src/utils.rs200
-rw-r--r--crates/completion/Cargo.toml2
-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.rs7
-rw-r--r--crates/completion/src/render.rs2
-rw-r--r--crates/completion/src/render/enum_variant.rs2
-rw-r--r--crates/completion/src/render/function.rs2
-rw-r--r--crates/completion/src/render/macro_.rs3
-rw-r--r--crates/ide/Cargo.toml1
-rw-r--r--crates/ide/src/inlay_hints.rs4
-rw-r--r--crates/ide/src/lib.rs4
-rw-r--r--crates/ide_helpers/Cargo.toml23
-rw-r--r--crates/ide_helpers/src/insert_use.rs (renamed from crates/assists/src/utils/insert_use.rs)6
-rw-r--r--crates/ide_helpers/src/lib.rs201
-rw-r--r--crates/rust-analyzer/Cargo.toml1
-rw-r--r--crates/rust-analyzer/src/config.rs6
30 files changed, 298 insertions, 254 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 633b99758..e7d1782cc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -53,6 +53,7 @@ dependencies = [
53 "either", 53 "either",
54 "hir", 54 "hir",
55 "ide_db", 55 "ide_db",
56 "ide_helpers",
56 "itertools", 57 "itertools",
57 "profile", 58 "profile",
58 "rustc-hash", 59 "rustc-hash",
@@ -253,12 +254,12 @@ dependencies = [
253name = "completion" 254name = "completion"
254version = "0.0.0" 255version = "0.0.0"
255dependencies = [ 256dependencies = [
256 "assists",
257 "base_db", 257 "base_db",
258 "either", 258 "either",
259 "expect-test", 259 "expect-test",
260 "hir", 260 "hir",
261 "ide_db", 261 "ide_db",
262 "ide_helpers",
262 "itertools", 263 "itertools",
263 "log", 264 "log",
264 "profile", 265 "profile",
@@ -657,6 +658,7 @@ dependencies = [
657 "expect-test", 658 "expect-test",
658 "hir", 659 "hir",
659 "ide_db", 660 "ide_db",
661 "ide_helpers",
660 "indexmap", 662 "indexmap",
661 "itertools", 663 "itertools",
662 "log", 664 "log",
@@ -694,6 +696,19 @@ dependencies = [
694] 696]
695 697
696[[package]] 698[[package]]
699name = "ide_helpers"
700version = "0.0.0"
701dependencies = [
702 "either",
703 "hir",
704 "ide_db",
705 "itertools",
706 "profile",
707 "syntax",
708 "test_utils",
709]
710
711[[package]]
697name = "idna" 712name = "idna"
698version = "0.2.0" 713version = "0.2.0"
699source = "registry+https://github.com/rust-lang/crates.io-index" 714source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1361,6 +1376,7 @@ dependencies = [
1361 "hir_ty", 1376 "hir_ty",
1362 "ide", 1377 "ide",
1363 "ide_db", 1378 "ide_db",
1379 "ide_helpers",
1364 "itertools", 1380 "itertools",
1365 "jod-thread", 1381 "jod-thread",
1366 "log", 1382 "log",
diff --git a/crates/assists/Cargo.toml b/crates/assists/Cargo.toml
index 108f656e9..91d9b6e3f 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" }
@@ -21,3 +21,4 @@ profile = { path = "../profile", version = "0.0.0" }
21ide_db = { path = "../ide_db", version = "0.0.0" } 21ide_db = { path = "../ide_db", version = "0.0.0" }
22hir = { path = "../hir", version = "0.0.0" } 22hir = { path = "../hir", version = "0.0.0" }
23test_utils = { path = "../test_utils", version = "0.0.0" } 23test_utils = { path = "../test_utils", version = "0.0.0" }
24ide_helpers = { path = "../ide_helpers", version = "0.0.0" }
diff --git a/crates/assists/src/assist_config.rs b/crates/assists/src/assist_config.rs
index b24527ec4..6d9934e93 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_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..95b060599 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_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..0b2d508d5 100644
--- a/crates/assists/src/handlers/auto_import.rs
+++ b/crates/assists/src/handlers/auto_import.rs
@@ -1,8 +1,11 @@
1use ide_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..fddd5354a 100644
--- a/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -3,6 +3,10 @@ use std::iter;
3use either::Either; 3use either::Either;
4use hir::{AsName, EnumVariant, Module, ModuleDef, Name}; 4use hir::{AsName, EnumVariant, Module, ModuleDef, Name};
5use ide_db::{defs::Definition, search::Reference, RootDatabase}; 5use ide_db::{defs::Definition, search::Reference, RootDatabase};
6use ide_helpers::{
7 insert_use::{insert_use, ImportScope},
8 mod_path_to_ast,
9};
6use rustc_hash::{FxHashMap, FxHashSet}; 10use rustc_hash::{FxHashMap, FxHashSet};
7use syntax::{ 11use syntax::{
8 algo::{find_node_at_offset, SyntaxRewriter}, 12 algo::{find_node_at_offset, SyntaxRewriter},
@@ -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_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..bd42e0f16 100644
--- a/crates/assists/src/handlers/fill_match_arms.rs
+++ b/crates/assists/src/handlers/fill_match_arms.rs
@@ -2,12 +2,13 @@ use std::iter;
2 2
3use hir::{Adt, HasSource, ModuleDef, Semantics}; 3use hir::{Adt, HasSource, ModuleDef, Semantics};
4use ide_db::RootDatabase; 4use ide_db::RootDatabase;
5use ide_helpers::{mod_path_to_ast, FamousDefs};
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_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..01b14d94d 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::RootDatabase; 1use ide_db::RootDatabase;
2use ide_helpers::FamousDefs;
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..8207f0e6e 100644
--- a/crates/assists/src/handlers/merge_imports.rs
+++ b/crates/assists/src/handlers/merge_imports.rs
@@ -1,3 +1,4 @@
1use ide_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..c0ee7ea0b 100644
--- a/crates/assists/src/handlers/qualify_path.rs
+++ b/crates/assists/src/handlers/qualify_path.rs
@@ -2,6 +2,7 @@ use std::iter;
2 2
3use hir::AsName; 3use hir::AsName;
4use ide_db::RootDatabase; 4use ide_db::RootDatabase;
5use ide_helpers::mod_path_to_ast;
5use syntax::{ 6use syntax::{
6 ast, 7 ast,
7 ast::{make, ArgListOwner}, 8 ast::{make, ArgListOwner},
@@ -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..fe262377c 100644
--- a/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -1,4 +1,5 @@
1use ide_db::imports_locator; 1use ide_db::imports_locator;
2use ide_helpers::mod_path_to_ast;
2use itertools::Itertools; 3use itertools::Itertools;
3use syntax::{ 4use syntax::{
4 ast::{self, make, AstNode}, 5 ast::{self, make, AstNode},
@@ -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..9b8caacd9 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_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//
@@ -53,7 +51,7 @@ pub(crate) fn replace_qualified_name_with_use(
53 ) 51 )
54} 52}
55 53
56/// Adds replacements to `re` that shorten `path` in all descendants of `node`. 54/// Adds replacements to `re` that shorten `path` in all descendants of `node`.g
57fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: &ast::Path) { 55fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: &ast::Path) {
58 for child in node.children() { 56 for child in node.children() {
59 match_ast! { 57 match_ast! {
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..102de33f8 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" }
@@ -23,6 +22,7 @@ base_db = { path = "../base_db", version = "0.0.0" }
23ide_db = { path = "../ide_db", version = "0.0.0" } 22ide_db = { path = "../ide_db", version = "0.0.0" }
24profile = { path = "../profile", version = "0.0.0" } 23profile = { path = "../profile", version = "0.0.0" }
25test_utils = { path = "../test_utils", version = "0.0.0" } 24test_utils = { path = "../test_utils", version = "0.0.0" }
25ide_helpers = { path = "../ide_helpers", version = "0.0.0" }
26 26
27# completions crate should depend only on the top-level `hir` package. if you need 27# completions crate should depend only on the top-level `hir` package. if you need
28# something from some `hir_xxx` subpackage, reexport the API via `hir`. 28# something from some `hir_xxx` subpackage, reexport the API via `hir`.
diff --git a/crates/completion/src/completions/record.rs b/crates/completion/src/completions/record.rs
index 2049b9d09..218a1923c 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_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_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..db5dbb7dd 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -1,9 +1,9 @@
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};
6use ide_db::imports_locator; 5use ide_db::imports_locator;
6use ide_helpers::insert_use::ImportScope;
7use syntax::AstNode; 7use syntax::AstNode;
8use test_utils::mark; 8use test_utils::mark;
9 9
diff --git a/crates/completion/src/config.rs b/crates/completion/src/config.rs
index f50735372..1995b0754 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_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..675cef8c4 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_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
@@ -300,7 +303,7 @@ impl Builder {
300 label = format!("{}::{}", import_path_without_last_segment, label); 303 label = format!("{}::{}", import_path_without_last_segment, label);
301 } 304 }
302 305
303 let rewriter = insert_use(&import_scope, import, merge_behaviour); 306 let rewriter = insert_use::insert_use(&import_scope, import, merge_behaviour);
304 if let Some(old_ast) = rewriter.rewrite_root() { 307 if let Some(old_ast) = rewriter.rewrite_root() {
305 algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut text_edits); 308 algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut text_edits);
306 } 309 }
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index bce02f577..e9704c27c 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -9,9 +9,9 @@ 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};
14use ide_db::RootDatabase; 13use ide_db::RootDatabase;
14use ide_helpers::insert_use::{ImportScope, MergeBehaviour};
15use syntax::TextRange; 15use syntax::TextRange;
16use test_utils::mark; 16use test_utils::mark;
17 17
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs
index 64e742b77..5d4fbb641 100644
--- a/crates/completion/src/render/enum_variant.rs
+++ b/crates/completion/src/render/enum_variant.rs
@@ -1,7 +1,7 @@
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};
4use ide_helpers::insert_use::{ImportScope, MergeBehaviour};
5use itertools::Itertools; 5use itertools::Itertools;
6use test_utils::mark; 6use test_utils::mark;
7 7
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
index e8b726ad6..07e99058a 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -1,7 +1,7 @@
1//! Renderer for function calls. 1//! Renderer for function calls.
2 2
3use assists::utils::{ImportScope, MergeBehaviour};
4use hir::{HasSource, ModPath, Type}; 3use hir::{HasSource, ModPath, Type};
4use ide_helpers::insert_use::{ImportScope, MergeBehaviour};
5use syntax::{ast::Fn, display::function_declaration}; 5use syntax::{ast::Fn, display::function_declaration};
6 6
7use crate::{ 7use crate::{
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs
index 91055a296..b1284f201 100644
--- a/crates/completion/src/render/macro_.rs
+++ b/crates/completion/src/render/macro_.rs
@@ -1,7 +1,7 @@
1//! Renderer for macro invocations. 1//! Renderer for macro invocations.
2 2
3use assists::utils::{ImportScope, MergeBehaviour};
4use hir::{Documentation, HasSource, ModPath}; 3use hir::{Documentation, HasSource, ModPath};
4use ide_helpers::insert_use::{ImportScope, MergeBehaviour};
5use syntax::display::macro_label; 5use syntax::display::macro_label;
6use test_utils::mark; 6use test_utils::mark;
7 7
@@ -12,6 +12,7 @@ use crate::{
12 12
13pub(crate) fn render_macro<'a>( 13pub(crate) fn render_macro<'a>(
14 ctx: RenderContext<'a>, 14 ctx: RenderContext<'a>,
15 // TODO kb add some object instead of a tuple?
15 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>, 16 import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
16 name: String, 17 name: String,
17 macro_: hir::MacroDef, 18 macro_: hir::MacroDef,
diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml
index 4d483580d..92d4e5e9f 100644
--- a/crates/ide/Cargo.toml
+++ b/crates/ide/Cargo.toml
@@ -24,6 +24,7 @@ stdx = { path = "../stdx", version = "0.0.0" }
24syntax = { path = "../syntax", version = "0.0.0" } 24syntax = { path = "../syntax", version = "0.0.0" }
25text_edit = { path = "../text_edit", version = "0.0.0" } 25text_edit = { path = "../text_edit", version = "0.0.0" }
26ide_db = { path = "../ide_db", version = "0.0.0" } 26ide_db = { path = "../ide_db", version = "0.0.0" }
27ide_helpers = { path = "../ide_helpers", version = "0.0.0" }
27cfg = { path = "../cfg", version = "0.0.0" } 28cfg = { path = "../cfg", version = "0.0.0" }
28profile = { path = "../profile", version = "0.0.0" } 29profile = { path = "../profile", version = "0.0.0" }
29test_utils = { path = "../test_utils", version = "0.0.0" } 30test_utils = { path = "../test_utils", version = "0.0.0" }
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 6cfb22e13..9c8bb7c45 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -1,7 +1,7 @@
1use assists::utils::FamousDefs;
2use either::Either; 1use either::Either;
3use hir::{known, Callable, HirDisplay, Semantics}; 2use hir::{known, Callable, HirDisplay, Semantics};
4use ide_db::RootDatabase; 3use ide_db::RootDatabase;
4use ide_helpers::FamousDefs;
5use stdx::to_lower_snake_case; 5use stdx::to_lower_snake_case;
6use syntax::{ 6use syntax::{
7 ast::{self, ArgListOwner, AstNode, NameOwner}, 7 ast::{self, ArgListOwner, AstNode, NameOwner},
@@ -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_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_helpers/Cargo.toml b/crates/ide_helpers/Cargo.toml
new file mode 100644
index 000000000..c5065b22b
--- /dev/null
+++ b/crates/ide_helpers/Cargo.toml
@@ -0,0 +1,23 @@
1[package]
2name = "ide_helpers"
3version = "0.0.0"
4description = "A set of helper methods shared between various ide-level modules"
5license = "MIT OR Apache-2.0"
6authors = ["rust-analyzer developers"]
7edition = "2018"
8
9[lib]
10doctest = false
11
12[features]
13wasm = []
14
15[dependencies]
16either = "1.6.1"
17itertools = "0.9.0"
18
19syntax = { path = "../syntax", version = "0.0.0" }
20ide_db = { path = "../ide_db", version = "0.0.0" }
21hir = { path = "../hir", version = "0.0.0" }
22profile = { path = "../profile", version = "0.0.0" }
23test_utils = { path = "../test_utils", version = "0.0.0" }
diff --git a/crates/assists/src/utils/insert_use.rs b/crates/ide_helpers/src/insert_use.rs
index 304adb93d..795009eb1 100644
--- a/crates/assists/src/utils/insert_use.rs
+++ b/crates/ide_helpers/src/insert_use.rs
@@ -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_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}
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 436f5041b..3afcd2eda 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_helpers = { path = "../ide_helpers", 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" }
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index a334cdb11..d7b711f94 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_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;