aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide/src/goto_definition.rs26
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs1
-rw-r--r--crates/ra_ide_db/src/defs.rs54
3 files changed, 57 insertions, 24 deletions
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index a6c86e99c..0798d2c36 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -1,6 +1,6 @@
1use hir::Semantics; 1use hir::Semantics;
2use ra_ide_db::{ 2use ra_ide_db::{
3 defs::{classify_name, classify_name_ref}, 3 defs::{classify_name, classify_name_ref, NameClass},
4 symbol_index, RootDatabase, 4 symbol_index, RootDatabase,
5}; 5};
6use ra_syntax::{ 6use ra_syntax::{
@@ -39,7 +39,10 @@ pub(crate) fn goto_definition(
39 reference_definition(&sema, &name_ref).to_vec() 39 reference_definition(&sema, &name_ref).to_vec()
40 }, 40 },
41 ast::Name(name) => { 41 ast::Name(name) => {
42 let def = classify_name(&sema, &name)?.definition(); 42 let def = match classify_name(&sema, &name)? {
43 NameClass::Definition(def) | NameClass::ConstReference(def) => def,
44 NameClass::FieldShorthand { local: _, field } => field,
45 };
43 let nav = def.try_to_nav(sema.db)?; 46 let nav = def.try_to_nav(sema.db)?;
44 vec![nav] 47 vec![nav]
45 }, 48 },
@@ -886,4 +889,23 @@ mod tests {
886 "x", 889 "x",
887 ) 890 )
888 } 891 }
892
893 #[test]
894 fn goto_def_for_enum_variant_field() {
895 check_goto(
896 "
897 //- /lib.rs
898 enum Foo {
899 Bar { x: i32 }
900 }
901 fn baz(foo: Foo) {
902 match foo {
903 Foo::Bar { x<|> } => x
904 };
905 }
906 ",
907 "x RECORD_FIELD_DEF FileId(1) 21..27 21..22",
908 "x: i32|x",
909 );
910 }
889} 911}
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 6903403b2..9ff7356c9 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -436,6 +436,7 @@ fn highlight_element(
436 highlight_name(db, def) | HighlightModifier::Definition 436 highlight_name(db, def) | HighlightModifier::Definition
437 } 437 }
438 Some(NameClass::ConstReference(def)) => highlight_name(db, def), 438 Some(NameClass::ConstReference(def)) => highlight_name(db, def),
439 Some(NameClass::FieldShorthand { .. }) => HighlightTag::Field.into(),
439 None => highlight_name_by_syntax(name) | HighlightModifier::Definition, 440 None => highlight_name_by_syntax(name) | HighlightModifier::Definition,
440 } 441 }
441 } 442 }
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index 1db60b87f..1826f3ac6 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -82,6 +82,10 @@ pub enum NameClass {
82 Definition(Definition), 82 Definition(Definition),
83 /// `None` in `if let None = Some(82) {}` 83 /// `None` in `if let None = Some(82) {}`
84 ConstReference(Definition), 84 ConstReference(Definition),
85 FieldShorthand {
86 local: Local,
87 field: Definition,
88 },
85} 89}
86 90
87impl NameClass { 91impl NameClass {
@@ -89,12 +93,14 @@ impl NameClass {
89 match self { 93 match self {
90 NameClass::Definition(it) => Some(it), 94 NameClass::Definition(it) => Some(it),
91 NameClass::ConstReference(_) => None, 95 NameClass::ConstReference(_) => None,
96 NameClass::FieldShorthand { local, field: _ } => Some(Definition::Local(local)),
92 } 97 }
93 } 98 }
94 99
95 pub fn definition(self) -> Definition { 100 pub fn definition(self) -> Definition {
96 match self { 101 match self {
97 NameClass::Definition(it) | NameClass::ConstReference(it) => it, 102 NameClass::Definition(it) | NameClass::ConstReference(it) => it,
103 NameClass::FieldShorthand { local: _, field } => field,
98 } 104 }
99 } 105 }
100} 106}
@@ -102,18 +108,14 @@ impl NameClass {
102pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> { 108pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameClass> {
103 let _p = profile("classify_name"); 109 let _p = profile("classify_name");
104 110
105 if let Some(bind_pat) = name.syntax().parent().and_then(ast::BindPat::cast) { 111 let parent = name.syntax().parent()?;
112
113 if let Some(bind_pat) = ast::BindPat::cast(parent.clone()) {
106 if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) { 114 if let Some(def) = sema.resolve_bind_pat_to_const(&bind_pat) {
107 return Some(NameClass::ConstReference(Definition::ModuleDef(def))); 115 return Some(NameClass::ConstReference(Definition::ModuleDef(def)));
108 } 116 }
109 } 117 }
110 118
111 classify_name_inner(sema, name).map(NameClass::Definition)
112}
113
114fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Definition> {
115 let parent = name.syntax().parent()?;
116
117 match_ast! { 119 match_ast! {
118 match parent { 120 match parent {
119 ast::Alias(it) => { 121 ast::Alias(it) => {
@@ -123,63 +125,71 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti
123 let name_ref = path_segment.name_ref()?; 125 let name_ref = path_segment.name_ref()?;
124 let name_ref_class = classify_name_ref(sema, &name_ref)?; 126 let name_ref_class = classify_name_ref(sema, &name_ref)?;
125 127
126 Some(name_ref_class.definition()) 128 Some(NameClass::Definition(name_ref_class.definition()))
127 }, 129 },
128 ast::BindPat(it) => { 130 ast::BindPat(it) => {
129 let local = sema.to_def(&it)?; 131 let local = sema.to_def(&it)?;
130 Some(Definition::Local(local)) 132
133 if let Some(record_field_pat) = it.syntax().parent().and_then(ast::RecordFieldPat::cast) {
134 if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) {
135 let field = Definition::Field(field);
136 return Some(NameClass::FieldShorthand { local, field });
137 }
138 }
139
140 Some(NameClass::Definition(Definition::Local(local)))
131 }, 141 },
132 ast::RecordFieldDef(it) => { 142 ast::RecordFieldDef(it) => {
133 let field: hir::Field = sema.to_def(&it)?; 143 let field: hir::Field = sema.to_def(&it)?;
134 Some(Definition::Field(field)) 144 Some(NameClass::Definition(Definition::Field(field)))
135 }, 145 },
136 ast::Module(it) => { 146 ast::Module(it) => {
137 let def = sema.to_def(&it)?; 147 let def = sema.to_def(&it)?;
138 Some(Definition::ModuleDef(def.into())) 148 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
139 }, 149 },
140 ast::StructDef(it) => { 150 ast::StructDef(it) => {
141 let def: hir::Struct = sema.to_def(&it)?; 151 let def: hir::Struct = sema.to_def(&it)?;
142 Some(Definition::ModuleDef(def.into())) 152 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
143 }, 153 },
144 ast::UnionDef(it) => { 154 ast::UnionDef(it) => {
145 let def: hir::Union = sema.to_def(&it)?; 155 let def: hir::Union = sema.to_def(&it)?;
146 Some(Definition::ModuleDef(def.into())) 156 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
147 }, 157 },
148 ast::EnumDef(it) => { 158 ast::EnumDef(it) => {
149 let def: hir::Enum = sema.to_def(&it)?; 159 let def: hir::Enum = sema.to_def(&it)?;
150 Some(Definition::ModuleDef(def.into())) 160 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
151 }, 161 },
152 ast::TraitDef(it) => { 162 ast::TraitDef(it) => {
153 let def: hir::Trait = sema.to_def(&it)?; 163 let def: hir::Trait = sema.to_def(&it)?;
154 Some(Definition::ModuleDef(def.into())) 164 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
155 }, 165 },
156 ast::StaticDef(it) => { 166 ast::StaticDef(it) => {
157 let def: hir::Static = sema.to_def(&it)?; 167 let def: hir::Static = sema.to_def(&it)?;
158 Some(Definition::ModuleDef(def.into())) 168 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
159 }, 169 },
160 ast::EnumVariant(it) => { 170 ast::EnumVariant(it) => {
161 let def: hir::EnumVariant = sema.to_def(&it)?; 171 let def: hir::EnumVariant = sema.to_def(&it)?;
162 Some(Definition::ModuleDef(def.into())) 172 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
163 }, 173 },
164 ast::FnDef(it) => { 174 ast::FnDef(it) => {
165 let def: hir::Function = sema.to_def(&it)?; 175 let def: hir::Function = sema.to_def(&it)?;
166 Some(Definition::ModuleDef(def.into())) 176 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
167 }, 177 },
168 ast::ConstDef(it) => { 178 ast::ConstDef(it) => {
169 let def: hir::Const = sema.to_def(&it)?; 179 let def: hir::Const = sema.to_def(&it)?;
170 Some(Definition::ModuleDef(def.into())) 180 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
171 }, 181 },
172 ast::TypeAliasDef(it) => { 182 ast::TypeAliasDef(it) => {
173 let def: hir::TypeAlias = sema.to_def(&it)?; 183 let def: hir::TypeAlias = sema.to_def(&it)?;
174 Some(Definition::ModuleDef(def.into())) 184 Some(NameClass::Definition(Definition::ModuleDef(def.into())))
175 }, 185 },
176 ast::MacroCall(it) => { 186 ast::MacroCall(it) => {
177 let def = sema.to_def(&it)?; 187 let def = sema.to_def(&it)?;
178 Some(Definition::Macro(def)) 188 Some(NameClass::Definition(Definition::Macro(def)))
179 }, 189 },
180 ast::TypeParam(it) => { 190 ast::TypeParam(it) => {
181 let def = sema.to_def(&it)?; 191 let def = sema.to_def(&it)?;
182 Some(Definition::TypeParam(def)) 192 Some(NameClass::Definition(Definition::TypeParam(def)))
183 }, 193 },
184 _ => None, 194 _ => None,
185 } 195 }