mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 03:54:42 +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,11 +2470,9 @@ 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, | ||||
|         }; | ||||
|         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 }) | ||||
|  | @ -2486,6 +2484,19 @@ impl Param { | |||
|                     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, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn pattern_source(self, db: &dyn HirDatabase) -> Option<ast::Pat> { | ||||
|         self.source(db).and_then(|p| p.value.right()?.pat()) | ||||
|  |  | |||
|  | @ -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
	
	 Lukas Wirth
						Lukas Wirth