about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/display.rs63
-rw-r--r--crates/hir/src/lib.rs15
-rw-r--r--crates/ide-ssr/src/matching.rs6
-rw-r--r--crates/ide/src/signature_help.rs21
4 files changed, 63 insertions, 42 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 9dfb98e459b..a701eb01192 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -8,7 +8,6 @@ use hir_def::{
     type_ref::{TypeBound, TypeRef},
     AdtId, GenericDefId,
 };
-use hir_expand::name;
 use hir_ty::{
     display::{
         write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
@@ -19,8 +18,9 @@ use hir_ty::{
 
 use crate::{
     Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field,
-    Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct,
-    Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant,
+    Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam,
+    Static, Struct, Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam,
+    Union, Variant,
 };
 
 impl HirDisplay for Function {
@@ -57,37 +57,21 @@ impl HirDisplay for Function {
 
         f.write_char('(')?;
 
-        let write_self_param = |ty: &TypeRef, f: &mut HirFormatter<'_>| match ty {
-            TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
-            TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner, TypeRef::Path(p) if p.is_self_type()) =>
-            {
-                f.write_char('&')?;
-                if let Some(lifetime) = lifetime {
-                    write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
-                }
-                if let hir_def::type_ref::Mutability::Mut = mut_ {
-                    f.write_str("mut ")?;
-                }
-                f.write_str("self")
-            }
-            _ => {
-                f.write_str("self: ")?;
-                ty.hir_fmt(f)
-            }
-        };
-
         let mut first = true;
+        let mut skip_self = 0;
+        if let Some(self_param) = self.self_param(db) {
+            self_param.hir_fmt(f)?;
+            first = false;
+            skip_self = 1;
+        }
+
         // FIXME: Use resolved `param.ty` once we no longer discard lifetimes
-        for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)) {
+        for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) {
             let local = param.as_local(db).map(|it| it.name(db));
             if !first {
                 f.write_str(", ")?;
             } else {
                 first = false;
-                if local == Some(name!(self)) {
-                    write_self_param(type_ref, f)?;
-                    continue;
-                }
             }
             match local {
                 Some(name) => write!(f, "{}: ", name.display(f.db.upcast()))?,
@@ -137,6 +121,31 @@ impl HirDisplay for Function {
     }
 }
 
+impl HirDisplay for SelfParam {
+    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
+        let data = f.db.function_data(self.func);
+        let param = data.params.first().unwrap();
+        match &**param {
+            TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
+            TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner, TypeRef::Path(p) if p.is_self_type()) =>
+            {
+                f.write_char('&')?;
+                if let Some(lifetime) = lifetime {
+                    write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
+                }
+                if let hir_def::type_ref::Mutability::Mut = mut_ {
+                    f.write_str("mut ")?;
+                }
+                f.write_str("self")
+            }
+            ty => {
+                f.write_str("self: ")?;
+                ty.hir_fmt(f)
+            }
+        }
+    }
+}
+
 impl HirDisplay for Adt {
     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
         match self {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 46def6c052f..b40b81fe0ff 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2090,14 +2090,6 @@ impl SelfParam {
             .unwrap_or(Access::Owned)
     }
 
-    pub fn display(self, db: &dyn HirDatabase) -> &'static str {
-        match self.access(db) {
-            Access::Shared => "&self",
-            Access::Exclusive => "&mut self",
-            Access::Owned => "self",
-        }
-    }
-
     pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
         let InFile { file_id, value } = Function::from(self.func).source(db)?;
         value
@@ -4406,14 +4398,13 @@ impl Callable {
             Other => CallableKind::Other,
         }
     }
-    pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(ast::SelfParam, Type)> {
+    pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
         let func = match self.callee {
             Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
             _ => return None,
         };
-        let src = func.lookup(db.upcast()).source(db.upcast());
-        let param_list = src.value.param_list()?;
-        Some((param_list.self_param()?, self.ty.derived(self.sig.params()[0].clone())))
+        let func = Function { id: func };
+        Some((func.self_param(db)?, self.ty.derived(self.sig.params()[0].clone())))
     }
     pub fn n_params(&self) -> usize {
         self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
diff --git a/crates/ide-ssr/src/matching.rs b/crates/ide-ssr/src/matching.rs
index a8e88369088..60fcbbbd397 100644
--- a/crates/ide-ssr/src/matching.rs
+++ b/crates/ide-ssr/src/matching.rs
@@ -560,8 +560,10 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
                         placeholder_value.autoref_kind = self
                             .sema
                             .resolve_method_call_as_callable(code)
-                            .and_then(|callable| callable.receiver_param(self.sema.db))
-                            .map(|(self_param, _)| self_param.kind())
+                            .and_then(|callable| {
+                                let (self_param, _) = callable.receiver_param(self.sema.db)?;
+                                Some(self_param.source(self.sema.db)?.value.kind())
+                            })
                             .unwrap_or(ast::SelfParamKind::Owned);
                     }
                 }
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index 7795be54e26..e3ad817e06a 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -202,7 +202,7 @@ fn signature_help_for_call(
     res.signature.push('(');
     {
         if let Some((self_param, _)) = callable.receiver_param(db) {
-            format_to!(res.signature, "{}", self_param)
+            format_to!(res.signature, "{}", self_param.display(db))
         }
         let mut buf = String::new();
         for (idx, (pat, ty)) in callable.params(db).into_iter().enumerate() {
@@ -1315,6 +1315,25 @@ id! {
     }
 
     #[test]
+    fn fn_signature_for_method_call_defined_in_macro() {
+        check(
+            r#"
+macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
+struct S;
+id! {
+    impl S {
+        fn foo<'a>(&'a mut self) {}
+    }
+}
+fn test() { S.foo($0); }
+"#,
+            expect![[r#"
+                fn foo(&'a mut self)
+            "#]],
+        );
+    }
+
+    #[test]
     fn call_info_for_lambdas() {
         check(
             r#"