aboutsummaryrefslogtreecommitdiff
path: root/crates/assists
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists')
-rw-r--r--crates/assists/src/handlers/add_turbo_fish.rs4
-rw-r--r--crates/assists/src/handlers/auto_import.rs55
-rw-r--r--crates/assists/src/handlers/change_visibility.rs18
-rw-r--r--crates/assists/src/handlers/expand_glob_import.rs4
-rw-r--r--crates/assists/src/handlers/fill_match_arms.rs2
-rw-r--r--crates/assists/src/handlers/fix_visibility.rs6
-rw-r--r--crates/assists/src/handlers/generate_from_impl_for_enum.rs2
-rw-r--r--crates/assists/src/utils.rs25
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 @@
1use ide_db::defs::{classify_name_ref, Definition, NameRefClass}; 1use ide_db::defs::{Definition, NameRefClass};
2use syntax::{ast, AstNode, SyntaxKind, T}; 2use syntax::{ast, AstNode, SyntaxKind, T};
3use test_utils::mark; 3use 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 @@
1use syntax::{ 1use 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};
7use test_utils::mark; 7use 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 @@
1use either::Either; 1use either::Either;
2use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef}; 2use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef};
3use ide_db::{ 3use ide_db::{
4 defs::{classify_name_ref, Definition, NameRefClass}, 4 defs::{Definition, NameRefClass},
5 search::SearchScope, 5 search::SearchScope,
6}; 6};
7use syntax::{ 7use 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 @@
1use base_db::FileId; 1use base_db::FileId;
2use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution}; 2use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution};
3use syntax::{ast, AstNode, TextRange, TextSize}; 3use syntax::{
4 ast::{self, VisibilityOwner},
5 AstNode, TextRange, TextSize,
6};
4 7
5use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists}; 8use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
6use 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.
278pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Crate); 278pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>);
279 279
280#[allow(non_snake_case)] 280#[allow(non_snake_case)]
281impl FamousDefs<'_, '_> { 281impl FamousDefs<'_, '_> {
@@ -362,6 +362,10 @@ pub mod prelude {
362pub use prelude::*; 362pub 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| {