diff options
Diffstat (limited to 'crates/ra_hir/src/source_analyzer.rs')
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 1d6c47103..f2e630ef1 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -14,11 +14,11 @@ 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, FieldId, LocalFieldId, VariantId, | 17 | AsMacroCall, DefWithBodyId, FieldId, FunctionId, LocalFieldId, VariantId, |
18 | }; | 18 | }; |
19 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | 19 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; |
20 | use hir_ty::{ | 20 | use hir_ty::{ |
21 | expr::{record_literal_missing_fields, record_pattern_missing_fields}, | 21 | diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, |
22 | InferenceResult, Substs, Ty, | 22 | InferenceResult, Substs, Ty, |
23 | }; | 23 | }; |
24 | use ra_syntax::{ | 24 | use ra_syntax::{ |
@@ -115,7 +115,7 @@ impl SourceAnalyzer { | |||
115 | Some(res) | 115 | Some(res) |
116 | } | 116 | } |
117 | 117 | ||
118 | pub(crate) fn type_of(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { | 118 | pub(crate) fn type_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> { |
119 | let expr_id = self.expr_id(db, expr)?; | 119 | let expr_id = self.expr_id(db, expr)?; |
120 | let ty = self.infer.as_ref()?[expr_id].clone(); | 120 | let ty = self.infer.as_ref()?[expr_id].clone(); |
121 | Type::new_with_resolver(db, &self.resolver, ty) | 121 | Type::new_with_resolver(db, &self.resolver, ty) |
@@ -127,13 +127,24 @@ impl SourceAnalyzer { | |||
127 | Type::new_with_resolver(db, &self.resolver, ty) | 127 | Type::new_with_resolver(db, &self.resolver, ty) |
128 | } | 128 | } |
129 | 129 | ||
130 | pub(crate) fn type_of_self( | ||
131 | &self, | ||
132 | db: &dyn HirDatabase, | ||
133 | param: &ast::SelfParam, | ||
134 | ) -> Option<Type> { | ||
135 | let src = InFile { file_id: self.file_id, value: param }; | ||
136 | let pat_id = self.body_source_map.as_ref()?.node_self_param(src)?; | ||
137 | let ty = self.infer.as_ref()?[pat_id].clone(); | ||
138 | Type::new_with_resolver(db, &self.resolver, ty) | ||
139 | } | ||
140 | |||
130 | pub(crate) fn resolve_method_call( | 141 | pub(crate) fn resolve_method_call( |
131 | &self, | 142 | &self, |
132 | db: &dyn HirDatabase, | 143 | db: &dyn HirDatabase, |
133 | call: &ast::MethodCallExpr, | 144 | call: &ast::MethodCallExpr, |
134 | ) -> Option<Function> { | 145 | ) -> Option<FunctionId> { |
135 | let expr_id = self.expr_id(db, &call.clone().into())?; | 146 | let expr_id = self.expr_id(db, &call.clone().into())?; |
136 | self.infer.as_ref()?.method_resolution(expr_id).map(Function::from) | 147 | self.infer.as_ref()?.method_resolution(expr_id) |
137 | } | 148 | } |
138 | 149 | ||
139 | pub(crate) fn resolve_field( | 150 | pub(crate) fn resolve_field( |
@@ -148,7 +159,7 @@ impl SourceAnalyzer { | |||
148 | pub(crate) fn resolve_record_field( | 159 | pub(crate) fn resolve_record_field( |
149 | &self, | 160 | &self, |
150 | db: &dyn HirDatabase, | 161 | db: &dyn HirDatabase, |
151 | field: &ast::RecordField, | 162 | field: &ast::RecordExprField, |
152 | ) -> Option<(Field, Option<Local>)> { | 163 | ) -> Option<(Field, Option<Local>)> { |
153 | let expr = field.expr()?; | 164 | let expr = field.expr()?; |
154 | let expr_id = self.expr_id(db, &expr)?; | 165 | let expr_id = self.expr_id(db, &expr)?; |
@@ -235,7 +246,7 @@ impl SourceAnalyzer { | |||
235 | } | 246 | } |
236 | } | 247 | } |
237 | 248 | ||
238 | if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordLit::cast) { | 249 | if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordExpr::cast) { |
239 | let expr_id = self.expr_id(db, &rec_lit.into())?; | 250 | let expr_id = self.expr_id(db, &rec_lit.into())?; |
240 | if let Some(VariantId::EnumVariantId(variant)) = | 251 | if let Some(VariantId::EnumVariantId(variant)) = |
241 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | 252 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) |
@@ -273,7 +284,7 @@ impl SourceAnalyzer { | |||
273 | pub(crate) fn record_literal_missing_fields( | 284 | pub(crate) fn record_literal_missing_fields( |
274 | &self, | 285 | &self, |
275 | db: &dyn HirDatabase, | 286 | db: &dyn HirDatabase, |
276 | literal: &ast::RecordLit, | 287 | literal: &ast::RecordExpr, |
277 | ) -> Option<Vec<(Field, Type)>> { | 288 | ) -> Option<Vec<(Field, Type)>> { |
278 | let krate = self.resolver.krate()?; | 289 | let krate = self.resolver.krate()?; |
279 | let body = self.body.as_ref()?; | 290 | let body = self.body.as_ref()?; |
@@ -341,13 +352,13 @@ impl SourceAnalyzer { | |||
341 | let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { | 352 | let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { |
342 | self.resolver.resolve_path_as_macro(db.upcast(), &path) | 353 | self.resolver.resolve_path_as_macro(db.upcast(), &path) |
343 | })?; | 354 | })?; |
344 | Some(macro_call_id.as_file()) | 355 | Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64) |
345 | } | 356 | } |
346 | 357 | ||
347 | pub(crate) fn resolve_variant( | 358 | pub(crate) fn resolve_variant( |
348 | &self, | 359 | &self, |
349 | db: &dyn HirDatabase, | 360 | db: &dyn HirDatabase, |
350 | record_lit: ast::RecordLit, | 361 | record_lit: ast::RecordExpr, |
351 | ) -> Option<VariantId> { | 362 | ) -> Option<VariantId> { |
352 | let infer = self.infer.as_ref()?; | 363 | let infer = self.infer.as_ref()?; |
353 | let expr_id = self.expr_id(db, &record_lit.into())?; | 364 | let expr_id = self.expr_id(db, &record_lit.into())?; |
@@ -394,8 +405,7 @@ fn scope_for_offset( | |||
394 | ) | 405 | ) |
395 | }) | 406 | }) |
396 | .map(|(expr_range, scope)| { | 407 | .map(|(expr_range, scope)| { |
397 | adjust(db, scopes, source_map, expr_range, offset.file_id, offset.value) | 408 | adjust(db, scopes, source_map, expr_range, offset).unwrap_or(*scope) |
398 | .unwrap_or(*scope) | ||
399 | }) | 409 | }) |
400 | } | 410 | } |
401 | 411 | ||
@@ -406,8 +416,7 @@ fn adjust( | |||
406 | scopes: &ExprScopes, | 416 | scopes: &ExprScopes, |
407 | source_map: &BodySourceMap, | 417 | source_map: &BodySourceMap, |
408 | expr_range: TextRange, | 418 | expr_range: TextRange, |
409 | file_id: HirFileId, | 419 | offset: InFile<TextSize>, |
410 | offset: TextSize, | ||
411 | ) -> Option<ScopeId> { | 420 | ) -> Option<ScopeId> { |
412 | let child_scopes = scopes | 421 | let child_scopes = scopes |
413 | .scope_by_expr() | 422 | .scope_by_expr() |
@@ -415,7 +424,7 @@ fn adjust( | |||
415 | .filter_map(|(id, scope)| { | 424 | .filter_map(|(id, scope)| { |
416 | let source = source_map.expr_syntax(*id).ok()?; | 425 | let source = source_map.expr_syntax(*id).ok()?; |
417 | // FIXME: correctly handle macro expansion | 426 | // FIXME: correctly handle macro expansion |
418 | if source.file_id != file_id { | 427 | if source.file_id != offset.file_id { |
419 | return None; | 428 | return None; |
420 | } | 429 | } |
421 | let root = source.file_syntax(db.upcast()); | 430 | let root = source.file_syntax(db.upcast()); |
@@ -423,7 +432,7 @@ fn adjust( | |||
423 | Some((node.syntax().text_range(), scope)) | 432 | Some((node.syntax().text_range(), scope)) |
424 | }) | 433 | }) |
425 | .filter(|&(range, _)| { | 434 | .filter(|&(range, _)| { |
426 | range.start() <= offset && expr_range.contains_range(range) && range != expr_range | 435 | range.start() <= offset.value && expr_range.contains_range(range) && range != expr_range |
427 | }); | 436 | }); |
428 | 437 | ||
429 | child_scopes | 438 | child_scopes |