From 5a91f015b489627d3c9578ec2b01735687c8880a Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 4 Mar 2023 20:33:28 +0100 Subject: [PATCH] internal: Handle fields called as method calls as the fields they resolve to --- crates/hir/src/semantics.rs | 19 ++++++++++++++++++- crates/hir/src/source_analyzer.rs | 16 ++++++++++++++++ crates/ide-db/src/defs.rs | 9 ++++++--- crates/ide/src/hover/tests.rs | 23 +++++++++++++++++++++++ 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index be2dffc29cc..697f4b43bc7 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -12,7 +12,7 @@ use hir_def::{ macro_id_to_def_id, resolver::{self, HasResolver, Resolver, TypeNs}, type_ref::Mutability, - AsMacroCall, DefWithBodyId, FunctionId, MacroId, TraitId, VariantId, + AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId, }; use hir_expand::{ db::AstDatabase, @@ -366,6 +366,16 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.resolve_method_call(call).map(Function::from) } + /// Attempts to resolve this call expression as a method call falling back to resolving it as a field. + pub fn resolve_method_call_field_fallback( + &self, + call: &ast::MethodCallExpr, + ) -> Option> { + self.imp + .resolve_method_call_fallback(call) + .map(|it| it.map_left(Function::from).map_right(Field::from)) + } + pub fn resolve_await_to_poll(&self, await_expr: &ast::AwaitExpr) -> Option { self.imp.resolve_await_to_poll(await_expr).map(Function::from) } @@ -1146,6 +1156,13 @@ impl<'db> SemanticsImpl<'db> { self.analyze(call.syntax())?.resolve_method_call(self.db, call) } + fn resolve_method_call_fallback( + &self, + call: &ast::MethodCallExpr, + ) -> Option> { + self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call) + } + fn resolve_await_to_poll(&self, await_expr: &ast::AwaitExpr) -> Option { self.analyze(await_expr.syntax())?.resolve_await_to_poll(self.db, await_expr) } diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index ada529fa74c..118a7f8ea86 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -10,6 +10,7 @@ use std::{ sync::Arc, }; +use either::Either; use hir_def::{ body::{ self, @@ -266,6 +267,21 @@ impl SourceAnalyzer { Some(self.resolve_impl_method_or_trait_def(db, f_in_trait, substs)) } + pub(crate) fn resolve_method_call_fallback( + &self, + db: &dyn HirDatabase, + call: &ast::MethodCallExpr, + ) -> Option> { + let expr_id = self.expr_id(db, &call.clone().into())?; + let inference_result = self.infer.as_ref()?; + match inference_result.method_resolution(expr_id) { + Some((f_in_trait, substs)) => { + Some(Either::Left(self.resolve_impl_method_or_trait_def(db, f_in_trait, substs))) + } + None => inference_result.field_resolution(expr_id).map(Either::Right), + } + } + pub(crate) fn resolve_await_to_poll( &self, db: &dyn HirDatabase, diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index cce33dcfe46..1322f5228e8 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -469,9 +469,12 @@ impl NameRefClass { match_ast! { match parent { ast::MethodCallExpr(method_call) => { - sema.resolve_method_call(&method_call) - .map(Definition::Function) - .map(NameRefClass::Definition) + sema.resolve_method_call_field_fallback(&method_call) + .map(|it| { + it.map_left(Definition::Function) + .map_right(Definition::Field) + .either(NameRefClass::Definition, NameRefClass::Definition) + }) }, ast::FieldExpr(field_expr) => { sema.resolve_field(&field_expr) diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 42f7c4339c7..2e67056b913 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -5797,3 +5797,26 @@ mod m { "#]], ); } + +#[test] +fn field_as_method_call_fallback() { + check( + r#" +struct S { f: u32 } +fn test() { + S { f: 0 }.f$0(); +} +"#, + expect![[r#" + *f* + + ```rust + test::S + ``` + + ```rust + f: u32 // size = 4, align = 4, offset = 0 + ``` + "#]], + ); +}