aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
authorEkaterina Babshukova <[email protected]>2019-10-10 16:51:51 +0100
committerEkaterina Babshukova <[email protected]>2019-10-22 21:47:31 +0100
commit5b03773fbeea55d86f64e5fb69a0d0f1d6a4f7e8 (patch)
tree1f3ce5c71343535ae0ca0751982a1d0f89480e45 /crates/ra_ide_api
parent01853e8d6c6f4b44801c74f4fcdef735d9e77b48 (diff)
implement search of references
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r--crates/ra_ide_api/src/name_kind.rs83
-rw-r--r--crates/ra_ide_api/src/references.rs50
-rw-r--r--crates/ra_ide_api/src/search_scope.rs77
3 files changed, 134 insertions, 76 deletions
diff --git a/crates/ra_ide_api/src/name_kind.rs b/crates/ra_ide_api/src/name_kind.rs
index 6d1eb153f..8eef540f6 100644
--- a/crates/ra_ide_api/src/name_kind.rs
+++ b/crates/ra_ide_api/src/name_kind.rs
@@ -10,6 +10,7 @@ use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr};
10 10
11use crate::db::RootDatabase; 11use crate::db::RootDatabase;
12 12
13#[derive(PartialEq, Eq)]
13pub enum NameKind { 14pub enum NameKind {
14 Macro(MacroDef), 15 Macro(MacroDef),
15 FieldAccess(StructField), 16 FieldAccess(StructField),
@@ -21,23 +22,24 @@ pub enum NameKind {
21 GenericParam(u32), 22 GenericParam(u32),
22} 23}
23 24
24pub(crate) struct Declaration { 25#[derive(PartialEq, Eq)]
26pub(crate) struct Definition {
25 pub visibility: Option<ast::Visibility>, 27 pub visibility: Option<ast::Visibility>,
26 pub container: Module, 28 pub container: Module,
27 pub item: NameKind, 29 pub item: NameKind,
28} 30}
29 31
30trait HasDeclaration { 32trait HasDefinition {
31 type Def; 33 type Def;
32 type Ref; 34 type Ref;
33 35
34 fn declaration(self, db: &RootDatabase) -> Declaration; 36 fn definition(self, db: &RootDatabase) -> Definition;
35 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Declaration>; 37 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition>;
36 fn from_ref( 38 fn from_ref(
37 db: &RootDatabase, 39 db: &RootDatabase,
38 analyzer: &SourceAnalyzer, 40 analyzer: &SourceAnalyzer,
39 refer: Self::Ref, 41 refer: Self::Ref,
40 ) -> Option<Declaration>; 42 ) -> Option<Definition>;
41} 43}
42 44
43macro_rules! match_ast { 45macro_rules! match_ast {
@@ -55,7 +57,7 @@ pub(crate) fn classify_name_ref(
55 file_id: FileId, 57 file_id: FileId,
56 analyzer: &SourceAnalyzer, 58 analyzer: &SourceAnalyzer,
57 name_ref: &ast::NameRef, 59 name_ref: &ast::NameRef,
58) -> Option<Declaration> { 60) -> Option<Definition> {
59 let parent = name_ref.syntax().parent()?; 61 let parent = name_ref.syntax().parent()?;
60 match_ast! { 62 match_ast! {
61 match parent { 63 match parent {
@@ -64,7 +66,7 @@ pub(crate) fn classify_name_ref(
64 }, 66 },
65 ast::FieldExpr(it) => { 67 ast::FieldExpr(it) => {
66 if let Some(field) = analyzer.resolve_field(&it) { 68 if let Some(field) = analyzer.resolve_field(&it) {
67 return Some(field.declaration(db)); 69 return Some(field.definition(db));
68 } 70 }
69 }, 71 },
70 ast::RecordField(it) => { 72 ast::RecordField(it) => {
@@ -73,7 +75,7 @@ pub(crate) fn classify_name_ref(
73 let hir_path = Path::from_name_ref(name_ref); 75 let hir_path = Path::from_name_ref(name_ref);
74 let hir_name = hir_path.as_ident()?; 76 let hir_name = hir_path.as_ident()?;
75 let field = variant_def.field(db, hir_name)?; 77 let field = variant_def.field(db, hir_name)?;
76 return Some(field.declaration(db)); 78 return Some(field.definition(db));
77 } 79 }
78 }, 80 },
79 _ => (), 81 _ => (),
@@ -83,12 +85,13 @@ pub(crate) fn classify_name_ref(
83 let ast = ModuleSource::from_child_node(db, file_id, &parent); 85 let ast = ModuleSource::from_child_node(db, file_id, &parent);
84 let file_id = file_id.into(); 86 let file_id = file_id.into();
85 let container = Module::from_definition(db, Source { file_id, ast })?; 87 let container = Module::from_definition(db, Source { file_id, ast })?;
88 let visibility = None;
86 89
87 if let Some(macro_call) = 90 if let Some(macro_call) =
88 parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) 91 parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast)
89 { 92 {
90 if let Some(mac) = analyzer.resolve_macro_call(db, &macro_call) { 93 if let Some(mac) = analyzer.resolve_macro_call(db, &macro_call) {
91 return Some(Declaration { item: NameKind::Macro(mac), container, visibility: None }); 94 return Some(Definition { item: NameKind::Macro(mac), container, visibility });
92 } 95 }
93 } 96 }
94 97
@@ -96,24 +99,24 @@ pub(crate) fn classify_name_ref(
96 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; 99 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
97 let resolved = analyzer.resolve_path(db, &path)?; 100 let resolved = analyzer.resolve_path(db, &path)?;
98 match resolved { 101 match resolved {
99 PathResolution::Def(def) => Some(def.declaration(db)), 102 PathResolution::Def(def) => Some(def.definition(db)),
100 PathResolution::LocalBinding(Either::A(pat)) => decl_from_pat(db, file_id, pat), 103 PathResolution::LocalBinding(Either::A(pat)) => decl_from_pat(db, file_id, pat),
101 PathResolution::LocalBinding(Either::B(par)) => { 104 PathResolution::LocalBinding(Either::B(par)) => {
102 Some(Declaration { item: NameKind::SelfParam(par), container, visibility: None }) 105 Some(Definition { item: NameKind::SelfParam(par), container, visibility })
103 } 106 }
104 PathResolution::GenericParam(par) => { 107 PathResolution::GenericParam(par) => {
105 // FIXME: get generic param def 108 // FIXME: get generic param def
106 Some(Declaration { item: NameKind::GenericParam(par), container, visibility: None }) 109 Some(Definition { item: NameKind::GenericParam(par), container, visibility })
107 } 110 }
108 PathResolution::Macro(def) => { 111 PathResolution::Macro(def) => {
109 Some(Declaration { item: NameKind::Macro(def), container, visibility: None }) 112 Some(Definition { item: NameKind::Macro(def), container, visibility })
110 } 113 }
111 PathResolution::SelfType(impl_block) => { 114 PathResolution::SelfType(impl_block) => {
112 let ty = impl_block.target_ty(db); 115 let ty = impl_block.target_ty(db);
113 let container = impl_block.module(); 116 let container = impl_block.module();
114 Some(Declaration { item: NameKind::SelfType(ty), container, visibility: None }) 117 Some(Definition { item: NameKind::SelfType(ty), container, visibility })
115 } 118 }
116 PathResolution::AssocItem(assoc) => Some(assoc.declaration(db)), 119 PathResolution::AssocItem(assoc) => Some(assoc.definition(db)),
117 } 120 }
118} 121}
119 122
@@ -121,7 +124,7 @@ pub(crate) fn classify_name(
121 db: &RootDatabase, 124 db: &RootDatabase,
122 file_id: FileId, 125 file_id: FileId,
123 name: &ast::Name, 126 name: &ast::Name,
124) -> Option<Declaration> { 127) -> Option<Definition> {
125 let parent = name.syntax().parent()?; 128 let parent = name.syntax().parent()?;
126 let file_id = file_id.into(); 129 let file_id = file_id.into();
127 130
@@ -145,7 +148,7 @@ pub(crate) fn classify_name(
145 ast::EnumVariant(it) => { 148 ast::EnumVariant(it) => {
146 let src = hir::Source { file_id, ast: it.clone() }; 149 let src = hir::Source { file_id, ast: it.clone() };
147 let def: ModuleDef = EnumVariant::from_source(db, src)?.into(); 150 let def: ModuleDef = EnumVariant::from_source(db, src)?.into();
148 Some(def.declaration(db)) 151 Some(def.definition(db))
149 }, 152 },
150 ast::ModuleItem(it) => { 153 ast::ModuleItem(it) => {
151 ModuleDef::from_def(db, file_id, it) 154 ModuleDef::from_def(db, file_id, it)
@@ -159,7 +162,7 @@ fn decl_from_pat(
159 db: &RootDatabase, 162 db: &RootDatabase,
160 file_id: HirFileId, 163 file_id: HirFileId,
161 pat: AstPtr<ast::BindPat>, 164 pat: AstPtr<ast::BindPat>,
162) -> Option<Declaration> { 165) -> Option<Definition> {
163 let root = db.parse_or_expand(file_id)?; 166 let root = db.parse_or_expand(file_id)?;
164 // FIXME: use match_ast! 167 // FIXME: use match_ast!
165 let def = pat.to_node(&root).syntax().ancestors().find_map(|node| { 168 let def = pat.to_node(&root).syntax().ancestors().find_map(|node| {
@@ -178,14 +181,14 @@ fn decl_from_pat(
178 })?; 181 })?;
179 let item = NameKind::Pat((def, pat)); 182 let item = NameKind::Pat((def, pat));
180 let container = def.module(db); 183 let container = def.module(db);
181 Some(Declaration { item, container, visibility: None }) 184 Some(Definition { item, container, visibility: None })
182} 185}
183 186
184impl HasDeclaration for StructField { 187impl HasDefinition for StructField {
185 type Def = ast::RecordFieldDef; 188 type Def = ast::RecordFieldDef;
186 type Ref = ast::FieldExpr; 189 type Ref = ast::FieldExpr;
187 190
188 fn declaration(self, db: &RootDatabase) -> Declaration { 191 fn definition(self, db: &RootDatabase) -> Definition {
189 let item = NameKind::FieldAccess(self); 192 let item = NameKind::FieldAccess(self);
190 let parent = self.parent_def(db); 193 let parent = self.parent_def(db);
191 let container = parent.module(db); 194 let container = parent.module(db);
@@ -193,30 +196,30 @@ impl HasDeclaration for StructField {
193 VariantDef::Struct(s) => s.source(db).ast.visibility(), 196 VariantDef::Struct(s) => s.source(db).ast.visibility(),
194 VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), 197 VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(),
195 }; 198 };
196 Declaration { item, container, visibility } 199 Definition { item, container, visibility }
197 } 200 }
198 201
199 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Declaration> { 202 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> {
200 let src = hir::Source { file_id, ast: hir::FieldSource::Named(def) }; 203 let src = hir::Source { file_id, ast: hir::FieldSource::Named(def) };
201 let field = StructField::from_source(db, src)?; 204 let field = StructField::from_source(db, src)?;
202 Some(field.declaration(db)) 205 Some(field.definition(db))
203 } 206 }
204 207
205 fn from_ref( 208 fn from_ref(
206 db: &RootDatabase, 209 db: &RootDatabase,
207 analyzer: &SourceAnalyzer, 210 analyzer: &SourceAnalyzer,
208 refer: Self::Ref, 211 refer: Self::Ref,
209 ) -> Option<Declaration> { 212 ) -> Option<Definition> {
210 let field = analyzer.resolve_field(&refer)?; 213 let field = analyzer.resolve_field(&refer)?;
211 Some(field.declaration(db)) 214 Some(field.definition(db))
212 } 215 }
213} 216}
214 217
215impl HasDeclaration for AssocItem { 218impl HasDefinition for AssocItem {
216 type Def = ast::ImplItem; 219 type Def = ast::ImplItem;
217 type Ref = ast::MethodCallExpr; 220 type Ref = ast::MethodCallExpr;
218 221
219 fn declaration(self, db: &RootDatabase) -> Declaration { 222 fn definition(self, db: &RootDatabase) -> Definition {
220 let item = NameKind::AssocItem(self); 223 let item = NameKind::AssocItem(self);
221 let container = self.module(db); 224 let container = self.module(db);
222 let visibility = match self { 225 let visibility = match self {
@@ -224,30 +227,30 @@ impl HasDeclaration for AssocItem {
224 AssocItem::Const(c) => c.source(db).ast.visibility(), 227 AssocItem::Const(c) => c.source(db).ast.visibility(),
225 AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), 228 AssocItem::TypeAlias(a) => a.source(db).ast.visibility(),
226 }; 229 };
227 Declaration { item, container, visibility } 230 Definition { item, container, visibility }
228 } 231 }
229 232
230 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Declaration> { 233 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> {
231 let src = hir::Source { file_id, ast: def }; 234 let src = hir::Source { file_id, ast: def };
232 let item = AssocItem::from_source(db, src)?; 235 let item = AssocItem::from_source(db, src)?;
233 Some(item.declaration(db)) 236 Some(item.definition(db))
234 } 237 }
235 238
236 fn from_ref( 239 fn from_ref(
237 db: &RootDatabase, 240 db: &RootDatabase,
238 analyzer: &SourceAnalyzer, 241 analyzer: &SourceAnalyzer,
239 refer: Self::Ref, 242 refer: Self::Ref,
240 ) -> Option<Declaration> { 243 ) -> Option<Definition> {
241 let func: AssocItem = analyzer.resolve_method_call(&refer)?.into(); 244 let func: AssocItem = analyzer.resolve_method_call(&refer)?.into();
242 Some(func.declaration(db)) 245 Some(func.definition(db))
243 } 246 }
244} 247}
245 248
246impl HasDeclaration for ModuleDef { 249impl HasDefinition for ModuleDef {
247 type Def = ast::ModuleItem; 250 type Def = ast::ModuleItem;
248 type Ref = ast::Path; 251 type Ref = ast::Path;
249 252
250 fn declaration(self, db: &RootDatabase) -> Declaration { 253 fn definition(self, db: &RootDatabase) -> Definition {
251 let (container, visibility) = match self { 254 let (container, visibility) = match self {
252 ModuleDef::Module(it) => { 255 ModuleDef::Module(it) => {
253 let container = it.parent(db).or_else(|| Some(it)).unwrap(); 256 let container = it.parent(db).or_else(|| Some(it)).unwrap();
@@ -270,22 +273,22 @@ impl HasDeclaration for ModuleDef {
270 ModuleDef::BuiltinType(..) => unreachable!(), 273 ModuleDef::BuiltinType(..) => unreachable!(),
271 }; 274 };
272 let item = NameKind::Def(self); 275 let item = NameKind::Def(self);
273 Declaration { item, container, visibility } 276 Definition { item, container, visibility }
274 } 277 }
275 278
276 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Declaration> { 279 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> {
277 let src = hir::Source { file_id, ast: def }; 280 let src = hir::Source { file_id, ast: def };
278 let def = ModuleDef::from_source(db, src)?; 281 let def = ModuleDef::from_source(db, src)?;
279 Some(def.declaration(db)) 282 Some(def.definition(db))
280 } 283 }
281 284
282 fn from_ref( 285 fn from_ref(
283 db: &RootDatabase, 286 db: &RootDatabase,
284 analyzer: &SourceAnalyzer, 287 analyzer: &SourceAnalyzer,
285 refer: Self::Ref, 288 refer: Self::Ref,
286 ) -> Option<Declaration> { 289 ) -> Option<Definition> {
287 None 290 None
288 } 291 }
289} 292}
290 293
291// FIXME: impl HasDeclaration for hir::MacroDef 294// FIXME: impl HasDefinition for hir::MacroDef
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index 24453452b..24cd7e827 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -7,10 +7,8 @@ use relative_path::{RelativePath, RelativePathBuf};
7 7
8use crate::{ 8use crate::{
9 db::RootDatabase, 9 db::RootDatabase,
10 name_kind::{ 10 name_kind::{classify_name, classify_name_ref, Definition, NameKind::*},
11 classify_name, classify_name_ref, 11 search_scope::find_refs,
12 NameKind::{self, *},
13 },
14 FileId, FilePosition, FileRange, FileSystemEdit, NavigationTarget, RangeInfo, SourceChange, 12 FileId, FilePosition, FileRange, FileSystemEdit, NavigationTarget, RangeInfo, SourceChange,
15 SourceFileEdit, TextRange, 13 SourceFileEdit, TextRange,
16}; 14};
@@ -58,9 +56,9 @@ pub(crate) fn find_all_refs(
58) -> Option<RangeInfo<ReferenceSearchResult>> { 56) -> Option<RangeInfo<ReferenceSearchResult>> {
59 let parse = db.parse(position.file_id); 57 let parse = db.parse(position.file_id);
60 let syntax = parse.tree().syntax().clone(); 58 let syntax = parse.tree().syntax().clone();
61 let RangeInfo { range, info: (analyzer, name_kind) } = find_name(db, &syntax, position)?; 59 let RangeInfo { range, info: (name, def) } = find_name(db, &syntax, position)?;
62 60
63 let declaration = match name_kind { 61 let declaration = match def.item {
64 Macro(mac) => NavigationTarget::from_macro_def(db, mac), 62 Macro(mac) => NavigationTarget::from_macro_def(db, mac),
65 FieldAccess(field) => NavigationTarget::from_field(db, field), 63 FieldAccess(field) => NavigationTarget::from_field(db, field),
66 AssocItem(assoc) => NavigationTarget::from_assoc_item(db, assoc), 64 AssocItem(assoc) => NavigationTarget::from_assoc_item(db, assoc),
@@ -74,14 +72,19 @@ pub(crate) fn find_all_refs(
74 GenericParam(_) => return None, 72 GenericParam(_) => return None,
75 }; 73 };
76 74
77 let references = match name_kind { 75 // let references = match name_kind {
78 Pat((_, pat)) => analyzer 76 // Pat((_, pat)) => analyzer
79 .find_all_refs(&pat.to_node(&syntax)) 77 // .find_all_refs(&pat.to_node(&syntax))
80 .into_iter() 78 // .into_iter()
81 .map(move |ref_desc| FileRange { file_id: position.file_id, range: ref_desc.range }) 79 // .map(move |ref_desc| FileRange { file_id: position.file_id, range: ref_desc.range })
82 .collect::<Vec<_>>(), 80 // .collect::<Vec<_>>(),
83 _ => vec![], 81 // _ => vec![],
84 }; 82 // };
83 let references = find_refs(db, def, name);
84 let references = references
85 .into_iter()
86 .map(move |ref_desc| FileRange { file_id: position.file_id, range: ref_desc.range })
87 .collect::<Vec<_>>();
85 88
86 return Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references })); 89 return Some(RangeInfo::new(range, ReferenceSearchResult { declaration, references }));
87 90
@@ -89,18 +92,17 @@ pub(crate) fn find_all_refs(
89 db: &RootDatabase, 92 db: &RootDatabase,
90 syntax: &SyntaxNode, 93 syntax: &SyntaxNode,
91 position: FilePosition, 94 position: FilePosition,
92 ) -> Option<RangeInfo<(hir::SourceAnalyzer, NameKind)>> { 95 ) -> Option<RangeInfo<(String, Definition)>> {
93 if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) { 96 if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) {
94 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name.syntax(), None); 97 let def = classify_name(db, position.file_id, &name)?;
95 let name_kind = classify_name(db, position.file_id, &name)?.item;
96 let range = name.syntax().text_range(); 98 let range = name.syntax().text_range();
97 return Some(RangeInfo::new(range, (analyzer, name_kind))); 99 return Some(RangeInfo::new(range, (name.text().to_string(), def)));
98 } 100 }
99 let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?; 101 let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?;
100 let range = name_ref.syntax().text_range(); 102 let range = name_ref.syntax().text_range();
101 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None); 103 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
102 let name_kind = classify_name_ref(db, position.file_id, &analyzer, &name_ref)?.item; 104 let def = classify_name_ref(db, position.file_id, &analyzer, &name_ref)?;
103 Some(RangeInfo::new(range, (analyzer, name_kind))) 105 Some(RangeInfo::new(range, (name_ref.text().to_string(), def)))
104 } 106 }
105} 107}
106 108
@@ -271,12 +273,16 @@ mod tests {
271 let code = r#" 273 let code = r#"
272 //- /lib.rs 274 //- /lib.rs
273 struct Foo { 275 struct Foo {
274 spam<|>: u32, 276 pub spam<|>: u32,
277 }
278
279 fn main(s: Foo) {
280 let f = s.spam;
275 } 281 }
276 "#; 282 "#;
277 283
278 let refs = get_all_refs(code); 284 let refs = get_all_refs(code);
279 assert_eq!(refs.len(), 1); 285 assert_eq!(refs.len(), 2);
280 } 286 }
281 287
282 #[test] 288 #[test]
diff --git a/crates/ra_ide_api/src/search_scope.rs b/crates/ra_ide_api/src/search_scope.rs
index 1cf1aed37..9fcbdcc3a 100644
--- a/crates/ra_ide_api/src/search_scope.rs
+++ b/crates/ra_ide_api/src/search_scope.rs
@@ -1,18 +1,69 @@
1use hir::{DefWithBody, HasSource, ModuleSource}; 1use hir::{
2 source_binder::ReferenceDescriptor, DefWithBody, HasSource, ModuleSource, SourceAnalyzer,
3};
2use ra_db::{FileId, SourceDatabase}; 4use ra_db::{FileId, SourceDatabase};
3use ra_syntax::{AstNode, TextRange}; 5use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, TextRange, TextUnit};
4 6
5use crate::{ 7use crate::{
6 db::RootDatabase, 8 db::RootDatabase,
7 name_kind::{Declaration, NameKind}, 9 name_kind::{classify_name_ref, Definition, NameKind},
8}; 10};
9 11
10pub struct SearchScope { 12pub(crate) struct SearchScope {
11 pub scope: Vec<(FileId, Option<TextRange>)>, 13 pub scope: Vec<(FileId, Option<TextRange>)>,
12} 14}
13 15
14impl Declaration { 16pub(crate) fn find_refs(
15 pub fn scope(self, db: &RootDatabase) -> Option<SearchScope> { 17 db: &RootDatabase,
18 def: Definition,
19 name: String,
20) -> Vec<ReferenceDescriptor> {
21 let pat = name.as_str();
22 let scope = def.scope(db).scope;
23 let mut refs = vec![];
24
25 let is_match = |file_id: FileId, name_ref: &ast::NameRef| -> bool {
26 let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None);
27 let classified = classify_name_ref(db, file_id, &analyzer, &name_ref);
28 if let Some(d) = classified {
29 d == def
30 } else {
31 false
32 }
33 };
34
35 for (file_id, text_range) in scope {
36 let text = db.file_text(file_id);
37 let parse = SourceFile::parse(&text);
38 let syntax = parse.tree().syntax().clone();
39
40 for (idx, _) in text.match_indices(pat) {
41 let offset = TextUnit::from_usize(idx);
42 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&syntax, offset) {
43 let name_range = name_ref.syntax().text_range();
44
45 if let Some(range) = text_range {
46 if name_range.is_subrange(&range) && is_match(file_id, &name_ref) {
47 refs.push(ReferenceDescriptor {
48 name: name_ref.text().to_string(),
49 range: name_ref.syntax().text_range(),
50 });
51 }
52 } else if is_match(file_id, &name_ref) {
53 refs.push(ReferenceDescriptor {
54 name: name_ref.text().to_string(),
55 range: name_ref.syntax().text_range(),
56 });
57 }
58 }
59 }
60 }
61
62 return refs;
63}
64
65impl Definition {
66 pub fn scope(&self, db: &RootDatabase) -> SearchScope {
16 let module_src = self.container.definition_source(db); 67 let module_src = self.container.definition_source(db);
17 let file_id = module_src.file_id.original_file(db); 68 let file_id = module_src.file_id.original_file(db);
18 69
@@ -22,16 +73,16 @@ impl Declaration {
22 DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), 73 DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(),
23 DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), 74 DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(),
24 }; 75 };
25 return Some(SearchScope { scope: vec![(file_id, Some(range))] }); 76 return SearchScope { scope: vec![(file_id, Some(range))] };
26 } 77 }
27 78
28 if let Some(vis) = self.visibility { 79 if let Some(ref vis) = self.visibility {
29 let source_root_id = db.file_source_root(file_id); 80 let source_root_id = db.file_source_root(file_id);
30 let source_root = db.source_root(source_root_id); 81 let source_root = db.source_root(source_root_id);
31 let mut files = source_root.walk().map(|id| (id.into(), None)).collect::<Vec<_>>(); 82 let mut files = source_root.walk().map(|id| (id.into(), None)).collect::<Vec<_>>();
32 83
33 if vis.syntax().text() == "pub(crate)" { 84 if vis.syntax().text() == "pub(crate)" {
34 return Some(SearchScope { scope: files }); 85 return SearchScope { scope: files };
35 } 86 }
36 if vis.syntax().text() == "pub" { 87 if vis.syntax().text() == "pub" {
37 let krate = self.container.krate(db).unwrap(); 88 let krate = self.container.krate(db).unwrap();
@@ -48,17 +99,15 @@ impl Declaration {
48 } 99 }
49 } 100 }
50 101
51 return Some(SearchScope { scope: files }); 102 return SearchScope { scope: files };
52 } 103 }
53 // FIXME: extend to "pub(super)" and "pub(in path)" cases, 104 // FIXME: "pub(super)", "pub(in path)"
54 // then remove `Option`
55 return None;
56 } 105 }
57 106
58 let range = match module_src.ast { 107 let range = match module_src.ast {
59 ModuleSource::Module(m) => Some(m.syntax().text_range()), 108 ModuleSource::Module(m) => Some(m.syntax().text_range()),
60 ModuleSource::SourceFile(_) => None, 109 ModuleSource::SourceFile(_) => None,
61 }; 110 };
62 Some(SearchScope { scope: vec![(file_id, range)] }) 111 SearchScope { scope: vec![(file_id, range)] }
63 } 112 }
64} 113}