Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/inlay_hints.rs')
| -rw-r--r-- | crates/ide/src/inlay_hints.rs | 69 |
1 files changed, 49 insertions, 20 deletions
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 93dd56a450..be99510af2 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -14,8 +14,8 @@ use smallvec::{smallvec, SmallVec}; use span::{Edition, EditionedFileId}; use stdx::never; use syntax::{ - ast::{self, AstNode}, - match_ast, NodeOrToken, SyntaxNode, TextRange, TextSize, WalkEvent, + ast::{self, AstNode, HasGenericParams}, + format_smolstr, match_ast, NodeOrToken, SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent, }; use text_edit::TextEdit; @@ -29,10 +29,10 @@ mod closing_brace; mod closure_captures; mod closure_ret; mod discriminant; -mod fn_lifetime_fn; mod generic_param; mod implicit_drop; mod implicit_static; +mod lifetime; mod param_name; mod range_exclusive; @@ -94,8 +94,8 @@ pub(crate) fn inlay_hints( }; let famous_defs = FamousDefs(&sema, scope.krate()); - let parent_impl = &mut None; - let hints = |node| hints(&mut acc, parent_impl, &famous_defs, config, file_id, node); + let ctx = &mut InlayHintCtx::default(); + let hints = |node| hints(&mut acc, ctx, &famous_defs, config, file_id, node); match range_limit { // FIXME: This can miss some hints that require the parent of the range to calculate Some(range) => match file.covering_element(range) { @@ -111,6 +111,12 @@ pub(crate) fn inlay_hints( acc } +#[derive(Default)] +struct InlayHintCtx { + lifetime_stacks: Vec<Vec<SmolStr>>, + is_param_list: bool, +} + pub(crate) fn inlay_hints_resolve( db: &RootDatabase, file_id: FileId, @@ -131,8 +137,8 @@ pub(crate) fn inlay_hints_resolve( let famous_defs = FamousDefs(&sema, scope.krate()); let mut acc = Vec::new(); - let parent_impl = &mut None; - let hints = |node| hints(&mut acc, parent_impl, &famous_defs, config, file_id, node); + let ctx = &mut InlayHintCtx::default(); + let hints = |node| hints(&mut acc, ctx, &famous_defs, config, file_id, node); let mut res = file.clone(); let res = loop { @@ -146,9 +152,11 @@ pub(crate) fn inlay_hints_resolve( acc.into_iter().find(|hint| hasher(hint) == hash) } +// FIXME: At some point when our hir infra is fleshed out enough we should flip this and traverse the +// HIR instead of the syntax tree. fn hints( hints: &mut Vec<InlayHint>, - parent_impl: &mut Option<ast::Impl>, + ctx: &mut InlayHintCtx, famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, config: &InlayHintsConfig, file_id: EditionedFileId, @@ -157,12 +165,30 @@ fn hints( let node = match node { WalkEvent::Enter(node) => node, WalkEvent::Leave(n) => { - if ast::Impl::can_cast(n.kind()) { - parent_impl.take(); + if ast::AnyHasGenericParams::can_cast(n.kind()) { + ctx.lifetime_stacks.pop(); + // pop + } + if ast::ParamList::can_cast(n.kind()) { + ctx.is_param_list = false; + // pop } return; } }; + + if let Some(node) = ast::AnyHasGenericParams::cast(node.clone()) { + let params = node + .generic_param_list() + .map(|it| { + it.lifetime_params() + .filter_map(|it| it.lifetime().map(|it| format_smolstr!("{}", &it.text()[1..]))) + .collect() + }) + .unwrap_or_default(); + ctx.lifetime_stacks.push(params); + } + 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); @@ -183,7 +209,7 @@ fn hints( closure_ret::hints(hints, famous_defs, config, file_id, it) }, ast::Expr::RangeExpr(it) => range_exclusive::hints(hints, famous_defs, config, file_id, it), - _ => None, + _ => Some(()), } }, ast::Pat(it) => { @@ -200,14 +226,9 @@ fn hints( Some(()) }, ast::Item(it) => match it { - // FIXME: record impl lifetimes so they aren't being reused in assoc item lifetime inlay hints - ast::Item::Impl(impl_) => { - *parent_impl = Some(impl_); - None - }, ast::Item::Fn(it) => { implicit_drop::hints(hints, famous_defs, config, file_id, &it); - fn_lifetime_fn::hints(hints, famous_defs, config, file_id, it) + lifetime::fn_hints(hints, ctx, famous_defs, config, file_id, it) }, // static type elisions ast::Item::Static(it) => implicit_static::hints(hints, famous_defs, config, file_id, Either::Left(it)), @@ -215,9 +236,17 @@ fn hints( ast::Item::Enum(it) => discriminant::enum_hints(hints, famous_defs, config, file_id, it), _ => None, }, - // FIXME: fn-ptr type, dyn fn type, and trait object type elisions - ast::Type(_) => None, - _ => None, + // FIXME: trait object type elisions + ast::Type(ty) => match ty { + ast::Type::FnPtrType(ptr) => lifetime::fn_ptr_hints(hints, ctx, famous_defs, config, file_id, ptr), + ast::Type::PathType(path) => lifetime::fn_path_hints(hints, ctx, famous_defs, config, file_id, path), + _ => Some(()), + }, + ast::ParamList(_) => { + ctx.is_param_list = true; + Some(()) + }, + _ => Some(()), } }; } |