aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/source_analyzer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/source_analyzer.rs')
-rw-r--r--crates/ra_hir/src/source_analyzer.rs90
1 files changed, 70 insertions, 20 deletions
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 815ca158c..45631f8fd 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -14,10 +14,13 @@ use hir_def::{
14 }, 14 },
15 expr::{ExprId, Pat, PatId}, 15 expr::{ExprId, Pat, PatId},
16 resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, 16 resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
17 AsMacroCall, DefWithBodyId, 17 AsMacroCall, DefWithBodyId, LocalStructFieldId, StructFieldId, VariantId,
18}; 18};
19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
20use hir_ty::InferenceResult; 20use hir_ty::{
21 expr::{record_literal_missing_fields, record_pattern_missing_fields},
22 InferenceResult, Substs, Ty,
23};
21use ra_syntax::{ 24use ra_syntax::{
22 ast::{self, AstNode}, 25 ast::{self, AstNode},
23 SyntaxNode, SyntaxNodePtr, TextUnit, 26 SyntaxNode, SyntaxNodePtr, TextUnit,
@@ -25,8 +28,10 @@ use ra_syntax::{
25 28
26use crate::{ 29use crate::{
27 db::HirDatabase, semantics::PathResolution, Adt, Const, EnumVariant, Function, Local, MacroDef, 30 db::HirDatabase, semantics::PathResolution, Adt, Const, EnumVariant, Function, Local, MacroDef,
28 ModPath, ModuleDef, Path, PathKind, Static, Struct, Trait, Type, TypeAlias, TypeParam, 31 ModPath, ModuleDef, Path, PathKind, Static, Struct, StructField, Trait, Type, TypeAlias,
32 TypeParam,
29}; 33};
34use ra_db::CrateId;
30 35
31/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of 36/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
32/// original source files. It should not be used inside the HIR itself. 37/// original source files. It should not be used inside the HIR itself.
@@ -164,23 +169,6 @@ impl SourceAnalyzer {
164 Some((struct_field.into(), local)) 169 Some((struct_field.into(), local))
165 } 170 }
166 171
167 pub(crate) fn resolve_record_literal(
168 &self,
169 db: &dyn HirDatabase,
170 record_lit: &ast::RecordLit,
171 ) -> Option<crate::VariantDef> {
172 let expr_id = self.expr_id(db, &record_lit.clone().into())?;
173 self.infer.as_ref()?.variant_resolution_for_expr(expr_id).map(|it| it.into())
174 }
175
176 pub(crate) fn resolve_record_pattern(
177 &self,
178 record_pat: &ast::RecordPat,
179 ) -> Option<crate::VariantDef> {
180 let pat_id = self.pat_id(&record_pat.clone().into())?;
181 self.infer.as_ref()?.variant_resolution_for_pat(pat_id).map(|it| it.into())
182 }
183
184 pub(crate) fn resolve_macro_call( 172 pub(crate) fn resolve_macro_call(
185 &self, 173 &self,
186 db: &dyn HirDatabase, 174 db: &dyn HirDatabase,
@@ -231,6 +219,68 @@ impl SourceAnalyzer {
231 resolve_hir_path(db, &self.resolver, &hir_path) 219 resolve_hir_path(db, &self.resolver, &hir_path)
232 } 220 }
233 221
222 pub(crate) fn record_literal_missing_fields(
223 &self,
224 db: &dyn HirDatabase,
225 literal: &ast::RecordLit,
226 ) -> Option<Vec<(StructField, Type)>> {
227 let krate = self.resolver.krate()?;
228 let body = self.body.as_ref()?;
229 let infer = self.infer.as_ref()?;
230
231 let expr_id = self.expr_id(db, &literal.clone().into())?;
232 let substs = match &infer.type_of_expr[expr_id] {
233 Ty::Apply(a_ty) => &a_ty.parameters,
234 _ => return None,
235 };
236
237 let (variant, missing_fields, _exhaustive) =
238 record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;
239 let res = self.missing_fields(db, krate, substs, variant, missing_fields);
240 Some(res)
241 }
242
243 pub(crate) fn record_pattern_missing_fields(
244 &self,
245 db: &dyn HirDatabase,
246 pattern: &ast::RecordPat,
247 ) -> Option<Vec<(StructField, Type)>> {
248 let krate = self.resolver.krate()?;
249 let body = self.body.as_ref()?;
250 let infer = self.infer.as_ref()?;
251
252 let pat_id = self.pat_id(&pattern.clone().into())?;
253 let substs = match &infer.type_of_pat[pat_id] {
254 Ty::Apply(a_ty) => &a_ty.parameters,
255 _ => return None,
256 };
257
258 let (variant, missing_fields) =
259 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
260 let res = self.missing_fields(db, krate, substs, variant, missing_fields);
261 Some(res)
262 }
263
264 fn missing_fields(
265 &self,
266 db: &dyn HirDatabase,
267 krate: CrateId,
268 substs: &Substs,
269 variant: VariantId,
270 missing_fields: Vec<LocalStructFieldId>,
271 ) -> Vec<(StructField, Type)> {
272 let field_types = db.field_types(variant);
273
274 missing_fields
275 .into_iter()
276 .map(|local_id| {
277 let field = StructFieldId { parent: variant, local_id };
278 let ty = field_types[local_id].clone().subst(substs);
279 (field.into(), Type::new_with_resolver_inner(db, krate, &self.resolver, ty))
280 })
281 .collect()
282 }
283
234 pub(crate) fn expand( 284 pub(crate) fn expand(
235 &self, 285 &self,
236 db: &dyn HirDatabase, 286 db: &dyn HirDatabase,