aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assists/add_import.rs9
-rw-r--r--crates/ra_assists/src/assists/auto_import.rs9
-rw-r--r--crates/ra_hir/src/lib.rs3
-rw-r--r--crates/ra_hir_def/src/path.rs4
-rw-r--r--crates/ra_hir_expand/src/name.rs6
-rw-r--r--crates/ra_ide/src/completion/complete_scope.rs71
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 @@
1use hir::{self, db::HirDatabase}; 1use hir::{self, db::HirDatabase, ModPath};
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, NameOwner}, 3 ast::{self, NameOwner},
4 AstNode, Direction, SmolStr, 4 AstNode, Direction, SmolStr,
@@ -21,9 +21,10 @@ pub fn auto_import_text_edit(
21 // The statement to use as anchor (last resort) 21 // The statement to use as anchor (last resort)
22 anchor: &SyntaxNode, 22 anchor: &SyntaxNode,
23 // The path to import as a sequence of strings 23 // The path to import as a sequence of strings
24 target: &[SmolStr], 24 path_to_import: &ModPath,
25 edit: &mut TextEditBuilder, 25 edit: &mut TextEditBuilder,
26) { 26) {
27 let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>();
27 let container = position.ancestors().find_map(|n| { 28 let container = position.ancestors().find_map(|n| {
28 if let Some(module) = ast::Module::cast(n.clone()) { 29 if let Some(module) = ast::Module::cast(n.clone()) {
29 return module.item_list().map(|it| it.syntax().clone()); 30 return module.item_list().map(|it| it.syntax().clone());
@@ -32,8 +33,8 @@ pub fn auto_import_text_edit(
32 }); 33 });
33 34
34 if let Some(container) = container { 35 if let Some(container) = container {
35 let action = best_action_for_target(container, anchor.clone(), target); 36 let action = best_action_for_target(container, anchor.clone(), &target);
36 make_assist(&action, target, edit); 37 make_assist(&action, &target, edit);
37 } 38 }
38} 39}
39 40
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 @@
1use hir::db::HirDatabase; 1use hir::{db::HirDatabase, ModPath};
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, AstNode}, 3 ast::{self, AstNode},
4 SmolStr,
5 SyntaxKind::USE_ITEM, 4 SyntaxKind::USE_ITEM,
6 SyntaxNode, 5 SyntaxNode,
7}; 6};
@@ -58,7 +57,6 @@ pub(crate) fn auto_import<F: ImportsLocator>(
58 .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def)) 57 .filter_map(|module_def| module_with_name_to_import.find_use_path(ctx.db, module_def))
59 .filter(|use_path| !use_path.segments.is_empty()) 58 .filter(|use_path| !use_path.segments.is_empty())
60 .take(20) 59 .take(20)
61 .map(|import| import.to_string())
62 .collect::<std::collections::BTreeSet<_>>(); 60 .collect::<std::collections::BTreeSet<_>>();
63 if proposed_imports.is_empty() { 61 if proposed_imports.is_empty() {
64 return None; 62 return None;
@@ -76,11 +74,10 @@ pub(crate) fn auto_import<F: ImportsLocator>(
76 ) 74 )
77} 75}
78 76
79fn import_to_action(import: String, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder { 77fn import_to_action(import: ModPath, position: &SyntaxNode, anchor: &SyntaxNode) -> ActionBuilder {
80 let mut action_builder = ActionBuilder::default(); 78 let mut action_builder = ActionBuilder::default();
81 action_builder.label(format!("Import `{}`", &import)); 79 action_builder.label(format!("Import `{}`", &import));
82 let import_segments = import.split("::").map(SmolStr::new).collect::<Vec<_>>(); 80 auto_import_text_edit(position, anchor, &import, action_builder.text_edit_builder());
83 auto_import_text_edit(position, anchor, &import_segments, action_builder.text_edit_builder());
84 action_builder 81 action_builder
85} 82}
86 83
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::{
59 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. 59 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.
60}; 60};
61pub use hir_expand::{ 61pub use hir_expand::{
62 name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, 62 name::{known, Name},
63 HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin,
63}; 64};
64pub use hir_ty::{display::HirDisplay, CallableDef}; 65pub 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;
16 16
17use crate::{type_ref::TypeRef, InFile}; 17use crate::{type_ref::TypeRef, InFile};
18 18
19#[derive(Debug, Clone, PartialEq, Eq, Hash)] 19#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub struct ModPath { 20pub struct ModPath {
21 pub kind: PathKind, 21 pub kind: PathKind,
22 pub segments: Vec<Name>, 22 pub segments: Vec<Name>,
23} 23}
24 24
25#[derive(Debug, Clone, PartialEq, Eq, Hash)] 25#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
26pub enum PathKind { 26pub enum PathKind {
27 Plain, 27 Plain,
28 /// `self::` is `Super(0)` 28 /// `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 {
143 std, 143 std,
144 core, 144 core,
145 alloc, 145 alloc,
146 hash,
147 fmt,
148 io,
146 iter, 149 iter,
147 ops, 150 ops,
148 future, 151 future,
@@ -167,6 +170,9 @@ pub mod known {
167 Neg, 170 Neg,
168 Not, 171 Not,
169 Index, 172 Index,
173 Display,
174 Iterator,
175 Hasher,
170 // Builtin macros 176 // Builtin macros
171 file, 177 file,
172 column, 178 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;
6use rustc_hash::FxHashMap; 6use rustc_hash::FxHashMap;
7 7
8use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions}; 8use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions};
9use hir::{ModPath, PathKind};
9 10
10pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { 11pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
11 if !ctx.is_trivial_path { 12 if !ctx.is_trivial_path {
@@ -54,58 +55,80 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
54 } 55 }
55} 56}
56 57
57fn build_import_label(name: &str, path: &[SmolStr]) -> String { 58fn build_import_label(name: &str, path: &ModPath) -> String {
58 let mut buf = String::with_capacity(64); 59 let mut buf = String::with_capacity(64);
59 buf.push_str(name); 60 buf.push_str(name);
60 buf.push_str(" ("); 61 buf.push_str(" (");
61 fmt_import_path(path, &mut buf); 62 buf.push_str(&path.to_string());
62 buf.push_str(")"); 63 buf.push_str(")");
63 buf 64 buf
64} 65}
65 66
66fn fmt_import_path(path: &[SmolStr], buf: &mut String) {
67 let mut segments = path.iter();
68 if let Some(s) = segments.next() {
69 buf.push_str(&s);
70 }
71 for s in segments {
72 buf.push_str("::");
73 buf.push_str(&s);
74 }
75}
76
77#[derive(Debug, Clone, Default)] 67#[derive(Debug, Clone, Default)]
78pub(crate) struct ImportResolver { 68pub(crate) struct ImportResolver {
79 // todo: use fst crate or something like that 69 // todo: use fst crate or something like that
80 dummy_names: Vec<(SmolStr, Vec<SmolStr>)>, 70 dummy_names: Vec<(SmolStr, ModPath)>,
81} 71}
82 72
83impl ImportResolver { 73impl ImportResolver {
84 pub(crate) fn new() -> Self { 74 pub(crate) fn new() -> Self {
85 let dummy_names = vec![ 75 let dummy_names = vec![
86 (SmolStr::new("fmt"), vec![SmolStr::new("std"), SmolStr::new("fmt")]), 76 (
87 (SmolStr::new("io"), vec![SmolStr::new("std"), SmolStr::new("io")]), 77 SmolStr::new("fmt"),
88 (SmolStr::new("iter"), vec![SmolStr::new("std"), SmolStr::new("iter")]), 78 ModPath { kind: PathKind::Plain, segments: vec![hir::known::std, hir::known::fmt] },
89 (SmolStr::new("hash"), vec![SmolStr::new("std"), SmolStr::new("hash")]), 79 ),
80 (
81 SmolStr::new("io"),
82 ModPath { kind: PathKind::Plain, segments: vec![hir::known::std, hir::known::io] },
83 ),
84 (
85 SmolStr::new("iter"),
86 ModPath {
87 kind: PathKind::Plain,
88 segments: vec![hir::known::std, hir::known::iter],
89 },
90 ),
91 (
92 SmolStr::new("hash"),
93 ModPath {
94 kind: PathKind::Plain,
95 segments: vec![hir::known::std, hir::known::hash],
96 },
97 ),
90 ( 98 (
91 SmolStr::new("Debug"), 99 SmolStr::new("Debug"),
92 vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Debug")], 100 ModPath {
101 kind: PathKind::Plain,
102 segments: vec![hir::known::std, hir::known::fmt, hir::known::Debug],
103 },
93 ), 104 ),
94 ( 105 (
95 SmolStr::new("Display"), 106 SmolStr::new("Display"),
96 vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Display")], 107 ModPath {
108 kind: PathKind::Plain,
109 segments: vec![hir::known::std, hir::known::fmt, hir::known::Display],
110 },
97 ), 111 ),
98 ( 112 (
99 SmolStr::new("Hash"), 113 SmolStr::new("Hash"),
100 vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hash")], 114 ModPath {
115 kind: PathKind::Plain,
116 segments: vec![hir::known::std, hir::known::hash, hir::known::Hash],
117 },
101 ), 118 ),
102 ( 119 (
103 SmolStr::new("Hasher"), 120 SmolStr::new("Hasher"),
104 vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hasher")], 121 ModPath {
122 kind: PathKind::Plain,
123 segments: vec![hir::known::std, hir::known::hash, hir::known::Hasher],
124 },
105 ), 125 ),
106 ( 126 (
107 SmolStr::new("Iterator"), 127 SmolStr::new("Iterator"),
108 vec![SmolStr::new("std"), SmolStr::new("iter"), SmolStr::new("Iterator")], 128 ModPath {
129 kind: PathKind::Plain,
130 segments: vec![hir::known::std, hir::known::iter, hir::known::Iterator],
131 },
109 ), 132 ),
110 ]; 133 ];
111 134
@@ -115,7 +138,7 @@ impl ImportResolver {
115 // Returns a map of importable items filtered by name. 138 // Returns a map of importable items filtered by name.
116 // The map associates item name with its full path. 139 // The map associates item name with its full path.
117 // todo: should return Resolutions 140 // todo: should return Resolutions
118 pub(crate) fn all_names(&self, name: &str) -> FxHashMap<SmolStr, Vec<SmolStr>> { 141 pub(crate) fn all_names(&self, name: &str) -> FxHashMap<SmolStr, ModPath> {
119 if name.len() > 1 { 142 if name.len() > 1 {
120 self.dummy_names.iter().filter(|(n, _)| n.contains(name)).cloned().collect() 143 self.dummy_names.iter().filter(|(n, _)| n.contains(name)).cloned().collect()
121 } else { 144 } else {