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.rs41
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};
19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 19use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
20use hir_ty::{ 20use 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};
24use ra_syntax::{ 24use 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