From a9669a5505939c28fd97e53e1bbb1571c2408cf1 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 2 Feb 2020 10:28:16 +0200 Subject: Merge imports when auto importing --- crates/ra_assists/src/assists/auto_import.rs | 36 +++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs index 932a52bff..0d15adb87 100644 --- a/crates/ra_assists/src/assists/auto_import.rs +++ b/crates/ra_assists/src/assists/auto_import.rs @@ -79,12 +79,8 @@ pub(crate) fn auto_import( fn import_to_action(import: String, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder { let mut action_builder = ActionBuilder::default(); action_builder.label(format!("Import `{}`", &import)); - auto_import_text_edit( - position, - anchor, - &[SmolStr::new(import)], - action_builder.text_edit_builder(), - ); + let import_segments = import.split("::").map(SmolStr::new).collect::>(); + auto_import_text_edit(position, anchor, &import_segments, action_builder.text_edit_builder()); action_builder } @@ -120,6 +116,34 @@ mod tests { ); } + #[test] + fn auto_imports_are_merged() { + check_assist_with_imports_locator( + auto_import, + TestImportsLocator::new, + r" + use PubMod::PubStruct1; + + PubStruct2<|> + + pub mod PubMod { + pub struct PubStruct1; + pub struct PubStruct2; + } + ", + r" + use PubMod::{PubStruct2, PubStruct1}; + + PubStruct2<|> + + pub mod PubMod { + pub struct PubStruct1; + pub struct PubStruct2; + } + ", + ); + } + #[test] fn applicable_when_found_multiple_imports() { check_assist_with_imports_locator( -- cgit v1.2.3 From 6dae5cbb1190cde6a20aa1758c7d87e84933378e Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 2 Feb 2020 14:06:51 +0200 Subject: Require ModPath for importing --- crates/ra_assists/src/assists/add_import.rs | 9 ++-- crates/ra_assists/src/assists/auto_import.rs | 9 ++-- crates/ra_hir/src/lib.rs | 3 +- crates/ra_hir_def/src/path.rs | 4 +- crates/ra_hir_expand/src/name.rs | 6 +++ crates/ra_ide/src/completion/complete_scope.rs | 71 +++++++++++++++++--------- 6 files changed, 65 insertions(+), 37 deletions(-) diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs index bf6cfe865..96a494c93 100644 --- a/crates/ra_assists/src/assists/add_import.rs +++ b/crates/ra_assists/src/assists/add_import.rs @@ -1,4 +1,4 @@ -use hir::{self, db::HirDatabase}; +use hir::{self, db::HirDatabase, ModPath}; use ra_syntax::{ ast::{self, NameOwner}, AstNode, Direction, SmolStr, @@ -21,9 +21,10 @@ pub fn auto_import_text_edit( // The statement to use as anchor (last resort) anchor: &SyntaxNode, // The path to import as a sequence of strings - target: &[SmolStr], + path_to_import: &ModPath, edit: &mut TextEditBuilder, ) { + let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::>(); let container = position.ancestors().find_map(|n| { if let Some(module) = ast::Module::cast(n.clone()) { return module.item_list().map(|it| it.syntax().clone()); @@ -32,8 +33,8 @@ pub fn auto_import_text_edit( }); if let Some(container) = container { - let action = best_action_for_target(container, anchor.clone(), target); - make_assist(&action, target, edit); + let action = best_action_for_target(container, anchor.clone(), &target); + make_assist(&action, &target, edit); } } diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs index 0d15adb87..9e874aebb 100644 --- a/crates/ra_assists/src/assists/auto_import.rs +++ b/crates/ra_assists/src/assists/auto_import.rs @@ -1,7 +1,6 @@ -use hir::db::HirDatabase; +use hir::{db::HirDatabase, ModPath}; use ra_syntax::{ ast::{self, AstNode}, - SmolStr, SyntaxKind::USE_ITEM, SyntaxNode, }; @@ -58,7 +57,6 @@ pub(crate) fn auto_import( .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) .filter(|use_path| !use_path.segments.is_empty()) .take(20) - .map(|import| import.to_string()) .collect::>(); if proposed_imports.is_empty() { return None; @@ -76,11 +74,10 @@ pub(crate) fn auto_import( ) } -fn import_to_action(import: String, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder { +fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder { let mut action_builder = ActionBuilder::default(); action_builder.label(format!("Import `{}`", &import)); - let import_segments = import.split("::").map(SmolStr::new).collect::>(); - auto_import_text_edit(position, anchor, &import_segments, action_builder.text_edit_builder()); + auto_import_text_edit(position, anchor, &import, action_builder.text_edit_builder()); action_builder } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 9e2673d13..64b55860d 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -59,6 +59,7 @@ pub use hir_def::{ ModuleDefId, // FIXME this is exposed and should be used for implementing the `TestImportsLocator` in `ra_assists` only, should be removed later along with the trait and the implementation. }; pub use hir_expand::{ - name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, + name::{known, Name}, + HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, }; pub use hir_ty::{display::HirDisplay, CallableDef}; diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index ab290e2c9..a150b899f 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -16,13 +16,13 @@ use ra_syntax::ast; use crate::{type_ref::TypeRef, InFile}; -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ModPath { pub kind: PathKind, pub segments: Vec, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum PathKind { Plain, /// `self::` is `Super(0)` diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index b2e10f445..44b47ec91 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -143,6 +143,9 @@ pub mod known { std, core, alloc, + hash, + fmt, + io, iter, ops, future, @@ -167,6 +170,9 @@ pub mod known { Neg, Not, Index, + Display, + Iterator, + Hasher, // Builtin macros file, column, diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index 458d7525e..fe0795984 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs @@ -6,6 +6,7 @@ use ra_text_edit::TextEditBuilder; use rustc_hash::FxHashMap; use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions}; +use hir::{ModPath, PathKind}; pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { if !ctx.is_trivial_path { @@ -54,58 +55,80 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { } } -fn build_import_label(name: &str, path: &[SmolStr]) -> String { +fn build_import_label(name: &str, path: &ModPath) -> String { let mut buf = String::with_capacity(64); buf.push_str(name); buf.push_str(" ("); - fmt_import_path(path, &mut buf); + buf.push_str(&path.to_string()); buf.push_str(")"); buf } -fn fmt_import_path(path: &[SmolStr], buf: &mut String) { - let mut segments = path.iter(); - if let Some(s) = segments.next() { - buf.push_str(&s); - } - for s in segments { - buf.push_str("::"); - buf.push_str(&s); - } -} - #[derive(Debug, Clone, Default)] pub(crate) struct ImportResolver { // todo: use fst crate or something like that - dummy_names: Vec<(SmolStr, Vec)>, + dummy_names: Vec<(SmolStr, ModPath)>, } impl ImportResolver { pub(crate) fn new() -> Self { let dummy_names = vec![ - (SmolStr::new("fmt"), vec![SmolStr::new("std"), SmolStr::new("fmt")]), - (SmolStr::new("io"), vec![SmolStr::new("std"), SmolStr::new("io")]), - (SmolStr::new("iter"), vec![SmolStr::new("std"), SmolStr::new("iter")]), - (SmolStr::new("hash"), vec![SmolStr::new("std"), SmolStr::new("hash")]), + ( + SmolStr::new("fmt"), + ModPath { kind: PathKind::Plain, segments: vec![hir::known::std, hir::known::fmt] }, + ), + ( + SmolStr::new("io"), + ModPath { kind: PathKind::Plain, segments: vec![hir::known::std, hir::known::io] }, + ), + ( + SmolStr::new("iter"), + ModPath { + kind: PathKind::Plain, + segments: vec![hir::known::std, hir::known::iter], + }, + ), + ( + SmolStr::new("hash"), + ModPath { + kind: PathKind::Plain, + segments: vec![hir::known::std, hir::known::hash], + }, + ), ( SmolStr::new("Debug"), - vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Debug")], + ModPath { + kind: PathKind::Plain, + segments: vec![hir::known::std, hir::known::fmt, hir::known::Debug], + }, ), ( SmolStr::new("Display"), - vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Display")], + ModPath { + kind: PathKind::Plain, + segments: vec![hir::known::std, hir::known::fmt, hir::known::Display], + }, ), ( SmolStr::new("Hash"), - vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hash")], + ModPath { + kind: PathKind::Plain, + segments: vec![hir::known::std, hir::known::hash, hir::known::Hash], + }, ), ( SmolStr::new("Hasher"), - vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hasher")], + ModPath { + kind: PathKind::Plain, + segments: vec![hir::known::std, hir::known::hash, hir::known::Hasher], + }, ), ( SmolStr::new("Iterator"), - vec![SmolStr::new("std"), SmolStr::new("iter"), SmolStr::new("Iterator")], + ModPath { + kind: PathKind::Plain, + segments: vec![hir::known::std, hir::known::iter, hir::known::Iterator], + }, ), ]; @@ -115,7 +138,7 @@ impl ImportResolver { // Returns a map of importable items filtered by name. // The map associates item name with its full path. // todo: should return Resolutions - pub(crate) fn all_names(&self, name: &str) -> FxHashMap> { + pub(crate) fn all_names(&self, name: &str) -> FxHashMap { if name.len() > 1 { self.dummy_names.iter().filter(|(n, _)| n.contains(name)).cloned().collect() } else { -- cgit v1.2.3 From c669b2f489cb551fbe53fd01f7532b5d55ffe704 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 2 Feb 2020 14:27:52 +0200 Subject: Code review fixes --- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir_expand/src/name.rs | 13 +++++++------ crates/ra_ide/src/completion/complete_scope.rs | 26 +++++++++++--------------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 64b55860d..ea06a4a58 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -59,7 +59,7 @@ pub use hir_def::{ ModuleDefId, // FIXME this is exposed and should be used for implementing the `TestImportsLocator` in `ra_assists` only, should be removed later along with the trait and the implementation. }; pub use hir_expand::{ - name::{known, Name}, + name::{name, Name}, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, }; pub use hir_ty::{display::HirDisplay, CallableDef}; diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 44b47ec91..133805bdb 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -143,9 +143,6 @@ pub mod known { std, core, alloc, - hash, - fmt, - io, iter, ops, future, @@ -170,9 +167,6 @@ pub mod known { Neg, Not, Index, - Display, - Iterator, - Hasher, // Builtin macros file, column, @@ -193,6 +187,13 @@ pub mod known { PartialOrd, Eq, PartialEq, + // FIXME delete those after `ImportResolver` is removed. + hash, + fmt, + io, + Display, + Iterator, + Hasher, ); // self/Self cannot be used as an identifier diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index fe0795984..64b04ec2b 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs @@ -72,62 +72,58 @@ pub(crate) struct ImportResolver { impl ImportResolver { pub(crate) fn new() -> Self { + use hir::name; + let dummy_names = vec![ ( SmolStr::new("fmt"), - ModPath { kind: PathKind::Plain, segments: vec![hir::known::std, hir::known::fmt] }, + ModPath { kind: PathKind::Plain, segments: vec![name![std], name![fmt]] }, ), ( SmolStr::new("io"), - ModPath { kind: PathKind::Plain, segments: vec![hir::known::std, hir::known::io] }, + ModPath { kind: PathKind::Plain, segments: vec![name![std], name![io]] }, ), ( SmolStr::new("iter"), - ModPath { - kind: PathKind::Plain, - segments: vec![hir::known::std, hir::known::iter], - }, + ModPath { kind: PathKind::Plain, segments: vec![name![std], name![iter]] }, ), ( SmolStr::new("hash"), - ModPath { - kind: PathKind::Plain, - segments: vec![hir::known::std, hir::known::hash], - }, + ModPath { kind: PathKind::Plain, segments: vec![name![std], name![hash]] }, ), ( SmolStr::new("Debug"), ModPath { kind: PathKind::Plain, - segments: vec![hir::known::std, hir::known::fmt, hir::known::Debug], + segments: vec![name![std], name![fmt], name![Debug]], }, ), ( SmolStr::new("Display"), ModPath { kind: PathKind::Plain, - segments: vec![hir::known::std, hir::known::fmt, hir::known::Display], + segments: vec![name![std], name![fmt], name![Display]], }, ), ( SmolStr::new("Hash"), ModPath { kind: PathKind::Plain, - segments: vec![hir::known::std, hir::known::hash, hir::known::Hash], + segments: vec![name![std], name![hash], name![Hash]], }, ), ( SmolStr::new("Hasher"), ModPath { kind: PathKind::Plain, - segments: vec![hir::known::std, hir::known::hash, hir::known::Hasher], + segments: vec![name![std], name![hash], name![Hasher]], }, ), ( SmolStr::new("Iterator"), ModPath { kind: PathKind::Plain, - segments: vec![hir::known::std, hir::known::iter, hir::known::Iterator], + segments: vec![name![std], name![iter], name![Iterator]], }, ), ]; -- cgit v1.2.3 From 2ee94e3e24a8cda1594eadba9c64a553ec046818 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 2 Feb 2020 14:59:07 +0200 Subject: Remove obsolete rustdoc --- crates/ra_assists/src/assists/add_import.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs index 96a494c93..fc038df78 100644 --- a/crates/ra_assists/src/assists/add_import.rs +++ b/crates/ra_assists/src/assists/add_import.rs @@ -20,7 +20,6 @@ pub fn auto_import_text_edit( position: &SyntaxNode, // The statement to use as anchor (last resort) anchor: &SyntaxNode, - // The path to import as a sequence of strings path_to_import: &ModPath, edit: &mut TextEditBuilder, ) { -- cgit v1.2.3