diff options
author | Aleksey Kladov <[email protected]> | 2020-03-02 18:00:38 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-03-02 18:00:38 +0000 |
commit | 2716a1fa3f8a7410248724a6ce5d4c28837db682 (patch) | |
tree | ad1faf323e4cb1478e1e34e2ed9fe858c5be80e5 /crates/ra_hir/src | |
parent | 96eca8a1abd79840b9040250db9d1e65ec663b0e (diff) |
More principled approach for gotodef for field shorhand
Callers can now decide for themselves if they should prefer field or
local definition. By default, it's the local.
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 27 |
2 files changed, 24 insertions, 10 deletions
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index a0853957c..afc7f7ee7 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -107,8 +107,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
107 | self.analyze(field.syntax()).resolve_field(field) | 107 | self.analyze(field.syntax()).resolve_field(field) |
108 | } | 108 | } |
109 | 109 | ||
110 | pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<StructField> { | 110 | pub fn resolve_record_field( |
111 | self.analyze(field.syntax()).resolve_record_field(field) | 111 | &self, |
112 | field: &ast::RecordField, | ||
113 | ) -> Option<(StructField, Option<Local>)> { | ||
114 | self.analyze(field.syntax()).resolve_record_field(self.db, field) | ||
112 | } | 115 | } |
113 | 116 | ||
114 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<VariantDef> { | 117 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<VariantDef> { |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 4c121eb73..015389fb0 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | //! | 5 | //! |
6 | //! So, this modules should not be used during hir construction, it exists | 6 | //! So, this modules should not be used during hir construction, it exists |
7 | //! purely for "IDE needs". | 7 | //! purely for "IDE needs". |
8 | use std::sync::Arc; | 8 | use std::{iter::once, sync::Arc}; |
9 | 9 | ||
10 | use either::Either; | 10 | use either::Either; |
11 | use hir_def::{ | 11 | use hir_def::{ |
@@ -25,8 +25,8 @@ use ra_syntax::{ | |||
25 | }; | 25 | }; |
26 | 26 | ||
27 | use crate::{ | 27 | use crate::{ |
28 | db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, ModuleDef, Path, Static, | 28 | db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, ModPath, ModuleDef, Path, |
29 | Struct, Trait, Type, TypeAlias, TypeParam, | 29 | PathKind, Static, Struct, Trait, Type, TypeAlias, TypeParam, |
30 | }; | 30 | }; |
31 | 31 | ||
32 | /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of | 32 | /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of |
@@ -162,16 +162,27 @@ impl SourceAnalyzer { | |||
162 | 162 | ||
163 | pub(crate) fn resolve_record_field( | 163 | pub(crate) fn resolve_record_field( |
164 | &self, | 164 | &self, |
165 | db: &impl HirDatabase, | ||
165 | field: &ast::RecordField, | 166 | field: &ast::RecordField, |
166 | ) -> Option<crate::StructField> { | 167 | ) -> Option<(crate::StructField, Option<Local>)> { |
167 | let expr_id = match field.expr() { | 168 | let (expr_id, local) = match field.expr() { |
168 | Some(it) => self.expr_id(&it)?, | 169 | Some(it) => (self.expr_id(&it)?, None), |
169 | None => { | 170 | None => { |
170 | let src = InFile { file_id: self.file_id, value: field }; | 171 | let src = InFile { file_id: self.file_id, value: field }; |
171 | self.body_source_map.as_ref()?.field_init_shorthand_expr(src)? | 172 | let expr_id = self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?; |
173 | let local_name = field.name_ref()?.as_name(); | ||
174 | let path = ModPath::from_segments(PathKind::Plain, once(local_name)); | ||
175 | let local = match self.resolver.resolve_path_in_value_ns_fully(db, &path) { | ||
176 | Some(ValueNs::LocalBinding(pat_id)) => { | ||
177 | Some(Local { pat_id, parent: self.resolver.body_owner()? }) | ||
178 | } | ||
179 | _ => None, | ||
180 | }; | ||
181 | (expr_id, local) | ||
172 | } | 182 | } |
173 | }; | 183 | }; |
174 | self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into()) | 184 | let struct_field = self.infer.as_ref()?.record_field_resolution(expr_id)?; |
185 | Some((struct_field.into(), local)) | ||
175 | } | 186 | } |
176 | 187 | ||
177 | pub(crate) fn resolve_record_literal( | 188 | pub(crate) fn resolve_record_literal( |