diff options
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 = [ | |||
253 | name = "completion" | 254 | name = "completion" |
254 | version = "0.0.0" | 255 | version = "0.0.0" |
255 | dependencies = [ | 256 | dependencies = [ |
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]] |
699 | name = "ide_helpers" | ||
700 | version = "0.0.0" | ||
701 | dependencies = [ | ||
702 | "either", | ||
703 | "hir", | ||
704 | "ide_db", | ||
705 | "itertools", | ||
706 | "profile", | ||
707 | "syntax", | ||
708 | "test_utils", | ||
709 | ] | ||
710 | |||
711 | [[package]] | ||
697 | name = "idna" | 712 | name = "idna" |
698 | version = "0.2.0" | 713 | version = "0.2.0" |
699 | source = "registry+https://github.com/rust-lang/crates.io-index" | 714 | source = "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] |
13 | rustc-hash = "1.1.0" | 13 | rustc-hash = "1.1.0" |
14 | itertools = "0.9.0" | 14 | itertools = "0.9.0" |
15 | either = "1.5.3" | 15 | either = "1.6.1" |
16 | 16 | ||
17 | stdx = { path = "../stdx", version = "0.0.0" } | 17 | stdx = { path = "../stdx", version = "0.0.0" } |
18 | syntax = { path = "../syntax", version = "0.0.0" } | 18 | syntax = { path = "../syntax", version = "0.0.0" } |
@@ -21,3 +21,4 @@ profile = { path = "../profile", version = "0.0.0" } | |||
21 | ide_db = { path = "../ide_db", version = "0.0.0" } | 21 | ide_db = { path = "../ide_db", version = "0.0.0" } |
22 | hir = { path = "../hir", version = "0.0.0" } | 22 | hir = { path = "../hir", version = "0.0.0" } |
23 | test_utils = { path = "../test_utils", version = "0.0.0" } | 23 | test_utils = { path = "../test_utils", version = "0.0.0" } |
24 | ide_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 | ||
7 | use hir::PrefixKind; | 7 | use hir::PrefixKind; |
8 | use ide_helpers::insert_use::MergeBehaviour; | ||
8 | 9 | ||
9 | use crate::{utils::MergeBehaviour, AssistKind}; | 10 | use crate::AssistKind; |
10 | 11 | ||
11 | #[derive(Clone, Debug, PartialEq, Eq)] | 12 | #[derive(Clone, Debug, PartialEq, Eq)] |
12 | pub struct AssistConfig { | 13 | pub 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. |
2 | use hir::{HirDisplay, PathResolution, SemanticsScope}; | 2 | use hir::{HirDisplay, PathResolution, SemanticsScope}; |
3 | use ide_helpers::mod_path_to_ast; | ||
3 | use rustc_hash::FxHashMap; | 4 | use rustc_hash::FxHashMap; |
4 | use syntax::{ | 5 | use syntax::{ |
5 | algo::SyntaxRewriter, | 6 | algo::SyntaxRewriter, |
@@ -7,8 +8,6 @@ use syntax::{ | |||
7 | SyntaxNode, | 8 | SyntaxNode, |
8 | }; | 9 | }; |
9 | 10 | ||
10 | use crate::utils::mod_path_to_ast; | ||
11 | |||
12 | pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N { | 11 | pub 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 @@ | |||
1 | use ide_helpers::{ | ||
2 | insert_use::{insert_use, ImportScope}, | ||
3 | mod_path_to_ast, | ||
4 | }; | ||
1 | use syntax::ast; | 5 | use syntax::ast; |
2 | 6 | ||
3 | use crate::{ | 7 | use 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; | |||
3 | use either::Either; | 3 | use either::Either; |
4 | use hir::{AsName, EnumVariant, Module, ModuleDef, Name}; | 4 | use hir::{AsName, EnumVariant, Module, ModuleDef, Name}; |
5 | use ide_db::{defs::Definition, search::Reference, RootDatabase}; | 5 | use ide_db::{defs::Definition, search::Reference, RootDatabase}; |
6 | use ide_helpers::{ | ||
7 | insert_use::{insert_use, ImportScope}, | ||
8 | mod_path_to_ast, | ||
9 | }; | ||
6 | use rustc_hash::{FxHashMap, FxHashSet}; | 10 | use rustc_hash::{FxHashMap, FxHashSet}; |
7 | use syntax::{ | 11 | use 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 | ||
13 | use crate::{ | 17 | use 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)] |
238 | mod tests { | 239 | mod 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 | ||
3 | use hir::{Adt, HasSource, ModuleDef, Semantics}; | 3 | use hir::{Adt, HasSource, ModuleDef, Semantics}; |
4 | use ide_db::RootDatabase; | 4 | use ide_db::RootDatabase; |
5 | use ide_helpers::{mod_path_to_ast, FamousDefs}; | ||
5 | use itertools::Itertools; | 6 | use itertools::Itertools; |
6 | use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat}; | 7 | use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat}; |
7 | use test_utils::mark; | 8 | use test_utils::mark; |
8 | 9 | ||
9 | use crate::{ | 10 | use 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)] |
214 | mod tests { | 215 | mod 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 @@ | |||
1 | use ide_db::RootDatabase; | 1 | use ide_db::RootDatabase; |
2 | use ide_helpers::FamousDefs; | ||
2 | use syntax::ast::{self, AstNode, NameOwner}; | 3 | use syntax::ast::{self, AstNode, NameOwner}; |
3 | use test_utils::mark; | 4 | use test_utils::mark; |
4 | 5 | ||
5 | use crate::{utils::FamousDefs, AssistContext, AssistId, AssistKind, Assists}; | 6 | use 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 @@ | |||
1 | use ide_helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehaviour}; | ||
1 | use syntax::{ | 2 | use syntax::{ |
2 | algo::{neighbor, SyntaxRewriter}, | 3 | algo::{neighbor, SyntaxRewriter}, |
3 | ast, AstNode, | 4 | ast, AstNode, |
@@ -5,10 +6,7 @@ use syntax::{ | |||
5 | 6 | ||
6 | use crate::{ | 7 | use 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 | ||
3 | use hir::AsName; | 3 | use hir::AsName; |
4 | use ide_db::RootDatabase; | 4 | use ide_db::RootDatabase; |
5 | use ide_helpers::mod_path_to_ast; | ||
5 | use syntax::{ | 6 | use syntax::{ |
6 | ast, | 7 | ast, |
7 | ast::{make, ArgListOwner}, | 8 | ast::{make, ArgListOwner}, |
@@ -12,7 +13,6 @@ use test_utils::mark; | |||
12 | use crate::{ | 13 | use 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 @@ | |||
1 | use ide_db::imports_locator; | 1 | use ide_db::imports_locator; |
2 | use ide_helpers::mod_path_to_ast; | ||
2 | use itertools::Itertools; | 3 | use itertools::Itertools; |
3 | use syntax::{ | 4 | use syntax::{ |
4 | ast::{self, make, AstNode}, | 5 | ast::{self, make, AstNode}, |
@@ -10,8 +11,7 @@ use syntax::{ | |||
10 | use crate::{ | 11 | use 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 @@ | |||
1 | use ide_helpers::insert_use::{insert_use, ImportScope}; | ||
1 | use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode}; | 2 | use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode}; |
2 | use test_utils::mark; | 3 | use test_utils::mark; |
3 | 4 | ||
4 | use crate::{ | 5 | use 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 |
57 | fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: &ast::Path) { | 55 | fn 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. |
2 | pub(crate) mod insert_use; | ||
3 | pub(crate) mod import_assets; | 2 | pub(crate) mod import_assets; |
4 | 3 | ||
5 | use std::ops; | 4 | use std::ops; |
6 | 5 | ||
7 | use hir::{Crate, Enum, HasSource, Module, ScopeDef, Semantics, Trait}; | 6 | use hir::HasSource; |
8 | use ide_db::RootDatabase; | 7 | use ide_db::RootDatabase; |
9 | use itertools::Itertools; | 8 | use itertools::Itertools; |
10 | use syntax::{ | 9 | use 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 | ||
25 | pub use insert_use::{insert_use, ImportScope, MergeBehaviour}; | ||
26 | |||
27 | pub 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 | |||
49 | pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { | 24 | pub(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. | ||
267 | pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>); | ||
268 | |||
269 | #[allow(non_snake_case)] | ||
270 | impl FamousDefs<'_, '_> { | ||
271 | pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core | ||
272 | pub mod convert { | ||
273 | pub trait From<T> { | ||
274 | fn from(t: T) -> Self; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | pub mod default { | ||
279 | pub trait Default { | ||
280 | fn default() -> Self; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | pub 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 | |||
349 | pub mod option { | ||
350 | pub enum Option<T> { None, Some(T)} | ||
351 | } | ||
352 | |||
353 | pub mod prelude { | ||
354 | pub use crate::{convert::From, iter::{IntoIterator, Iterator}, option::Option::{self, *}, default::Default}; | ||
355 | } | ||
356 | #[prelude_import] | ||
357 | pub 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 | |||
436 | pub(crate) fn next_prev() -> impl Iterator<Item = Direction> { | 238 | pub(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" | |||
15 | rustc-hash = "1.1.0" | 15 | rustc-hash = "1.1.0" |
16 | either = "1.6.1" | 16 | either = "1.6.1" |
17 | 17 | ||
18 | assists = { path = "../assists", version = "0.0.0" } | ||
19 | stdx = { path = "../stdx", version = "0.0.0" } | 18 | stdx = { path = "../stdx", version = "0.0.0" } |
20 | syntax = { path = "../syntax", version = "0.0.0" } | 19 | syntax = { path = "../syntax", version = "0.0.0" } |
21 | text_edit = { path = "../text_edit", version = "0.0.0" } | 20 | text_edit = { path = "../text_edit", version = "0.0.0" } |
@@ -23,6 +22,7 @@ base_db = { path = "../base_db", version = "0.0.0" } | |||
23 | ide_db = { path = "../ide_db", version = "0.0.0" } | 22 | ide_db = { path = "../ide_db", version = "0.0.0" } |
24 | profile = { path = "../profile", version = "0.0.0" } | 23 | profile = { path = "../profile", version = "0.0.0" } |
25 | test_utils = { path = "../test_utils", version = "0.0.0" } | 24 | test_utils = { path = "../test_utils", version = "0.0.0" } |
25 | ide_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. |
2 | use assists::utils::FamousDefs; | 2 | use ide_helpers::FamousDefs; |
3 | use syntax::ast::Expr; | 3 | use syntax::ast::Expr; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
@@ -45,8 +45,8 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> | |||
45 | 45 | ||
46 | #[cfg(test)] | 46 | #[cfg(test)] |
47 | mod tests { | 47 | mod 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 | ||
3 | use assists::utils::ImportScope; | ||
4 | use either::Either; | 3 | use either::Either; |
5 | use hir::{Adt, ModuleDef, ScopeDef, Type}; | 4 | use hir::{Adt, ModuleDef, ScopeDef, Type}; |
6 | use ide_db::imports_locator; | 5 | use ide_db::imports_locator; |
6 | use ide_helpers::insert_use::ImportScope; | ||
7 | use syntax::AstNode; | 7 | use syntax::AstNode; |
8 | use test_utils::mark; | 8 | use 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 | ||
7 | use assists::utils::MergeBehaviour; | 7 | use ide_helpers::insert_use::MergeBehaviour; |
8 | 8 | ||
9 | #[derive(Clone, Debug, PartialEq, Eq)] | 9 | #[derive(Clone, Debug, PartialEq, Eq)] |
10 | pub struct CompletionConfig { | 10 | pub 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 | ||
3 | use std::fmt; | 3 | use std::fmt; |
4 | 4 | ||
5 | use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour}; | ||
6 | use hir::{Documentation, ModPath, Mutability}; | 5 | use hir::{Documentation, ModPath, Mutability}; |
6 | use ide_helpers::{ | ||
7 | insert_use::{self, ImportScope, MergeBehaviour}, | ||
8 | mod_path_to_ast, | ||
9 | }; | ||
7 | use syntax::{algo, TextRange}; | 10 | use syntax::{algo, TextRange}; |
8 | use text_edit::TextEdit; | 11 | use 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 | ||
10 | mod builder_ext; | 10 | mod builder_ext; |
11 | 11 | ||
12 | use assists::utils::{ImportScope, MergeBehaviour}; | ||
13 | use hir::{Documentation, HasAttrs, HirDisplay, ModPath, Mutability, ScopeDef, Type}; | 12 | use hir::{Documentation, HasAttrs, HirDisplay, ModPath, Mutability, ScopeDef, Type}; |
14 | use ide_db::RootDatabase; | 13 | use ide_db::RootDatabase; |
14 | use ide_helpers::insert_use::{ImportScope, MergeBehaviour}; | ||
15 | use syntax::TextRange; | 15 | use syntax::TextRange; |
16 | use test_utils::mark; | 16 | use 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 | ||
3 | use assists::utils::{ImportScope, MergeBehaviour}; | ||
4 | use hir::{HasAttrs, HirDisplay, ModPath, StructKind}; | 3 | use hir::{HasAttrs, HirDisplay, ModPath, StructKind}; |
4 | use ide_helpers::insert_use::{ImportScope, MergeBehaviour}; | ||
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | use test_utils::mark; | 6 | use 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 | ||
3 | use assists::utils::{ImportScope, MergeBehaviour}; | ||
4 | use hir::{HasSource, ModPath, Type}; | 3 | use hir::{HasSource, ModPath, Type}; |
4 | use ide_helpers::insert_use::{ImportScope, MergeBehaviour}; | ||
5 | use syntax::{ast::Fn, display::function_declaration}; | 5 | use syntax::{ast::Fn, display::function_declaration}; |
6 | 6 | ||
7 | use crate::{ | 7 | use 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 | ||
3 | use assists::utils::{ImportScope, MergeBehaviour}; | ||
4 | use hir::{Documentation, HasSource, ModPath}; | 3 | use hir::{Documentation, HasSource, ModPath}; |
4 | use ide_helpers::insert_use::{ImportScope, MergeBehaviour}; | ||
5 | use syntax::display::macro_label; | 5 | use syntax::display::macro_label; |
6 | use test_utils::mark; | 6 | use test_utils::mark; |
7 | 7 | ||
@@ -12,6 +12,7 @@ use crate::{ | |||
12 | 12 | ||
13 | pub(crate) fn render_macro<'a>( | 13 | pub(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" } | |||
24 | syntax = { path = "../syntax", version = "0.0.0" } | 24 | syntax = { path = "../syntax", version = "0.0.0" } |
25 | text_edit = { path = "../text_edit", version = "0.0.0" } | 25 | text_edit = { path = "../text_edit", version = "0.0.0" } |
26 | ide_db = { path = "../ide_db", version = "0.0.0" } | 26 | ide_db = { path = "../ide_db", version = "0.0.0" } |
27 | ide_helpers = { path = "../ide_helpers", version = "0.0.0" } | ||
27 | cfg = { path = "../cfg", version = "0.0.0" } | 28 | cfg = { path = "../cfg", version = "0.0.0" } |
28 | profile = { path = "../profile", version = "0.0.0" } | 29 | profile = { path = "../profile", version = "0.0.0" } |
29 | test_utils = { path = "../test_utils", version = "0.0.0" } | 30 | test_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 @@ | |||
1 | use assists::utils::FamousDefs; | ||
2 | use either::Either; | 1 | use either::Either; |
3 | use hir::{known, Callable, HirDisplay, Semantics}; | 2 | use hir::{known, Callable, HirDisplay, Semantics}; |
4 | use ide_db::RootDatabase; | 3 | use ide_db::RootDatabase; |
4 | use ide_helpers::FamousDefs; | ||
5 | use stdx::to_lower_snake_case; | 5 | use stdx::to_lower_snake_case; |
6 | use syntax::{ | 6 | use 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)] |
429 | mod tests { | 429 | mod 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 | ||
90 | pub use assists::{ | 90 | pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist}; |
91 | utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist, | ||
92 | }; | ||
93 | pub use hir::{Documentation, Semantics}; | 91 | pub use hir::{Documentation, Semantics}; |
94 | pub use ide_db::base_db::{ | 92 | pub 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] | ||
2 | name = "ide_helpers" | ||
3 | version = "0.0.0" | ||
4 | description = "A set of helper methods shared between various ide-level modules" | ||
5 | license = "MIT OR Apache-2.0" | ||
6 | authors = ["rust-analyzer developers"] | ||
7 | edition = "2018" | ||
8 | |||
9 | [lib] | ||
10 | doctest = false | ||
11 | |||
12 | [features] | ||
13 | wasm = [] | ||
14 | |||
15 | [dependencies] | ||
16 | either = "1.6.1" | ||
17 | itertools = "0.9.0" | ||
18 | |||
19 | syntax = { path = "../syntax", version = "0.0.0" } | ||
20 | ide_db = { path = "../ide_db", version = "0.0.0" } | ||
21 | hir = { path = "../hir", version = "0.0.0" } | ||
22 | profile = { path = "../profile", version = "0.0.0" } | ||
23 | test_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 | ||
24 | impl ImportScope { | 24 | impl 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 | ||
183 | pub(crate) fn try_merge_imports( | 183 | pub 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 | ||
198 | pub(crate) fn try_merge_trees( | 198 | pub 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 @@ | |||
1 | use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait}; | ||
2 | use ide_db::RootDatabase; | ||
3 | use syntax::ast::{self, make}; | ||
4 | |||
5 | pub mod insert_use; | ||
6 | |||
7 | pub 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. | ||
34 | pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>); | ||
35 | |||
36 | #[allow(non_snake_case)] | ||
37 | impl FamousDefs<'_, '_> { | ||
38 | pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core | ||
39 | pub mod convert { | ||
40 | pub trait From<T> { | ||
41 | fn from(t: T) -> Self; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | pub mod default { | ||
46 | pub trait Default { | ||
47 | fn default() -> Self; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | pub 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 | |||
116 | pub mod option { | ||
117 | pub enum Option<T> { None, Some(T)} | ||
118 | } | ||
119 | |||
120 | pub mod prelude { | ||
121 | pub use crate::{convert::From, iter::{IntoIterator, Iterator}, option::Option::{self, *}, default::Default}; | ||
122 | } | ||
123 | #[prelude_import] | ||
124 | pub 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" } | |||
39 | stdx = { path = "../stdx", version = "0.0.0" } | 39 | stdx = { path = "../stdx", version = "0.0.0" } |
40 | flycheck = { path = "../flycheck", version = "0.0.0" } | 40 | flycheck = { path = "../flycheck", version = "0.0.0" } |
41 | ide = { path = "../ide", version = "0.0.0" } | 41 | ide = { path = "../ide", version = "0.0.0" } |
42 | ide_helpers = { path = "../ide_helpers", version = "0.0.0" } | ||
42 | profile = { path = "../profile", version = "0.0.0" } | 43 | profile = { path = "../profile", version = "0.0.0" } |
43 | project_model = { path = "../project_model", version = "0.0.0" } | 44 | project_model = { path = "../project_model", version = "0.0.0" } |
44 | syntax = { path = "../syntax", version = "0.0.0" } | 45 | syntax = { 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 | ||
12 | use flycheck::FlycheckConfig; | 12 | use flycheck::FlycheckConfig; |
13 | use hir::PrefixKind; | 13 | use hir::PrefixKind; |
14 | use ide::{ | 14 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; |
15 | AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig, | 15 | use ide_helpers::insert_use::MergeBehaviour; |
16 | MergeBehaviour, | ||
17 | }; | ||
18 | use lsp_types::{ClientCapabilities, MarkupKind}; | 16 | use lsp_types::{ClientCapabilities, MarkupKind}; |
19 | use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; | 17 | use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; |
20 | use rustc_hash::FxHashSet; | 18 | use rustc_hash::FxHashSet; |