aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r--crates/ra_ide_api/src/name_kind.rs116
-rw-r--r--crates/ra_ide_api/src/search_scope.rs186
2 files changed, 86 insertions, 216 deletions
diff --git a/crates/ra_ide_api/src/name_kind.rs b/crates/ra_ide_api/src/name_kind.rs
index 64adb1784..0effeb8a1 100644
--- a/crates/ra_ide_api/src/name_kind.rs
+++ b/crates/ra_ide_api/src/name_kind.rs
@@ -102,36 +102,92 @@ pub(crate) fn classify_name(
102 let parent = name.syntax().parent()?; 102 let parent = name.syntax().parent()?;
103 let file_id = file_id.into(); 103 let file_id = file_id.into();
104 104
105 if let Some(pat) = ast::BindPat::cast(parent.clone()) { 105 macro_rules! match_ast {
106 return Some(Pat(AstPtr::new(&pat))); 106 (match $node:ident {
107 $( ast::$ast:ident($it:ident) => $res:block, )*
108 _ => $catch_all:expr,
109 }) => {{
110 $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )*
111 { $catch_all }
112 }};
107 } 113 }
108 if let Some(var) = ast::EnumVariant::cast(parent.clone()) {
109 let src = hir::Source { file_id, ast: var };
110 let var = hir::EnumVariant::from_source(db, src)?;
111 return Some(Def(var.into()));
112 }
113 if let Some(field) = ast::RecordFieldDef::cast(parent.clone()) {
114 let src = hir::Source { file_id, ast: hir::FieldSource::Named(field) };
115 let field = hir::StructField::from_source(db, src)?;
116 return Some(FieldAccess(field));
117 }
118 if let Some(field) = ast::TupleFieldDef::cast(parent.clone()) {
119 let src = hir::Source { file_id, ast: hir::FieldSource::Pos(field) };
120 let field = hir::StructField::from_source(db, src)?;
121 return Some(FieldAccess(field));
122 }
123 if let Some(_) = parent.parent().and_then(ast::ItemList::cast) {
124 let ast = ast::ImplItem::cast(parent.clone())?;
125 let src = hir::Source { file_id, ast };
126 let item = hir::AssocItem::from_source(db, src)?;
127 return Some(AssocItem(item));
128 }
129 if let Some(item) = ast::ModuleItem::cast(parent.clone()) {
130 let src = hir::Source { file_id, ast: item };
131 let def = hir::ModuleDef::from_source(db, src)?;
132 return Some(Def(def));
133 }
134 // FIXME: TYPE_PARAM, ALIAS, MACRO_CALL; Union
135 114
136 None 115 // FIXME: add ast::MacroCall(it)
116 match_ast! {
117 match parent {
118 ast::BindPat(it) => {
119 let pat = AstPtr::new(&it);
120 Some(Pat(pat))
121 },
122 ast::RecordFieldDef(it) => {
123 let src = hir::Source { file_id, ast: hir::FieldSource::Named(it) };
124 let field = hir::StructField::from_source(db, src)?;
125 Some(FieldAccess(field))
126 },
127 ast::FnDef(it) => {
128 if parent.parent().and_then(ast::ItemList::cast).is_some() {
129 let src = hir::Source { file_id, ast: ast::ImplItem::from(it) };
130 let item = hir::AssocItem::from_source(db, src)?;
131 Some(AssocItem(item))
132 } else {
133 let src = hir::Source { file_id, ast: it };
134 let def = hir::Function::from_source(db, src)?;
135 Some(Def(def.into()))
136 }
137 },
138 ast::ConstDef(it) => {
139 if parent.parent().and_then(ast::ItemList::cast).is_some() {
140 let src = hir::Source { file_id, ast: ast::ImplItem::from(it) };
141 let item = hir::AssocItem::from_source(db, src)?;
142 Some(AssocItem(item))
143 } else {
144 let src = hir::Source { file_id, ast: it };
145 let def = hir::Const::from_source(db, src)?;
146 Some(Def(def.into()))
147 }
148 },
149 ast::TypeAliasDef(it) => {
150 if parent.parent().and_then(ast::ItemList::cast).is_some() {
151 let src = hir::Source { file_id, ast: ast::ImplItem::from(it) };
152 let item = hir::AssocItem::from_source(db, src)?;
153 Some(AssocItem(item))
154 } else {
155 let src = hir::Source { file_id, ast: it };
156 let def = hir::TypeAlias::from_source(db, src)?;
157 Some(Def(def.into()))
158 }
159 },
160 ast::Module(it) => {
161 let src = hir::Source { file_id, ast: hir::ModuleSource::Module(it) };
162 let def = hir::Module::from_definition(db, src)?;
163 Some(Def(def.into()))
164 },
165 ast::StructDef(it) => {
166 let src = hir::Source { file_id, ast: it };
167 let def = hir::Struct::from_source(db, src)?;
168 Some(Def(def.into()))
169 },
170 ast::EnumDef(it) => {
171 let src = hir::Source { file_id, ast: it };
172 let def = hir::Enum::from_source(db, src)?;
173 Some(Def(def.into()))
174 },
175 ast::TraitDef(it) => {
176 let src = hir::Source { file_id, ast: it };
177 let def = hir::Trait::from_source(db, src)?;
178 Some(Def(def.into()))
179 },
180 ast::StaticDef(it) => {
181 let src = hir::Source { file_id, ast: it };
182 let def = hir::Static::from_source(db, src)?;
183 Some(Def(def.into()))
184 },
185 ast::EnumVariant(it) => {
186 let src = hir::Source { file_id, ast: it };
187 let def = hir::EnumVariant::from_source(db, src)?;
188 Some(Def(def.into()))
189 },
190 _ => None,
191 }
192 }
137} 193}
diff --git a/crates/ra_ide_api/src/search_scope.rs b/crates/ra_ide_api/src/search_scope.rs
deleted file mode 100644
index ca1ac2b03..000000000
--- a/crates/ra_ide_api/src/search_scope.rs
+++ /dev/null
@@ -1,186 +0,0 @@
1pub enum SearchScope {
2 Function(hir::Function),
3 Module(hir::Module),
4 Crate(hir::Crate),
5 Crates(Vec<hir::Crate>),
6}
7
8pub struct SearchScope{
9 pub scope: Vec<SyntaxNode>
10}
11
12pub fn find_all_refs(db: &RootDatabase, decl: NameKind) -> Vec<ReferenceDescriptor> {
13 let (module, visibility) = match decl {
14 FieldAccess(field) => {
15 let parent = field.parent_def(db);
16 let module = parent.module(db);
17 let visibility = match parent {
18 VariantDef::Struct(s) => s.source(db).ast.visibility(),
19 VariantDef::EnumVariant(v) => v.parent_enum(db).source(db).ast.visibility(),
20 };
21 (module, visibility)
22 }
23 AssocItem(item) => {
24 let parent = item.parent_trait(db)?;
25 let module = parent.module(db);
26 let visibility = parent.source(db).ast.visibility();
27 (module, visibility)
28 }
29 Def(def) => {
30 let (module, visibility) = match def {
31 ModuleDef::Module(m) => (m, ),
32 ModuleDef::Function(f) => (f.module(db), f.source(db).ast.visibility()),
33 ModuleDef::Adt::Struct(s) => (s.module(db), s.source(db).ast.visibility()),
34 ModuleDef::Adt::Union(u) => (u.module(db), u.source(db).ast.visibility()),
35 ModuleDef::Adt::Enum(e) => (e.module(db), e.source(db).ast.visibility()),
36 ModuleDef::EnumVariant(v) => (v.module(db), v.source(db).ast.visibility()),
37 ModuleDef::Const(c) => (c.module(db), c.source(db).ast.visibility()),
38 ModuleDef::Static(s) => (s.module(db), s.source(db).ast.visibility()),
39 ModuleDef::Trait(t) => (t.module(db), t.source(db).ast.visibility()),
40 ModuleDef::TypeAlias(a) => (a.module(db), a.source(db).ast.visibility()),
41 ModuleDef::BuiltinType(_) => return vec![];
42 };
43 (module, visibility)
44 }
45 // FIXME: add missing kinds
46 _ => return vec![];
47 };
48 let scope = scope(db, module, visibility);
49}
50
51fn scope(db: &RootDatabase, module: hir::Module, item_vis: Option<ast::Visibility>) -> SearchScope {
52 if let Some(v) = item_vis {
53 let krate = module.krate(db)?;
54
55 if v.syntax().text() == "pub" {
56 SearchScope::Crate(krate)
57 }
58 if v.syntax().text() == "pub(crate)" {
59 let crate_graph = db.crate_graph();
60 let crates = crate_graph.iter().filter(|id| {
61 crate_graph.dependencies(id).any(|d| d.crate_id() == krate.crate_id())
62 }).map(|id| Crate { id }).collect::<Vec<_>>();
63 crates.insert(0, krate);
64 SearchScope::Crates(crates)
65 }
66 // FIXME: "pub(super)", "pub(in path)"
67 SearchScope::Module(module)
68 }
69 SearchScope::Module(module)
70}
71
72fn process_one(db, scope: SearchScope, pat) {
73 match scope {
74 SearchScope::Crate(krate) => {
75 let text = db.file_text(position.file_id).as_str();
76 let parse = SourceFile::parse(text);
77 for (offset, name) in text.match_indices(pat) {
78 if let Some() = find_node_at_offset<ast::NameRef>(parse, offset) {
79
80 }
81 }
82 }
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use crate::{
89 mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId,
90 ReferenceSearchResult,
91 };
92 use insta::assert_debug_snapshot;
93 use test_utils::assert_eq_text;
94
95 #[test]
96 fn test_find_all_refs_for_local() {
97 let code = r#"
98 fn main() {
99 let mut i = 1;
100 let j = 1;
101 i = i<|> + j;
102
103 {
104 i = 0;
105 }
106
107 i = 5;
108 }
109 "#;
110
111 let refs = get_all_refs(code);
112 assert_eq!(refs.len(), 5);
113 }
114
115 #[test]
116 fn test_find_all_refs_for_param_inside() {
117 let code = r#"
118 fn foo(i : u32) -> u32 {
119 i<|>
120 }"#;
121
122 let refs = get_all_refs(code);
123 assert_eq!(refs.len(), 2);
124 }
125
126 #[test]
127 fn test_find_all_refs_for_fn_param() {
128 let code = r#"
129 fn foo(i<|> : u32) -> u32 {
130 i
131 }"#;
132
133 let refs = get_all_refs(code);
134 assert_eq!(refs.len(), 2);
135 }
136
137 #[test]
138 fn test_find_all_refs_field_name() {
139 let code = r#"
140 //- /lib.rs
141 struct Foo {
142 spam<|>: u32,
143 }
144 "#;
145
146 let refs = get_all_refs(code);
147 assert_eq!(refs.len(), 1);
148 }
149
150 #[test]
151 fn test_find_all_refs_methods() {
152 let code = r#"
153 //- /lib.rs
154 struct Foo;
155 impl Foo {
156 pub fn a() {
157 self.b()
158 }
159 fn b(&self) {}
160 }
161 "#;
162
163 let refs = get_all_refs(code);
164 assert_eq!(refs.len(), 1);
165 }
166
167 #[test]
168 fn test_find_all_refs_pub_enum() {
169 let code = r#"
170 //- /lib.rs
171 pub enum Foo {
172 A,
173 B<|>,
174 C,
175 }
176 "#;
177
178 let refs = get_all_refs(code);
179 assert_eq!(refs.len(), 1);
180 }
181
182 fn get_all_refs(text: &str) -> ReferenceSearchResult {
183 let (analysis, position) = single_file_with_position(text);
184 analysis.find_all_refs(position).unwrap().unwrap()
185 }
186} \ No newline at end of file