diff options
author | Lukas Wirth <[email protected]> | 2020-12-13 21:13:16 +0000 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2020-12-14 15:04:28 +0000 |
commit | c6172f3f6d3fb0982ae17f48507608609d46d179 (patch) | |
tree | fc22462068c549baacaa261cc7243e36791f3c1e /crates/hir | |
parent | dbd0cfba531c21de01af7b1a12ce9eb6b1271a5d (diff) |
Add LifetimeParam resolving to Semantics
Diffstat (limited to 'crates/hir')
-rw-r--r-- | crates/hir/src/code_model.rs | 8 | ||||
-rw-r--r-- | crates/hir/src/from_id.rs | 17 | ||||
-rw-r--r-- | crates/hir/src/has_source.rs | 14 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 51 | ||||
-rw-r--r-- | crates/hir/src/semantics/source_to_def.rs | 21 |
5 files changed, 98 insertions, 13 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index fcc42c6bb..42dc35b76 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -1250,6 +1250,14 @@ impl LifetimeParam { | |||
1250 | let params = db.generic_params(self.id.parent); | 1250 | let params = db.generic_params(self.id.parent); |
1251 | params.lifetimes[self.id.local_id].name.clone() | 1251 | params.lifetimes[self.id.local_id].name.clone() |
1252 | } | 1252 | } |
1253 | |||
1254 | pub fn module(self, db: &dyn HirDatabase) -> Module { | ||
1255 | self.id.parent.module(db.upcast()).into() | ||
1256 | } | ||
1257 | |||
1258 | pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef { | ||
1259 | self.id.parent.into() | ||
1260 | } | ||
1253 | } | 1261 | } |
1254 | 1262 | ||
1255 | // FIXME: rename from `ImplDef` to `Impl` | 1263 | // FIXME: rename from `ImplDef` to `Impl` |
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index 265ef6d1f..dd3fcfe4a 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs | |||
@@ -41,6 +41,7 @@ from_id![ | |||
41 | (hir_def::FunctionId, crate::Function), | 41 | (hir_def::FunctionId, crate::Function), |
42 | (hir_def::ImplId, crate::ImplDef), | 42 | (hir_def::ImplId, crate::ImplDef), |
43 | (hir_def::TypeParamId, crate::TypeParam), | 43 | (hir_def::TypeParamId, crate::TypeParam), |
44 | (hir_def::LifetimeParamId, crate::LifetimeParam), | ||
44 | (hir_expand::MacroDefId, crate::MacroDef) | 45 | (hir_expand::MacroDefId, crate::MacroDef) |
45 | ]; | 46 | ]; |
46 | 47 | ||
@@ -154,6 +155,22 @@ impl From<GenericDef> for GenericDefId { | |||
154 | } | 155 | } |
155 | } | 156 | } |
156 | 157 | ||
158 | impl From<GenericDefId> for GenericDef { | ||
159 | fn from(def: GenericDefId) -> Self { | ||
160 | match def { | ||
161 | GenericDefId::FunctionId(it) => GenericDef::Function(it.into()), | ||
162 | GenericDefId::AdtId(it) => GenericDef::Adt(it.into()), | ||
163 | GenericDefId::TraitId(it) => GenericDef::Trait(it.into()), | ||
164 | GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()), | ||
165 | GenericDefId::ImplId(it) => GenericDef::ImplDef(it.into()), | ||
166 | GenericDefId::EnumVariantId(it) => { | ||
167 | GenericDef::EnumVariant(EnumVariant { parent: it.parent.into(), id: it.local_id }) | ||
168 | } | ||
169 | GenericDefId::ConstId(it) => GenericDef::Const(it.into()), | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | |||
157 | impl From<Adt> for GenericDefId { | 174 | impl From<Adt> for GenericDefId { |
158 | fn from(id: Adt) -> Self { | 175 | fn from(id: Adt) -> Self { |
159 | match id { | 176 | match id { |
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index c77494152..1e64a1614 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs | |||
@@ -10,8 +10,8 @@ use hir_expand::InFile; | |||
10 | use syntax::ast; | 10 | use syntax::ast; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef, MacroDef, | 13 | db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef, |
14 | Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, | 14 | LifetimeParam, MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | pub trait HasSource { | 17 | pub trait HasSource { |
@@ -129,6 +129,14 @@ impl HasSource for TypeParam { | |||
129 | type Ast = Either<ast::Trait, ast::TypeParam>; | 129 | type Ast = Either<ast::Trait, ast::TypeParam>; |
130 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { | 130 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { |
131 | let child_source = self.id.parent.child_source(db.upcast()); | 131 | let child_source = self.id.parent.child_source(db.upcast()); |
132 | child_source.map(|it| it[self.id.local_id].clone()) | 132 | child_source.map(|it| it.type_params[self.id.local_id].clone()) |
133 | } | ||
134 | } | ||
135 | |||
136 | impl HasSource for LifetimeParam { | ||
137 | type Ast = ast::LifetimeParam; | ||
138 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { | ||
139 | let child_source = self.id.parent.child_source(db.upcast()); | ||
140 | child_source.map(|it| it.lifetime_params[self.id.local_id].clone()) | ||
133 | } | 141 | } |
134 | } | 142 | } |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 4bd22ed27..e4fc21ced 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -13,7 +13,11 @@ use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; | |||
13 | use hir_ty::associated_type_shorthand_candidates; | 13 | use hir_ty::associated_type_shorthand_candidates; |
14 | use itertools::Itertools; | 14 | use itertools::Itertools; |
15 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
16 | use syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode, SyntaxToken, TextSize}; | 16 | use syntax::{ |
17 | algo::find_node_at_offset, | ||
18 | ast::{self, GenericParamsOwner}, | ||
19 | match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize, | ||
20 | }; | ||
17 | 21 | ||
18 | use crate::{ | 22 | use crate::{ |
19 | code_model::Access, | 23 | code_model::Access, |
@@ -21,8 +25,9 @@ use crate::{ | |||
21 | diagnostics::Diagnostic, | 25 | diagnostics::Diagnostic, |
22 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 26 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
23 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, | 27 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, |
24 | AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, | 28 | AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, LifetimeParam, Local, |
25 | Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, | 29 | MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, |
30 | VariantDef, | ||
26 | }; | 31 | }; |
27 | 32 | ||
28 | #[derive(Debug, Clone, PartialEq, Eq)] | 33 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -173,6 +178,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
173 | self.imp.descend_node_at_offset(node, offset).find_map(N::cast) | 178 | self.imp.descend_node_at_offset(node, offset).find_map(N::cast) |
174 | } | 179 | } |
175 | 180 | ||
181 | // FIXME: Replace the SyntaxToken with a typed ast Node/Token | ||
182 | pub fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> { | ||
183 | self.imp.resolve_lifetime_param(lifetime_token) | ||
184 | } | ||
185 | |||
176 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { | 186 | pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { |
177 | self.imp.type_of_expr(expr) | 187 | self.imp.type_of_expr(expr) |
178 | } | 188 | } |
@@ -392,16 +402,44 @@ impl<'db> SemanticsImpl<'db> { | |||
392 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) | 402 | .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) |
393 | } | 403 | } |
394 | 404 | ||
405 | // FIXME: Replace the SyntaxToken with a typed ast Node/Token | ||
406 | fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> { | ||
407 | if lifetime_token.kind() != syntax::SyntaxKind::LIFETIME { | ||
408 | return None; | ||
409 | } | ||
410 | let lifetime_text = lifetime_token.text(); | ||
411 | let lifetime_param = lifetime_token.parent().ancestors().find_map(|syn| { | ||
412 | let gpl = match_ast! { | ||
413 | match syn { | ||
414 | ast::Fn(it) => it.generic_param_list()?, | ||
415 | ast::TypeAlias(it) => it.generic_param_list()?, | ||
416 | ast::Struct(it) => it.generic_param_list()?, | ||
417 | ast::Enum(it) => it.generic_param_list()?, | ||
418 | ast::Union(it) => it.generic_param_list()?, | ||
419 | ast::Trait(it) => it.generic_param_list()?, | ||
420 | ast::Impl(it) => it.generic_param_list()?, | ||
421 | ast::WherePred(it) => it.generic_param_list()?, | ||
422 | ast::ForType(it) => it.generic_param_list()?, | ||
423 | _ => return None, | ||
424 | } | ||
425 | }; | ||
426 | gpl.lifetime_params() | ||
427 | .find(|tp| tp.lifetime_token().as_ref().map(|lt| lt.text()) == Some(lifetime_text)) | ||
428 | })?; | ||
429 | let src = self.find_file(lifetime_param.syntax().clone()).with_value(lifetime_param); | ||
430 | ToDef::to_def(self, src) | ||
431 | } | ||
432 | |||
395 | fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { | 433 | fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { |
396 | self.analyze(expr.syntax()).type_of_expr(self.db, &expr) | 434 | self.analyze(expr.syntax()).type_of_expr(self.db, expr) |
397 | } | 435 | } |
398 | 436 | ||
399 | fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { | 437 | fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { |
400 | self.analyze(pat.syntax()).type_of_pat(self.db, &pat) | 438 | self.analyze(pat.syntax()).type_of_pat(self.db, pat) |
401 | } | 439 | } |
402 | 440 | ||
403 | fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { | 441 | fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { |
404 | self.analyze(param.syntax()).type_of_self(self.db, ¶m) | 442 | self.analyze(param.syntax()).type_of_self(self.db, param) |
405 | } | 443 | } |
406 | 444 | ||
407 | fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { | 445 | fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { |
@@ -684,6 +722,7 @@ to_def_impls![ | |||
684 | (crate::Field, ast::TupleField, tuple_field_to_def), | 722 | (crate::Field, ast::TupleField, tuple_field_to_def), |
685 | (crate::EnumVariant, ast::Variant, enum_variant_to_def), | 723 | (crate::EnumVariant, ast::Variant, enum_variant_to_def), |
686 | (crate::TypeParam, ast::TypeParam, type_param_to_def), | 724 | (crate::TypeParam, ast::TypeParam, type_param_to_def), |
725 | (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def), | ||
687 | (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros | 726 | (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros |
688 | (crate::Local, ast::IdentPat, bind_pat_to_def), | 727 | (crate::Local, ast::IdentPat, bind_pat_to_def), |
689 | ]; | 728 | ]; |
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 66fc11611..badcf0ae8 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs | |||
@@ -7,7 +7,8 @@ use hir_def::{ | |||
7 | expr::PatId, | 7 | expr::PatId, |
8 | keys::{self, Key}, | 8 | keys::{self, Key}, |
9 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId, | 9 | ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId, |
10 | ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId, | 10 | LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, |
11 | VariantId, | ||
11 | }; | 12 | }; |
12 | use hir_expand::{name::AsName, AstId, MacroDefKind}; | 13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; |
13 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
@@ -128,13 +129,25 @@ impl SourceToDefCtx<'_, '_> { | |||
128 | 129 | ||
129 | pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> { | 130 | pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> { |
130 | let container: ChildContainer = | 131 | let container: ChildContainer = |
131 | self.find_type_param_container(src.as_ref().map(|it| it.syntax()))?.into(); | 132 | self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into(); |
132 | let db = self.db; | 133 | let db = self.db; |
133 | let dyn_map = | 134 | let dyn_map = |
134 | &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); | 135 | &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); |
135 | dyn_map[keys::TYPE_PARAM].get(&src).copied() | 136 | dyn_map[keys::TYPE_PARAM].get(&src).copied() |
136 | } | 137 | } |
137 | 138 | ||
139 | pub(super) fn lifetime_param_to_def( | ||
140 | &mut self, | ||
141 | src: InFile<ast::LifetimeParam>, | ||
142 | ) -> Option<LifetimeParamId> { | ||
143 | let container: ChildContainer = | ||
144 | self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into(); | ||
145 | let db = self.db; | ||
146 | let dyn_map = | ||
147 | &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); | ||
148 | dyn_map[keys::LIFETIME_PARAM].get(&src).copied() | ||
149 | } | ||
150 | |||
138 | // FIXME: use DynMap as well? | 151 | // FIXME: use DynMap as well? |
139 | pub(super) fn macro_call_to_def(&mut self, src: InFile<ast::MacroCall>) -> Option<MacroDefId> { | 152 | pub(super) fn macro_call_to_def(&mut self, src: InFile<ast::MacroCall>) -> Option<MacroDefId> { |
140 | let kind = MacroDefKind::Declarative; | 153 | let kind = MacroDefKind::Declarative; |
@@ -203,7 +216,7 @@ impl SourceToDefCtx<'_, '_> { | |||
203 | Some(def.into()) | 216 | Some(def.into()) |
204 | } | 217 | } |
205 | 218 | ||
206 | fn find_type_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> { | 219 | fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> { |
207 | for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { | 220 | for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { |
208 | let res: GenericDefId = match_ast! { | 221 | let res: GenericDefId = match_ast! { |
209 | match (container.value) { | 222 | match (container.value) { |
@@ -247,7 +260,7 @@ pub(crate) enum ChildContainer { | |||
247 | VariantId(VariantId), | 260 | VariantId(VariantId), |
248 | TypeAliasId(TypeAliasId), | 261 | TypeAliasId(TypeAliasId), |
249 | /// XXX: this might be the same def as, for example an `EnumId`. However, | 262 | /// XXX: this might be the same def as, for example an `EnumId`. However, |
250 | /// here the children generic parameters, and not, eg enum variants. | 263 | /// here the children are generic parameters, and not, eg enum variants. |
251 | GenericDefId(GenericDefId), | 264 | GenericDefId(GenericDefId), |
252 | } | 265 | } |
253 | impl_from! { | 266 | impl_from! { |