Query for nearest parent block around the hint to resolve

This way, parameter hints will be found for resolution
This commit is contained in:
Kirill Bulatov 2023-12-11 14:50:41 +02:00
parent 457b966b17
commit be6d34b810
4 changed files with 30 additions and 20 deletions

View File

@ -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<TextRange>,
range_limit: Option<RangeLimit>,
config: &InlayHintsConfig,
) -> Vec<InlayHint> {
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),
};
}

View File

@ -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 =

View File

@ -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<TextRange>,
range: Option<RangeLimit>,
) -> Cancellable<Vec<InlayHint>> {
self.with_db(|db| inlay_hints::inlay_hints(db, file_id, range, config))
}

View File

@ -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