diff options
Diffstat (limited to 'crates/assists')
-rw-r--r-- | crates/assists/src/handlers/add_turbo_fish.rs | 4 | ||||
-rw-r--r-- | crates/assists/src/handlers/auto_import.rs | 55 | ||||
-rw-r--r-- | crates/assists/src/handlers/change_visibility.rs | 18 | ||||
-rw-r--r-- | crates/assists/src/handlers/expand_glob_import.rs | 4 | ||||
-rw-r--r-- | crates/assists/src/handlers/fill_match_arms.rs | 2 | ||||
-rw-r--r-- | crates/assists/src/handlers/fix_visibility.rs | 6 | ||||
-rw-r--r-- | crates/assists/src/handlers/generate_from_impl_for_enum.rs | 2 | ||||
-rw-r--r-- | crates/assists/src/utils.rs | 25 |
8 files changed, 94 insertions, 22 deletions
diff --git a/crates/assists/src/handlers/add_turbo_fish.rs b/crates/assists/src/handlers/add_turbo_fish.rs index f4f997d8e..e3d84d698 100644 --- a/crates/assists/src/handlers/add_turbo_fish.rs +++ b/crates/assists/src/handlers/add_turbo_fish.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use ide_db::defs::{classify_name_ref, Definition, NameRefClass}; | 1 | use ide_db::defs::{Definition, NameRefClass}; |
2 | use syntax::{ast, AstNode, SyntaxKind, T}; | 2 | use syntax::{ast, AstNode, SyntaxKind, T}; |
3 | use test_utils::mark; | 3 | use test_utils::mark; |
4 | 4 | ||
@@ -39,7 +39,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<( | |||
39 | return None; | 39 | return None; |
40 | } | 40 | } |
41 | let name_ref = ast::NameRef::cast(ident.parent())?; | 41 | let name_ref = ast::NameRef::cast(ident.parent())?; |
42 | let def = match classify_name_ref(&ctx.sema, &name_ref)? { | 42 | let def = match NameRefClass::classify(&ctx.sema, &name_ref)? { |
43 | NameRefClass::Definition(def) => def, | 43 | NameRefClass::Definition(def) => def, |
44 | NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None, | 44 | NameRefClass::ExternCrate(_) | NameRefClass::FieldShorthand { .. } => return None, |
45 | }; | 45 | }; |
diff --git a/crates/assists/src/handlers/auto_import.rs b/crates/assists/src/handlers/auto_import.rs index 13e390a1f..e49e641b3 100644 --- a/crates/assists/src/handlers/auto_import.rs +++ b/crates/assists/src/handlers/auto_import.rs | |||
@@ -6,6 +6,61 @@ use crate::{ | |||
6 | AssistContext, AssistId, AssistKind, Assists, GroupLabel, | 6 | AssistContext, AssistId, AssistKind, Assists, GroupLabel, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | // Feature: Auto Import | ||
10 | // | ||
11 | // Using the `auto-import` assist it is possible to insert missing imports for unresolved items. | ||
12 | // When inserting an import it will do so in a structured manner by keeping imports grouped, | ||
13 | // separated by a newline in the following order: | ||
14 | // | ||
15 | // - `std` and `core` | ||
16 | // - External Crates | ||
17 | // - Current Crate, paths prefixed by `crate` | ||
18 | // - Current Module, paths prefixed by `self` | ||
19 | // - Super Module, paths prefixed by `super` | ||
20 | // | ||
21 | // Example: | ||
22 | // ```rust | ||
23 | // use std::fs::File; | ||
24 | // | ||
25 | // use itertools::Itertools; | ||
26 | // use syntax::ast; | ||
27 | // | ||
28 | // use crate::utils::insert_use; | ||
29 | // | ||
30 | // use self::auto_import; | ||
31 | // | ||
32 | // use super::AssistContext; | ||
33 | // ``` | ||
34 | // | ||
35 | // .Merge Behaviour | ||
36 | // | ||
37 | // It is possible to configure how use-trees are merged with the `importMergeBehaviour` setting. | ||
38 | // It has the following configurations: | ||
39 | // | ||
40 | // - `full`: This setting will cause auto-import to always completely merge use-trees that share the | ||
41 | // same path prefix while also merging inner trees that share the same path-prefix. This kind of | ||
42 | // nesting is only supported in Rust versions later than 1.24. | ||
43 | // - `last`: This setting will cause auto-import to merge use-trees as long as the resulting tree | ||
44 | // will only contain a nesting of single segment paths at the very end. | ||
45 | // - `none`: This setting will cause auto-import to never merge use-trees keeping them as simple | ||
46 | // paths. | ||
47 | // | ||
48 | // In `VS Code` the configuration for this is `rust-analyzer.assist.importMergeBehaviour`. | ||
49 | // | ||
50 | // .Import Prefix | ||
51 | // | ||
52 | // The style of imports in the same crate is configurable through the `importPrefix` setting. | ||
53 | // It has the following configurations: | ||
54 | // | ||
55 | // - `by_crate`: This setting will force paths to be always absolute, starting with the `crate` | ||
56 | // prefix, unless the item is defined outside of the current crate. | ||
57 | // - `by_self`: This setting will force paths that are relative to the current module to always | ||
58 | // start with `self`. This will result in paths that always start with either `crate`, `self`, | ||
59 | // `super` or an extern crate identifier. | ||
60 | // - `plain`: This setting does not impose any restrictions in imports. | ||
61 | // | ||
62 | // In `VS Code` the configuration for this is `rust-analyzer.assist.importPrefix`. | ||
63 | |||
9 | // Assist: auto_import | 64 | // Assist: auto_import |
10 | // | 65 | // |
11 | // If the name is unresolved, provides all possible imports for it. | 66 | // If the name is unresolved, provides all possible imports for it. |
diff --git a/crates/assists/src/handlers/change_visibility.rs b/crates/assists/src/handlers/change_visibility.rs index 32dc05378..22d7c95d9 100644 --- a/crates/assists/src/handlers/change_visibility.rs +++ b/crates/assists/src/handlers/change_visibility.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use syntax::{ | 1 | use syntax::{ |
2 | ast::{self, NameOwner, VisibilityOwner}, | 2 | ast::{self, NameOwner, VisibilityOwner}, |
3 | AstNode, | 3 | AstNode, |
4 | SyntaxKind::{CONST, ENUM, FN, MODULE, STATIC, STRUCT, TRAIT, VISIBILITY}, | 4 | SyntaxKind::{CONST, ENUM, FN, MODULE, STATIC, STRUCT, TRAIT, TYPE_ALIAS, VISIBILITY}, |
5 | T, | 5 | T, |
6 | }; | 6 | }; |
7 | use test_utils::mark; | 7 | use test_utils::mark; |
@@ -30,13 +30,20 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | |||
30 | let item_keyword = ctx.token_at_offset().find(|leaf| { | 30 | let item_keyword = ctx.token_at_offset().find(|leaf| { |
31 | matches!( | 31 | matches!( |
32 | leaf.kind(), | 32 | leaf.kind(), |
33 | T![const] | T![static] | T![fn] | T![mod] | T![struct] | T![enum] | T![trait] | 33 | T![const] |
34 | | T![static] | ||
35 | | T![fn] | ||
36 | | T![mod] | ||
37 | | T![struct] | ||
38 | | T![enum] | ||
39 | | T![trait] | ||
40 | | T![type] | ||
34 | ) | 41 | ) |
35 | }); | 42 | }); |
36 | 43 | ||
37 | let (offset, target) = if let Some(keyword) = item_keyword { | 44 | let (offset, target) = if let Some(keyword) = item_keyword { |
38 | let parent = keyword.parent(); | 45 | let parent = keyword.parent(); |
39 | let def_kws = vec![CONST, STATIC, FN, MODULE, STRUCT, ENUM, TRAIT]; | 46 | let def_kws = vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT]; |
40 | // Parent is not a definition, can't add visibility | 47 | // Parent is not a definition, can't add visibility |
41 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { | 48 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) { |
42 | return None; | 49 | return None; |
@@ -160,6 +167,11 @@ mod tests { | |||
160 | } | 167 | } |
161 | 168 | ||
162 | #[test] | 169 | #[test] |
170 | fn change_visibility_type_alias() { | ||
171 | check_assist(change_visibility, "<|>type T = ();", "pub(crate) type T = ();"); | ||
172 | } | ||
173 | |||
174 | #[test] | ||
163 | fn change_visibility_handles_comment_attrs() { | 175 | fn change_visibility_handles_comment_attrs() { |
164 | check_assist( | 176 | check_assist( |
165 | change_visibility, | 177 | change_visibility, |
diff --git a/crates/assists/src/handlers/expand_glob_import.rs b/crates/assists/src/handlers/expand_glob_import.rs index d1adff972..316a58d88 100644 --- a/crates/assists/src/handlers/expand_glob_import.rs +++ b/crates/assists/src/handlers/expand_glob_import.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use either::Either; | 1 | use either::Either; |
2 | use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef}; | 2 | use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef}; |
3 | use ide_db::{ | 3 | use ide_db::{ |
4 | defs::{classify_name_ref, Definition, NameRefClass}, | 4 | defs::{Definition, NameRefClass}, |
5 | search::SearchScope, | 5 | search::SearchScope, |
6 | }; | 6 | }; |
7 | use syntax::{ | 7 | use syntax::{ |
@@ -217,7 +217,7 @@ fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def> | |||
217 | .flatten() | 217 | .flatten() |
218 | .filter_map(|n| Some(n.descendants().filter_map(ast::NameRef::cast))) | 218 | .filter_map(|n| Some(n.descendants().filter_map(ast::NameRef::cast))) |
219 | .flatten() | 219 | .flatten() |
220 | .filter_map(|r| match classify_name_ref(&ctx.sema, &r)? { | 220 | .filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? { |
221 | NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)), | 221 | NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)), |
222 | NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)), | 222 | NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)), |
223 | _ => None, | 223 | _ => None, |
diff --git a/crates/assists/src/handlers/fill_match_arms.rs b/crates/assists/src/handlers/fill_match_arms.rs index 676f5ad92..eda45f5b3 100644 --- a/crates/assists/src/handlers/fill_match_arms.rs +++ b/crates/assists/src/handlers/fill_match_arms.rs | |||
@@ -59,7 +59,7 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
59 | .filter(|variant_pat| is_variant_missing(&mut arms, variant_pat)) | 59 | .filter(|variant_pat| is_variant_missing(&mut arms, variant_pat)) |
60 | .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) | 60 | .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) |
61 | .collect::<Vec<_>>(); | 61 | .collect::<Vec<_>>(); |
62 | if Some(enum_def) == FamousDefs(&ctx.sema, module.krate()).core_option_Option() { | 62 | if Some(enum_def) == FamousDefs(&ctx.sema, Some(module.krate())).core_option_Option() { |
63 | // Match `Some` variant first. | 63 | // Match `Some` variant first. |
64 | mark::hit!(option_order); | 64 | mark::hit!(option_order); |
65 | variants.reverse() | 65 | variants.reverse() |
diff --git a/crates/assists/src/handlers/fix_visibility.rs b/crates/assists/src/handlers/fix_visibility.rs index d505e9444..66f74150c 100644 --- a/crates/assists/src/handlers/fix_visibility.rs +++ b/crates/assists/src/handlers/fix_visibility.rs | |||
@@ -1,9 +1,11 @@ | |||
1 | use base_db::FileId; | 1 | use base_db::FileId; |
2 | use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution}; | 2 | use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution}; |
3 | use syntax::{ast, AstNode, TextRange, TextSize}; | 3 | use syntax::{ |
4 | ast::{self, VisibilityOwner}, | ||
5 | AstNode, TextRange, TextSize, | ||
6 | }; | ||
4 | 7 | ||
5 | use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; | 8 | use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; |
6 | use ast::VisibilityOwner; | ||
7 | 9 | ||
8 | // FIXME: this really should be a fix for diagnostic, rather than an assist. | 10 | // FIXME: this really should be a fix for diagnostic, rather than an assist. |
9 | 11 | ||
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 7f04b9572..674e5a175 100644 --- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs +++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs | |||
@@ -75,7 +75,7 @@ fn existing_from_impl( | |||
75 | let enum_ = variant.parent_enum(sema.db); | 75 | let enum_ = variant.parent_enum(sema.db); |
76 | let krate = enum_.module(sema.db).krate(); | 76 | let krate = enum_.module(sema.db).krate(); |
77 | 77 | ||
78 | let from_trait = FamousDefs(sema, krate).core_convert_From()?; | 78 | let from_trait = FamousDefs(sema, Some(krate)).core_convert_From()?; |
79 | 79 | ||
80 | let enum_type = enum_.ty(sema.db); | 80 | let enum_type = enum_.ty(sema.db); |
81 | 81 | ||
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index b37b0d2b6..1a6b48b45 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs | |||
@@ -275,7 +275,7 @@ impl TryEnum { | |||
275 | /// somewhat similar to the known paths infra inside hir, but it different; We | 275 | /// somewhat similar to the known paths infra inside hir, but it different; We |
276 | /// want to make sure that IDE specific paths don't become interesting inside | 276 | /// want to make sure that IDE specific paths don't become interesting inside |
277 | /// the compiler itself as well. | 277 | /// the compiler itself as well. |
278 | pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Crate); | 278 | pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>); |
279 | 279 | ||
280 | #[allow(non_snake_case)] | 280 | #[allow(non_snake_case)] |
281 | impl FamousDefs<'_, '_> { | 281 | impl FamousDefs<'_, '_> { |
@@ -362,6 +362,10 @@ pub mod prelude { | |||
362 | pub use prelude::*; | 362 | pub use prelude::*; |
363 | "#; | 363 | "#; |
364 | 364 | ||
365 | pub fn core(&self) -> Option<Crate> { | ||
366 | self.find_crate("core") | ||
367 | } | ||
368 | |||
365 | pub(crate) fn core_convert_From(&self) -> Option<Trait> { | 369 | pub(crate) fn core_convert_From(&self) -> Option<Trait> { |
366 | self.find_trait("core:convert:From") | 370 | self.find_trait("core:convert:From") |
367 | } | 371 | } |
@@ -399,21 +403,20 @@ pub use prelude::*; | |||
399 | } | 403 | } |
400 | } | 404 | } |
401 | 405 | ||
406 | fn find_crate(&self, name: &str) -> Option<Crate> { | ||
407 | let krate = self.1?; | ||
408 | let db = self.0.db; | ||
409 | let res = | ||
410 | krate.dependencies(db).into_iter().find(|dep| dep.name.to_string() == name)?.krate; | ||
411 | Some(res) | ||
412 | } | ||
413 | |||
402 | fn find_def(&self, path: &str) -> Option<ScopeDef> { | 414 | fn find_def(&self, path: &str) -> Option<ScopeDef> { |
403 | let db = self.0.db; | 415 | let db = self.0.db; |
404 | let mut path = path.split(':'); | 416 | let mut path = path.split(':'); |
405 | let trait_ = path.next_back()?; | 417 | let trait_ = path.next_back()?; |
406 | let std_crate = path.next()?; | 418 | let std_crate = path.next()?; |
407 | let std_crate = if self | 419 | let std_crate = self.find_crate(std_crate)?; |
408 | .1 | ||
409 | .declaration_name(db) | ||
410 | .map(|name| name.to_string() == std_crate) | ||
411 | .unwrap_or(false) | ||
412 | { | ||
413 | self.1 | ||
414 | } else { | ||
415 | self.1.dependencies(db).into_iter().find(|dep| dep.name.to_string() == std_crate)?.krate | ||
416 | }; | ||
417 | let mut module = std_crate.root_module(db); | 420 | let mut module = std_crate.root_module(db); |
418 | for segment in path { | 421 | for segment in path { |
419 | module = module.children(db).find_map(|child| { | 422 | module = module.children(db).find_map(|child| { |