aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r--crates/ra_ide/src/assists.rs4
-rw-r--r--crates/ra_ide/src/imports_locator.rs76
-rw-r--r--crates/ra_ide/src/lib.rs1
-rw-r--r--crates/ra_ide/src/references.rs5
-rw-r--r--crates/ra_ide/src/references/classify.rs112
-rw-r--r--crates/ra_ide/src/references/name_definition.rs85
-rw-r--r--crates/ra_ide/src/references/search_scope.rs102
7 files changed, 57 insertions, 328 deletions
diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs
index f26047570..4a7d8cfa9 100644
--- a/crates/ra_ide/src/assists.rs
+++ b/crates/ra_ide/src/assists.rs
@@ -3,9 +3,9 @@
3use either::Either; 3use either::Either;
4use ra_assists::{AssistAction, AssistLabel}; 4use ra_assists::{AssistAction, AssistLabel};
5use ra_db::{FilePosition, FileRange}; 5use ra_db::{FilePosition, FileRange};
6use ra_ide_db::RootDatabase; 6use ra_ide_db::{imports_locator::ImportsLocatorIde, RootDatabase};
7 7
8use crate::{imports_locator::ImportsLocatorIde, FileId, SourceChange, SourceFileEdit}; 8use crate::{FileId, SourceChange, SourceFileEdit};
9 9
10pub use ra_assists::AssistId; 10pub use ra_assists::AssistId;
11 11
diff --git a/crates/ra_ide/src/imports_locator.rs b/crates/ra_ide/src/imports_locator.rs
deleted file mode 100644
index cfd58aafe..000000000
--- a/crates/ra_ide/src/imports_locator.rs
+++ /dev/null
@@ -1,76 +0,0 @@
1//! This module contains an import search funcionality that is provided to the ra_assists module.
2//! Later, this should be moved away to a separate crate that is accessible from the ra_assists module.
3
4use hir::{db::HirDatabase, ModuleDef, SourceBinder};
5use ra_assists::ImportsLocator;
6use ra_ide_db::{
7 symbol_index::{self, FileSymbol},
8 RootDatabase,
9};
10use ra_prof::profile;
11use ra_syntax::{ast, AstNode, SyntaxKind::NAME};
12
13use crate::{
14 references::{classify_name, NameDefinition, NameKind},
15 Query,
16};
17
18pub(crate) struct ImportsLocatorIde<'a> {
19 source_binder: SourceBinder<'a, RootDatabase>,
20}
21
22impl<'a> ImportsLocatorIde<'a> {
23 pub(crate) fn new(db: &'a RootDatabase) -> Self {
24 Self { source_binder: SourceBinder::new(db) }
25 }
26
27 fn get_name_definition(
28 &mut self,
29 db: &impl HirDatabase,
30 import_candidate: &FileSymbol,
31 ) -> Option<NameDefinition> {
32 let _p = profile("get_name_definition");
33 let file_id = import_candidate.file_id.into();
34 let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
35 let candidate_name_node = if candidate_node.kind() != NAME {
36 candidate_node.children().find(|it| it.kind() == NAME)?
37 } else {
38 candidate_node
39 };
40 classify_name(
41 &mut self.source_binder,
42 hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
43 )
44 }
45}
46
47impl ImportsLocator for ImportsLocatorIde<'_> {
48 fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> {
49 let _p = profile("search_for_imports");
50 let db = self.source_binder.db;
51
52 let project_results = {
53 let mut query = Query::new(name_to_import.to_string());
54 query.exact();
55 query.limit(40);
56 symbol_index::world_symbols(db, query)
57 };
58 let lib_results = {
59 let mut query = Query::new(name_to_import.to_string());
60 query.libs();
61 query.exact();
62 query.limit(40);
63 symbol_index::world_symbols(db, query)
64 };
65
66 project_results
67 .into_iter()
68 .chain(lib_results.into_iter())
69 .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate))
70 .filter_map(|name_definition_to_import| match name_definition_to_import.kind {
71 NameKind::Def(module_def) => Some(module_def),
72 _ => None,
73 })
74 .collect()
75 }
76}
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 5fb111a90..689921f3f 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -26,7 +26,6 @@ mod syntax_highlighting;
26mod parent_module; 26mod parent_module;
27mod references; 27mod references;
28mod impls; 28mod impls;
29mod imports_locator;
30mod assists; 29mod assists;
31mod diagnostics; 30mod diagnostics;
32mod syntax_tree; 31mod syntax_tree;
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index b47f8bcd9..c215040f4 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -10,7 +10,6 @@
10//! resolved to the search element definition, we get a reference. 10//! resolved to the search element definition, we get a reference.
11 11
12mod classify; 12mod classify;
13mod name_definition;
14mod rename; 13mod rename;
15mod search_scope; 14mod search_scope;
16 15
@@ -29,9 +28,9 @@ use crate::{display::ToNav, FilePosition, FileRange, NavigationTarget, RangeInfo
29 28
30pub(crate) use self::{ 29pub(crate) use self::{
31 classify::{classify_name, classify_name_ref}, 30 classify::{classify_name, classify_name_ref},
32 name_definition::{NameDefinition, NameKind},
33 rename::rename, 31 rename::rename,
34}; 32};
33pub(crate) use ra_ide_db::defs::{NameDefinition, NameKind};
35 34
36pub use self::search_scope::SearchScope; 35pub use self::search_scope::SearchScope;
37 36
@@ -137,7 +136,7 @@ pub(crate) fn find_all_refs(
137 }; 136 };
138 137
139 let search_scope = { 138 let search_scope = {
140 let base = def.search_scope(db); 139 let base = SearchScope::for_def(&def, db);
141 match search_scope { 140 match search_scope {
142 None => base, 141 None => base,
143 Some(scope) => base.intersection(&scope), 142 Some(scope) => base.intersection(&scope),
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs
index 758ea4e8b..0326fd379 100644
--- a/crates/ra_ide/src/references/classify.rs
+++ b/crates/ra_ide/src/references/classify.rs
@@ -2,119 +2,13 @@
2 2
3use hir::{InFile, PathResolution, SourceBinder}; 3use hir::{InFile, PathResolution, SourceBinder};
4use ra_prof::profile; 4use ra_prof::profile;
5use ra_syntax::{ast, match_ast, AstNode}; 5use ra_syntax::{ast, AstNode};
6use test_utils::tested_by; 6use test_utils::tested_by;
7 7
8use super::{ 8use super::{NameDefinition, NameKind};
9 name_definition::{from_assoc_item, from_module_def, from_struct_field},
10 NameDefinition, NameKind,
11};
12use ra_ide_db::RootDatabase; 9use ra_ide_db::RootDatabase;
13 10
14pub(crate) fn classify_name( 11pub use ra_ide_db::defs::{classify_name, from_assoc_item, from_module_def, from_struct_field};
15 sb: &mut SourceBinder<RootDatabase>,
16 name: InFile<&ast::Name>,
17) -> Option<NameDefinition> {
18 let _p = profile("classify_name");
19 let parent = name.value.syntax().parent()?;
20
21 match_ast! {
22 match parent {
23 ast::BindPat(it) => {
24 let src = name.with_value(it);
25 let local = sb.to_def(src)?;
26 Some(NameDefinition {
27 visibility: None,
28 container: local.module(sb.db),
29 kind: NameKind::Local(local),
30 })
31 },
32 ast::RecordFieldDef(it) => {
33 let src = name.with_value(it);
34 let field: hir::StructField = sb.to_def(src)?;
35 Some(from_struct_field(sb.db, field))
36 },
37 ast::Module(it) => {
38 let def = sb.to_def(name.with_value(it))?;
39 Some(from_module_def(sb.db, def.into(), None))
40 },
41 ast::StructDef(it) => {
42 let src = name.with_value(it);
43 let def: hir::Struct = sb.to_def(src)?;
44 Some(from_module_def(sb.db, def.into(), None))
45 },
46 ast::EnumDef(it) => {
47 let src = name.with_value(it);
48 let def: hir::Enum = sb.to_def(src)?;
49 Some(from_module_def(sb.db, def.into(), None))
50 },
51 ast::TraitDef(it) => {
52 let src = name.with_value(it);
53 let def: hir::Trait = sb.to_def(src)?;
54 Some(from_module_def(sb.db, def.into(), None))
55 },
56 ast::StaticDef(it) => {
57 let src = name.with_value(it);
58 let def: hir::Static = sb.to_def(src)?;
59 Some(from_module_def(sb.db, def.into(), None))
60 },
61 ast::EnumVariant(it) => {
62 let src = name.with_value(it);
63 let def: hir::EnumVariant = sb.to_def(src)?;
64 Some(from_module_def(sb.db, def.into(), None))
65 },
66 ast::FnDef(it) => {
67 let src = name.with_value(it);
68 let def: hir::Function = sb.to_def(src)?;
69 if parent.parent().and_then(ast::ItemList::cast).is_some() {
70 Some(from_assoc_item(sb.db, def.into()))
71 } else {
72 Some(from_module_def(sb.db, def.into(), None))
73 }
74 },
75 ast::ConstDef(it) => {
76 let src = name.with_value(it);
77 let def: hir::Const = sb.to_def(src)?;
78 if parent.parent().and_then(ast::ItemList::cast).is_some() {
79 Some(from_assoc_item(sb.db, def.into()))
80 } else {
81 Some(from_module_def(sb.db, def.into(), None))
82 }
83 },
84 ast::TypeAliasDef(it) => {
85 let src = name.with_value(it);
86 let def: hir::TypeAlias = sb.to_def(src)?;
87 if parent.parent().and_then(ast::ItemList::cast).is_some() {
88 Some(from_assoc_item(sb.db, def.into()))
89 } else {
90 Some(from_module_def(sb.db, def.into(), None))
91 }
92 },
93 ast::MacroCall(it) => {
94 let src = name.with_value(it);
95 let def = sb.to_def(src.clone())?;
96
97 let module = sb.to_module_def(src.file_id.original_file(sb.db))?;
98
99 Some(NameDefinition {
100 visibility: None,
101 container: module,
102 kind: NameKind::Macro(def),
103 })
104 },
105 ast::TypeParam(it) => {
106 let src = name.with_value(it);
107 let def = sb.to_def(src)?;
108 Some(NameDefinition {
109 visibility: None,
110 container: def.module(sb.db),
111 kind: NameKind::TypeParam(def),
112 })
113 },
114 _ => None,
115 }
116 }
117}
118 12
119pub(crate) fn classify_name_ref( 13pub(crate) fn classify_name_ref(
120 sb: &mut SourceBinder<RootDatabase>, 14 sb: &mut SourceBinder<RootDatabase>,
diff --git a/crates/ra_ide/src/references/name_definition.rs b/crates/ra_ide/src/references/name_definition.rs
deleted file mode 100644
index 71565e6d3..000000000
--- a/crates/ra_ide/src/references/name_definition.rs
+++ /dev/null
@@ -1,85 +0,0 @@
1//! `NameDefinition` keeps information about the element we want to search references for.
2//! The element is represented by `NameKind`. It's located inside some `container` and
3//! has a `visibility`, which defines a search scope.
4//! Note that the reference search is possible for not all of the classified items.
5
6use hir::{
7 Adt, AssocItem, HasSource, ImplBlock, Local, MacroDef, Module, ModuleDef, StructField,
8 TypeParam, VariantDef,
9};
10use ra_syntax::{ast, ast::VisibilityOwner};
11
12use ra_ide_db::RootDatabase;
13
14#[derive(Debug, PartialEq, Eq)]
15pub enum NameKind {
16 Macro(MacroDef),
17 Field(StructField),
18 AssocItem(AssocItem),
19 Def(ModuleDef),
20 SelfType(ImplBlock),
21 Local(Local),
22 TypeParam(TypeParam),
23}
24
25#[derive(PartialEq, Eq)]
26pub(crate) struct NameDefinition {
27 pub visibility: Option<ast::Visibility>,
28 /// FIXME: this doesn't really make sense. For example, builtin types don't
29 /// really have a module.
30 pub container: Module,
31 pub kind: NameKind,
32}
33
34pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition {
35 let container = item.module(db);
36 let visibility = match item {
37 AssocItem::Function(f) => f.source(db).value.visibility(),
38 AssocItem::Const(c) => c.source(db).value.visibility(),
39 AssocItem::TypeAlias(a) => a.source(db).value.visibility(),
40 };
41 let kind = NameKind::AssocItem(item);
42 NameDefinition { kind, container, visibility }
43}
44
45pub(super) fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDefinition {
46 let kind = NameKind::Field(field);
47 let parent = field.parent_def(db);
48 let container = parent.module(db);
49 let visibility = match parent {
50 VariantDef::Struct(s) => s.source(db).value.visibility(),
51 VariantDef::Union(e) => e.source(db).value.visibility(),
52 VariantDef::EnumVariant(e) => e.source(db).value.parent_enum().visibility(),
53 };
54 NameDefinition { kind, container, visibility }
55}
56
57pub(super) fn from_module_def(
58 db: &RootDatabase,
59 def: ModuleDef,
60 module: Option<Module>,
61) -> NameDefinition {
62 let kind = NameKind::Def(def);
63 let (container, visibility) = match def {
64 ModuleDef::Module(it) => {
65 let container = it.parent(db).or_else(|| Some(it)).unwrap();
66 let visibility = it.declaration_source(db).and_then(|s| s.value.visibility());
67 (container, visibility)
68 }
69 ModuleDef::EnumVariant(it) => {
70 let container = it.module(db);
71 let visibility = it.source(db).value.parent_enum().visibility();
72 (container, visibility)
73 }
74 ModuleDef::Function(it) => (it.module(db), it.source(db).value.visibility()),
75 ModuleDef::Const(it) => (it.module(db), it.source(db).value.visibility()),
76 ModuleDef::Static(it) => (it.module(db), it.source(db).value.visibility()),
77 ModuleDef::Trait(it) => (it.module(db), it.source(db).value.visibility()),
78 ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).value.visibility()),
79 ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).value.visibility()),
80 ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).value.visibility()),
81 ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).value.visibility()),
82 ModuleDef::BuiltinType(..) => (module.unwrap(), None),
83 };
84 NameDefinition { kind, container, visibility }
85}
diff --git a/crates/ra_ide/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs
index 97c65c2cd..279f57be0 100644
--- a/crates/ra_ide/src/references/search_scope.rs
+++ b/crates/ra_ide/src/references/search_scope.rs
@@ -19,59 +19,13 @@ pub struct SearchScope {
19} 19}
20 20
21impl SearchScope { 21impl SearchScope {
22 fn new(entries: FxHashMap<FileId, Option<TextRange>>) -> SearchScope { 22 pub(crate) fn for_def(def: &NameDefinition, db: &RootDatabase) -> SearchScope {
23 SearchScope { entries }
24 }
25 pub fn single_file(file: FileId) -> SearchScope {
26 SearchScope::new(std::iter::once((file, None)).collect())
27 }
28 pub(crate) fn intersection(&self, other: &SearchScope) -> SearchScope {
29 let (mut small, mut large) = (&self.entries, &other.entries);
30 if small.len() > large.len() {
31 mem::swap(&mut small, &mut large)
32 }
33
34 let res = small
35 .iter()
36 .filter_map(|(file_id, r1)| {
37 let r2 = large.get(file_id)?;
38 let r = intersect_ranges(*r1, *r2)?;
39 Some((*file_id, r))
40 })
41 .collect();
42 return SearchScope::new(res);
43
44 fn intersect_ranges(
45 r1: Option<TextRange>,
46 r2: Option<TextRange>,
47 ) -> Option<Option<TextRange>> {
48 match (r1, r2) {
49 (None, r) | (r, None) => Some(r),
50 (Some(r1), Some(r2)) => {
51 let r = r1.intersection(&r2)?;
52 Some(Some(r))
53 }
54 }
55 }
56 }
57}
58
59impl IntoIterator for SearchScope {
60 type Item = (FileId, Option<TextRange>);
61 type IntoIter = std::collections::hash_map::IntoIter<FileId, Option<TextRange>>;
62 fn into_iter(self) -> Self::IntoIter {
63 self.entries.into_iter()
64 }
65}
66
67impl NameDefinition {
68 pub(crate) fn search_scope(&self, db: &RootDatabase) -> SearchScope {
69 let _p = profile("search_scope"); 23 let _p = profile("search_scope");
70 24
71 let module_src = self.container.definition_source(db); 25 let module_src = def.container.definition_source(db);
72 let file_id = module_src.file_id.original_file(db); 26 let file_id = module_src.file_id.original_file(db);
73 27
74 if let NameKind::Local(var) = self.kind { 28 if let NameKind::Local(var) = def.kind {
75 let range = match var.parent(db) { 29 let range = match var.parent(db) {
76 DefWithBody::Function(f) => f.source(db).value.syntax().text_range(), 30 DefWithBody::Function(f) => f.source(db).value.syntax().text_range(),
77 DefWithBody::Const(c) => c.source(db).value.syntax().text_range(), 31 DefWithBody::Const(c) => c.source(db).value.syntax().text_range(),
@@ -82,10 +36,10 @@ impl NameDefinition {
82 return SearchScope::new(res); 36 return SearchScope::new(res);
83 } 37 }
84 38
85 let vis = self.visibility.as_ref().map(|v| v.syntax().to_string()).unwrap_or_default(); 39 let vis = def.visibility.as_ref().map(|v| v.syntax().to_string()).unwrap_or_default();
86 40
87 if vis.as_str() == "pub(super)" { 41 if vis.as_str() == "pub(super)" {
88 if let Some(parent_module) = self.container.parent(db) { 42 if let Some(parent_module) = def.container.parent(db) {
89 let mut res = FxHashMap::default(); 43 let mut res = FxHashMap::default();
90 let parent_src = parent_module.definition_source(db); 44 let parent_src = parent_module.definition_source(db);
91 let file_id = parent_src.file_id.original_file(db); 45 let file_id = parent_src.file_id.original_file(db);
@@ -118,7 +72,7 @@ impl NameDefinition {
118 return SearchScope::new(res); 72 return SearchScope::new(res);
119 } 73 }
120 if vis.as_str() == "pub" { 74 if vis.as_str() == "pub" {
121 let krate = self.container.krate(); 75 let krate = def.container.krate();
122 for rev_dep in krate.reverse_dependencies(db) { 76 for rev_dep in krate.reverse_dependencies(db) {
123 let root_file = rev_dep.root_file(db); 77 let root_file = rev_dep.root_file(db);
124 let source_root_id = db.file_source_root(root_file); 78 let source_root_id = db.file_source_root(root_file);
@@ -137,4 +91,48 @@ impl NameDefinition {
137 res.insert(file_id, range); 91 res.insert(file_id, range);
138 SearchScope::new(res) 92 SearchScope::new(res)
139 } 93 }
94
95 fn new(entries: FxHashMap<FileId, Option<TextRange>>) -> SearchScope {
96 SearchScope { entries }
97 }
98 pub fn single_file(file: FileId) -> SearchScope {
99 SearchScope::new(std::iter::once((file, None)).collect())
100 }
101 pub(crate) fn intersection(&self, other: &SearchScope) -> SearchScope {
102 let (mut small, mut large) = (&self.entries, &other.entries);
103 if small.len() > large.len() {
104 mem::swap(&mut small, &mut large)
105 }
106
107 let res = small
108 .iter()
109 .filter_map(|(file_id, r1)| {
110 let r2 = large.get(file_id)?;
111 let r = intersect_ranges(*r1, *r2)?;
112 Some((*file_id, r))
113 })
114 .collect();
115 return SearchScope::new(res);
116
117 fn intersect_ranges(
118 r1: Option<TextRange>,
119 r2: Option<TextRange>,
120 ) -> Option<Option<TextRange>> {
121 match (r1, r2) {
122 (None, r) | (r, None) => Some(r),
123 (Some(r1), Some(r2)) => {
124 let r = r1.intersection(&r2)?;
125 Some(Some(r))
126 }
127 }
128 }
129 }
130}
131
132impl IntoIterator for SearchScope {
133 type Item = (FileId, Option<TextRange>);
134 type IntoIter = std::collections::hash_map::IntoIter<FileId, Option<TextRange>>;
135 fn into_iter(self) -> Self::IntoIter {
136 self.entries.into_iter()
137 }
140} 138}