mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-03 13:23:25 +00:00
Merge pull request #19647 from roife/fix-issue-19646
fix: panics in inlay hints that produce empty text edits for closure return types
This commit is contained in:
commit
4e4aee41c9
3 changed files with 31 additions and 41 deletions
|
|
@ -8,7 +8,7 @@ use hir::{
|
||||||
ClosureStyle, DisplayTarget, EditionedFileId, HasVisibility, HirDisplay, HirDisplayError,
|
ClosureStyle, DisplayTarget, EditionedFileId, HasVisibility, HirDisplay, HirDisplayError,
|
||||||
HirWrite, ModuleDef, ModuleDefId, Semantics, sym,
|
HirWrite, ModuleDef, ModuleDefId, Semantics, sym,
|
||||||
};
|
};
|
||||||
use ide_db::{FileRange, RootDatabase, famous_defs::FamousDefs};
|
use ide_db::{FileRange, RootDatabase, famous_defs::FamousDefs, text_edit::TextEditBuilder};
|
||||||
use ide_db::{FxHashSet, text_edit::TextEdit};
|
use ide_db::{FxHashSet, text_edit::TextEdit};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
|
|
@ -813,7 +813,8 @@ fn ty_to_text_edit(
|
||||||
config: &InlayHintsConfig,
|
config: &InlayHintsConfig,
|
||||||
node_for_hint: &SyntaxNode,
|
node_for_hint: &SyntaxNode,
|
||||||
ty: &hir::Type,
|
ty: &hir::Type,
|
||||||
offset_to_insert: TextSize,
|
offset_to_insert_ty: TextSize,
|
||||||
|
additional_edits: &dyn Fn(&mut TextEditBuilder),
|
||||||
prefix: impl Into<String>,
|
prefix: impl Into<String>,
|
||||||
) -> Option<LazyProperty<TextEdit>> {
|
) -> Option<LazyProperty<TextEdit>> {
|
||||||
// FIXME: Limit the length and bail out on excess somehow?
|
// FIXME: Limit the length and bail out on excess somehow?
|
||||||
|
|
@ -822,8 +823,11 @@ fn ty_to_text_edit(
|
||||||
.and_then(|scope| ty.display_source_code(scope.db, scope.module().into(), false).ok())?;
|
.and_then(|scope| ty.display_source_code(scope.db, scope.module().into(), false).ok())?;
|
||||||
Some(config.lazy_text_edit(|| {
|
Some(config.lazy_text_edit(|| {
|
||||||
let mut builder = TextEdit::builder();
|
let mut builder = TextEdit::builder();
|
||||||
builder.insert(offset_to_insert, prefix.into());
|
builder.insert(offset_to_insert_ty, prefix.into());
|
||||||
builder.insert(offset_to_insert, rendered);
|
builder.insert(offset_to_insert_ty, rendered);
|
||||||
|
|
||||||
|
additional_edits(&mut builder);
|
||||||
|
|
||||||
builder.finish()
|
builder.finish()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ pub(super) fn hints(
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or_else(|| pat.syntax().text_range(), |t| t.text_range())
|
.map_or_else(|| pat.syntax().text_range(), |t| t.text_range())
|
||||||
.end(),
|
.end(),
|
||||||
|
&|_| (),
|
||||||
if colon_token.is_some() { "" } else { ": " },
|
if colon_token.is_some() { "" } else { ": " },
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
//! Implementation of "closure return type" inlay hints.
|
//! Implementation of "closure return type" inlay hints.
|
||||||
//!
|
//!
|
||||||
//! Tests live in [`bind_pat`][super::bind_pat] module.
|
//! Tests live in [`bind_pat`][super::bind_pat] module.
|
||||||
use hir::{DisplayTarget, HirDisplay};
|
use hir::DisplayTarget;
|
||||||
use ide_db::{famous_defs::FamousDefs, text_edit::TextEdit};
|
use ide_db::{famous_defs::FamousDefs, text_edit::TextEditBuilder};
|
||||||
use syntax::ast::{self, AstNode};
|
use syntax::ast::{self, AstNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -49,44 +49,29 @@ pub(super) fn hints(
|
||||||
if arrow.is_none() {
|
if arrow.is_none() {
|
||||||
label.prepend_str(" -> ");
|
label.prepend_str(" -> ");
|
||||||
}
|
}
|
||||||
let text_edit = if has_block_body {
|
|
||||||
ty_to_text_edit(
|
let offset_to_insert_ty =
|
||||||
|
arrow.as_ref().map_or_else(|| param_list.syntax().text_range(), |t| t.text_range()).end();
|
||||||
|
|
||||||
|
// Insert braces if necessary
|
||||||
|
let insert_braces = |builder: &mut TextEditBuilder| {
|
||||||
|
if !has_block_body {
|
||||||
|
if let Some(range) = closure.body().map(|b| b.syntax().text_range()) {
|
||||||
|
builder.insert(range.start(), "{ ".to_owned());
|
||||||
|
builder.insert(range.end(), " }".to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let text_edit = ty_to_text_edit(
|
||||||
sema,
|
sema,
|
||||||
config,
|
config,
|
||||||
descended_closure.syntax(),
|
descended_closure.syntax(),
|
||||||
&ty,
|
&ty,
|
||||||
arrow
|
offset_to_insert_ty,
|
||||||
.as_ref()
|
&insert_braces,
|
||||||
.map_or_else(|| param_list.syntax().text_range(), |t| t.text_range())
|
|
||||||
.end(),
|
|
||||||
if arrow.is_none() { " -> " } else { "" },
|
if arrow.is_none() { " -> " } else { "" },
|
||||||
)
|
);
|
||||||
} else {
|
|
||||||
Some(config.lazy_text_edit(|| {
|
|
||||||
let body = closure.body();
|
|
||||||
let body_range = match body {
|
|
||||||
Some(body) => body.syntax().text_range(),
|
|
||||||
None => return TextEdit::builder().finish(),
|
|
||||||
};
|
|
||||||
let mut builder = TextEdit::builder();
|
|
||||||
let insert_pos = param_list.syntax().text_range().end();
|
|
||||||
|
|
||||||
let rendered = match sema.scope(descended_closure.syntax()).and_then(|scope| {
|
|
||||||
ty.display_source_code(scope.db, scope.module().into(), false).ok()
|
|
||||||
}) {
|
|
||||||
Some(rendered) => rendered,
|
|
||||||
None => return TextEdit::builder().finish(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let arrow_text = if arrow.is_none() { " -> ".to_owned() } else { "".to_owned() };
|
|
||||||
builder.insert(insert_pos, arrow_text);
|
|
||||||
builder.insert(insert_pos, rendered);
|
|
||||||
builder.insert(body_range.start(), "{ ".to_owned());
|
|
||||||
builder.insert(body_range.end(), " }".to_owned());
|
|
||||||
|
|
||||||
builder.finish()
|
|
||||||
}))
|
|
||||||
};
|
|
||||||
|
|
||||||
acc.push(InlayHint {
|
acc.push(InlayHint {
|
||||||
range: param_list.syntax().text_range(),
|
range: param_list.syntax().text_range(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue