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/completion/presentation.rs6
-rw-r--r--crates/ra_ide/src/diagnostics.rs29
-rw-r--r--crates/ra_ide/src/extend_selection.rs27
-rw-r--r--crates/ra_ide/src/goto_definition.rs18
-rw-r--r--crates/ra_ide/src/hover.rs63
-rw-r--r--crates/ra_ide/src/references.rs32
-rw-r--r--crates/ra_ide/src/references/classify.rs42
-rw-r--r--crates/ra_ide/src/references/search_scope.rs21
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs44
9 files changed, 174 insertions, 108 deletions
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 1a3bcffae..a524987fd 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -135,11 +135,7 @@ impl Completions {
135 let (before, after) = (&docs[..idx], &docs[idx + s.len()..]); 135 let (before, after) = (&docs[..idx], &docs[idx + s.len()..]);
136 // Ensure to match the full word 136 // Ensure to match the full word
137 if after.starts_with('!') 137 if after.starts_with('!')
138 && before 138 && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric())
139 .chars()
140 .rev()
141 .next()
142 .map_or(true, |c| c != '_' && !c.is_ascii_alphanumeric())
143 { 139 {
144 // It may have spaces before the braces like `foo! {}` 140 // It may have spaces before the braces like `foo! {}`
145 match after[1..].chars().find(|&c| !c.is_whitespace()) { 141 match after[1..].chars().find(|&c| !c.is_whitespace()) {
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index 82596c665..9cf86b26d 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -470,6 +470,35 @@ mod tests {
470 } 470 }
471 471
472 #[test] 472 #[test]
473 fn test_fill_struct_fields_enum() {
474 let before = r"
475 enum Expr {
476 Bin { lhs: Box<Expr>, rhs: Box<Expr> }
477 }
478
479 impl Expr {
480 fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
481 Expr::Bin { <|> }
482 }
483 }
484
485 ";
486 let after = r"
487 enum Expr {
488 Bin { lhs: Box<Expr>, rhs: Box<Expr> }
489 }
490
491 impl Expr {
492 fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
493 Expr::Bin { lhs: (), rhs: () <|> }
494 }
495 }
496
497 ";
498 check_apply_diagnostic_fix(before, after);
499 }
500
501 #[test]
473 fn test_fill_struct_fields_partial() { 502 fn test_fill_struct_fields_partial() {
474 let before = r" 503 let before = r"
475 struct TestStruct { 504 struct TestStruct {
diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs
index 726963a33..4757d8e22 100644
--- a/crates/ra_ide/src/extend_selection.rs
+++ b/crates/ra_ide/src/extend_selection.rs
@@ -44,6 +44,7 @@ fn try_extend_selection(
44 ARRAY_EXPR, 44 ARRAY_EXPR,
45 TUPLE_EXPR, 45 TUPLE_EXPR,
46 TUPLE_TYPE, 46 TUPLE_TYPE,
47 TUPLE_PAT,
47 WHERE_CLAUSE, 48 WHERE_CLAUSE,
48 ]; 49 ];
49 50
@@ -612,6 +613,32 @@ fn main() { let var = (
612 } 613 }
613 614
614 #[test] 615 #[test]
616 fn test_extend_selection_on_tuple_pat() {
617 do_check(
618 r#"fn main() { let (krate, _crate_def_map<|>, module_id) = var; }"#,
619 &["_crate_def_map", "_crate_def_map, ", "(krate, _crate_def_map, module_id)"],
620 );
621 // white space variations
622 do_check(
623 r#"fn main() { let (krate,_crate<|>_def_map,module_id) = var; }"#,
624 &["_crate_def_map", "_crate_def_map,", "(krate,_crate_def_map,module_id)"],
625 );
626 do_check(
627 r#"
628fn main() { let (
629 krate,
630 _crate_def_map<|>,
631 module_id
632) = var; }"#,
633 &[
634 "_crate_def_map",
635 "_crate_def_map,",
636 "(\n krate,\n _crate_def_map,\n module_id\n)",
637 ],
638 );
639 }
640
641 #[test]
615 fn extend_selection_inside_macros() { 642 fn extend_selection_inside_macros() {
616 do_check( 643 do_check(
617 r#"macro_rules! foo { ($item:item) => {$item} } 644 r#"macro_rules! foo { ($item:item) => {$item} }
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index de5551a4c..cce539e56 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -1,7 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{db::AstDatabase, InFile, SourceBinder}; 3use hir::{db::AstDatabase, InFile, SourceBinder};
4use ra_ide_db::{symbol_index, RootDatabase}; 4use ra_ide_db::{defs::NameDefinition, symbol_index, RootDatabase};
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, DocCommentsOwner}, 6 ast::{self, DocCommentsOwner},
7 match_ast, AstNode, 7 match_ast, AstNode,
@@ -12,7 +12,7 @@ use ra_syntax::{
12use crate::{ 12use crate::{
13 display::{ShortLabel, ToNav}, 13 display::{ShortLabel, ToNav},
14 expand::descend_into_macros, 14 expand::descend_into_macros,
15 references::{classify_name_ref, NameKind::*}, 15 references::classify_name_ref,
16 FilePosition, NavigationTarget, RangeInfo, 16 FilePosition, NavigationTarget, RangeInfo,
17}; 17};
18 18
@@ -73,17 +73,17 @@ pub(crate) fn reference_definition(
73) -> ReferenceResult { 73) -> ReferenceResult {
74 use self::ReferenceResult::*; 74 use self::ReferenceResult::*;
75 75
76 let name_kind = classify_name_ref(sb, name_ref).map(|d| d.kind); 76 let name_kind = classify_name_ref(sb, name_ref);
77 match name_kind { 77 match name_kind {
78 Some(Macro(it)) => return Exact(it.to_nav(sb.db)), 78 Some(NameDefinition::Macro(it)) => return Exact(it.to_nav(sb.db)),
79 Some(StructField(it)) => return Exact(it.to_nav(sb.db)), 79 Some(NameDefinition::StructField(it)) => return Exact(it.to_nav(sb.db)),
80 Some(TypeParam(it)) => return Exact(it.to_nav(sb.db)), 80 Some(NameDefinition::TypeParam(it)) => return Exact(it.to_nav(sb.db)),
81 Some(Local(it)) => return Exact(it.to_nav(sb.db)), 81 Some(NameDefinition::Local(it)) => return Exact(it.to_nav(sb.db)),
82 Some(ModuleDef(def)) => match NavigationTarget::from_def(sb.db, def) { 82 Some(NameDefinition::ModuleDef(def)) => match NavigationTarget::from_def(sb.db, def) {
83 Some(nav) => return Exact(nav), 83 Some(nav) => return Exact(nav),
84 None => return Approximate(vec![]), 84 None => return Approximate(vec![]),
85 }, 85 },
86 Some(SelfType(imp)) => { 86 Some(NameDefinition::SelfType(imp)) => {
87 // FIXME: ideally, this should point to the type in the impl, and 87 // FIXME: ideally, this should point to the type in the impl, and
88 // not at the whole impl. And goto **type** definition should bring 88 // not at the whole impl. And goto **type** definition should bring
89 // us to the actual type 89 // us to the actual type
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 3f88bb260..1c6ca36df 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -2,7 +2,7 @@
2 2
3use hir::{db::AstDatabase, Adt, HasSource, HirDisplay, SourceBinder}; 3use hir::{db::AstDatabase, Adt, HasSource, HirDisplay, SourceBinder};
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::{defs::NameDefinition, RootDatabase};
6use ra_syntax::{ 6use ra_syntax::{
7 algo::find_covering_element, 7 algo::find_covering_element,
8 ast::{self, DocCommentsOwner}, 8 ast::{self, DocCommentsOwner},
@@ -13,8 +13,8 @@ use ra_syntax::{
13 13
14use crate::{ 14use crate::{
15 display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, 15 display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel},
16 expand::descend_into_macros, 16 expand::{descend_into_macros, original_range},
17 references::{classify_name, classify_name_ref, NameKind, NameKind::*}, 17 references::{classify_name, classify_name_ref},
18 FilePosition, FileRange, RangeInfo, 18 FilePosition, FileRange, RangeInfo,
19}; 19};
20 20
@@ -92,20 +92,20 @@ fn hover_text(docs: Option<String>, desc: Option<String>) -> Option<String> {
92 } 92 }
93} 93}
94 94
95fn hover_text_from_name_kind(db: &RootDatabase, name_kind: NameKind) -> Option<String> { 95fn hover_text_from_name_kind(db: &RootDatabase, def: NameDefinition) -> Option<String> {
96 return match name_kind { 96 return match def {
97 Macro(it) => { 97 NameDefinition::Macro(it) => {
98 let src = it.source(db); 98 let src = it.source(db);
99 hover_text(src.value.doc_comment_text(), Some(macro_label(&src.value))) 99 hover_text(src.value.doc_comment_text(), Some(macro_label(&src.value)))
100 } 100 }
101 StructField(it) => { 101 NameDefinition::StructField(it) => {
102 let src = it.source(db); 102 let src = it.source(db);
103 match src.value { 103 match src.value {
104 hir::FieldSource::Named(it) => hover_text(it.doc_comment_text(), it.short_label()), 104 hir::FieldSource::Named(it) => hover_text(it.doc_comment_text(), it.short_label()),
105 _ => None, 105 _ => None,
106 } 106 }
107 } 107 }
108 ModuleDef(it) => match it { 108 NameDefinition::ModuleDef(it) => match it {
109 hir::ModuleDef::Module(it) => match it.definition_source(db).value { 109 hir::ModuleDef::Module(it) => match it.definition_source(db).value {
110 hir::ModuleSource::Module(it) => { 110 hir::ModuleSource::Module(it) => {
111 hover_text(it.doc_comment_text(), it.short_label()) 111 hover_text(it.doc_comment_text(), it.short_label())
@@ -123,8 +123,10 @@ fn hover_text_from_name_kind(db: &RootDatabase, name_kind: NameKind) -> Option<S
123 hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), 123 hir::ModuleDef::TypeAlias(it) => from_def_source(db, it),
124 hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), 124 hir::ModuleDef::BuiltinType(it) => Some(it.to_string()),
125 }, 125 },
126 Local(it) => Some(rust_code_markup(it.ty(db).display_truncated(db, None).to_string())), 126 NameDefinition::Local(it) => {
127 TypeParam(_) | SelfType(_) => { 127 Some(rust_code_markup(it.ty(db).display_truncated(db, None).to_string()))
128 }
129 NameDefinition::TypeParam(_) | NameDefinition::SelfType(_) => {
128 // FIXME: Hover for generic param 130 // FIXME: Hover for generic param
129 None 131 None
130 } 132 }
@@ -148,17 +150,18 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
148 let mut res = HoverResult::new(); 150 let mut res = HoverResult::new();
149 151
150 let mut sb = SourceBinder::new(db); 152 let mut sb = SourceBinder::new(db);
151 if let Some((range, name_kind)) = match_ast! { 153 if let Some((node, name_kind)) = match_ast! {
152 match (token.value.parent()) { 154 match (token.value.parent()) {
153 ast::NameRef(name_ref) => { 155 ast::NameRef(name_ref) => {
154 classify_name_ref(&mut sb, token.with_value(&name_ref)).map(|d| (name_ref.syntax().text_range(), d.kind)) 156 classify_name_ref(&mut sb, token.with_value(&name_ref)).map(|d| (name_ref.syntax().clone(), d))
155 }, 157 },
156 ast::Name(name) => { 158 ast::Name(name) => {
157 classify_name(&mut sb, token.with_value(&name)).map(|d| (name.syntax().text_range(), d.kind)) 159 classify_name(&mut sb, token.with_value(&name)).map(|d| (name.syntax().clone(), d))
158 }, 160 },
159 _ => None, 161 _ => None,
160 } 162 }
161 } { 163 } {
164 let range = original_range(db, token.with_value(&node)).range;
162 res.extend(hover_text_from_name_kind(db, name_kind)); 165 res.extend(hover_text_from_name_kind(db, name_kind));
163 166
164 if !res.is_empty() { 167 if !res.is_empty() {
@@ -171,8 +174,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
171 .ancestors() 174 .ancestors()
172 .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?; 175 .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?;
173 176
174 // The following logic will not work if token is coming from a macro 177 let frange = original_range(db, token.with_value(&node));
175 let frange = FileRange { file_id: position.file_id, range: node.text_range() };
176 res.extend(type_of(db, frange).map(rust_code_markup)); 178 res.extend(type_of(db, frange).map(rust_code_markup));
177 if res.is_empty() { 179 if res.is_empty() {
178 return None; 180 return None;
@@ -220,6 +222,7 @@ mod tests {
220 use crate::mock_analysis::{ 222 use crate::mock_analysis::{
221 analysis_and_position, single_file_with_position, single_file_with_range, 223 analysis_and_position, single_file_with_position, single_file_with_range,
222 }; 224 };
225 use ra_db::FileLoader;
223 use ra_syntax::TextRange; 226 use ra_syntax::TextRange;
224 227
225 fn trim_markup(s: &str) -> &str { 228 fn trim_markup(s: &str) -> &str {
@@ -230,7 +233,7 @@ mod tests {
230 s.map(trim_markup) 233 s.map(trim_markup)
231 } 234 }
232 235
233 fn check_hover_result(fixture: &str, expected: &[&str]) { 236 fn check_hover_result(fixture: &str, expected: &[&str]) -> String {
234 let (analysis, position) = analysis_and_position(fixture); 237 let (analysis, position) = analysis_and_position(fixture);
235 let hover = analysis.hover(position).unwrap().unwrap(); 238 let hover = analysis.hover(position).unwrap().unwrap();
236 let mut results = Vec::from(hover.info.results()); 239 let mut results = Vec::from(hover.info.results());
@@ -243,6 +246,9 @@ mod tests {
243 } 246 }
244 247
245 assert_eq!(hover.info.len(), expected.len()); 248 assert_eq!(hover.info.len(), expected.len());
249
250 let content = analysis.db.file_text(position.file_id);
251 content[hover.range].to_string()
246 } 252 }
247 253
248 #[test] 254 #[test]
@@ -711,7 +717,7 @@ fn func(foo: i32) { if true { <|>foo; }; }
711 717
712 #[test] 718 #[test]
713 fn test_hover_through_macro() { 719 fn test_hover_through_macro() {
714 check_hover_result( 720 let hover_on = check_hover_result(
715 " 721 "
716 //- /lib.rs 722 //- /lib.rs
717 macro_rules! id { 723 macro_rules! id {
@@ -726,11 +732,13 @@ fn func(foo: i32) { if true { <|>foo; }; }
726 ", 732 ",
727 &["fn foo()"], 733 &["fn foo()"],
728 ); 734 );
735
736 assert_eq!(hover_on, "foo")
729 } 737 }
730 738
731 #[test] 739 #[test]
732 fn test_hover_through_expr_in_macro() { 740 fn test_hover_through_expr_in_macro() {
733 check_hover_result( 741 let hover_on = check_hover_result(
734 " 742 "
735 //- /lib.rs 743 //- /lib.rs
736 macro_rules! id { 744 macro_rules! id {
@@ -742,5 +750,24 @@ fn func(foo: i32) { if true { <|>foo; }; }
742 ", 750 ",
743 &["u32"], 751 &["u32"],
744 ); 752 );
753
754 assert_eq!(hover_on, "bar")
755 }
756
757 #[test]
758 fn test_hover_non_ascii_space_doc() {
759 check_hover_result(
760 "
761 //- /lib.rs
762 /// <- `\u{3000}` here
763 fn foo() {
764 }
765
766 fn bar() {
767 fo<|>o();
768 }
769 ",
770 &["fn foo()\n```\n\n<- `\u{3000}` here"],
771 );
745 } 772 }
746} 773}
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index 97c08ade5..7f790a62d 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -31,7 +31,7 @@ pub(crate) use self::{
31 classify::{classify_name, classify_name_ref}, 31 classify::{classify_name, classify_name_ref},
32 rename::rename, 32 rename::rename,
33}; 33};
34pub(crate) use ra_ide_db::defs::{NameDefinition, NameKind}; 34pub(crate) use ra_ide_db::defs::NameDefinition;
35 35
36pub use self::search_scope::SearchScope; 36pub use self::search_scope::SearchScope;
37 37
@@ -126,13 +126,13 @@ pub(crate) fn find_all_refs(
126 126
127 let RangeInfo { range, info: (name, def) } = find_name(db, &syntax, position, opt_name)?; 127 let RangeInfo { range, info: (name, def) } = find_name(db, &syntax, position, opt_name)?;
128 128
129 let declaration = match def.kind { 129 let declaration = match def {
130 NameKind::Macro(mac) => mac.to_nav(db), 130 NameDefinition::Macro(mac) => mac.to_nav(db),
131 NameKind::StructField(field) => field.to_nav(db), 131 NameDefinition::StructField(field) => field.to_nav(db),
132 NameKind::ModuleDef(def) => NavigationTarget::from_def(db, def)?, 132 NameDefinition::ModuleDef(def) => NavigationTarget::from_def(db, def)?,
133 NameKind::SelfType(imp) => imp.to_nav(db), 133 NameDefinition::SelfType(imp) => imp.to_nav(db),
134 NameKind::Local(local) => local.to_nav(db), 134 NameDefinition::Local(local) => local.to_nav(db),
135 NameKind::TypeParam(_) => return None, 135 NameDefinition::TypeParam(_) => return None,
136 }; 136 };
137 137
138 let search_scope = { 138 let search_scope = {
@@ -148,7 +148,7 @@ pub(crate) fn find_all_refs(
148 let declaration = Declaration { 148 let declaration = Declaration {
149 nav: declaration, 149 nav: declaration,
150 kind: ReferenceKind::Other, 150 kind: ReferenceKind::Other,
151 access: decl_access(&def.kind, &name, &syntax, decl_range), 151 access: decl_access(&def, &name, &syntax, decl_range),
152 }; 152 };
153 153
154 let references = process_definition(db, def, name, search_scope) 154 let references = process_definition(db, def, name, search_scope)
@@ -247,7 +247,7 @@ fn process_definition(
247 refs.push(Reference { 247 refs.push(Reference {
248 file_range: FileRange { file_id, range }, 248 file_range: FileRange { file_id, range },
249 kind, 249 kind,
250 access: reference_access(&d.kind, &name_ref.value), 250 access: reference_access(&d, &name_ref.value),
251 }); 251 });
252 } 252 }
253 } 253 }
@@ -257,13 +257,13 @@ fn process_definition(
257} 257}
258 258
259fn decl_access( 259fn decl_access(
260 kind: &NameKind, 260 def: &NameDefinition,
261 name: &str, 261 name: &str,
262 syntax: &SyntaxNode, 262 syntax: &SyntaxNode,
263 range: TextRange, 263 range: TextRange,
264) -> Option<ReferenceAccess> { 264) -> Option<ReferenceAccess> {
265 match kind { 265 match def {
266 NameKind::Local(_) | NameKind::StructField(_) => {} 266 NameDefinition::Local(_) | NameDefinition::StructField(_) => {}
267 _ => return None, 267 _ => return None,
268 }; 268 };
269 269
@@ -280,10 +280,10 @@ fn decl_access(
280 None 280 None
281} 281}
282 282
283fn reference_access(kind: &NameKind, name_ref: &ast::NameRef) -> Option<ReferenceAccess> { 283fn reference_access(def: &NameDefinition, name_ref: &ast::NameRef) -> Option<ReferenceAccess> {
284 // Only Locals and Fields have accesses for now. 284 // Only Locals and Fields have accesses for now.
285 match kind { 285 match def {
286 NameKind::Local(_) | NameKind::StructField(_) => {} 286 NameDefinition::Local(_) | NameDefinition::StructField(_) => {}
287 _ => return None, 287 _ => return None,
288 }; 288 };
289 289
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs
index d0f03d8a8..478e18871 100644
--- a/crates/ra_ide/src/references/classify.rs
+++ b/crates/ra_ide/src/references/classify.rs
@@ -5,7 +5,7 @@ use ra_prof::profile;
5use ra_syntax::{ast, AstNode}; 5use ra_syntax::{ast, AstNode};
6use test_utils::tested_by; 6use test_utils::tested_by;
7 7
8use super::{NameDefinition, NameKind}; 8use super::NameDefinition;
9use ra_ide_db::RootDatabase; 9use ra_ide_db::RootDatabase;
10 10
11pub use ra_ide_db::defs::{classify_name, from_module_def, from_struct_field}; 11pub use ra_ide_db::defs::{classify_name, from_module_def, from_struct_field};
@@ -22,14 +22,14 @@ pub(crate) fn classify_name_ref(
22 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { 22 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
23 tested_by!(goto_def_for_methods); 23 tested_by!(goto_def_for_methods);
24 if let Some(func) = analyzer.resolve_method_call(&method_call) { 24 if let Some(func) = analyzer.resolve_method_call(&method_call) {
25 return Some(from_module_def(sb.db, func.into(), None)); 25 return Some(from_module_def(func.into()));
26 } 26 }
27 } 27 }
28 28
29 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { 29 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
30 tested_by!(goto_def_for_fields); 30 tested_by!(goto_def_for_fields);
31 if let Some(field) = analyzer.resolve_field(&field_expr) { 31 if let Some(field) = analyzer.resolve_field(&field_expr) {
32 return Some(from_struct_field(sb.db, field)); 32 return Some(from_struct_field(field));
33 } 33 }
34 } 34 }
35 35
@@ -37,55 +37,35 @@ pub(crate) fn classify_name_ref(
37 tested_by!(goto_def_for_record_fields); 37 tested_by!(goto_def_for_record_fields);
38 tested_by!(goto_def_for_field_init_shorthand); 38 tested_by!(goto_def_for_field_init_shorthand);
39 if let Some(field_def) = analyzer.resolve_record_field(&record_field) { 39 if let Some(field_def) = analyzer.resolve_record_field(&record_field) {
40 return Some(from_struct_field(sb.db, field_def)); 40 return Some(from_struct_field(field_def));
41 } 41 }
42 } 42 }
43 43
44 // FIXME: find correct container and visibility for each case
45 let visibility = None;
46 let container = sb.to_module_def(name_ref.file_id.original_file(sb.db))?;
47
48 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 44 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
49 tested_by!(goto_def_for_macros); 45 tested_by!(goto_def_for_macros);
50 if let Some(macro_def) = 46 if let Some(macro_def) =
51 analyzer.resolve_macro_call(sb.db, name_ref.with_value(&macro_call)) 47 analyzer.resolve_macro_call(sb.db, name_ref.with_value(&macro_call))
52 { 48 {
53 let kind = NameKind::Macro(macro_def); 49 return Some(NameDefinition::Macro(macro_def));
54 return Some(NameDefinition { kind, container, visibility });
55 } 50 }
56 } 51 }
57 52
58 let path = name_ref.value.syntax().ancestors().find_map(ast::Path::cast)?; 53 let path = name_ref.value.syntax().ancestors().find_map(ast::Path::cast)?;
59 let resolved = analyzer.resolve_path(sb.db, &path)?; 54 let resolved = analyzer.resolve_path(sb.db, &path)?;
60 let res = match resolved { 55 let res = match resolved {
61 PathResolution::Def(def) => from_module_def(sb.db, def, Some(container)), 56 PathResolution::Def(def) => from_module_def(def),
62 PathResolution::AssocItem(item) => { 57 PathResolution::AssocItem(item) => {
63 let def = match item { 58 let def = match item {
64 hir::AssocItem::Function(it) => it.into(), 59 hir::AssocItem::Function(it) => it.into(),
65 hir::AssocItem::Const(it) => it.into(), 60 hir::AssocItem::Const(it) => it.into(),
66 hir::AssocItem::TypeAlias(it) => it.into(), 61 hir::AssocItem::TypeAlias(it) => it.into(),
67 }; 62 };
68 from_module_def(sb.db, def, Some(container)) 63 from_module_def(def)
69 }
70 PathResolution::Local(local) => {
71 let kind = NameKind::Local(local);
72 let container = local.module(sb.db);
73 NameDefinition { kind, container, visibility: None }
74 }
75 PathResolution::TypeParam(par) => {
76 let kind = NameKind::TypeParam(par);
77 let container = par.module(sb.db);
78 NameDefinition { kind, container, visibility }
79 }
80 PathResolution::Macro(def) => {
81 let kind = NameKind::Macro(def);
82 NameDefinition { kind, container, visibility }
83 }
84 PathResolution::SelfType(impl_block) => {
85 let kind = NameKind::SelfType(impl_block);
86 let container = impl_block.module(sb.db);
87 NameDefinition { kind, container, visibility }
88 } 64 }
65 PathResolution::Local(local) => NameDefinition::Local(local),
66 PathResolution::TypeParam(par) => NameDefinition::TypeParam(par),
67 PathResolution::Macro(def) => NameDefinition::Macro(def),
68 PathResolution::SelfType(impl_block) => NameDefinition::SelfType(impl_block),
89 }; 69 };
90 Some(res) 70 Some(res)
91} 71}
diff --git a/crates/ra_ide/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs
index 279f57be0..27d483233 100644
--- a/crates/ra_ide/src/references/search_scope.rs
+++ b/crates/ra_ide/src/references/search_scope.rs
@@ -12,20 +12,27 @@ use rustc_hash::FxHashMap;
12 12
13use ra_ide_db::RootDatabase; 13use ra_ide_db::RootDatabase;
14 14
15use super::{NameDefinition, NameKind}; 15use super::NameDefinition;
16 16
17pub struct SearchScope { 17pub struct SearchScope {
18 entries: FxHashMap<FileId, Option<TextRange>>, 18 entries: FxHashMap<FileId, Option<TextRange>>,
19} 19}
20 20
21impl SearchScope { 21impl SearchScope {
22 fn empty() -> SearchScope {
23 SearchScope { entries: FxHashMap::default() }
24 }
25
22 pub(crate) fn for_def(def: &NameDefinition, db: &RootDatabase) -> SearchScope { 26 pub(crate) fn for_def(def: &NameDefinition, db: &RootDatabase) -> SearchScope {
23 let _p = profile("search_scope"); 27 let _p = profile("search_scope");
24 28 let module = match def.module(db) {
25 let module_src = def.container.definition_source(db); 29 Some(it) => it,
30 None => return SearchScope::empty(),
31 };
32 let module_src = module.definition_source(db);
26 let file_id = module_src.file_id.original_file(db); 33 let file_id = module_src.file_id.original_file(db);
27 34
28 if let NameKind::Local(var) = def.kind { 35 if let NameDefinition::Local(var) = def {
29 let range = match var.parent(db) { 36 let range = match var.parent(db) {
30 DefWithBody::Function(f) => f.source(db).value.syntax().text_range(), 37 DefWithBody::Function(f) => f.source(db).value.syntax().text_range(),
31 DefWithBody::Const(c) => c.source(db).value.syntax().text_range(), 38 DefWithBody::Const(c) => c.source(db).value.syntax().text_range(),
@@ -36,10 +43,10 @@ impl SearchScope {
36 return SearchScope::new(res); 43 return SearchScope::new(res);
37 } 44 }
38 45
39 let vis = def.visibility.as_ref().map(|v| v.syntax().to_string()).unwrap_or_default(); 46 let vis = def.visibility(db).as_ref().map(|v| v.syntax().to_string()).unwrap_or_default();
40 47
41 if vis.as_str() == "pub(super)" { 48 if vis.as_str() == "pub(super)" {
42 if let Some(parent_module) = def.container.parent(db) { 49 if let Some(parent_module) = module.parent(db) {
43 let mut res = FxHashMap::default(); 50 let mut res = FxHashMap::default();
44 let parent_src = parent_module.definition_source(db); 51 let parent_src = parent_module.definition_source(db);
45 let file_id = parent_src.file_id.original_file(db); 52 let file_id = parent_src.file_id.original_file(db);
@@ -72,7 +79,7 @@ impl SearchScope {
72 return SearchScope::new(res); 79 return SearchScope::new(res);
73 } 80 }
74 if vis.as_str() == "pub" { 81 if vis.as_str() == "pub" {
75 let krate = def.container.krate(); 82 let krate = module.krate();
76 for rev_dep in krate.reverse_dependencies(db) { 83 for rev_dep in krate.reverse_dependencies(db) {
77 let root_file = rev_dep.root_file(db); 84 let root_file = rev_dep.root_file(db);
78 let source_root_id = db.file_source_root(root_file); 85 let source_root_id = db.file_source_root(root_file);
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 8e793e479..d873f153e 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -2,7 +2,7 @@
2 2
3use hir::{HirFileId, InFile, Name, SourceAnalyzer, SourceBinder}; 3use hir::{HirFileId, InFile, Name, SourceAnalyzer, SourceBinder};
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::{defs::NameDefinition, RootDatabase};
6use ra_prof::profile; 6use ra_prof::profile;
7use ra_syntax::{ 7use ra_syntax::{
8 ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxToken, TextRange, 8 ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxToken, TextRange,
@@ -12,7 +12,7 @@ use rustc_hash::FxHashMap;
12 12
13use crate::{ 13use crate::{
14 expand::descend_into_macros_with_analyzer, 14 expand::descend_into_macros_with_analyzer,
15 references::{classify_name, classify_name_ref, NameKind}, 15 references::{classify_name, classify_name_ref},
16 FileId, 16 FileId,
17}; 17};
18 18
@@ -186,10 +186,10 @@ fn highlight_node(
186 NAME_REF if node.value.ancestors().any(|it| it.kind() == ATTR) => return None, 186 NAME_REF if node.value.ancestors().any(|it| it.kind() == ATTR) => return None,
187 NAME_REF => { 187 NAME_REF => {
188 let name_ref = node.value.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); 188 let name_ref = node.value.as_node().cloned().and_then(ast::NameRef::cast).unwrap();
189 let name_kind = classify_name_ref(sb, node.with_value(&name_ref)).map(|d| d.kind); 189 let name_kind = classify_name_ref(sb, node.with_value(&name_ref));
190 match name_kind { 190 match name_kind {
191 Some(name_kind) => { 191 Some(name_kind) => {
192 if let NameKind::Local(local) = &name_kind { 192 if let NameDefinition::Local(local) = &name_kind {
193 if let Some(name) = local.name(db) { 193 if let Some(name) = local.name(db) {
194 let shadow_count = 194 let shadow_count =
195 bindings_shadow_count.entry(name.clone()).or_default(); 195 bindings_shadow_count.entry(name.clone()).or_default();
@@ -205,9 +205,9 @@ fn highlight_node(
205 } 205 }
206 NAME => { 206 NAME => {
207 let name = node.value.as_node().cloned().and_then(ast::Name::cast).unwrap(); 207 let name = node.value.as_node().cloned().and_then(ast::Name::cast).unwrap();
208 let name_kind = classify_name(sb, node.with_value(&name)).map(|d| d.kind); 208 let name_kind = classify_name(sb, node.with_value(&name));
209 209
210 if let Some(NameKind::Local(local)) = &name_kind { 210 if let Some(NameDefinition::Local(local)) = &name_kind {
211 if let Some(name) = local.name(db) { 211 if let Some(name) = local.name(db) {
212 let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); 212 let shadow_count = bindings_shadow_count.entry(name.clone()).or_default();
213 *shadow_count += 1; 213 *shadow_count += 1;
@@ -310,22 +310,22 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo
310 buf 310 buf
311} 311}
312 312
313fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { 313fn highlight_name(db: &RootDatabase, def: NameDefinition) -> &'static str {
314 match name_kind { 314 match def {
315 NameKind::Macro(_) => tags::MACRO, 315 NameDefinition::Macro(_) => tags::MACRO,
316 NameKind::StructField(_) => tags::FIELD, 316 NameDefinition::StructField(_) => tags::FIELD,
317 NameKind::ModuleDef(hir::ModuleDef::Module(_)) => tags::MODULE, 317 NameDefinition::ModuleDef(hir::ModuleDef::Module(_)) => tags::MODULE,
318 NameKind::ModuleDef(hir::ModuleDef::Function(_)) => tags::FUNCTION, 318 NameDefinition::ModuleDef(hir::ModuleDef::Function(_)) => tags::FUNCTION,
319 NameKind::ModuleDef(hir::ModuleDef::Adt(_)) => tags::TYPE, 319 NameDefinition::ModuleDef(hir::ModuleDef::Adt(_)) => tags::TYPE,
320 NameKind::ModuleDef(hir::ModuleDef::EnumVariant(_)) => tags::CONSTANT, 320 NameDefinition::ModuleDef(hir::ModuleDef::EnumVariant(_)) => tags::CONSTANT,
321 NameKind::ModuleDef(hir::ModuleDef::Const(_)) => tags::CONSTANT, 321 NameDefinition::ModuleDef(hir::ModuleDef::Const(_)) => tags::CONSTANT,
322 NameKind::ModuleDef(hir::ModuleDef::Static(_)) => tags::CONSTANT, 322 NameDefinition::ModuleDef(hir::ModuleDef::Static(_)) => tags::CONSTANT,
323 NameKind::ModuleDef(hir::ModuleDef::Trait(_)) => tags::TYPE, 323 NameDefinition::ModuleDef(hir::ModuleDef::Trait(_)) => tags::TYPE,
324 NameKind::ModuleDef(hir::ModuleDef::TypeAlias(_)) => tags::TYPE, 324 NameDefinition::ModuleDef(hir::ModuleDef::TypeAlias(_)) => tags::TYPE,
325 NameKind::ModuleDef(hir::ModuleDef::BuiltinType(_)) => tags::TYPE_BUILTIN, 325 NameDefinition::ModuleDef(hir::ModuleDef::BuiltinType(_)) => tags::TYPE_BUILTIN,
326 NameKind::SelfType(_) => tags::TYPE_SELF, 326 NameDefinition::SelfType(_) => tags::TYPE_SELF,
327 NameKind::TypeParam(_) => tags::TYPE_PARAM, 327 NameDefinition::TypeParam(_) => tags::TYPE_PARAM,
328 NameKind::Local(local) => { 328 NameDefinition::Local(local) => {
329 if local.is_mut(db) || local.ty(db).is_mutable_reference() { 329 if local.is_mut(db) || local.ty(db).is_mutable_reference() {
330 tags::VARIABLE_MUT 330 tags::VARIABLE_MUT
331 } else { 331 } else {