mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-28 10:39:45 +00:00
Fix Param::as_local treating closures wrong
This commit is contained in:
parent
76585539f5
commit
831e3535e6
4 changed files with 66 additions and 52 deletions
|
|
@ -45,7 +45,7 @@ use hir_def::{
|
|||
body::BodyDiagnostic,
|
||||
data::{adt::VariantData, TraitFlags},
|
||||
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
|
||||
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
|
||||
hir::{BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat},
|
||||
item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
|
||||
lang_item::LangItemTarget,
|
||||
layout::{self, ReprOptions, TargetDataLayout},
|
||||
|
|
@ -2470,20 +2470,31 @@ impl Param {
|
|||
}
|
||||
|
||||
pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
|
||||
let parent = match self.func {
|
||||
Callee::Def(CallableDefId::FunctionId(it)) => DefWithBodyId::FunctionId(it),
|
||||
Callee::Closure(closure, _) => db.lookup_intern_closure(closure.into()).0,
|
||||
_ => return None,
|
||||
};
|
||||
let body = db.body(parent);
|
||||
if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
|
||||
Some(Local { parent, binding_id: self_param })
|
||||
} else if let Pat::Bind { id, .. } =
|
||||
&body[body.params[self.idx - body.self_param.is_some() as usize]]
|
||||
{
|
||||
Some(Local { parent, binding_id: *id })
|
||||
} else {
|
||||
None
|
||||
match self.func {
|
||||
Callee::Def(CallableDefId::FunctionId(it)) => {
|
||||
let parent = DefWithBodyId::FunctionId(it);
|
||||
let body = db.body(parent);
|
||||
if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
|
||||
Some(Local { parent, binding_id: self_param })
|
||||
} else if let Pat::Bind { id, .. } =
|
||||
&body[body.params[self.idx - body.self_param.is_some() as usize]]
|
||||
{
|
||||
Some(Local { parent, binding_id: *id })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Callee::Closure(closure, _) => {
|
||||
let c = db.lookup_intern_closure(closure.into());
|
||||
let body = db.body(c.0);
|
||||
if let Expr::Closure { args, .. } = &body[c.1] {
|
||||
if let Pat::Bind { id, .. } = &body[args[self.idx]] {
|
||||
return Some(Local { parent: c.0, binding_id: *id });
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ fn hints(
|
|||
) {
|
||||
closing_brace::hints(hints, sema, config, file_id, node.clone());
|
||||
if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
|
||||
generic_param::hints(hints, sema, config, any_has_generic_args);
|
||||
generic_param::hints(hints, famous_defs, config, any_has_generic_args);
|
||||
}
|
||||
|
||||
match_ast! {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
//! Implementation of inlay hints for generic parameters.
|
||||
use ide_db::{active_parameter::generic_def_for_node, RootDatabase};
|
||||
use ide_db::{active_parameter::generic_def_for_node, famous_defs::FamousDefs};
|
||||
use syntax::{
|
||||
ast::{self, AnyHasGenericArgs, HasGenericArgs, HasName},
|
||||
AstNode,
|
||||
};
|
||||
|
||||
use crate::{inlay_hints::GenericParameterHints, InlayHint, InlayHintsConfig, InlayKind};
|
||||
use crate::{
|
||||
inlay_hints::GenericParameterHints, InlayHint, InlayHintLabel, InlayHintsConfig, InlayKind,
|
||||
};
|
||||
|
||||
use super::param_name::{is_argument_similar_to_param_name, render_label};
|
||||
use super::param_name::is_argument_similar_to_param_name;
|
||||
|
||||
pub(crate) fn hints(
|
||||
acc: &mut Vec<InlayHint>,
|
||||
sema: &hir::Semantics<'_, RootDatabase>,
|
||||
FamousDefs(sema, krate): &FamousDefs<'_, '_>,
|
||||
config: &InlayHintsConfig,
|
||||
node: AnyHasGenericArgs,
|
||||
) -> Option<()> {
|
||||
|
|
@ -45,12 +47,11 @@ pub(crate) fn hints(
|
|||
return None;
|
||||
}
|
||||
|
||||
let name = param.name(sema.db);
|
||||
let param_name = name.as_str();
|
||||
let param_name = param.name(sema.db);
|
||||
|
||||
let should_hide = {
|
||||
let argument = get_string_representation(&arg)?;
|
||||
is_argument_similar_to_param_name(&argument, param_name)
|
||||
is_argument_similar_to_param_name(&argument, param_name.as_str())
|
||||
};
|
||||
|
||||
if should_hide {
|
||||
|
|
@ -64,7 +65,7 @@ pub(crate) fn hints(
|
|||
if !type_hints || !matches!(arg, ast::GenericArg::TypeArg(_)) {
|
||||
return None;
|
||||
}
|
||||
sema.source(it.merge())?.value.syntax().clone()
|
||||
sema.source(it.merge()).map(|it| it.value.syntax().clone())
|
||||
}
|
||||
hir::GenericParam::ConstParam(it) => {
|
||||
if !const_hints || !matches!(arg, ast::GenericArg::ConstArg(_)) {
|
||||
|
|
@ -72,17 +73,22 @@ pub(crate) fn hints(
|
|||
}
|
||||
let syntax = sema.source(it.merge())?.value.syntax().clone();
|
||||
let const_param = ast::ConstParam::cast(syntax)?;
|
||||
const_param.name()?.syntax().clone()
|
||||
const_param.name().map(|it| it.syntax().clone())
|
||||
}
|
||||
hir::GenericParam::LifetimeParam(it) => {
|
||||
if !lifetime_hints || !matches!(arg, ast::GenericArg::LifetimeArg(_)) {
|
||||
return None;
|
||||
}
|
||||
sema.source(it)?.value.syntax().clone()
|
||||
sema.source(it).map(|it| it.value.syntax().clone())
|
||||
}
|
||||
};
|
||||
let linked_location = sema.original_range_opt(&source_syntax);
|
||||
let label = render_label(param_name, config, linked_location);
|
||||
let linked_location = source_syntax.and_then(|it| sema.original_range_opt(&it));
|
||||
let colon = if config.render_colons { ":" } else { "" };
|
||||
let label = InlayHintLabel::simple(
|
||||
format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))),
|
||||
None,
|
||||
linked_location.map(Into::into),
|
||||
);
|
||||
|
||||
Some(InlayHint {
|
||||
range,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
//! fn max(x: i32, y: i32) -> i32 { x + y }
|
||||
//! _ = max(/*x*/4, /*y*/4);
|
||||
//! ```
|
||||
use std::fmt::Display;
|
||||
|
||||
use either::Either;
|
||||
use hir::{Callable, Semantics};
|
||||
|
|
@ -20,7 +19,7 @@ use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, Inla
|
|||
|
||||
pub(super) fn hints(
|
||||
acc: &mut Vec<InlayHint>,
|
||||
FamousDefs(sema, _): &FamousDefs<'_, '_>,
|
||||
FamousDefs(sema, krate): &FamousDefs<'_, '_>,
|
||||
config: &InlayHintsConfig,
|
||||
_file_id: EditionedFileId,
|
||||
expr: ast::Expr,
|
||||
|
|
@ -37,23 +36,31 @@ pub(super) fn hints(
|
|||
.filter_map(|(p, arg)| {
|
||||
// Only annotate hints for expressions that exist in the original file
|
||||
let range = sema.original_range_opt(arg.syntax())?;
|
||||
let source = sema.source(p)?;
|
||||
let (param_name, name_syntax) = match source.value.as_ref() {
|
||||
Either::Left(pat) => (pat.name()?, pat.name()),
|
||||
Either::Right(param) => match param.pat()? {
|
||||
ast::Pat::IdentPat(it) => (it.name()?, it.name()),
|
||||
_ => return None,
|
||||
},
|
||||
};
|
||||
Some((name_syntax, param_name, arg, range))
|
||||
let param_name = p.name(sema.db)?;
|
||||
Some((p, param_name, arg, range))
|
||||
})
|
||||
.filter(|(_, param_name, arg, _)| {
|
||||
!should_hide_param_name_hint(sema, &callable, ¶m_name.text(), arg)
|
||||
!should_hide_param_name_hint(sema, &callable, param_name.as_str(), arg)
|
||||
})
|
||||
.map(|(param, param_name, _, hir::FileRange { range, .. })| {
|
||||
let linked_location = param.and_then(|name| sema.original_range_opt(name.syntax()));
|
||||
let linked_location = (|| {
|
||||
let source = sema.source(param)?;
|
||||
let name_syntax = match source.value.as_ref() {
|
||||
Either::Left(pat) => pat.name(),
|
||||
Either::Right(param) => match param.pat()? {
|
||||
ast::Pat::IdentPat(it) => it.name(),
|
||||
_ => None,
|
||||
},
|
||||
}?;
|
||||
sema.original_range_opt(name_syntax.syntax())
|
||||
})();
|
||||
|
||||
let label = render_label(¶m_name, config, linked_location);
|
||||
let colon = if config.render_colons { ":" } else { "" };
|
||||
let label = InlayHintLabel::simple(
|
||||
format!("{}{colon}", param_name.display(sema.db, krate.edition(sema.db))),
|
||||
None,
|
||||
linked_location.map(Into::into),
|
||||
);
|
||||
InlayHint {
|
||||
range,
|
||||
kind: InlayKind::Parameter,
|
||||
|
|
@ -70,16 +77,6 @@ pub(super) fn hints(
|
|||
Some(())
|
||||
}
|
||||
|
||||
pub(super) fn render_label(
|
||||
param_name: impl Display,
|
||||
config: &InlayHintsConfig,
|
||||
linked_location: Option<hir::FileRange>,
|
||||
) -> InlayHintLabel {
|
||||
let colon = if config.render_colons { ":" } else { "" };
|
||||
|
||||
InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location.map(Into::into))
|
||||
}
|
||||
|
||||
fn get_callable(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
expr: &ast::Expr,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue