mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Auto merge of #13699 - HKalbasi:inlaylink, r=Veykril
Implement location link for type inlay hints fix #11701 This actually doesn't work due a problem in vscode: https://github.com/microsoft/vscode/issues/167564
This commit is contained in:
commit
271f7b44d3
12 changed files with 496 additions and 105 deletions
|
@ -16,7 +16,7 @@ use hir_def::{
|
||||||
path::{Path, PathKind},
|
path::{Path, PathKind},
|
||||||
type_ref::{ConstScalar, TraitBoundModifier, TypeBound, TypeRef},
|
type_ref::{ConstScalar, TraitBoundModifier, TypeBound, TypeRef},
|
||||||
visibility::Visibility,
|
visibility::Visibility,
|
||||||
HasModule, ItemContainerId, Lookup, ModuleId, TraitId,
|
HasModule, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
|
||||||
};
|
};
|
||||||
use hir_expand::{hygiene::Hygiene, name::Name};
|
use hir_expand::{hygiene::Hygiene, name::Name};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -35,9 +35,27 @@ use crate::{
|
||||||
TraitRefExt, Ty, TyExt, TyKind, WhereClause,
|
TraitRefExt, Ty, TyExt, TyKind, WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub trait HirWrite: fmt::Write {
|
||||||
|
fn start_location_link(&mut self, location: ModuleDefId);
|
||||||
|
fn end_location_link(&mut self);
|
||||||
|
}
|
||||||
|
|
||||||
|
// String will ignore link metadata
|
||||||
|
impl HirWrite for String {
|
||||||
|
fn start_location_link(&mut self, _: ModuleDefId) {}
|
||||||
|
|
||||||
|
fn end_location_link(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// `core::Formatter` will ignore metadata
|
||||||
|
impl HirWrite for fmt::Formatter<'_> {
|
||||||
|
fn start_location_link(&mut self, _: ModuleDefId) {}
|
||||||
|
fn end_location_link(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct HirFormatter<'a> {
|
pub struct HirFormatter<'a> {
|
||||||
pub db: &'a dyn HirDatabase,
|
pub db: &'a dyn HirDatabase,
|
||||||
fmt: &'a mut dyn fmt::Write,
|
fmt: &'a mut dyn HirWrite,
|
||||||
buf: String,
|
buf: String,
|
||||||
curr_size: usize,
|
curr_size: usize,
|
||||||
pub(crate) max_size: Option<usize>,
|
pub(crate) max_size: Option<usize>,
|
||||||
|
@ -45,6 +63,16 @@ pub struct HirFormatter<'a> {
|
||||||
display_target: DisplayTarget,
|
display_target: DisplayTarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HirFormatter<'_> {
|
||||||
|
fn start_location_link(&mut self, location: ModuleDefId) {
|
||||||
|
self.fmt.start_location_link(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end_location_link(&mut self) {
|
||||||
|
self.fmt.end_location_link();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait HirDisplay {
|
pub trait HirDisplay {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>;
|
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError>;
|
||||||
|
|
||||||
|
@ -245,12 +273,9 @@ pub struct HirDisplayWrapper<'a, T> {
|
||||||
display_target: DisplayTarget,
|
display_target: DisplayTarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> fmt::Display for HirDisplayWrapper<'a, T>
|
impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
|
||||||
where
|
pub fn write_to<F: HirWrite>(&self, f: &mut F) -> Result<(), HirDisplayError> {
|
||||||
T: HirDisplay,
|
self.t.hir_fmt(&mut HirFormatter {
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self.t.hir_fmt(&mut HirFormatter {
|
|
||||||
db: self.db,
|
db: self.db,
|
||||||
fmt: f,
|
fmt: f,
|
||||||
buf: String::with_capacity(20),
|
buf: String::with_capacity(20),
|
||||||
|
@ -258,7 +283,16 @@ where
|
||||||
max_size: self.max_size,
|
max_size: self.max_size,
|
||||||
omit_verbose_types: self.omit_verbose_types,
|
omit_verbose_types: self.omit_verbose_types,
|
||||||
display_target: self.display_target,
|
display_target: self.display_target,
|
||||||
}) {
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> fmt::Display for HirDisplayWrapper<'a, T>
|
||||||
|
where
|
||||||
|
T: HirDisplay,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self.write_to(f) {
|
||||||
Ok(()) => Ok(()),
|
Ok(()) => Ok(()),
|
||||||
Err(HirDisplayError::FmtError) => Err(fmt::Error),
|
Err(HirDisplayError::FmtError) => Err(fmt::Error),
|
||||||
Err(HirDisplayError::DisplaySourceCodeError(_)) => {
|
Err(HirDisplayError::DisplaySourceCodeError(_)) => {
|
||||||
|
@ -530,6 +564,7 @@ impl HirDisplay for Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::Adt(AdtId(def_id), parameters) => {
|
TyKind::Adt(AdtId(def_id), parameters) => {
|
||||||
|
f.start_location_link((*def_id).into());
|
||||||
match f.display_target {
|
match f.display_target {
|
||||||
DisplayTarget::Diagnostics | DisplayTarget::Test => {
|
DisplayTarget::Diagnostics | DisplayTarget::Test => {
|
||||||
let name = match *def_id {
|
let name = match *def_id {
|
||||||
|
@ -554,6 +589,7 @@ impl HirDisplay for Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
f.end_location_link();
|
||||||
|
|
||||||
if parameters.len(Interner) > 0 {
|
if parameters.len(Interner) > 0 {
|
||||||
let parameters_to_write = if f.display_target.is_source_code()
|
let parameters_to_write = if f.display_target.is_source_code()
|
||||||
|
|
|
@ -114,12 +114,20 @@ pub use {
|
||||||
path::{ModPath, PathKind},
|
path::{ModPath, PathKind},
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
visibility::Visibility,
|
visibility::Visibility,
|
||||||
|
// FIXME: This is here since it is input of a method in `HirWrite`
|
||||||
|
// and things outside of hir need to implement that trait. We probably
|
||||||
|
// should move whole `hir_ty::display` to this crate so we will become
|
||||||
|
// able to use `ModuleDef` or `Definition` instead of `ModuleDefId`.
|
||||||
|
ModuleDefId,
|
||||||
},
|
},
|
||||||
hir_expand::{
|
hir_expand::{
|
||||||
name::{known, Name},
|
name::{known, Name},
|
||||||
ExpandResult, HirFileId, InFile, MacroFile, Origin,
|
ExpandResult, HirFileId, InFile, MacroFile, Origin,
|
||||||
},
|
},
|
||||||
hir_ty::{display::HirDisplay, PointerCast, Safety},
|
hir_ty::{
|
||||||
|
display::{HirDisplay, HirWrite},
|
||||||
|
PointerCast, Safety,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// These are negative re-exports: pub using these names is forbidden, they
|
// These are negative re-exports: pub using these names is forbidden, they
|
||||||
|
|
|
@ -1,15 +1,19 @@
|
||||||
use std::fmt;
|
use std::{
|
||||||
|
fmt::{self, Write},
|
||||||
|
mem::take,
|
||||||
|
};
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{known, HasVisibility, HirDisplay, Semantics};
|
use hir::{known, HasVisibility, HirDisplay, HirWrite, ModuleDef, ModuleDefId, Semantics};
|
||||||
use ide_db::{base_db::FileRange, famous_defs::FamousDefs, RootDatabase};
|
use ide_db::{base_db::FileRange, famous_defs::FamousDefs, RootDatabase};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use stdx::never;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
match_ast, NodeOrToken, SyntaxNode, TextRange, TextSize,
|
match_ast, NodeOrToken, SyntaxNode, TextRange, TextSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::FileId;
|
use crate::{navigation_target::TryToNav, FileId};
|
||||||
|
|
||||||
mod closing_brace;
|
mod closing_brace;
|
||||||
mod implicit_static;
|
mod implicit_static;
|
||||||
|
@ -23,6 +27,7 @@ mod bind_pat;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct InlayHintsConfig {
|
pub struct InlayHintsConfig {
|
||||||
|
pub location_links: bool,
|
||||||
pub render_colons: bool,
|
pub render_colons: bool,
|
||||||
pub type_hints: bool,
|
pub type_hints: bool,
|
||||||
pub parameter_hints: bool,
|
pub parameter_hints: bool,
|
||||||
|
@ -89,6 +94,7 @@ pub enum InlayTooltip {
|
||||||
HoverOffset(FileId, TextSize),
|
HoverOffset(FileId, TextSize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct InlayHintLabel {
|
pub struct InlayHintLabel {
|
||||||
pub parts: Vec<InlayHintLabelPart>,
|
pub parts: Vec<InlayHintLabelPart>,
|
||||||
}
|
}
|
||||||
|
@ -172,6 +178,104 @@ impl fmt::Debug for InlayHintLabelPart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct InlayHintLabelBuilder<'a> {
|
||||||
|
db: &'a RootDatabase,
|
||||||
|
result: InlayHintLabel,
|
||||||
|
last_part: String,
|
||||||
|
location_link_enabled: bool,
|
||||||
|
location: Option<FileRange>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Write for InlayHintLabelBuilder<'_> {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
self.last_part.write_str(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HirWrite for InlayHintLabelBuilder<'_> {
|
||||||
|
fn start_location_link(&mut self, def: ModuleDefId) {
|
||||||
|
if !self.location_link_enabled {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if self.location.is_some() {
|
||||||
|
never!("location link is already started");
|
||||||
|
}
|
||||||
|
self.make_new_part();
|
||||||
|
let Some(location) = ModuleDef::from(def).try_to_nav(self.db) else { return };
|
||||||
|
let location =
|
||||||
|
FileRange { file_id: location.file_id, range: location.focus_or_full_range() };
|
||||||
|
self.location = Some(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end_location_link(&mut self) {
|
||||||
|
if !self.location_link_enabled {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.make_new_part();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlayHintLabelBuilder<'_> {
|
||||||
|
fn make_new_part(&mut self) {
|
||||||
|
self.result.parts.push(InlayHintLabelPart {
|
||||||
|
text: take(&mut self.last_part),
|
||||||
|
linked_location: self.location.take(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(mut self) -> InlayHintLabel {
|
||||||
|
self.make_new_part();
|
||||||
|
self.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn label_of_ty(
|
||||||
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
|
desc_pat: &impl AstNode,
|
||||||
|
config: &InlayHintsConfig,
|
||||||
|
ty: hir::Type,
|
||||||
|
) -> Option<InlayHintLabel> {
|
||||||
|
fn rec(
|
||||||
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
|
famous_defs: &FamousDefs<'_, '_>,
|
||||||
|
mut max_length: Option<usize>,
|
||||||
|
ty: hir::Type,
|
||||||
|
label_builder: &mut InlayHintLabelBuilder<'_>,
|
||||||
|
) {
|
||||||
|
let iter_item_type = hint_iterator(sema, &famous_defs, &ty);
|
||||||
|
match iter_item_type {
|
||||||
|
Some(ty) => {
|
||||||
|
const LABEL_START: &str = "impl Iterator<Item = ";
|
||||||
|
const LABEL_END: &str = ">";
|
||||||
|
|
||||||
|
max_length =
|
||||||
|
max_length.map(|len| len.saturating_sub(LABEL_START.len() + LABEL_END.len()));
|
||||||
|
|
||||||
|
label_builder.write_str(LABEL_START).unwrap();
|
||||||
|
rec(sema, famous_defs, max_length, ty, label_builder);
|
||||||
|
label_builder.write_str(LABEL_END).unwrap();
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let _ = ty.display_truncated(sema.db, max_length).write_to(label_builder);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let krate = sema.scope(desc_pat.syntax())?.krate();
|
||||||
|
let famous_defs = FamousDefs(sema, krate);
|
||||||
|
let mut label_builder = InlayHintLabelBuilder {
|
||||||
|
db: sema.db,
|
||||||
|
last_part: String::new(),
|
||||||
|
location: None,
|
||||||
|
location_link_enabled: config.location_links,
|
||||||
|
result: InlayHintLabel::default(),
|
||||||
|
};
|
||||||
|
rec(sema, &famous_defs, config.max_length, ty, &mut label_builder);
|
||||||
|
let r = label_builder.finish();
|
||||||
|
Some(r)
|
||||||
|
}
|
||||||
|
|
||||||
// Feature: Inlay Hints
|
// Feature: Inlay Hints
|
||||||
//
|
//
|
||||||
// rust-analyzer shows additional information inline with the source code.
|
// rust-analyzer shows additional information inline with the source code.
|
||||||
|
@ -224,7 +328,7 @@ pub(crate) fn inlay_hints(
|
||||||
|
|
||||||
fn hints(
|
fn hints(
|
||||||
hints: &mut Vec<InlayHint>,
|
hints: &mut Vec<InlayHint>,
|
||||||
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
|
FamousDefs(sema, _): &FamousDefs<'_, '_>,
|
||||||
config: &InlayHintsConfig,
|
config: &InlayHintsConfig,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
node: SyntaxNode,
|
node: SyntaxNode,
|
||||||
|
@ -233,14 +337,14 @@ fn hints(
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match node {
|
match node {
|
||||||
ast::Expr(expr) => {
|
ast::Expr(expr) => {
|
||||||
chaining::hints(hints, sema, &famous_defs, config, file_id, &expr);
|
chaining::hints(hints, sema, config, file_id, &expr);
|
||||||
adjustment::hints(hints, sema, config, &expr);
|
adjustment::hints(hints, sema, config, &expr);
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expr::CallExpr(it) => param_name::hints(hints, sema, config, ast::Expr::from(it)),
|
ast::Expr::CallExpr(it) => param_name::hints(hints, sema, config, ast::Expr::from(it)),
|
||||||
ast::Expr::MethodCallExpr(it) => {
|
ast::Expr::MethodCallExpr(it) => {
|
||||||
param_name::hints(hints, sema, config, ast::Expr::from(it))
|
param_name::hints(hints, sema, config, ast::Expr::from(it))
|
||||||
}
|
}
|
||||||
ast::Expr::ClosureExpr(it) => closure_ret::hints(hints, sema, &famous_defs, config, file_id, it),
|
ast::Expr::ClosureExpr(it) => closure_ret::hints(hints, sema, config, file_id, it),
|
||||||
// We could show reborrows for all expressions, but usually that is just noise to the user
|
// We could show reborrows for all expressions, but usually that is just noise to the user
|
||||||
// and the main point here is to show why "moving" a mutable reference doesn't necessarily move it
|
// and the main point here is to show why "moving" a mutable reference doesn't necessarily move it
|
||||||
// ast::Expr::PathExpr(_) => reborrow_hints(hints, sema, config, &expr),
|
// ast::Expr::PathExpr(_) => reborrow_hints(hints, sema, config, &expr),
|
||||||
|
@ -270,13 +374,12 @@ fn hints(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the type is an Iterator from std::iter and replaces its hint with an `impl Iterator<Item = Ty>`.
|
/// Checks if the type is an Iterator from std::iter and returns its item type.
|
||||||
fn hint_iterator(
|
fn hint_iterator(
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
famous_defs: &FamousDefs<'_, '_>,
|
famous_defs: &FamousDefs<'_, '_>,
|
||||||
config: &InlayHintsConfig,
|
|
||||||
ty: &hir::Type,
|
ty: &hir::Type,
|
||||||
) -> Option<String> {
|
) -> Option<hir::Type> {
|
||||||
let db = sema.db;
|
let db = sema.db;
|
||||||
let strukt = ty.strip_references().as_adt()?;
|
let strukt = ty.strip_references().as_adt()?;
|
||||||
let krate = strukt.module(db).krate();
|
let krate = strukt.module(db).krate();
|
||||||
|
@ -299,21 +402,7 @@ fn hint_iterator(
|
||||||
_ => None,
|
_ => None,
|
||||||
})?;
|
})?;
|
||||||
if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) {
|
if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) {
|
||||||
const LABEL_START: &str = "impl Iterator<Item = ";
|
return Some(ty);
|
||||||
const LABEL_END: &str = ">";
|
|
||||||
|
|
||||||
let ty_display = hint_iterator(sema, famous_defs, config, &ty)
|
|
||||||
.map(|assoc_type_impl| assoc_type_impl.to_string())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
ty.display_truncated(
|
|
||||||
db,
|
|
||||||
config
|
|
||||||
.max_length
|
|
||||||
.map(|len| len.saturating_sub(LABEL_START.len() + LABEL_END.len())),
|
|
||||||
)
|
|
||||||
.to_string()
|
|
||||||
});
|
|
||||||
return Some(format!("{}{}{}", LABEL_START, ty_display, LABEL_END));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +425,7 @@ mod tests {
|
||||||
use super::ClosureReturnTypeHints;
|
use super::ClosureReturnTypeHints;
|
||||||
|
|
||||||
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
||||||
|
location_links: false,
|
||||||
render_colons: false,
|
render_colons: false,
|
||||||
type_hints: false,
|
type_hints: false,
|
||||||
parameter_hints: false,
|
parameter_hints: false,
|
||||||
|
@ -350,6 +440,8 @@ mod tests {
|
||||||
max_length: None,
|
max_length: None,
|
||||||
closing_brace_hints_min_lines: None,
|
closing_brace_hints_min_lines: None,
|
||||||
};
|
};
|
||||||
|
pub(super) const DISABLED_CONFIG_WITH_LINKS: InlayHintsConfig =
|
||||||
|
InlayHintsConfig { location_links: true, ..DISABLED_CONFIG };
|
||||||
pub(super) const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
pub(super) const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
||||||
type_hints: true,
|
type_hints: true,
|
||||||
parameter_hints: true,
|
parameter_hints: true,
|
||||||
|
@ -357,7 +449,7 @@ mod tests {
|
||||||
closure_return_type_hints: ClosureReturnTypeHints::WithBlock,
|
closure_return_type_hints: ClosureReturnTypeHints::WithBlock,
|
||||||
binding_mode_hints: true,
|
binding_mode_hints: true,
|
||||||
lifetime_elision_hints: LifetimeElisionHints::Always,
|
lifetime_elision_hints: LifetimeElisionHints::Always,
|
||||||
..DISABLED_CONFIG
|
..DISABLED_CONFIG_WITH_LINKS
|
||||||
};
|
};
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
//! fn f(a: i32, b: i32) -> i32 { a + b }
|
//! fn f(a: i32, b: i32) -> i32 { a + b }
|
||||||
//! let _x /* i32 */= f(4, 4);
|
//! let _x /* i32 */= f(4, 4);
|
||||||
//! ```
|
//! ```
|
||||||
use hir::{HirDisplay, Semantics, TypeInfo};
|
use hir::{Semantics, TypeInfo};
|
||||||
use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase};
|
use ide_db::{base_db::FileId, RootDatabase};
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
|
@ -13,10 +13,11 @@ use syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
inlay_hints::{closure_has_block_body, hint_iterator},
|
inlay_hints::closure_has_block_body, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip,
|
||||||
InlayHint, InlayHintsConfig, InlayKind, InlayTooltip,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::label_of_ty;
|
||||||
|
|
||||||
pub(super) fn hints(
|
pub(super) fn hints(
|
||||||
acc: &mut Vec<InlayHint>,
|
acc: &mut Vec<InlayHint>,
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
|
@ -36,22 +37,13 @@ pub(super) fn hints(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let krate = sema.scope(desc_pat.syntax())?.krate();
|
let label = label_of_ty(sema, desc_pat, config, ty)?;
|
||||||
let famous_defs = FamousDefs(sema, krate);
|
|
||||||
let label = hint_iterator(sema, &famous_defs, config, &ty);
|
|
||||||
|
|
||||||
let label = match label {
|
if config.hide_named_constructor_hints
|
||||||
Some(label) => label,
|
&& is_named_constructor(sema, pat, &label.to_string()).is_some()
|
||||||
None => {
|
{
|
||||||
let ty_name = ty.display_truncated(sema.db, config.max_length).to_string();
|
return None;
|
||||||
if config.hide_named_constructor_hints
|
}
|
||||||
&& is_named_constructor(sema, pat, &ty_name).is_some()
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
ty_name
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
acc.push(InlayHint {
|
acc.push(InlayHint {
|
||||||
range: match pat.name() {
|
range: match pat.name() {
|
||||||
|
@ -59,7 +51,7 @@ pub(super) fn hints(
|
||||||
None => pat.syntax().text_range(),
|
None => pat.syntax().text_range(),
|
||||||
},
|
},
|
||||||
kind: InlayKind::TypeHint,
|
kind: InlayKind::TypeHint,
|
||||||
label: label.into(),
|
label,
|
||||||
tooltip: pat
|
tooltip: pat
|
||||||
.name()
|
.name()
|
||||||
.map(|it| it.syntax().text_range())
|
.map(|it| it.syntax().text_range())
|
||||||
|
@ -202,7 +194,8 @@ mod tests {
|
||||||
use crate::{fixture, inlay_hints::InlayHintsConfig};
|
use crate::{fixture, inlay_hints::InlayHintsConfig};
|
||||||
|
|
||||||
use crate::inlay_hints::tests::{
|
use crate::inlay_hints::tests::{
|
||||||
check, check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG,
|
check, check_expect, check_with_config, DISABLED_CONFIG, DISABLED_CONFIG_WITH_LINKS,
|
||||||
|
TEST_CONFIG,
|
||||||
};
|
};
|
||||||
use crate::ClosureReturnTypeHints;
|
use crate::ClosureReturnTypeHints;
|
||||||
|
|
||||||
|
@ -298,7 +291,7 @@ fn main() {
|
||||||
fn iterator_hint_regression_issue_12674() {
|
fn iterator_hint_regression_issue_12674() {
|
||||||
// Ensure we don't crash while solving the projection type of iterators.
|
// Ensure we don't crash while solving the projection type of iterators.
|
||||||
check_expect(
|
check_expect(
|
||||||
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
|
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG_WITH_LINKS },
|
||||||
r#"
|
r#"
|
||||||
//- minicore: iterators
|
//- minicore: iterators
|
||||||
struct S<T>(T);
|
struct S<T>(T);
|
||||||
|
@ -346,7 +339,31 @@ fn main(a: SliceIter<'_, Container>) {
|
||||||
range: 484..485,
|
range: 484..485,
|
||||||
kind: ChainingHint,
|
kind: ChainingHint,
|
||||||
label: [
|
label: [
|
||||||
"SliceIter<Container>",
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "SliceIter",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 289..298,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"<",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "Container",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 238..247,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
">",
|
||||||
],
|
],
|
||||||
tooltip: Some(
|
tooltip: Some(
|
||||||
HoverRanged(
|
HoverRanged(
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
//! Implementation of "chaining" inlay hints.
|
//! Implementation of "chaining" inlay hints.
|
||||||
use hir::{HirDisplay, Semantics};
|
use hir::Semantics;
|
||||||
use ide_db::{famous_defs::FamousDefs, RootDatabase};
|
use ide_db::RootDatabase;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
Direction, NodeOrToken, SyntaxKind, T,
|
Direction, NodeOrToken, SyntaxKind, T,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{FileId, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip};
|
||||||
inlay_hints::hint_iterator, FileId, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip,
|
|
||||||
};
|
use super::label_of_ty;
|
||||||
|
|
||||||
pub(super) fn hints(
|
pub(super) fn hints(
|
||||||
acc: &mut Vec<InlayHint>,
|
acc: &mut Vec<InlayHint>,
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
famous_defs: &FamousDefs<'_, '_>,
|
|
||||||
config: &InlayHintsConfig,
|
config: &InlayHintsConfig,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
|
@ -62,9 +61,7 @@ pub(super) fn hints(
|
||||||
acc.push(InlayHint {
|
acc.push(InlayHint {
|
||||||
range: expr.syntax().text_range(),
|
range: expr.syntax().text_range(),
|
||||||
kind: InlayKind::ChainingHint,
|
kind: InlayKind::ChainingHint,
|
||||||
label: hint_iterator(sema, &famous_defs, config, &ty)
|
label: label_of_ty(sema, desc_expr, config, ty)?,
|
||||||
.unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string())
|
|
||||||
.into(),
|
|
||||||
tooltip: Some(InlayTooltip::HoverRanged(file_id, expr.syntax().text_range())),
|
tooltip: Some(InlayTooltip::HoverRanged(file_id, expr.syntax().text_range())),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -77,7 +74,10 @@ mod tests {
|
||||||
use expect_test::expect;
|
use expect_test::expect;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG},
|
inlay_hints::tests::{
|
||||||
|
check_expect, check_with_config, DISABLED_CONFIG, DISABLED_CONFIG_WITH_LINKS,
|
||||||
|
TEST_CONFIG,
|
||||||
|
},
|
||||||
InlayHintsConfig,
|
InlayHintsConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,7 +89,11 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn chaining_hints_ignore_comments() {
|
fn chaining_hints_ignore_comments() {
|
||||||
check_expect(
|
check_expect(
|
||||||
InlayHintsConfig { type_hints: false, chaining_hints: true, ..DISABLED_CONFIG },
|
InlayHintsConfig {
|
||||||
|
type_hints: false,
|
||||||
|
chaining_hints: true,
|
||||||
|
..DISABLED_CONFIG_WITH_LINKS
|
||||||
|
},
|
||||||
r#"
|
r#"
|
||||||
struct A(B);
|
struct A(B);
|
||||||
impl A { fn into_b(self) -> B { self.0 } }
|
impl A { fn into_b(self) -> B { self.0 } }
|
||||||
|
@ -110,7 +114,19 @@ fn main() {
|
||||||
range: 147..172,
|
range: 147..172,
|
||||||
kind: ChainingHint,
|
kind: ChainingHint,
|
||||||
label: [
|
label: [
|
||||||
"B",
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "B",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 63..64,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"",
|
||||||
],
|
],
|
||||||
tooltip: Some(
|
tooltip: Some(
|
||||||
HoverRanged(
|
HoverRanged(
|
||||||
|
@ -125,7 +141,19 @@ fn main() {
|
||||||
range: 147..154,
|
range: 147..154,
|
||||||
kind: ChainingHint,
|
kind: ChainingHint,
|
||||||
label: [
|
label: [
|
||||||
"A",
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "A",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 7..8,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"",
|
||||||
],
|
],
|
||||||
tooltip: Some(
|
tooltip: Some(
|
||||||
HoverRanged(
|
HoverRanged(
|
||||||
|
@ -158,27 +186,27 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn struct_access_chaining_hints() {
|
fn disabled_location_links() {
|
||||||
check_expect(
|
check_expect(
|
||||||
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
|
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
|
||||||
r#"
|
r#"
|
||||||
struct A { pub b: B }
|
struct A { pub b: B }
|
||||||
struct B { pub c: C }
|
struct B { pub c: C }
|
||||||
struct C(pub bool);
|
struct C(pub bool);
|
||||||
struct D;
|
struct D;
|
||||||
|
|
||||||
impl D {
|
impl D {
|
||||||
fn foo(&self) -> i32 { 42 }
|
fn foo(&self) -> i32 { 42 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = A { b: B { c: C(true) } }
|
let x = A { b: B { c: C(true) } }
|
||||||
.b
|
.b
|
||||||
.c
|
.c
|
||||||
.0;
|
.0;
|
||||||
let x = D
|
let x = D
|
||||||
.foo();
|
.foo();
|
||||||
}"#,
|
}"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
[
|
[
|
||||||
InlayHint {
|
InlayHint {
|
||||||
|
@ -216,10 +244,93 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_access_chaining_hints() {
|
||||||
|
check_expect(
|
||||||
|
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG_WITH_LINKS },
|
||||||
|
r#"
|
||||||
|
struct A { pub b: B }
|
||||||
|
struct B { pub c: C }
|
||||||
|
struct C(pub bool);
|
||||||
|
struct D;
|
||||||
|
|
||||||
|
impl D {
|
||||||
|
fn foo(&self) -> i32 { 42 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = A { b: B { c: C(true) } }
|
||||||
|
.b
|
||||||
|
.c
|
||||||
|
.0;
|
||||||
|
let x = D
|
||||||
|
.foo();
|
||||||
|
}"#,
|
||||||
|
expect![[r#"
|
||||||
|
[
|
||||||
|
InlayHint {
|
||||||
|
range: 143..190,
|
||||||
|
kind: ChainingHint,
|
||||||
|
label: [
|
||||||
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "C",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 51..52,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
],
|
||||||
|
tooltip: Some(
|
||||||
|
HoverRanged(
|
||||||
|
FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
143..190,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
InlayHint {
|
||||||
|
range: 143..179,
|
||||||
|
kind: ChainingHint,
|
||||||
|
label: [
|
||||||
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "B",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 29..30,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"",
|
||||||
|
],
|
||||||
|
tooltip: Some(
|
||||||
|
HoverRanged(
|
||||||
|
FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
143..179,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn generic_chaining_hints() {
|
fn generic_chaining_hints() {
|
||||||
check_expect(
|
check_expect(
|
||||||
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
|
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG_WITH_LINKS },
|
||||||
r#"
|
r#"
|
||||||
struct A<T>(T);
|
struct A<T>(T);
|
||||||
struct B<T>(T);
|
struct B<T>(T);
|
||||||
|
@ -245,7 +356,31 @@ fn main() {
|
||||||
range: 246..283,
|
range: 246..283,
|
||||||
kind: ChainingHint,
|
kind: ChainingHint,
|
||||||
label: [
|
label: [
|
||||||
"B<X<i32, bool>>",
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "B",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 23..24,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"<",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "X",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 55..56,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"<i32, bool>>",
|
||||||
],
|
],
|
||||||
tooltip: Some(
|
tooltip: Some(
|
||||||
HoverRanged(
|
HoverRanged(
|
||||||
|
@ -260,7 +395,31 @@ fn main() {
|
||||||
range: 246..265,
|
range: 246..265,
|
||||||
kind: ChainingHint,
|
kind: ChainingHint,
|
||||||
label: [
|
label: [
|
||||||
"A<X<i32, bool>>",
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "A",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 7..8,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"<",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "X",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 55..56,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"<i32, bool>>",
|
||||||
],
|
],
|
||||||
tooltip: Some(
|
tooltip: Some(
|
||||||
HoverRanged(
|
HoverRanged(
|
||||||
|
@ -279,7 +438,7 @@ fn main() {
|
||||||
#[test]
|
#[test]
|
||||||
fn shorten_iterator_chaining_hints() {
|
fn shorten_iterator_chaining_hints() {
|
||||||
check_expect(
|
check_expect(
|
||||||
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG },
|
InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG_WITH_LINKS },
|
||||||
r#"
|
r#"
|
||||||
//- minicore: iterators
|
//- minicore: iterators
|
||||||
use core::iter;
|
use core::iter;
|
||||||
|
@ -352,7 +511,19 @@ fn main() {
|
||||||
range: 174..189,
|
range: 174..189,
|
||||||
kind: ChainingHint,
|
kind: ChainingHint,
|
||||||
label: [
|
label: [
|
||||||
"&mut MyIter",
|
"&mut ",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "MyIter",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 24..30,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"",
|
||||||
],
|
],
|
||||||
tooltip: Some(
|
tooltip: Some(
|
||||||
HoverRanged(
|
HoverRanged(
|
||||||
|
@ -396,7 +567,19 @@ fn main() {
|
||||||
range: 124..130,
|
range: 124..130,
|
||||||
kind: TypeHint,
|
kind: TypeHint,
|
||||||
label: [
|
label: [
|
||||||
"Struct",
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "Struct",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 7..13,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"",
|
||||||
],
|
],
|
||||||
tooltip: Some(
|
tooltip: Some(
|
||||||
HoverRanged(
|
HoverRanged(
|
||||||
|
@ -411,7 +594,19 @@ fn main() {
|
||||||
range: 145..185,
|
range: 145..185,
|
||||||
kind: ChainingHint,
|
kind: ChainingHint,
|
||||||
label: [
|
label: [
|
||||||
"Struct",
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "Struct",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 7..13,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"",
|
||||||
],
|
],
|
||||||
tooltip: Some(
|
tooltip: Some(
|
||||||
HoverRanged(
|
HoverRanged(
|
||||||
|
@ -426,7 +621,19 @@ fn main() {
|
||||||
range: 145..168,
|
range: 145..168,
|
||||||
kind: ChainingHint,
|
kind: ChainingHint,
|
||||||
label: [
|
label: [
|
||||||
"Struct",
|
"",
|
||||||
|
InlayHintLabelPart {
|
||||||
|
text: "Struct",
|
||||||
|
linked_location: Some(
|
||||||
|
FileRange {
|
||||||
|
file_id: FileId(
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
range: 7..13,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"",
|
||||||
],
|
],
|
||||||
tooltip: Some(
|
tooltip: Some(
|
||||||
HoverRanged(
|
HoverRanged(
|
||||||
|
|
|
@ -109,7 +109,10 @@ pub(super) fn hints(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let linked_location = name_range.map(|range| FileRange { file_id, range });
|
let linked_location = config
|
||||||
|
.location_links
|
||||||
|
.then(|| name_range.map(|range| FileRange { file_id, range }))
|
||||||
|
.flatten();
|
||||||
acc.push(InlayHint {
|
acc.push(InlayHint {
|
||||||
range: closing_token.text_range(),
|
range: closing_token.text_range(),
|
||||||
kind: InlayKind::ClosingBraceHint,
|
kind: InlayKind::ClosingBraceHint,
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
//! Implementation of "closure return type" inlay hints.
|
//! Implementation of "closure return type" inlay hints.
|
||||||
use hir::{HirDisplay, Semantics};
|
use hir::Semantics;
|
||||||
use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase};
|
use ide_db::{base_db::FileId, RootDatabase};
|
||||||
use syntax::ast::{self, AstNode};
|
use syntax::ast::{self, AstNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
inlay_hints::{closure_has_block_body, hint_iterator},
|
inlay_hints::closure_has_block_body, ClosureReturnTypeHints, InlayHint, InlayHintsConfig,
|
||||||
ClosureReturnTypeHints, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip,
|
InlayKind, InlayTooltip,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::label_of_ty;
|
||||||
|
|
||||||
pub(super) fn hints(
|
pub(super) fn hints(
|
||||||
acc: &mut Vec<InlayHint>,
|
acc: &mut Vec<InlayHint>,
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
famous_defs: &FamousDefs<'_, '_>,
|
|
||||||
config: &InlayHintsConfig,
|
config: &InlayHintsConfig,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
closure: ast::ClosureExpr,
|
closure: ast::ClosureExpr,
|
||||||
|
@ -42,9 +43,7 @@ pub(super) fn hints(
|
||||||
acc.push(InlayHint {
|
acc.push(InlayHint {
|
||||||
range: param_list.syntax().text_range(),
|
range: param_list.syntax().text_range(),
|
||||||
kind: InlayKind::ClosureReturnTypeHint,
|
kind: InlayKind::ClosureReturnTypeHint,
|
||||||
label: hint_iterator(sema, &famous_defs, config, &ty)
|
label: label_of_ty(sema, ¶m_list, config, ty)?,
|
||||||
.unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string())
|
|
||||||
.into(),
|
|
||||||
tooltip: Some(InlayTooltip::HoverRanged(file_id, param_list.syntax().text_range())),
|
tooltip: Some(InlayTooltip::HoverRanged(file_id, param_list.syntax().text_range())),
|
||||||
});
|
});
|
||||||
Some(())
|
Some(())
|
||||||
|
|
|
@ -106,6 +106,7 @@ impl StaticIndex<'_> {
|
||||||
.analysis
|
.analysis
|
||||||
.inlay_hints(
|
.inlay_hints(
|
||||||
&InlayHintsConfig {
|
&InlayHintsConfig {
|
||||||
|
location_links: true,
|
||||||
render_colons: true,
|
render_colons: true,
|
||||||
type_hints: true,
|
type_hints: true,
|
||||||
parameter_hints: true,
|
parameter_hints: true,
|
||||||
|
|
|
@ -183,6 +183,8 @@ fn run_server() -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.client_specific_adjustments(&initialize_params.client_info);
|
||||||
|
|
||||||
let server_capabilities = rust_analyzer::server_capabilities(&config);
|
let server_capabilities = rust_analyzer::server_capabilities(&config);
|
||||||
|
|
||||||
let initialize_result = lsp_types::InitializeResult {
|
let initialize_result = lsp_types::InitializeResult {
|
||||||
|
|
|
@ -20,7 +20,7 @@ use ide_db::{
|
||||||
SnippetCap,
|
SnippetCap,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lsp_types::{ClientCapabilities, MarkupKind};
|
use lsp_types::{ClientCapabilities, ClientInfo, MarkupKind};
|
||||||
use project_model::{
|
use project_model::{
|
||||||
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource,
|
CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource,
|
||||||
UnsetTestCrates,
|
UnsetTestCrates,
|
||||||
|
@ -333,6 +333,8 @@ config_data! {
|
||||||
inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"",
|
inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = "\"never\"",
|
||||||
/// Whether to prefer using parameter names as the name for elided lifetime hints if possible.
|
/// Whether to prefer using parameter names as the name for elided lifetime hints if possible.
|
||||||
inlayHints_lifetimeElisionHints_useParameterNames: bool = "false",
|
inlayHints_lifetimeElisionHints_useParameterNames: bool = "false",
|
||||||
|
/// Whether to use location links for parts of type mentioned in inlay hints.
|
||||||
|
inlayHints_locationLinks: bool = "true",
|
||||||
/// Maximum length for inlay hints. Set to null to have an unlimited length.
|
/// Maximum length for inlay hints. Set to null to have an unlimited length.
|
||||||
inlayHints_maxLength: Option<usize> = "25",
|
inlayHints_maxLength: Option<usize> = "25",
|
||||||
/// Whether to show function parameter name inlay hints at the call
|
/// Whether to show function parameter name inlay hints at the call
|
||||||
|
@ -714,6 +716,19 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn client_specific_adjustments(&mut self, client_info: &Option<ClientInfo>) {
|
||||||
|
// FIXME: remove this when we drop support for vscode 1.65 and below
|
||||||
|
if let Some(client) = client_info {
|
||||||
|
if client.name.contains("Code") || client.name.contains("Codium") {
|
||||||
|
if let Some(version) = &client.version {
|
||||||
|
if version.as_str() < "1.76" {
|
||||||
|
self.data.inlayHints_locationLinks = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, mut json: serde_json::Value) -> Result<(), ConfigUpdateError> {
|
pub fn update(&mut self, mut json: serde_json::Value) -> Result<(), ConfigUpdateError> {
|
||||||
tracing::info!("updating config from JSON: {:#}", json);
|
tracing::info!("updating config from JSON: {:#}", json);
|
||||||
if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) {
|
if json.is_null() || json.as_object().map_or(false, |it| it.is_empty()) {
|
||||||
|
@ -1196,6 +1211,7 @@ impl Config {
|
||||||
|
|
||||||
pub fn inlay_hints(&self) -> InlayHintsConfig {
|
pub fn inlay_hints(&self) -> InlayHintsConfig {
|
||||||
InlayHintsConfig {
|
InlayHintsConfig {
|
||||||
|
location_links: self.data.inlayHints_locationLinks,
|
||||||
render_colons: self.data.inlayHints_renderColons,
|
render_colons: self.data.inlayHints_renderColons,
|
||||||
type_hints: self.data.inlayHints_typeHints_enable,
|
type_hints: self.data.inlayHints_typeHints_enable,
|
||||||
parameter_hints: self.data.inlayHints_parameterHints_enable,
|
parameter_hints: self.data.inlayHints_parameterHints_enable,
|
||||||
|
|
|
@ -469,6 +469,11 @@ Whether to show inlay type hints for elided lifetimes in function signatures.
|
||||||
--
|
--
|
||||||
Whether to prefer using parameter names as the name for elided lifetime hints if possible.
|
Whether to prefer using parameter names as the name for elided lifetime hints if possible.
|
||||||
--
|
--
|
||||||
|
[[rust-analyzer.inlayHints.locationLinks]]rust-analyzer.inlayHints.locationLinks (default: `true`)::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
Whether to use location links for parts of type mentioned in inlay hints.
|
||||||
|
--
|
||||||
[[rust-analyzer.inlayHints.maxLength]]rust-analyzer.inlayHints.maxLength (default: `25`)::
|
[[rust-analyzer.inlayHints.maxLength]]rust-analyzer.inlayHints.maxLength (default: `25`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
|
|
|
@ -995,6 +995,11 @@
|
||||||
"default": false,
|
"default": false,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"rust-analyzer.inlayHints.locationLinks": {
|
||||||
|
"markdownDescription": "Whether to use location links for parts of type mentioned in inlay hints.",
|
||||||
|
"default": true,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"rust-analyzer.inlayHints.maxLength": {
|
"rust-analyzer.inlayHints.maxLength": {
|
||||||
"markdownDescription": "Maximum length for inlay hints. Set to null to have an unlimited length.",
|
"markdownDescription": "Maximum length for inlay hints. Set to null to have an unlimited length.",
|
||||||
"default": 25,
|
"default": 25,
|
||||||
|
|
Loading…
Reference in a new issue