aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-04-22 13:56:28 +0100
committerAleksey Kladov <[email protected]>2019-04-22 13:56:28 +0100
commite01052d1f0b8bf70a418a10538528923c5f400d5 (patch)
tree18ed1c151e7782b791214df4c4a2966c617ae1c6 /crates
parent200032852be0c66b978c875a8edf0eca1f08b901 (diff)
move auto-imoprter into IDE
auto-import is purely an IDE concern, so it should be done outside of HIR
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/auto_import.rs4
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/name.rs13
-rw-r--r--crates/ra_hir/src/resolve.rs59
-rw-r--r--crates/ra_hir/src/source_binder.rs15
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs55
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs12
7 files changed, 68 insertions, 92 deletions
diff --git a/crates/ra_assists/src/auto_import.rs b/crates/ra_assists/src/auto_import.rs
index b002d0e4d..7c856c19b 100644
--- a/crates/ra_assists/src/auto_import.rs
+++ b/crates/ra_assists/src/auto_import.rs
@@ -492,7 +492,6 @@ fn apply_auto_import(
492 } 492 }
493} 493}
494 494
495#[allow(unused)]
496pub fn collect_hir_path_segments(path: &hir::Path) -> Vec<SmolStr> { 495pub fn collect_hir_path_segments(path: &hir::Path) -> Vec<SmolStr> {
497 let mut ps = Vec::<SmolStr>::with_capacity(10); 496 let mut ps = Vec::<SmolStr>::with_capacity(10);
498 match path.kind { 497 match path.kind {
@@ -503,7 +502,7 @@ pub fn collect_hir_path_segments(path: &hir::Path) -> Vec<SmolStr> {
503 hir::PathKind::Super => ps.push("super".into()), 502 hir::PathKind::Super => ps.push("super".into()),
504 } 503 }
505 for s in path.segments.iter() { 504 for s in path.segments.iter() {
506 ps.push(s.name.to_smolstr()); 505 ps.push(s.name.to_string().into());
507 } 506 }
508 ps 507 ps
509} 508}
@@ -511,7 +510,6 @@ pub fn collect_hir_path_segments(path: &hir::Path) -> Vec<SmolStr> {
511// This function produces sequence of text edits into edit 510// This function produces sequence of text edits into edit
512// to import the target path in the most appropriate scope given 511// to import the target path in the most appropriate scope given
513// the cursor position 512// the cursor position
514#[allow(unused)]
515pub fn auto_import_text_edit( 513pub fn auto_import_text_edit(
516 // Ideally the position of the cursor, used to 514 // Ideally the position of the cursor, used to
517 position: &SyntaxNode, 515 position: &SyntaxNode,
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index f156e3f07..4411715de 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -52,7 +52,7 @@ use crate::{
52 db::{HirDatabase, DefDatabase}, 52 db::{HirDatabase, DefDatabase},
53 name::{AsName, KnownName}, 53 name::{AsName, KnownName},
54 source_id::{FileAstId, AstId}, 54 source_id::{FileAstId, AstId},
55 resolve::Resolver, resolve::ImportResolver, 55 resolve::Resolver,
56}; 56};
57 57
58pub use self::{ 58pub use self::{
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index 331da6027..9a999e66c 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -46,8 +46,17 @@ impl Name {
46 Name::new(idx.to_string().into()) 46 Name::new(idx.to_string().into())
47 } 47 }
48 48
49 pub fn to_smolstr(&self) -> SmolStr { 49 // There's should be no way to extract a string out of `Name`: `Name` in the
50 self.text.clone() 50 // future, `Name` will include hygiene information, and you can't encode
51 // hygiene into a String.
52 //
53 // If you need to compare something with `Name`, compare `Name`s directly.
54 //
55 // If you need to render `Name` for the user, use the `Display` impl, but be
56 // aware that it strips hygiene info.
57 #[deprecated(note = "use to_string instead")]
58 pub fn as_smolstr(&self) -> &SmolStr {
59 &self.text
51 } 60 }
52 61
53 pub(crate) fn as_known_name(&self) -> Option<KnownName> { 62 pub(crate) fn as_known_name(&self) -> Option<KnownName> {
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index ce80be17f..bd0f074c1 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -23,12 +23,6 @@ pub(crate) struct Resolver {
23 scopes: Vec<Scope>, 23 scopes: Vec<Scope>,
24} 24}
25 25
26#[derive(Debug, Clone, Default)]
27pub(crate) struct ImportResolver {
28 // todo: use fst crate or something like that
29 dummy_names: Vec<(SmolStr, Vec<SmolStr>)>,
30}
31
32// FIXME how to store these best 26// FIXME how to store these best
33#[derive(Debug, Clone)] 27#[derive(Debug, Clone)]
34pub(crate) struct ModuleItemMap { 28pub(crate) struct ModuleItemMap {
@@ -317,56 +311,3 @@ impl Scope {
317 } 311 }
318 } 312 }
319} 313}
320
321impl ImportResolver {
322 pub(crate) fn new() -> Self {
323 let dummy_names = vec![
324 (SmolStr::new("fmt"), vec![SmolStr::new("std"), SmolStr::new("fmt")]),
325 (SmolStr::new("io"), vec![SmolStr::new("std"), SmolStr::new("io")]),
326 (SmolStr::new("iter"), vec![SmolStr::new("std"), SmolStr::new("iter")]),
327 (SmolStr::new("hash"), vec![SmolStr::new("std"), SmolStr::new("hash")]),
328 (
329 SmolStr::new("Debug"),
330 vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Debug")],
331 ),
332 (
333 SmolStr::new("Display"),
334 vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Display")],
335 ),
336 (
337 SmolStr::new("Hash"),
338 vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hash")],
339 ),
340 (
341 SmolStr::new("Hasher"),
342 vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hasher")],
343 ),
344 (
345 SmolStr::new("Iterator"),
346 vec![SmolStr::new("std"), SmolStr::new("iter"), SmolStr::new("Iterator")],
347 ),
348 ];
349
350 ImportResolver { dummy_names }
351 }
352
353 // Returns a map of importable items filtered by name.
354 // The map associates item name with its full path.
355 // todo: should return Resolutions
356 pub(crate) fn all_names(
357 &self,
358 _db: &impl HirDatabase,
359 name: &Name,
360 ) -> FxHashMap<SmolStr, Vec<SmolStr>> {
361 let name = name.to_smolstr();
362 if name.len() > 1 {
363 self.dummy_names
364 .iter()
365 .filter(|(n, _)| n.as_str().contains(name.as_str()))
366 .cloned()
367 .collect()
368 } else {
369 FxHashMap::default()
370 }
371 }
372}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 42399622a..2959e3eca 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -14,12 +14,11 @@ use ra_syntax::{
14 ast::{self, AstNode, NameOwner}, 14 ast::{self, AstNode, NameOwner},
15 algo::find_node_at_offset, 15 algo::find_node_at_offset,
16 SyntaxKind::*, 16 SyntaxKind::*,
17 SmolStr,
18}; 17};
19 18
20use crate::{ 19use crate::{
21 HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name, 20 HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody, PerNs, Name,
22 AsName, Module, HirFileId, Crate, Trait, Resolver, Ty, ImportResolver, 21 AsName, Module, HirFileId, Crate, Trait, Resolver, Ty,
23 expr::{BodySourceMap, scope::{ScopeId, ExprScopes}}, 22 expr::{BodySourceMap, scope::{ScopeId, ExprScopes}},
24 ids::LocationCtx, 23 ids::LocationCtx,
25 expr, AstId, 24 expr, AstId,
@@ -171,7 +170,6 @@ fn def_with_body_from_child_node(
171#[derive(Debug)] 170#[derive(Debug)]
172pub struct SourceAnalyzer { 171pub struct SourceAnalyzer {
173 resolver: Resolver, 172 resolver: Resolver,
174 import_resolver: ImportResolver,
175 body_source_map: Option<Arc<BodySourceMap>>, 173 body_source_map: Option<Arc<BodySourceMap>>,
176 infer: Option<Arc<crate::ty::InferenceResult>>, 174 infer: Option<Arc<crate::ty::InferenceResult>>,
177 scopes: Option<Arc<crate::expr::ExprScopes>>, 175 scopes: Option<Arc<crate::expr::ExprScopes>>,
@@ -219,7 +217,6 @@ impl SourceAnalyzer {
219 offset: Option<TextUnit>, 217 offset: Option<TextUnit>,
220 ) -> SourceAnalyzer { 218 ) -> SourceAnalyzer {
221 let def_with_body = def_with_body_from_child_node(db, file_id, node); 219 let def_with_body = def_with_body_from_child_node(db, file_id, node);
222 let import_resolver = ImportResolver::new();
223 if let Some(def) = def_with_body { 220 if let Some(def) = def_with_body {
224 let source_map = def.body_source_map(db); 221 let source_map = def.body_source_map(db);
225 let scopes = db.expr_scopes(def); 222 let scopes = db.expr_scopes(def);
@@ -230,7 +227,6 @@ impl SourceAnalyzer {
230 let resolver = expr::resolver_for_scope(def.body(db), db, scope); 227 let resolver = expr::resolver_for_scope(def.body(db), db, scope);
231 SourceAnalyzer { 228 SourceAnalyzer {
232 resolver, 229 resolver,
233 import_resolver,
234 body_source_map: Some(source_map), 230 body_source_map: Some(source_map),
235 infer: Some(def.infer(db)), 231 infer: Some(def.infer(db)),
236 scopes: Some(scopes), 232 scopes: Some(scopes),
@@ -241,7 +237,6 @@ impl SourceAnalyzer {
241 .ancestors() 237 .ancestors()
242 .find_map(|node| try_get_resolver_for_node(db, file_id, node)) 238 .find_map(|node| try_get_resolver_for_node(db, file_id, node))
243 .unwrap_or_default(), 239 .unwrap_or_default(),
244 import_resolver,
245 body_source_map: None, 240 body_source_map: None,
246 infer: None, 241 infer: None,
247 scopes: None, 242 scopes: None,
@@ -328,14 +323,6 @@ impl SourceAnalyzer {
328 self.resolver.all_names(db) 323 self.resolver.all_names(db)
329 } 324 }
330 325
331 pub fn all_import_names(
332 &self,
333 db: &impl HirDatabase,
334 name: &Name,
335 ) -> FxHashMap<SmolStr, Vec<SmolStr>> {
336 self.import_resolver.all_names(db, name)
337 }
338
339 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> { 326 pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec<ReferenceDescriptor> {
340 // FIXME: at least, this should work with any DefWithBody, but ideally 327 // FIXME: at least, this should work with any DefWithBody, but ideally
341 // this should be hir-based altogether 328 // this should be hir-based altogether
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 5bd5376c9..a2523c5ef 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -1,6 +1,8 @@
1use rustc_hash::FxHashMap;
1use ra_text_edit::TextEditBuilder; 2use ra_text_edit::TextEditBuilder;
2use ra_syntax::SmolStr; 3use ra_syntax::SmolStr;
3use ra_assists::auto_import; 4use ra_assists::auto_import;
5
4use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionContext}; 6use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionContext};
5 7
6pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { 8pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
@@ -10,7 +12,8 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
10 } 12 }
11 13
12 if let Some(name) = ctx.path_ident.as_ref() { 14 if let Some(name) = ctx.path_ident.as_ref() {
13 let import_names = ctx.analyzer.all_import_names(ctx.db, name); 15 let import_resolver = ImportResolver::new();
16 let import_names = import_resolver.all_names(&name.to_string());
14 import_names.into_iter().for_each(|(name, path)| { 17 import_names.into_iter().for_each(|(name, path)| {
15 let edit = { 18 let edit = {
16 let mut builder = TextEditBuilder::default(); 19 let mut builder = TextEditBuilder::default();
@@ -64,6 +67,56 @@ fn fmt_import_path(path: &Vec<SmolStr>, buf: &mut String) {
64 } 67 }
65} 68}
66 69
70#[derive(Debug, Clone, Default)]
71pub(crate) struct ImportResolver {
72 // todo: use fst crate or something like that
73 dummy_names: Vec<(SmolStr, Vec<SmolStr>)>,
74}
75
76impl ImportResolver {
77 pub(crate) fn new() -> Self {
78 let dummy_names = vec![
79 (SmolStr::new("fmt"), vec![SmolStr::new("std"), SmolStr::new("fmt")]),
80 (SmolStr::new("io"), vec![SmolStr::new("std"), SmolStr::new("io")]),
81 (SmolStr::new("iter"), vec![SmolStr::new("std"), SmolStr::new("iter")]),
82 (SmolStr::new("hash"), vec![SmolStr::new("std"), SmolStr::new("hash")]),
83 (
84 SmolStr::new("Debug"),
85 vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Debug")],
86 ),
87 (
88 SmolStr::new("Display"),
89 vec![SmolStr::new("std"), SmolStr::new("fmt"), SmolStr::new("Display")],
90 ),
91 (
92 SmolStr::new("Hash"),
93 vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hash")],
94 ),
95 (
96 SmolStr::new("Hasher"),
97 vec![SmolStr::new("std"), SmolStr::new("hash"), SmolStr::new("Hasher")],
98 ),
99 (
100 SmolStr::new("Iterator"),
101 vec![SmolStr::new("std"), SmolStr::new("iter"), SmolStr::new("Iterator")],
102 ),
103 ];
104
105 ImportResolver { dummy_names }
106 }
107
108 // Returns a map of importable items filtered by name.
109 // The map associates item name with its full path.
110 // todo: should return Resolutions
111 pub(crate) fn all_names(&self, name: &str) -> FxHashMap<SmolStr, Vec<SmolStr>> {
112 if name.len() > 1 {
113 self.dummy_names.iter().filter(|(n, _)| n.contains(name)).cloned().collect()
114 } else {
115 FxHashMap::default()
116 }
117 }
118}
119
67#[cfg(test)] 120#[cfg(test)]
68mod tests { 121mod tests {
69 use crate::completion::{CompletionKind, check_completion}; 122 use crate::completion::{CompletionKind, check_completion};
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index ca8f7900d..0d630fdf6 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -86,18 +86,6 @@ impl<'a> CompletionContext<'a> {
86 } 86 }
87 87
88 fn fill(&mut self, original_file: &'a SourceFile, offset: TextUnit) { 88 fn fill(&mut self, original_file: &'a SourceFile, offset: TextUnit) {
89 // We heed the original NameRef before the "intellijRulezz" hack
90 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(original_file.syntax(), offset)
91 {
92 if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
93 if let Some(path) = hir::Path::from_ast(path) {
94 if let Some(ident) = path.as_ident() {
95 self.path_ident = Some(ident.clone());
96 }
97 }
98 }
99 }
100
101 // Insert a fake ident to get a valid parse tree. We will use this file 89 // Insert a fake ident to get a valid parse tree. We will use this file
102 // to determine context, though the original_file will be used for 90 // to determine context, though the original_file will be used for
103 // actual completion. 91 // actual completion.