aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/from_source.rs60
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs2
-rw-r--r--crates/ra_ide_api/src/hover.rs2
-rw-r--r--crates/ra_ide_api/src/references.rs10
-rw-r--r--crates/ra_ide_api/src/references/classify.rs196
-rw-r--r--crates/ra_ide_api/src/references/definition.rs177
-rw-r--r--crates/ra_ide_api/src/references/name_definition.rs104
-rw-r--r--crates/ra_ide_api/src/references/search_scope.rs4
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs2
9 files changed, 227 insertions, 330 deletions
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index e09414ca3..f80d8eb5f 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -11,9 +11,8 @@ use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
12 ids::{AstItemDef, LocationCtx}, 12 ids::{AstItemDef, LocationCtx},
13 name::AsName, 13 name::AsName,
14 AssocItem, Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, 14 Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module,
15 Module, ModuleDef, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, 15 ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef,
16 VariantDef,
17}; 16};
18 17
19pub trait FromSource: Sized { 18pub trait FromSource: Sized {
@@ -130,61 +129,6 @@ impl FromSource for StructField {
130 } 129 }
131} 130}
132 131
133impl FromSource for AssocItem {
134 type Ast = ast::ImplItem;
135 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
136 macro_rules! def {
137 ($kind:ident, $ast:ident) => {
138 $kind::from_source(db, Source { file_id: src.file_id, ast: $ast })
139 .and_then(|it| Some(AssocItem::from(it)))
140 };
141 }
142
143 match src.ast {
144 ast::ImplItem::FnDef(f) => def!(Function, f),
145 ast::ImplItem::ConstDef(c) => def!(Const, c),
146 ast::ImplItem::TypeAliasDef(a) => def!(TypeAlias, a),
147 }
148 }
149}
150
151// not fully matched
152impl FromSource for ModuleDef {
153 type Ast = ast::ModuleItem;
154 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
155 macro_rules! def {
156 ($kind:ident, $ast:ident) => {
157 $kind::from_source(db, Source { file_id: src.file_id, ast: $ast })
158 .and_then(|it| Some(ModuleDef::from(it)))
159 };
160 }
161
162 match src.ast {
163 ast::ModuleItem::FnDef(f) => def!(Function, f),
164 ast::ModuleItem::ConstDef(c) => def!(Const, c),
165 ast::ModuleItem::TypeAliasDef(a) => def!(TypeAlias, a),
166 ast::ModuleItem::TraitDef(t) => def!(Trait, t),
167 ast::ModuleItem::StaticDef(s) => def!(Static, s),
168 ast::ModuleItem::StructDef(s) => {
169 let src = Source { file_id: src.file_id, ast: s };
170 let s = Struct::from_source(db, src)?;
171 Some(ModuleDef::Adt(s.into()))
172 }
173 ast::ModuleItem::EnumDef(e) => {
174 let src = Source { file_id: src.file_id, ast: e };
175 let e = Enum::from_source(db, src)?;
176 Some(ModuleDef::Adt(e.into()))
177 }
178 ast::ModuleItem::Module(ref m) if !m.has_semi() => {
179 let src = Source { file_id: src.file_id, ast: ModuleSource::Module(m.clone()) };
180 let module = Module::from_definition(db, src)?;
181 Some(ModuleDef::Module(module))
182 }
183 _ => None,
184 }
185 }
186}
187
188// FIXME: simplify it 132// FIXME: simplify it
189impl ModuleSource { 133impl ModuleSource {
190 pub fn from_position( 134 pub fn from_position(
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index c35d8da41..1b4ad3a59 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -57,7 +57,7 @@ pub(crate) fn reference_definition(
57 let name_kind = classify_name_ref(db, file_id, &name_ref).and_then(|d| Some(d.item)); 57 let name_kind = classify_name_ref(db, file_id, &name_ref).and_then(|d| Some(d.item));
58 match name_kind { 58 match name_kind {
59 Some(Macro(mac)) => return Exact(NavigationTarget::from_macro_def(db, mac)), 59 Some(Macro(mac)) => return Exact(NavigationTarget::from_macro_def(db, mac)),
60 Some(FieldAccess(field)) => return Exact(NavigationTarget::from_field(db, field)), 60 Some(Field(field)) => return Exact(NavigationTarget::from_field(db, field)),
61 Some(AssocItem(assoc)) => return Exact(NavigationTarget::from_assoc_item(db, assoc)), 61 Some(AssocItem(assoc)) => return Exact(NavigationTarget::from_assoc_item(db, assoc)),
62 Some(Def(def)) => match NavigationTarget::from_def(db, def) { 62 Some(Def(def)) => match NavigationTarget::from_def(db, def) {
63 Some(nav) => return Exact(nav), 63 Some(nav) => return Exact(nav),
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 189094ae5..318708df3 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -107,7 +107,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
107 let src = it.source(db); 107 let src = it.source(db);
108 res.extend(hover_text(src.ast.doc_comment_text(), Some(macro_label(&src.ast)))); 108 res.extend(hover_text(src.ast.doc_comment_text(), Some(macro_label(&src.ast))));
109 } 109 }
110 Some(FieldAccess(it)) => { 110 Some(Field(it)) => {
111 let src = it.source(db); 111 let src = it.source(db);
112 if let hir::FieldSource::Named(it) = src.ast { 112 if let hir::FieldSource::Named(it) = src.ast {
113 res.extend(hover_text(it.doc_comment_text(), it.short_label())); 113 res.extend(hover_text(it.doc_comment_text(), it.short_label()));
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index f54542787..3761fd6e7 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -1,7 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3mod classify; 3mod classify;
4mod definition; 4mod name_definition;
5mod rename; 5mod rename;
6mod search_scope; 6mod search_scope;
7 7
@@ -12,7 +12,7 @@ use crate::{db::RootDatabase, FileId, FilePosition, FileRange, NavigationTarget,
12 12
13pub(crate) use self::{ 13pub(crate) use self::{
14 classify::{classify_name, classify_name_ref}, 14 classify::{classify_name, classify_name_ref},
15 definition::{Definition, NameKind}, 15 name_definition::{NameDefinition, NameKind},
16 rename::rename, 16 rename::rename,
17}; 17};
18 18
@@ -63,7 +63,7 @@ pub(crate) fn find_all_refs(
63 63
64 let declaration = match def.item { 64 let declaration = match def.item {
65 NameKind::Macro(mac) => NavigationTarget::from_macro_def(db, mac), 65 NameKind::Macro(mac) => NavigationTarget::from_macro_def(db, mac),
66 NameKind::FieldAccess(field) => NavigationTarget::from_field(db, field), 66 NameKind::Field(field) => NavigationTarget::from_field(db, field),
67 NameKind::AssocItem(assoc) => NavigationTarget::from_assoc_item(db, assoc), 67 NameKind::AssocItem(assoc) => NavigationTarget::from_assoc_item(db, assoc),
68 NameKind::Def(def) => NavigationTarget::from_def(db, def)?, 68 NameKind::Def(def) => NavigationTarget::from_def(db, def)?,
69 NameKind::SelfType(ref ty) => match ty.as_adt() { 69 NameKind::SelfType(ref ty) => match ty.as_adt() {
@@ -84,7 +84,7 @@ fn find_name<'a>(
84 db: &RootDatabase, 84 db: &RootDatabase,
85 syntax: &SyntaxNode, 85 syntax: &SyntaxNode,
86 position: FilePosition, 86 position: FilePosition,
87) -> Option<RangeInfo<(String, Definition)>> { 87) -> Option<RangeInfo<(String, NameDefinition)>> {
88 if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) { 88 if let Some(name) = find_node_at_offset::<ast::Name>(&syntax, position.offset) {
89 let def = classify_name(db, position.file_id, &name)?; 89 let def = classify_name(db, position.file_id, &name)?;
90 let range = name.syntax().text_range(); 90 let range = name.syntax().text_range();
@@ -96,7 +96,7 @@ fn find_name<'a>(
96 Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) 96 Some(RangeInfo::new(range, (name_ref.text().to_string(), def)))
97} 97}
98 98
99fn process_definition(db: &RootDatabase, def: Definition, name: String) -> Vec<FileRange> { 99fn process_definition(db: &RootDatabase, def: NameDefinition, name: String) -> Vec<FileRange> {
100 let pat = name.as_str(); 100 let pat = name.as_str();
101 let scope = def.scope(db).scope; 101 let scope = def.scope(db).scope;
102 let mut refs = vec![]; 102 let mut refs = vec![];
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs
index 0b604a5cf..2ba1cf71c 100644
--- a/crates/ra_ide_api/src/references/classify.rs
+++ b/crates/ra_ide_api/src/references/classify.rs
@@ -1,47 +1,90 @@
1use hir::{ 1use hir::{Either, FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer};
2 AssocItem, Either, EnumVariant, FromSource, Module, ModuleDef, ModuleSource, Path,
3 PathResolution, Source, SourceAnalyzer, StructField,
4};
5use ra_db::FileId; 2use ra_db::FileId;
6use ra_syntax::{ast, match_ast, AstNode, AstPtr}; 3use ra_syntax::{ast, match_ast, AstNode, AstPtr};
7 4
8use super::{definition::HasDefinition, Definition, NameKind}; 5use super::{
6 name_definition::{from_assoc_item, from_module_def, from_pat, from_struct_field},
7 NameDefinition, NameKind,
8};
9use crate::db::RootDatabase; 9use crate::db::RootDatabase;
10 10
11use hir::{db::AstDatabase, HirFileId};
12
13pub(crate) fn classify_name( 11pub(crate) fn classify_name(
14 db: &RootDatabase, 12 db: &RootDatabase,
15 file_id: FileId, 13 file_id: FileId,
16 name: &ast::Name, 14 name: &ast::Name,
17) -> Option<Definition> { 15) -> Option<NameDefinition> {
18 let parent = name.syntax().parent()?; 16 let parent = name.syntax().parent()?;
19 let file_id = file_id.into(); 17 let file_id = file_id.into();
20 18
19 // FIXME: add ast::MacroCall(it)
21 match_ast! { 20 match_ast! {
22 match parent { 21 match parent {
23 ast::BindPat(it) => { 22 ast::BindPat(it) => {
24 decl_from_pat(db, file_id, AstPtr::new(&it)) 23 from_pat(db, file_id, AstPtr::new(&it))
25 }, 24 },
26 ast::RecordFieldDef(it) => { 25 ast::RecordFieldDef(it) => {
27 StructField::from_def(db, file_id, it) 26 let ast = hir::FieldSource::Named(it);
27 let src = hir::Source { file_id, ast };
28 let field = hir::StructField::from_source(db, src)?;
29 Some(from_struct_field(db, field))
30 },
31 ast::Module(it) => {
32 let ast = hir::ModuleSource::Module(it);
33 let src = hir::Source { file_id, ast };
34 let def = hir::Module::from_definition(db, src)?;
35 Some(from_module_def(db, def.into()))
28 }, 36 },
29 ast::ImplItem(it) => { 37 ast::StructDef(it) => {
30 AssocItem::from_def(db, file_id, it.clone()).or_else(|| { 38 let src = hir::Source { file_id, ast: it };
31 match it { 39 let def = hir::Struct::from_source(db, src)?;
32 ast::ImplItem::FnDef(f) => ModuleDef::from_def(db, file_id, f.into()), 40 Some(from_module_def(db, def.into()))
33 ast::ImplItem::ConstDef(c) => ModuleDef::from_def(db, file_id, c.into()), 41 },
34 ast::ImplItem::TypeAliasDef(a) => ModuleDef::from_def(db, file_id, a.into()), 42 ast::EnumDef(it) => {
35 } 43 let src = hir::Source { file_id, ast: it };
36 }) 44 let def = hir::Enum::from_source(db, src)?;
45 Some(from_module_def(db, def.into()))
46 },
47 ast::TraitDef(it) => {
48 let src = hir::Source { file_id, ast: it };
49 let def = hir::Trait::from_source(db, src)?;
50 Some(from_module_def(db, def.into()))
51 },
52 ast::StaticDef(it) => {
53 let src = hir::Source { file_id, ast: it };
54 let def = hir::Static::from_source(db, src)?;
55 Some(from_module_def(db, def.into()))
37 }, 56 },
38 ast::EnumVariant(it) => { 57 ast::EnumVariant(it) => {
39 let src = hir::Source { file_id, ast: it.clone() }; 58 let src = hir::Source { file_id, ast: it };
40 let def: ModuleDef = EnumVariant::from_source(db, src)?.into(); 59 let def = hir::EnumVariant::from_source(db, src)?;
41 Some(def.definition(db)) 60 Some(from_module_def(db, def.into()))
61 },
62 ast::FnDef(it) => {
63 let src = hir::Source { file_id, ast: it };
64 let def = hir::Function::from_source(db, src)?;
65 if parent.parent().and_then(ast::ItemList::cast).is_some() {
66 Some(from_assoc_item(db, def.into()))
67 } else {
68 Some(from_module_def(db, def.into()))
69 }
70 },
71 ast::ConstDef(it) => {
72 let src = hir::Source { file_id, ast: it };
73 let def = hir::Const::from_source(db, src)?;
74 if parent.parent().and_then(ast::ItemList::cast).is_some() {
75 Some(from_assoc_item(db, def.into()))
76 } else {
77 Some(from_module_def(db, def.into()))
78 }
42 }, 79 },
43 ast::ModuleItem(it) => { 80 ast::TypeAliasDef(it) => {
44 ModuleDef::from_def(db, file_id, it) 81 let src = hir::Source { file_id, ast: it };
82 let def = hir::TypeAlias::from_source(db, src)?;
83 if parent.parent().and_then(ast::ItemList::cast).is_some() {
84 Some(from_assoc_item(db, def.into()))
85 } else {
86 Some(from_module_def(db, def.into()))
87 }
45 }, 88 },
46 _ => None, 89 _ => None,
47 } 90 }
@@ -52,92 +95,75 @@ pub(crate) fn classify_name_ref(
52 db: &RootDatabase, 95 db: &RootDatabase,
53 file_id: FileId, 96 file_id: FileId,
54 name_ref: &ast::NameRef, 97 name_ref: &ast::NameRef,
55) -> Option<Definition> { 98) -> Option<NameDefinition> {
56 let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); 99 use PathResolution::*;
100
57 let parent = name_ref.syntax().parent()?; 101 let parent = name_ref.syntax().parent()?;
58 match_ast! { 102 let analyzer = SourceAnalyzer::new(db, file_id, name_ref.syntax(), None);
59 match parent { 103
60 ast::MethodCallExpr(it) => { 104 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
61 return AssocItem::from_ref(db, &analyzer, it); 105 let func = analyzer.resolve_method_call(&method_call)?;
62 }, 106 return Some(from_assoc_item(db, func.into()));
63 ast::FieldExpr(it) => { 107 }
64 if let Some(field) = analyzer.resolve_field(&it) { 108
65 return Some(field.definition(db)); 109 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
66 } 110 if let Some(field) = analyzer.resolve_field(&field_expr) {
67 }, 111 return Some(from_struct_field(db, field));
68 ast::RecordField(it) => { 112 }
69 if let Some(record_lit) = it.syntax().ancestors().find_map(ast::RecordLit::cast) { 113 }
70 let variant_def = analyzer.resolve_record_literal(&record_lit)?; 114
71 let hir_path = Path::from_name_ref(name_ref); 115 if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
72 let hir_name = hir_path.as_ident()?; 116 if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) {
73 let field = variant_def.field(db, hir_name)?; 117 let variant_def = analyzer.resolve_record_literal(&record_lit)?;
74 return Some(field.definition(db)); 118 let hir_path = Path::from_name_ref(name_ref);
75 } 119 let hir_name = hir_path.as_ident()?;
76 }, 120 let field = variant_def.field(db, hir_name)?;
77 _ => (), 121 return Some(from_struct_field(db, field));
78 } 122 }
79 } 123 }
80 124
81 let ast = ModuleSource::from_child_node(db, file_id, &parent); 125 let ast = ModuleSource::from_child_node(db, file_id, &parent);
82 let file_id = file_id.into(); 126 let file_id = file_id.into();
127 // FIXME: find correct container and visibility for each case
83 let container = Module::from_definition(db, Source { file_id, ast })?; 128 let container = Module::from_definition(db, Source { file_id, ast })?;
84 let visibility = None; 129 let visibility = None;
85 130
86 if let Some(macro_call) = 131 if let Some(macro_call) =
87 parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast) 132 parent.parent().and_then(|node| node.parent()).and_then(ast::MacroCall::cast)
88 { 133 {
89 if let Some(mac) = analyzer.resolve_macro_call(db, &macro_call) { 134 if let Some(macro_def) = analyzer.resolve_macro_call(db, &macro_call) {
90 return Some(Definition { item: NameKind::Macro(mac), container, visibility }); 135 return Some(NameDefinition {
136 item: NameKind::Macro(macro_def),
137 container,
138 visibility,
139 });
91 } 140 }
92 } 141 }
93 142
94 // General case, a path or a local:
95 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; 143 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
96 let resolved = analyzer.resolve_path(db, &path)?; 144 let resolved = analyzer.resolve_path(db, &path)?;
97 match resolved { 145 match resolved {
98 PathResolution::Def(def) => Some(def.definition(db)), 146 Def(def) => Some(from_module_def(db, def)),
99 PathResolution::LocalBinding(Either::A(pat)) => decl_from_pat(db, file_id, pat), 147 AssocItem(item) => Some(from_assoc_item(db, item)),
100 PathResolution::LocalBinding(Either::B(par)) => { 148 LocalBinding(Either::A(pat)) => from_pat(db, file_id, pat),
101 Some(Definition { item: NameKind::SelfParam(par), container, visibility }) 149 LocalBinding(Either::B(par)) => {
150 let item = NameKind::SelfParam(par);
151 Some(NameDefinition { item, container, visibility })
102 } 152 }
103 PathResolution::GenericParam(par) => { 153 GenericParam(par) => {
104 // FIXME: get generic param def 154 // FIXME: get generic param def
105 Some(Definition { item: NameKind::GenericParam(par), container, visibility }) 155 let item = NameKind::GenericParam(par);
156 Some(NameDefinition { item, container, visibility })
106 } 157 }
107 PathResolution::Macro(def) => { 158 Macro(def) => {
108 Some(Definition { item: NameKind::Macro(def), container, visibility }) 159 let item = NameKind::Macro(def);
160 Some(NameDefinition { item, container, visibility })
109 } 161 }
110 PathResolution::SelfType(impl_block) => { 162 SelfType(impl_block) => {
111 let ty = impl_block.target_ty(db); 163 let ty = impl_block.target_ty(db);
164 let item = NameKind::SelfType(ty);
112 let container = impl_block.module(); 165 let container = impl_block.module();
113 Some(Definition { item: NameKind::SelfType(ty), container, visibility }) 166 Some(NameDefinition { item, container, visibility })
114 } 167 }
115 PathResolution::AssocItem(assoc) => Some(assoc.definition(db)),
116 } 168 }
117} 169}
118
119fn decl_from_pat(
120 db: &RootDatabase,
121 file_id: HirFileId,
122 pat: AstPtr<ast::BindPat>,
123) -> Option<Definition> {
124 let root = db.parse_or_expand(file_id)?;
125 // FIXME: use match_ast!
126 let def = pat.to_node(&root).syntax().ancestors().find_map(|node| {
127 if let Some(it) = ast::FnDef::cast(node.clone()) {
128 let src = hir::Source { file_id, ast: it };
129 Some(hir::Function::from_source(db, src)?.into())
130 } else if let Some(it) = ast::ConstDef::cast(node.clone()) {
131 let src = hir::Source { file_id, ast: it };
132 Some(hir::Const::from_source(db, src)?.into())
133 } else if let Some(it) = ast::StaticDef::cast(node.clone()) {
134 let src = hir::Source { file_id, ast: it };
135 Some(hir::Static::from_source(db, src)?.into())
136 } else {
137 None
138 }
139 })?;
140 let item = NameKind::Pat((def, pat));
141 let container = def.module(db);
142 Some(Definition { item, container, visibility: None })
143}
diff --git a/crates/ra_ide_api/src/references/definition.rs b/crates/ra_ide_api/src/references/definition.rs
deleted file mode 100644
index 65b1f8dd7..000000000
--- a/crates/ra_ide_api/src/references/definition.rs
+++ /dev/null
@@ -1,177 +0,0 @@
1use hir::{
2 db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef,
3 Module, ModuleDef, SourceAnalyzer, StructField, Ty, VariantDef,
4};
5use ra_syntax::{ast, ast::VisibilityOwner, AstNode, AstPtr};
6
7use crate::db::RootDatabase;
8
9#[derive(Debug, PartialEq, Eq)]
10pub enum NameKind {
11 Macro(MacroDef),
12 FieldAccess(StructField),
13 AssocItem(AssocItem),
14 Def(ModuleDef),
15 SelfType(Ty),
16 Pat((DefWithBody, AstPtr<ast::BindPat>)),
17 SelfParam(AstPtr<ast::SelfParam>),
18 GenericParam(u32),
19}
20
21#[derive(PartialEq, Eq)]
22pub(crate) struct Definition {
23 pub visibility: Option<ast::Visibility>,
24 pub container: Module,
25 pub item: NameKind,
26}
27
28pub(super) trait HasDefinition {
29 type Def;
30 type Ref;
31
32 fn definition(self, db: &RootDatabase) -> Definition;
33 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition>;
34 fn from_ref(
35 db: &RootDatabase,
36 analyzer: &SourceAnalyzer,
37 refer: Self::Ref,
38 ) -> Option<Definition>;
39}
40
41// fn decl_from_pat(
42// db: &RootDatabase,
43// file_id: HirFileId,
44// pat: AstPtr<ast::BindPat>,
45// ) -> Option<Definition> {
46// let root = db.parse_or_expand(file_id)?;
47// // FIXME: use match_ast!
48// let def = pat.to_node(&root).syntax().ancestors().find_map(|node| {
49// if let Some(it) = ast::FnDef::cast(node.clone()) {
50// let src = hir::Source { file_id, ast: it };
51// Some(hir::Function::from_source(db, src)?.into())
52// } else if let Some(it) = ast::ConstDef::cast(node.clone()) {
53// let src = hir::Source { file_id, ast: it };
54// Some(hir::Const::from_source(db, src)?.into())
55// } else if let Some(it) = ast::StaticDef::cast(node.clone()) {
56// let src = hir::Source { file_id, ast: it };
57// Some(hir::Static::from_source(db, src)?.into())
58// } else {
59// None
60// }
61// })?;
62// let item = NameKind::Pat((def, pat));
63// let container = def.module(db);
64// Some(Definition { item, container, visibility: None })
65// }
66
67impl HasDefinition for StructField {
68 type Def = ast::RecordFieldDef;
69 type Ref = ast::FieldExpr;
70
71 fn definition(self, db: &RootDatabase) -> Definition {
72 let item = NameKind::FieldAccess(self);
73 let parent = self.parent_def(db);
74 let container = parent.module(db);
75 let visibility = match parent {
76 VariantDef::Struct(s) => s.source(db).ast.visibility(),
77 VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(),
78 };
79 Definition { item, container, visibility }
80 }
81
82 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> {
83 let src = hir::Source { file_id, ast: hir::FieldSource::Named(def) };
84 let field = StructField::from_source(db, src)?;
85 Some(field.definition(db))
86 }
87
88 fn from_ref(
89 db: &RootDatabase,
90 analyzer: &SourceAnalyzer,
91 refer: Self::Ref,
92 ) -> Option<Definition> {
93 let field = analyzer.resolve_field(&refer)?;
94 Some(field.definition(db))
95 }
96}
97
98impl HasDefinition for AssocItem {
99 type Def = ast::ImplItem;
100 type Ref = ast::MethodCallExpr;
101
102 fn definition(self, db: &RootDatabase) -> Definition {
103 let item = NameKind::AssocItem(self);
104 let container = self.module(db);
105 let visibility = match self {
106 AssocItem::Function(f) => f.source(db).ast.visibility(),
107 AssocItem::Const(c) => c.source(db).ast.visibility(),
108 AssocItem::TypeAlias(a) => a.source(db).ast.visibility(),
109 };
110 Definition { item, container, visibility }
111 }
112
113 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> {
114 if def.syntax().parent().and_then(ast::ItemList::cast).is_none() {
115 return None;
116 }
117 let src = hir::Source { file_id, ast: def };
118 let item = AssocItem::from_source(db, src)?;
119 Some(item.definition(db))
120 }
121
122 fn from_ref(
123 db: &RootDatabase,
124 analyzer: &SourceAnalyzer,
125 refer: Self::Ref,
126 ) -> Option<Definition> {
127 let func: AssocItem = analyzer.resolve_method_call(&refer)?.into();
128 Some(func.definition(db))
129 }
130}
131
132impl HasDefinition for ModuleDef {
133 type Def = ast::ModuleItem;
134 type Ref = ast::Path;
135
136 fn definition(self, db: &RootDatabase) -> Definition {
137 let (container, visibility) = match self {
138 ModuleDef::Module(it) => {
139 let container = it.parent(db).or_else(|| Some(it)).unwrap();
140 let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility());
141 (container, visibility)
142 }
143 ModuleDef::EnumVariant(it) => {
144 let container = it.module(db);
145 let visibility = it.source(db).ast.parent_enum().visibility();
146 (container, visibility)
147 }
148 ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()),
149 ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()),
150 ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()),
151 ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()),
152 ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()),
153 ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()),
154 ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()),
155 ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()),
156 ModuleDef::BuiltinType(..) => unreachable!(),
157 };
158 let item = NameKind::Def(self);
159 Definition { item, container, visibility }
160 }
161
162 fn from_def(db: &RootDatabase, file_id: HirFileId, def: Self::Def) -> Option<Definition> {
163 let src = hir::Source { file_id, ast: def };
164 let def = ModuleDef::from_source(db, src)?;
165 Some(def.definition(db))
166 }
167
168 fn from_ref(
169 db: &RootDatabase,
170 analyzer: &SourceAnalyzer,
171 refer: Self::Ref,
172 ) -> Option<Definition> {
173 None
174 }
175}
176
177// FIXME: impl HasDefinition for hir::MacroDef
diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs
new file mode 100644
index 000000000..19702eba0
--- /dev/null
+++ b/crates/ra_ide_api/src/references/name_definition.rs
@@ -0,0 +1,104 @@
1use hir::{
2 db::AstDatabase, Adt, AssocItem, DefWithBody, FromSource, HasSource, HirFileId, MacroDef,
3 Module, ModuleDef, StructField, Ty, VariantDef,
4};
5use ra_syntax::{ast, ast::VisibilityOwner, match_ast, AstNode, AstPtr};
6
7use crate::db::RootDatabase;
8
9#[derive(Debug, PartialEq, Eq)]
10pub enum NameKind {
11 Macro(MacroDef),
12 Field(StructField),
13 AssocItem(AssocItem),
14 Def(ModuleDef),
15 SelfType(Ty),
16 Pat((DefWithBody, AstPtr<ast::BindPat>)),
17 SelfParam(AstPtr<ast::SelfParam>),
18 GenericParam(u32),
19}
20
21#[derive(PartialEq, Eq)]
22pub(crate) struct NameDefinition {
23 pub visibility: Option<ast::Visibility>,
24 pub container: Module,
25 pub item: NameKind,
26}
27
28pub(super) fn from_pat(
29 db: &RootDatabase,
30 file_id: HirFileId,
31 pat: AstPtr<ast::BindPat>,
32) -> Option<NameDefinition> {
33 let root = db.parse_or_expand(file_id)?;
34 let def = pat.to_node(&root).syntax().ancestors().find_map(|node| {
35 match_ast! {
36 match node {
37 ast::FnDef(it) => {
38 let src = hir::Source { file_id, ast: it };
39 Some(hir::Function::from_source(db, src)?.into())
40 },
41 ast::ConstDef(it) => {
42 let src = hir::Source { file_id, ast: it };
43 Some(hir::Const::from_source(db, src)?.into())
44 },
45 ast::StaticDef(it) => {
46 let src = hir::Source { file_id, ast: it };
47 Some(hir::Static::from_source(db, src)?.into())
48 },
49 _ => None,
50 }
51 }
52 })?;
53 let item = NameKind::Pat((def, pat));
54 let container = def.module(db);
55 Some(NameDefinition { item, container, visibility: None })
56}
57
58pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition {
59 let container = item.module(db);
60 let visibility = match item {
61 AssocItem::Function(f) => f.source(db).ast.visibility(),
62 AssocItem::Const(c) => c.source(db).ast.visibility(),
63 AssocItem::TypeAlias(a) => a.source(db).ast.visibility(),
64 };
65 let item = NameKind::AssocItem(item);
66 NameDefinition { item, container, visibility }
67}
68
69pub(super) fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDefinition {
70 let item = NameKind::Field(field);
71 let parent = field.parent_def(db);
72 let container = parent.module(db);
73 let visibility = match parent {
74 VariantDef::Struct(s) => s.source(db).ast.visibility(),
75 VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(),
76 };
77 NameDefinition { item, container, visibility }
78}
79
80pub(super) fn from_module_def(db: &RootDatabase, def: ModuleDef) -> NameDefinition {
81 let item = NameKind::Def(def);
82 let (container, visibility) = match def {
83 ModuleDef::Module(it) => {
84 let container = it.parent(db).or_else(|| Some(it)).unwrap();
85 let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility());
86 (container, visibility)
87 }
88 ModuleDef::EnumVariant(it) => {
89 let container = it.module(db);
90 let visibility = it.source(db).ast.parent_enum().visibility();
91 (container, visibility)
92 }
93 ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()),
94 ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()),
95 ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()),
96 ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()),
97 ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()),
98 ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()),
99 ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()),
100 ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()),
101 ModuleDef::BuiltinType(..) => unreachable!(),
102 };
103 NameDefinition { item, container, visibility }
104}
diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs
index 557ee7b57..346815d31 100644
--- a/crates/ra_ide_api/src/references/search_scope.rs
+++ b/crates/ra_ide_api/src/references/search_scope.rs
@@ -4,13 +4,13 @@ use ra_syntax::{AstNode, TextRange};
4 4
5use crate::db::RootDatabase; 5use crate::db::RootDatabase;
6 6
7use super::{Definition, NameKind}; 7use super::{NameDefinition, NameKind};
8 8
9pub(crate) struct SearchScope { 9pub(crate) struct SearchScope {
10 pub scope: Vec<(FileId, Option<TextRange>)>, 10 pub scope: Vec<(FileId, Option<TextRange>)>,
11} 11}
12 12
13impl Definition { 13impl NameDefinition {
14 pub fn scope(&self, db: &RootDatabase) -> SearchScope { 14 pub fn scope(&self, db: &RootDatabase) -> SearchScope {
15 let module_src = self.container.definition_source(db); 15 let module_src = self.container.definition_source(db);
16 let file_id = module_src.file_id.original_file(db); 16 let file_id = module_src.file_id.original_file(db);
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 28c50102e..a27d9f367 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -105,7 +105,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
105 classify_name_ref(db, file_id, &name_ref).and_then(|d| Some(d.item)); 105 classify_name_ref(db, file_id, &name_ref).and_then(|d| Some(d.item));
106 match name_kind { 106 match name_kind {
107 Some(Macro(_)) => "macro", 107 Some(Macro(_)) => "macro",
108 Some(FieldAccess(_)) => "field", 108 Some(Field(_)) => "field",
109 Some(AssocItem(hir::AssocItem::Function(_))) => "function", 109 Some(AssocItem(hir::AssocItem::Function(_))) => "function",
110 Some(AssocItem(hir::AssocItem::Const(_))) => "constant", 110 Some(AssocItem(hir::AssocItem::Const(_))) => "constant",
111 Some(AssocItem(hir::AssocItem::TypeAlias(_))) => "type", 111 Some(AssocItem(hir::AssocItem::TypeAlias(_))) => "type",