From be6d34b810141710f60a94959a8cc67adceb1fca Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 11 Dec 2023 14:50:41 +0200 Subject: [PATCH 1/2] Query for nearest parent block around the hint to resolve This way, parameter hints will be found for resolution --- crates/ide/src/inlay_hints.rs | 19 +++++++++++++++++-- crates/ide/src/inlay_hints/bind_pat.rs | 8 ++++++-- crates/ide/src/lib.rs | 4 ++-- crates/rust-analyzer/src/handlers/request.rs | 19 +++++-------------- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index ca334e91579..cdf83ff7d28 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -422,6 +422,11 @@ fn ty_to_text_edit( Some(builder.finish()) } +pub enum RangeLimit { + Fixed(TextRange), + NearestParentBlock(TextSize), +} + // Feature: Inlay Hints // // rust-analyzer shows additional information inline with the source code. @@ -443,7 +448,7 @@ fn ty_to_text_edit( pub(crate) fn inlay_hints( db: &RootDatabase, file_id: FileId, - range_limit: Option, + range_limit: Option, config: &InlayHintsConfig, ) -> Vec { let _p = profile::span("inlay_hints"); @@ -458,13 +463,23 @@ pub(crate) fn inlay_hints( let hints = |node| hints(&mut acc, &famous_defs, config, file_id, node); match range_limit { - Some(range) => match file.covering_element(range) { + Some(RangeLimit::Fixed(range)) => match file.covering_element(range) { NodeOrToken::Token(_) => return acc, NodeOrToken::Node(n) => n .descendants() .filter(|descendant| range.intersect(descendant.text_range()).is_some()) .for_each(hints), }, + Some(RangeLimit::NearestParentBlock(position)) => { + match file + .token_at_offset(position) + .left_biased() + .and_then(|token| token.parent_ancestors().find_map(ast::BlockExpr::cast)) + { + Some(parent_block) => parent_block.syntax().descendants().for_each(hints), + None => return acc, + } + } None => file.descendants().for_each(hints), }; } diff --git a/crates/ide/src/inlay_hints/bind_pat.rs b/crates/ide/src/inlay_hints/bind_pat.rs index 680035c721b..45b51e35570 100644 --- a/crates/ide/src/inlay_hints/bind_pat.rs +++ b/crates/ide/src/inlay_hints/bind_pat.rs @@ -177,7 +177,11 @@ mod tests { use syntax::{TextRange, TextSize}; use test_utils::extract_annotations; - use crate::{fixture, inlay_hints::InlayHintsConfig, ClosureReturnTypeHints}; + use crate::{ + fixture, + inlay_hints::{InlayHintsConfig, RangeLimit}, + ClosureReturnTypeHints, + }; use crate::inlay_hints::tests::{ check, check_edit, check_no_edit, check_with_config, DISABLED_CONFIG, TEST_CONFIG, @@ -400,7 +404,7 @@ fn main() { .inlay_hints( &InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG }, file_id, - Some(TextRange::new(TextSize::from(500), TextSize::from(600))), + Some(RangeLimit::Fixed(TextRange::new(TextSize::from(500), TextSize::from(600)))), ) .unwrap(); let actual = diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index d8f6e4e1b1b..e3548f3f0cb 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -94,7 +94,7 @@ pub use crate::{ inlay_hints::{ AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintPosition, - InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, + InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, RangeLimit, }, join_lines::JoinLinesConfig, markup::Markup, @@ -397,7 +397,7 @@ impl Analysis { &self, config: &InlayHintsConfig, file_id: FileId, - range: Option, + range: Option, ) -> Cancellable> { self.with_db(|db| inlay_hints::inlay_hints(db, file_id, range, config)) } diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 57955ebf897..6ec9fe153b9 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -12,8 +12,8 @@ use anyhow::Context; use ide::{ AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, FilePosition, FileRange, - HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query, RangeInfo, ReferenceCategory, - Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit, + HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query, RangeInfo, RangeLimit, + ReferenceCategory, Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit, }; use ide_db::SymbolKind; use lsp_server::ErrorCode; @@ -1409,7 +1409,7 @@ pub(crate) fn handle_inlay_hints( let inlay_hints_config = snap.config.inlay_hints(); Ok(Some( snap.analysis - .inlay_hints(&inlay_hints_config, file_id, Some(range))? + .inlay_hints(&inlay_hints_config, file_id, Some(RangeLimit::Fixed(range)))? .into_iter() .map(|it| { to_proto::inlay_hint( @@ -1440,22 +1440,13 @@ pub(crate) fn handle_inlay_hints_resolve( anyhow::ensure!(snap.file_exists(file_id), "Invalid LSP resolve data"); let line_index = snap.file_line_index(file_id)?; - let range = from_proto::text_range( - &line_index, - lsp_types::Range { start: original_hint.position, end: original_hint.position }, - )?; - let range_start = range.start(); - let range_end = range.end(); - let large_range = TextRange::new( - range_start.checked_sub(1.into()).unwrap_or(range_start), - range_end.checked_add(1.into()).unwrap_or(range_end), - ); + let hint_position = from_proto::offset(&line_index, original_hint.position)?; let mut forced_resolve_inlay_hints_config = snap.config.inlay_hints(); forced_resolve_inlay_hints_config.fields_to_resolve = InlayFieldsToResolve::empty(); let resolve_hints = snap.analysis.inlay_hints( &forced_resolve_inlay_hints_config, file_id, - Some(large_range), + Some(RangeLimit::NearestParentBlock(hint_position)), )?; let mut resolved_hints = resolve_hints From 8ae42b55e79a127c811d85411ecea204b9529091 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 11 Dec 2023 15:16:55 +0200 Subject: [PATCH 2/2] Search for parent blocks and items when resolving inlay hints --- crates/ide/src/inlay_hints.rs | 24 +++++++++++++------- crates/rust-analyzer/src/handlers/request.rs | 2 +- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index cdf83ff7d28..e82d730e4a3 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -424,7 +424,7 @@ fn ty_to_text_edit( pub enum RangeLimit { Fixed(TextRange), - NearestParentBlock(TextSize), + NearestParent(TextSize), } // Feature: Inlay Hints @@ -470,13 +470,21 @@ pub(crate) fn inlay_hints( .filter(|descendant| range.intersect(descendant.text_range()).is_some()) .for_each(hints), }, - Some(RangeLimit::NearestParentBlock(position)) => { - match file - .token_at_offset(position) - .left_biased() - .and_then(|token| token.parent_ancestors().find_map(ast::BlockExpr::cast)) - { - Some(parent_block) => parent_block.syntax().descendants().for_each(hints), + Some(RangeLimit::NearestParent(position)) => { + match file.token_at_offset(position).left_biased() { + Some(token) => { + if let Some(parent_block) = + token.parent_ancestors().find_map(ast::BlockExpr::cast) + { + parent_block.syntax().descendants().for_each(hints) + } else if let Some(parent_item) = + token.parent_ancestors().find_map(ast::Item::cast) + { + parent_item.syntax().descendants().for_each(hints) + } else { + return acc; + } + } None => return acc, } } diff --git a/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs index 6ec9fe153b9..d8a590c8088 100644 --- a/crates/rust-analyzer/src/handlers/request.rs +++ b/crates/rust-analyzer/src/handlers/request.rs @@ -1446,7 +1446,7 @@ pub(crate) fn handle_inlay_hints_resolve( let resolve_hints = snap.analysis.inlay_hints( &forced_resolve_inlay_hints_config, file_id, - Some(RangeLimit::NearestParentBlock(hint_position)), + Some(RangeLimit::NearestParent(hint_position)), )?; let mut resolved_hints = resolve_hints