aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/doc_tests/generated.rs17
-rw-r--r--crates/ra_assists/src/handlers/remove_mut.rs32
-rw-r--r--crates/ra_assists/src/lib.rs4
-rw-r--r--crates/ra_hir/src/code_model.rs29
-rw-r--r--crates/ra_hir_ty/src/expr.rs18
-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
-rw-r--r--crates/ra_ide_db/src/defs.rs134
-rw-r--r--crates/ra_ide_db/src/imports_locator.rs8
-rw-r--r--crates/ra_mbe/src/subtree_source.rs2
-rw-r--r--crates/ra_prof/Cargo.toml2
-rw-r--r--crates/ra_prof/src/lib.rs1
-rw-r--r--crates/ra_syntax/src/ast/traits.rs4
-rw-r--r--crates/rust-analyzer/src/caps.rs1
21 files changed, 333 insertions, 201 deletions
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs
index 4ab09b167..3f56dd508 100644
--- a/crates/ra_assists/src/doc_tests/generated.rs
+++ b/crates/ra_assists/src/doc_tests/generated.rs
@@ -549,6 +549,23 @@ fn main() {
549} 549}
550 550
551#[test] 551#[test]
552fn doctest_remove_mut() {
553 check(
554 "remove_mut",
555 r#####"
556impl Walrus {
557 fn feed(&mut<|> self, amount: u32) {}
558}
559"#####,
560 r#####"
561impl Walrus {
562 fn feed(&self, amount: u32) {}
563}
564"#####,
565 )
566}
567
568#[test]
552fn doctest_replace_if_let_with_match() { 569fn doctest_replace_if_let_with_match() {
553 check( 570 check(
554 "replace_if_let_with_match", 571 "replace_if_let_with_match",
diff --git a/crates/ra_assists/src/handlers/remove_mut.rs b/crates/ra_assists/src/handlers/remove_mut.rs
new file mode 100644
index 000000000..6884830eb
--- /dev/null
+++ b/crates/ra_assists/src/handlers/remove_mut.rs
@@ -0,0 +1,32 @@
1use ra_syntax::{SyntaxKind, TextRange, T};
2
3use crate::{Assist, AssistCtx, AssistId};
4
5// Assist: remove_mut
6//
7// Removes the `mut` keyword.
8//
9// ```
10// impl Walrus {
11// fn feed(&mut<|> self, amount: u32) {}
12// }
13// ```
14// ->
15// ```
16// impl Walrus {
17// fn feed(&self, amount: u32) {}
18// }
19// ```
20pub(crate) fn remove_mut(ctx: AssistCtx) -> Option<Assist> {
21 let mut_token = ctx.find_token_at_offset(T![mut])?;
22 let delete_from = mut_token.text_range().start();
23 let delete_to = match mut_token.next_token() {
24 Some(it) if it.kind() == SyntaxKind::WHITESPACE => it.text_range().end(),
25 _ => mut_token.text_range().end(),
26 };
27
28 ctx.add_assist(AssistId("remove_mut"), "Remove `mut` keyword", |edit| {
29 edit.set_cursor(delete_from);
30 edit.delete(TextRange::from_to(delete_from, delete_to));
31 })
32}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index a0e7fe17e..d7998b0d1 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -38,7 +38,7 @@ pub struct GroupLabel(pub String);
38impl AssistLabel { 38impl AssistLabel {
39 pub(crate) fn new(label: String, id: AssistId) -> AssistLabel { 39 pub(crate) fn new(label: String, id: AssistId) -> AssistLabel {
40 // FIXME: make fields private, so that this invariant can't be broken 40 // FIXME: make fields private, so that this invariant can't be broken
41 assert!(label.chars().next().unwrap().is_uppercase()); 41 assert!(label.starts_with(|c: char| c.is_uppercase()));
42 AssistLabel { label, id } 42 AssistLabel { label, id }
43 } 43 }
44} 44}
@@ -108,6 +108,7 @@ mod handlers {
108 mod introduce_variable; 108 mod introduce_variable;
109 mod inline_local_variable; 109 mod inline_local_variable;
110 mod raw_string; 110 mod raw_string;
111 mod remove_mut;
111 mod replace_if_let_with_match; 112 mod replace_if_let_with_match;
112 mod split_import; 113 mod split_import;
113 mod remove_dbg; 114 mod remove_dbg;
@@ -147,6 +148,7 @@ mod handlers {
147 raw_string::make_raw_string, 148 raw_string::make_raw_string,
148 raw_string::make_usual_string, 149 raw_string::make_usual_string,
149 raw_string::remove_hash, 150 raw_string::remove_hash,
151 remove_mut::remove_mut,
150 early_return::convert_to_guarded_return, 152 early_return::convert_to_guarded_return,
151 auto_import::auto_import, 153 auto_import::auto_import,
152 ] 154 ]
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 1bdcda069..efc3502d0 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -30,6 +30,7 @@ use ra_syntax::{
30 ast::{self, AttrsOwner}, 30 ast::{self, AttrsOwner},
31 AstNode, 31 AstNode,
32}; 32};
33use rustc_hash::FxHashSet;
33 34
34use crate::{ 35use crate::{
35 db::{DefDatabase, HirDatabase}, 36 db::{DefDatabase, HirDatabase},
@@ -123,10 +124,25 @@ impl_froms!(
123 BuiltinType 124 BuiltinType
124); 125);
125 126
127impl ModuleDef {
128 pub fn module(self, db: &impl HirDatabase) -> Option<Module> {
129 match self {
130 ModuleDef::Module(it) => it.parent(db),
131 ModuleDef::Function(it) => Some(it.module(db)),
132 ModuleDef::Adt(it) => Some(it.module(db)),
133 ModuleDef::EnumVariant(it) => Some(it.module(db)),
134 ModuleDef::Const(it) => Some(it.module(db)),
135 ModuleDef::Static(it) => Some(it.module(db)),
136 ModuleDef::Trait(it) => Some(it.module(db)),
137 ModuleDef::TypeAlias(it) => Some(it.module(db)),
138 ModuleDef::BuiltinType(_) => None,
139 }
140 }
141}
142
126pub use hir_def::{ 143pub use hir_def::{
127 attr::Attrs, item_scope::ItemInNs, visibility::Visibility, AssocItemId, AssocItemLoc, 144 attr::Attrs, item_scope::ItemInNs, visibility::Visibility, AssocItemId, AssocItemLoc,
128}; 145};
129use rustc_hash::FxHashSet;
130 146
131impl Module { 147impl Module {
132 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { 148 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
@@ -649,6 +665,17 @@ pub struct MacroDef {
649 pub(crate) id: MacroDefId, 665 pub(crate) id: MacroDefId,
650} 666}
651 667
668impl MacroDef {
669 /// FIXME: right now, this just returns the root module of the crate that
670 /// defines this macro. The reasons for this is that macros are expanded
671 /// early, in `ra_hir_expand`, where modules simply do not exist yet.
672 pub fn module(self, db: &impl HirDatabase) -> Option<Module> {
673 let krate = self.id.krate?;
674 let module_id = db.crate_def_map(krate).root;
675 Some(Module::new(Crate { id: krate }, module_id))
676 }
677}
678
652/// Invariant: `inner.as_assoc_item(db).is_some()` 679/// Invariant: `inner.as_assoc_item(db).is_some()`
653/// We do not actively enforce this invariant. 680/// We do not actively enforce this invariant.
654#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 681#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs
index 0d11b537c..22f24890d 100644
--- a/crates/ra_hir_ty/src/expr.rs
+++ b/crates/ra_hir_ty/src/expr.rs
@@ -15,6 +15,7 @@ use rustc_hash::FxHashSet;
15use crate::{ 15use crate::{
16 db::HirDatabase, 16 db::HirDatabase,
17 diagnostics::{MissingFields, MissingOkInTailExpr}, 17 diagnostics::{MissingFields, MissingOkInTailExpr},
18 utils::variant_data,
18 ApplicationTy, InferenceResult, Ty, TypeCtor, 19 ApplicationTy, InferenceResult, Ty, TypeCtor,
19}; 20};
20 21
@@ -27,6 +28,7 @@ pub use hir_def::{
27 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, 28 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp,
28 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp, 29 MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp,
29 }, 30 },
31 VariantId,
30}; 32};
31 33
32pub struct ExprValidator<'a, 'b: 'a> { 34pub struct ExprValidator<'a, 'b: 'a> {
@@ -69,17 +71,19 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
69 ) { 71 ) {
70 if spread.is_some() { 72 if spread.is_some() {
71 return; 73 return;
74 };
75 let variant_def: VariantId = match self.infer.variant_resolution_for_expr(id) {
76 Some(VariantId::UnionId(_)) | None => return,
77 Some(it) => it,
78 };
79 if let VariantId::UnionId(_) = variant_def {
80 return;
72 } 81 }
73 82
74 let struct_def = match self.infer[id].as_adt() { 83 let variant_data = variant_data(db, variant_def);
75 Some((AdtId::StructId(s), _)) => s,
76 _ => return,
77 };
78 let struct_data = db.struct_data(struct_def);
79 84
80 let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 85 let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
81 let missed_fields: Vec<Name> = struct_data 86 let missed_fields: Vec<Name> = variant_data
82 .variant_data
83 .fields() 87 .fields()
84 .iter() 88 .iter()
85 .filter_map(|(_f, d)| { 89 .filter_map(|(_f, d)| {
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 {
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index 030f44f86..04c214624 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -6,8 +6,8 @@
6// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). 6// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
7 7
8use hir::{ 8use hir::{
9 Adt, HasSource, ImplBlock, InFile, Local, MacroDef, Module, ModuleDef, SourceBinder, 9 Adt, FieldSource, HasSource, ImplBlock, InFile, Local, MacroDef, Module, ModuleDef,
10 StructField, TypeParam, VariantDef, 10 SourceBinder, StructField, TypeParam,
11}; 11};
12use ra_prof::profile; 12use ra_prof::profile;
13use ra_syntax::{ 13use ra_syntax::{
@@ -18,7 +18,7 @@ use ra_syntax::{
18use crate::RootDatabase; 18use crate::RootDatabase;
19 19
20#[derive(Debug, PartialEq, Eq)] 20#[derive(Debug, PartialEq, Eq)]
21pub enum NameKind { 21pub enum NameDefinition {
22 Macro(MacroDef), 22 Macro(MacroDef),
23 StructField(StructField), 23 StructField(StructField),
24 ModuleDef(ModuleDef), 24 ModuleDef(ModuleDef),
@@ -27,13 +27,45 @@ pub enum NameKind {
27 TypeParam(TypeParam), 27 TypeParam(TypeParam),
28} 28}
29 29
30#[derive(PartialEq, Eq)] 30impl NameDefinition {
31pub struct NameDefinition { 31 pub fn module(&self, db: &RootDatabase) -> Option<Module> {
32 pub visibility: Option<ast::Visibility>, 32 match self {
33 /// FIXME: this doesn't really make sense. For example, builtin types don't 33 NameDefinition::Macro(it) => it.module(db),
34 /// really have a module. 34 NameDefinition::StructField(it) => Some(it.parent_def(db).module(db)),
35 pub container: Module, 35 NameDefinition::ModuleDef(it) => it.module(db),
36 pub kind: NameKind, 36 NameDefinition::SelfType(it) => Some(it.module(db)),
37 NameDefinition::Local(it) => Some(it.module(db)),
38 NameDefinition::TypeParam(it) => Some(it.module(db)),
39 }
40 }
41
42 pub fn visibility(&self, db: &RootDatabase) -> Option<ast::Visibility> {
43 match self {
44 NameDefinition::Macro(_) => None,
45 NameDefinition::StructField(sf) => match sf.source(db).value {
46 FieldSource::Named(it) => it.visibility(),
47 FieldSource::Pos(it) => it.visibility(),
48 },
49 NameDefinition::ModuleDef(def) => match def {
50 ModuleDef::Module(it) => it.declaration_source(db)?.value.visibility(),
51 ModuleDef::Function(it) => it.source(db).value.visibility(),
52 ModuleDef::Adt(adt) => match adt {
53 Adt::Struct(it) => it.source(db).value.visibility(),
54 Adt::Union(it) => it.source(db).value.visibility(),
55 Adt::Enum(it) => it.source(db).value.visibility(),
56 },
57 ModuleDef::Const(it) => it.source(db).value.visibility(),
58 ModuleDef::Static(it) => it.source(db).value.visibility(),
59 ModuleDef::Trait(it) => it.source(db).value.visibility(),
60 ModuleDef::TypeAlias(it) => it.source(db).value.visibility(),
61 ModuleDef::EnumVariant(_) => None,
62 ModuleDef::BuiltinType(_) => None,
63 },
64 NameDefinition::SelfType(_) => None,
65 NameDefinition::Local(_) => None,
66 NameDefinition::TypeParam(_) => None,
67 }
68 }
37} 69}
38 70
39pub fn classify_name( 71pub fn classify_name(
@@ -48,125 +80,77 @@ pub fn classify_name(
48 ast::BindPat(it) => { 80 ast::BindPat(it) => {
49 let src = name.with_value(it); 81 let src = name.with_value(it);
50 let local = sb.to_def(src)?; 82 let local = sb.to_def(src)?;
51 Some(NameDefinition { 83 Some(NameDefinition::Local(local))
52 visibility: None,
53 container: local.module(sb.db),
54 kind: NameKind::Local(local),
55 })
56 }, 84 },
57 ast::RecordFieldDef(it) => { 85 ast::RecordFieldDef(it) => {
58 let src = name.with_value(it); 86 let src = name.with_value(it);
59 let field: hir::StructField = sb.to_def(src)?; 87 let field: hir::StructField = sb.to_def(src)?;
60 Some(from_struct_field(sb.db, field)) 88 Some(from_struct_field(field))
61 }, 89 },
62 ast::Module(it) => { 90 ast::Module(it) => {
63 let def = sb.to_def(name.with_value(it))?; 91 let def = sb.to_def(name.with_value(it))?;
64 Some(from_module_def(sb.db, def.into(), None)) 92 Some(from_module_def(def.into()))
65 }, 93 },
66 ast::StructDef(it) => { 94 ast::StructDef(it) => {
67 let src = name.with_value(it); 95 let src = name.with_value(it);
68 let def: hir::Struct = sb.to_def(src)?; 96 let def: hir::Struct = sb.to_def(src)?;
69 Some(from_module_def(sb.db, def.into(), None)) 97 Some(from_module_def(def.into()))
70 }, 98 },
71 ast::EnumDef(it) => { 99 ast::EnumDef(it) => {
72 let src = name.with_value(it); 100 let src = name.with_value(it);
73 let def: hir::Enum = sb.to_def(src)?; 101 let def: hir::Enum = sb.to_def(src)?;
74 Some(from_module_def(sb.db, def.into(), None)) 102 Some(from_module_def(def.into()))
75 }, 103 },
76 ast::TraitDef(it) => { 104 ast::TraitDef(it) => {
77 let src = name.with_value(it); 105 let src = name.with_value(it);
78 let def: hir::Trait = sb.to_def(src)?; 106 let def: hir::Trait = sb.to_def(src)?;
79 Some(from_module_def(sb.db, def.into(), None)) 107 Some(from_module_def(def.into()))
80 }, 108 },
81 ast::StaticDef(it) => { 109 ast::StaticDef(it) => {
82 let src = name.with_value(it); 110 let src = name.with_value(it);
83 let def: hir::Static = sb.to_def(src)?; 111 let def: hir::Static = sb.to_def(src)?;
84 Some(from_module_def(sb.db, def.into(), None)) 112 Some(from_module_def(def.into()))
85 }, 113 },
86 ast::EnumVariant(it) => { 114 ast::EnumVariant(it) => {
87 let src = name.with_value(it); 115 let src = name.with_value(it);
88 let def: hir::EnumVariant = sb.to_def(src)?; 116 let def: hir::EnumVariant = sb.to_def(src)?;
89 Some(from_module_def(sb.db, def.into(), None)) 117 Some(from_module_def(def.into()))
90 }, 118 },
91 ast::FnDef(it) => { 119 ast::FnDef(it) => {
92 let src = name.with_value(it); 120 let src = name.with_value(it);
93 let def: hir::Function = sb.to_def(src)?; 121 let def: hir::Function = sb.to_def(src)?;
94 Some(from_module_def(sb.db, def.into(), None)) 122 Some(from_module_def(def.into()))
95 }, 123 },
96 ast::ConstDef(it) => { 124 ast::ConstDef(it) => {
97 let src = name.with_value(it); 125 let src = name.with_value(it);
98 let def: hir::Const = sb.to_def(src)?; 126 let def: hir::Const = sb.to_def(src)?;
99 Some(from_module_def(sb.db, def.into(), None)) 127 Some(from_module_def(def.into()))
100 }, 128 },
101 ast::TypeAliasDef(it) => { 129 ast::TypeAliasDef(it) => {
102 let src = name.with_value(it); 130 let src = name.with_value(it);
103 let def: hir::TypeAlias = sb.to_def(src)?; 131 let def: hir::TypeAlias = sb.to_def(src)?;
104 Some(from_module_def(sb.db, def.into(), None)) 132 Some(from_module_def(def.into()))
105 }, 133 },
106 ast::MacroCall(it) => { 134 ast::MacroCall(it) => {
107 let src = name.with_value(it); 135 let src = name.with_value(it);
108 let def = sb.to_def(src.clone())?; 136 let def = sb.to_def(src.clone())?;
109 137
110 let module = sb.to_module_def(src.file_id.original_file(sb.db))?; 138 Some(NameDefinition::Macro(def))
111
112 Some(NameDefinition {
113 visibility: None,
114 container: module,
115 kind: NameKind::Macro(def),
116 })
117 }, 139 },
118 ast::TypeParam(it) => { 140 ast::TypeParam(it) => {
119 let src = name.with_value(it); 141 let src = name.with_value(it);
120 let def = sb.to_def(src)?; 142 let def = sb.to_def(src)?;
121 Some(NameDefinition { 143 Some(NameDefinition::TypeParam(def))
122 visibility: None,
123 container: def.module(sb.db),
124 kind: NameKind::TypeParam(def),
125 })
126 }, 144 },
127 _ => None, 145 _ => None,
128 } 146 }
129 } 147 }
130} 148}
131 149
132pub fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDefinition { 150pub fn from_struct_field(field: StructField) -> NameDefinition {
133 let kind = NameKind::StructField(field); 151 NameDefinition::StructField(field)
134 let parent = field.parent_def(db);
135 let container = parent.module(db);
136 let visibility = match parent {
137 VariantDef::Struct(s) => s.source(db).value.visibility(),
138 VariantDef::Union(e) => e.source(db).value.visibility(),
139 VariantDef::EnumVariant(e) => e.source(db).value.parent_enum().visibility(),
140 };
141 NameDefinition { kind, container, visibility }
142} 152}
143 153
144pub fn from_module_def( 154pub fn from_module_def(def: ModuleDef) -> NameDefinition {
145 db: &RootDatabase, 155 NameDefinition::ModuleDef(def)
146 def: ModuleDef,
147 module: Option<Module>,
148) -> NameDefinition {
149 let kind = NameKind::ModuleDef(def);
150 let (container, visibility) = match def {
151 ModuleDef::Module(it) => {
152 let container = it.parent(db).or_else(|| Some(it)).unwrap();
153 let visibility = it.declaration_source(db).and_then(|s| s.value.visibility());
154 (container, visibility)
155 }
156 ModuleDef::EnumVariant(it) => {
157 let container = it.module(db);
158 let visibility = it.source(db).value.parent_enum().visibility();
159 (container, visibility)
160 }
161 ModuleDef::Function(it) => (it.module(db), it.source(db).value.visibility()),
162 ModuleDef::Const(it) => (it.module(db), it.source(db).value.visibility()),
163 ModuleDef::Static(it) => (it.module(db), it.source(db).value.visibility()),
164 ModuleDef::Trait(it) => (it.module(db), it.source(db).value.visibility()),
165 ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).value.visibility()),
166 ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).value.visibility()),
167 ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).value.visibility()),
168 ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).value.visibility()),
169 ModuleDef::BuiltinType(..) => (module.unwrap(), None),
170 };
171 NameDefinition { kind, container, visibility }
172} 156}
diff --git a/crates/ra_ide_db/src/imports_locator.rs b/crates/ra_ide_db/src/imports_locator.rs
index 86383bcd0..b8dd358a9 100644
--- a/crates/ra_ide_db/src/imports_locator.rs
+++ b/crates/ra_ide_db/src/imports_locator.rs
@@ -6,8 +6,7 @@ use ra_prof::profile;
6use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; 6use ra_syntax::{ast, AstNode, SyntaxKind::NAME};
7 7
8use crate::{ 8use crate::{
9 defs::classify_name, 9 defs::{classify_name, NameDefinition},
10 defs::NameKind,
11 symbol_index::{self, FileSymbol, Query}, 10 symbol_index::{self, FileSymbol, Query},
12 RootDatabase, 11 RootDatabase,
13}; 12};
@@ -44,7 +43,7 @@ impl<'a> ImportsLocator<'a> {
44 .chain(lib_results.into_iter()) 43 .chain(lib_results.into_iter())
45 .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate)) 44 .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate))
46 .filter_map(|name_definition_to_import| match name_definition_to_import { 45 .filter_map(|name_definition_to_import| match name_definition_to_import {
47 NameKind::ModuleDef(module_def) => Some(module_def), 46 NameDefinition::ModuleDef(module_def) => Some(module_def),
48 _ => None, 47 _ => None,
49 }) 48 })
50 .collect() 49 .collect()
@@ -54,7 +53,7 @@ impl<'a> ImportsLocator<'a> {
54 &mut self, 53 &mut self,
55 db: &impl HirDatabase, 54 db: &impl HirDatabase,
56 import_candidate: &FileSymbol, 55 import_candidate: &FileSymbol,
57 ) -> Option<NameKind> { 56 ) -> Option<NameDefinition> {
58 let _p = profile("get_name_definition"); 57 let _p = profile("get_name_definition");
59 let file_id = import_candidate.file_id.into(); 58 let file_id = import_candidate.file_id.into();
60 let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?); 59 let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?);
@@ -67,6 +66,5 @@ impl<'a> ImportsLocator<'a> {
67 &mut self.source_binder, 66 &mut self.source_binder,
68 hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? }, 67 hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? },
69 ) 68 )
70 .map(|it| it.kind)
71 } 69 }
72} 70}
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs
index eb8b79e9a..dacca8279 100644
--- a/crates/ra_mbe/src/subtree_source.rs
+++ b/crates/ra_mbe/src/subtree_source.rs
@@ -141,7 +141,7 @@ fn convert_literal(l: &tt::Literal) -> TtToken {
141} 141}
142 142
143fn convert_ident(ident: &tt::Ident) -> TtToken { 143fn convert_ident(ident: &tt::Ident) -> TtToken {
144 let kind = if let Some('\'') = ident.text.chars().next() { 144 let kind = if ident.text.starts_with('\'') {
145 LIFETIME 145 LIFETIME
146 } else { 146 } else {
147 SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT) 147 SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT)
diff --git a/crates/ra_prof/Cargo.toml b/crates/ra_prof/Cargo.toml
index e06a6d7d2..823745795 100644
--- a/crates/ra_prof/Cargo.toml
+++ b/crates/ra_prof/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
11[dependencies] 11[dependencies]
12once_cell = "1.3.1" 12once_cell = "1.3.1"
13itertools = "0.8.2" 13itertools = "0.8.2"
14backtrace = "0.3.44" 14backtrace = { version = "0.3.44", optional = true }
15 15
16[target.'cfg(not(target_env = "msvc"))'.dependencies] 16[target.'cfg(not(target_env = "msvc"))'.dependencies]
17jemallocator = { version = "0.3.2", optional = true } 17jemallocator = { version = "0.3.2", optional = true }
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs
index 660d85b42..6853a4794 100644
--- a/crates/ra_prof/src/lib.rs
+++ b/crates/ra_prof/src/lib.rs
@@ -315,6 +315,7 @@ fn idx_to_children(msgs: &[Message]) -> Vec<Vec<usize>> {
315} 315}
316 316
317/// Prints backtrace to stderr, useful for debugging. 317/// Prints backtrace to stderr, useful for debugging.
318#[cfg(feature = "backtrace")]
318pub fn print_backtrace() { 319pub fn print_backtrace() {
319 let bt = backtrace::Backtrace::new(); 320 let bt = backtrace::Backtrace::new();
320 eprintln!("{:?}", bt); 321 eprintln!("{:?}", bt);
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs
index f99984fe0..f8cf1e3eb 100644
--- a/crates/ra_syntax/src/ast/traits.rs
+++ b/crates/ra_syntax/src/ast/traits.rs
@@ -126,8 +126,8 @@ pub trait DocCommentsOwner: AstNode {
126 126
127 // Determine if the prefix or prefix + 1 char is stripped 127 // Determine if the prefix or prefix + 1 char is stripped
128 let pos = 128 let pos =
129 if line.chars().nth(prefix_len).map(|c| c.is_whitespace()).unwrap_or(false) { 129 if let Some(ws) = line.chars().nth(prefix_len).filter(|c| c.is_whitespace()) {
130 prefix_len + 1 130 prefix_len + ws.len_utf8()
131 } else { 131 } else {
132 prefix_len 132 prefix_len
133 }; 133 };
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index c4711076c..c9fd645f1 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -57,6 +57,7 @@ pub fn server_capabilities() -> ServerCapabilities {
57 execute_command_provider: None, 57 execute_command_provider: None,
58 workspace: None, 58 workspace: None,
59 call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)), 59 call_hierarchy_provider: Some(CallHierarchyServerCapability::Simple(true)),
60 semantic_tokens_provider: None,
60 experimental: Default::default(), 61 experimental: Default::default(),
61 } 62 }
62} 63}