mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
feat: add inlay hints for generic parameters
fixes #11091 By default, only hints for const generic parameters are shown.
This commit is contained in:
parent
a5b21ea0aa
commit
35b4957b80
10 changed files with 443 additions and 14 deletions
|
@ -29,6 +29,7 @@ mod closure_captures;
|
||||||
mod closure_ret;
|
mod closure_ret;
|
||||||
mod discriminant;
|
mod discriminant;
|
||||||
mod fn_lifetime_fn;
|
mod fn_lifetime_fn;
|
||||||
|
mod generic_param;
|
||||||
mod implicit_drop;
|
mod implicit_drop;
|
||||||
mod implicit_static;
|
mod implicit_static;
|
||||||
mod param_name;
|
mod param_name;
|
||||||
|
@ -40,6 +41,7 @@ pub struct InlayHintsConfig {
|
||||||
pub type_hints: bool,
|
pub type_hints: bool,
|
||||||
pub discriminant_hints: DiscriminantHints,
|
pub discriminant_hints: DiscriminantHints,
|
||||||
pub parameter_hints: bool,
|
pub parameter_hints: bool,
|
||||||
|
pub generic_parameter_hints: GenericParameterHints,
|
||||||
pub chaining_hints: bool,
|
pub chaining_hints: bool,
|
||||||
pub adjustment_hints: AdjustmentHints,
|
pub adjustment_hints: AdjustmentHints,
|
||||||
pub adjustment_hints_mode: AdjustmentHintsMode,
|
pub adjustment_hints_mode: AdjustmentHintsMode,
|
||||||
|
@ -94,6 +96,13 @@ pub enum DiscriminantHints {
|
||||||
Fieldless,
|
Fieldless,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct GenericParameterHints {
|
||||||
|
pub type_hints: bool,
|
||||||
|
pub lifetime_hints: bool,
|
||||||
|
pub const_hints: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum LifetimeElisionHints {
|
pub enum LifetimeElisionHints {
|
||||||
Always,
|
Always,
|
||||||
|
@ -127,6 +136,7 @@ pub enum InlayKind {
|
||||||
GenericParamList,
|
GenericParamList,
|
||||||
Lifetime,
|
Lifetime,
|
||||||
Parameter,
|
Parameter,
|
||||||
|
GenericParameter,
|
||||||
Type,
|
Type,
|
||||||
Drop,
|
Drop,
|
||||||
RangeExclusive,
|
RangeExclusive,
|
||||||
|
@ -447,6 +457,7 @@ fn ty_to_text_edit(
|
||||||
//
|
//
|
||||||
// * types of local variables
|
// * types of local variables
|
||||||
// * names of function arguments
|
// * names of function arguments
|
||||||
|
// * names of const generic parameters
|
||||||
// * types of chained expressions
|
// * types of chained expressions
|
||||||
//
|
//
|
||||||
// Optionally, one can enable additional hints for
|
// Optionally, one can enable additional hints for
|
||||||
|
@ -454,6 +465,7 @@ fn ty_to_text_edit(
|
||||||
// * return types of closure expressions
|
// * return types of closure expressions
|
||||||
// * elided lifetimes
|
// * elided lifetimes
|
||||||
// * compiler inserted reborrows
|
// * compiler inserted reborrows
|
||||||
|
// * names of generic type and lifetime parameters
|
||||||
//
|
//
|
||||||
// Note: inlay hints for function argument names are heuristically omitted to reduce noise and will not appear if
|
// Note: inlay hints for function argument names are heuristically omitted to reduce noise and will not appear if
|
||||||
// any of the
|
// any of the
|
||||||
|
@ -543,6 +555,9 @@ fn hints(
|
||||||
node: SyntaxNode,
|
node: SyntaxNode,
|
||||||
) {
|
) {
|
||||||
closing_brace::hints(hints, sema, config, file_id, node.clone());
|
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);
|
||||||
|
}
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match node {
|
match node {
|
||||||
ast::Expr(expr) => {
|
ast::Expr(expr) => {
|
||||||
|
@ -645,13 +660,18 @@ mod tests {
|
||||||
use crate::DiscriminantHints;
|
use crate::DiscriminantHints;
|
||||||
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
|
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
|
||||||
|
|
||||||
use super::{ClosureReturnTypeHints, InlayFieldsToResolve};
|
use super::{ClosureReturnTypeHints, GenericParameterHints, InlayFieldsToResolve};
|
||||||
|
|
||||||
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
||||||
discriminant_hints: DiscriminantHints::Never,
|
discriminant_hints: DiscriminantHints::Never,
|
||||||
render_colons: false,
|
render_colons: false,
|
||||||
type_hints: false,
|
type_hints: false,
|
||||||
parameter_hints: false,
|
parameter_hints: false,
|
||||||
|
generic_parameter_hints: GenericParameterHints {
|
||||||
|
type_hints: false,
|
||||||
|
lifetime_hints: false,
|
||||||
|
const_hints: false,
|
||||||
|
},
|
||||||
chaining_hints: false,
|
chaining_hints: false,
|
||||||
lifetime_elision_hints: LifetimeElisionHints::Never,
|
lifetime_elision_hints: LifetimeElisionHints::Never,
|
||||||
closure_return_type_hints: ClosureReturnTypeHints::Never,
|
closure_return_type_hints: ClosureReturnTypeHints::Never,
|
||||||
|
|
315
crates/ide/src/inlay_hints/generic_param.rs
Normal file
315
crates/ide/src/inlay_hints/generic_param.rs
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
//! Implementation of inlay hints for generic parameters.
|
||||||
|
use ide_db::{active_parameter::generic_def_for_node, RootDatabase};
|
||||||
|
use syntax::{
|
||||||
|
ast::{self, AnyHasGenericArgs, HasGenericArgs, HasName},
|
||||||
|
AstNode,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{inlay_hints::GenericParameterHints, InlayHint, InlayHintsConfig, InlayKind};
|
||||||
|
|
||||||
|
use super::param_name::{is_argument_similar_to_param_name, render_label};
|
||||||
|
|
||||||
|
pub(crate) fn hints(
|
||||||
|
acc: &mut Vec<InlayHint>,
|
||||||
|
sema: &hir::Semantics<'_, RootDatabase>,
|
||||||
|
config: &InlayHintsConfig,
|
||||||
|
node: AnyHasGenericArgs,
|
||||||
|
) -> Option<()> {
|
||||||
|
let GenericParameterHints { type_hints, lifetime_hints, const_hints } =
|
||||||
|
config.generic_parameter_hints;
|
||||||
|
if !(type_hints || lifetime_hints || const_hints) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let generic_arg_list = node.generic_arg_list()?;
|
||||||
|
|
||||||
|
let (generic_def, _, _, _) =
|
||||||
|
generic_def_for_node(sema, &generic_arg_list, &node.syntax().first_token()?)?;
|
||||||
|
|
||||||
|
let mut args = generic_arg_list.generic_args().peekable();
|
||||||
|
let start_with_lifetime = matches!(args.peek()?, ast::GenericArg::LifetimeArg(_));
|
||||||
|
let params = generic_def.params(sema.db).into_iter().filter(|p| {
|
||||||
|
if let hir::GenericParam::TypeParam(it) = p {
|
||||||
|
if it.is_implicit(sema.db) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !start_with_lifetime {
|
||||||
|
return !matches!(p, hir::GenericParam::LifetimeParam(_));
|
||||||
|
}
|
||||||
|
true
|
||||||
|
});
|
||||||
|
|
||||||
|
let hints = params.zip(args).filter_map(|(param, arg)| {
|
||||||
|
if matches!(arg, ast::GenericArg::AssocTypeArg(_)) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = param.name(sema.db);
|
||||||
|
let param_name = name.as_str()?;
|
||||||
|
|
||||||
|
let should_hide = {
|
||||||
|
let argument = get_string_representation(&arg)?;
|
||||||
|
is_argument_similar_to_param_name(&argument, param_name)
|
||||||
|
};
|
||||||
|
|
||||||
|
if should_hide {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let range = sema.original_range_opt(arg.syntax())?.range;
|
||||||
|
|
||||||
|
let source_syntax = match param {
|
||||||
|
hir::GenericParam::TypeParam(it) => {
|
||||||
|
if !type_hints || !matches!(arg, ast::GenericArg::TypeArg(_)) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
sema.source(it.merge())?.value.syntax().clone()
|
||||||
|
}
|
||||||
|
hir::GenericParam::ConstParam(it) => {
|
||||||
|
if !const_hints || !matches!(arg, ast::GenericArg::ConstArg(_)) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let syntax = sema.source(it.merge())?.value.syntax().clone();
|
||||||
|
let const_param = ast::ConstParam::cast(syntax)?;
|
||||||
|
const_param.name()?.syntax().clone()
|
||||||
|
}
|
||||||
|
hir::GenericParam::LifetimeParam(it) => {
|
||||||
|
if !lifetime_hints || !matches!(arg, ast::GenericArg::LifetimeArg(_)) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
sema.source(it)?.value.syntax().clone()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let linked_location = sema.original_range_opt(&source_syntax);
|
||||||
|
let label = render_label(param_name, config, linked_location);
|
||||||
|
|
||||||
|
Some(InlayHint {
|
||||||
|
range,
|
||||||
|
position: crate::InlayHintPosition::Before,
|
||||||
|
pad_left: false,
|
||||||
|
pad_right: true,
|
||||||
|
kind: InlayKind::GenericParameter,
|
||||||
|
label,
|
||||||
|
text_edit: None,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
acc.extend(hints);
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_string_representation(arg: &ast::GenericArg) -> Option<String> {
|
||||||
|
return match arg {
|
||||||
|
ast::GenericArg::AssocTypeArg(_) => None,
|
||||||
|
ast::GenericArg::ConstArg(const_arg) => Some(const_arg.to_string()),
|
||||||
|
ast::GenericArg::LifetimeArg(lifetime_arg) => {
|
||||||
|
let lifetime = lifetime_arg.lifetime()?;
|
||||||
|
Some(lifetime.to_string())
|
||||||
|
}
|
||||||
|
ast::GenericArg::TypeArg(type_arg) => {
|
||||||
|
let ty = type_arg.ty()?;
|
||||||
|
Some(
|
||||||
|
type_path_segment(&ty)
|
||||||
|
.map_or_else(|| type_arg.to_string(), |segment| segment.to_string()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn type_path_segment(ty: &ast::Type) -> Option<ast::PathSegment> {
|
||||||
|
match ty {
|
||||||
|
ast::Type::ArrayType(it) => type_path_segment(&it.ty()?),
|
||||||
|
ast::Type::ForType(it) => type_path_segment(&it.ty()?),
|
||||||
|
ast::Type::ParenType(it) => type_path_segment(&it.ty()?),
|
||||||
|
ast::Type::PathType(path_type) => path_type.path()?.segment(),
|
||||||
|
ast::Type::PtrType(it) => type_path_segment(&it.ty()?),
|
||||||
|
ast::Type::RefType(it) => type_path_segment(&it.ty()?),
|
||||||
|
ast::Type::SliceType(it) => type_path_segment(&it.ty()?),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{
|
||||||
|
inlay_hints::{
|
||||||
|
tests::{check_with_config, DISABLED_CONFIG},
|
||||||
|
GenericParameterHints,
|
||||||
|
},
|
||||||
|
InlayHintsConfig,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn generic_param_name_hints_always(ra_fixture: &str) {
|
||||||
|
check_with_config(
|
||||||
|
InlayHintsConfig {
|
||||||
|
generic_parameter_hints: GenericParameterHints {
|
||||||
|
type_hints: true,
|
||||||
|
lifetime_hints: true,
|
||||||
|
const_hints: true,
|
||||||
|
},
|
||||||
|
..DISABLED_CONFIG
|
||||||
|
},
|
||||||
|
ra_fixture,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn generic_param_name_hints_const_only(ra_fixture: &str) {
|
||||||
|
check_with_config(
|
||||||
|
InlayHintsConfig {
|
||||||
|
generic_parameter_hints: GenericParameterHints {
|
||||||
|
type_hints: false,
|
||||||
|
lifetime_hints: false,
|
||||||
|
const_hints: true,
|
||||||
|
},
|
||||||
|
..DISABLED_CONFIG
|
||||||
|
},
|
||||||
|
ra_fixture,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_only() {
|
||||||
|
generic_param_name_hints_always(
|
||||||
|
r#"
|
||||||
|
struct A<X, Y> {
|
||||||
|
x: X,
|
||||||
|
y: Y,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(a: A<usize, u32>) {}
|
||||||
|
//^^^^^ X ^^^ Y
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lifetime_and_type() {
|
||||||
|
generic_param_name_hints_always(
|
||||||
|
r#"
|
||||||
|
struct A<'a, X> {
|
||||||
|
x: &'a X
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<'b>(a: A<'b, u32>) {}
|
||||||
|
//^^ 'a^^^ X
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn omit_lifetime() {
|
||||||
|
generic_param_name_hints_always(
|
||||||
|
r#"
|
||||||
|
struct A<'a, X> {
|
||||||
|
x: &'a X
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() {
|
||||||
|
let x: i32 = 1;
|
||||||
|
let a: A<i32> = A { x: &x };
|
||||||
|
// ^^^ X
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn const_only() {
|
||||||
|
generic_param_name_hints_always(
|
||||||
|
r#"
|
||||||
|
struct A<const X: usize, const Y: usize> {};
|
||||||
|
|
||||||
|
fn foo(a: A<12, 2>) {}
|
||||||
|
//^^ X^ Y
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lifetime_and_type_and_const() {
|
||||||
|
generic_param_name_hints_always(
|
||||||
|
r#"
|
||||||
|
struct A<'a, X, const LEN: usize> {
|
||||||
|
x: &'a [X; LEN],
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<'b>(a: A<
|
||||||
|
'b,
|
||||||
|
// ^^ 'a
|
||||||
|
u32,
|
||||||
|
// ^^^ X
|
||||||
|
3
|
||||||
|
// ^ LEN
|
||||||
|
>) {}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn const_only_config() {
|
||||||
|
generic_param_name_hints_const_only(
|
||||||
|
r#"
|
||||||
|
struct A<'a, X, const LEN: usize> {
|
||||||
|
x: &'a [X; LEN],
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<'b>(a: A<
|
||||||
|
'b,
|
||||||
|
u32,
|
||||||
|
3
|
||||||
|
// ^ LEN
|
||||||
|
>) {}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assoc_type() {
|
||||||
|
generic_param_name_hints_always(
|
||||||
|
r#"
|
||||||
|
trait Trait<T> {
|
||||||
|
type Assoc1;
|
||||||
|
type Assoc2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() -> impl Trait<i32, Assoc1 = u32, Assoc2 = u32> {}
|
||||||
|
// ^^^ T
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hide_similar() {
|
||||||
|
generic_param_name_hints_always(
|
||||||
|
r#"
|
||||||
|
struct A<'a, X, const N: usize> {
|
||||||
|
x: &'a [X; N],
|
||||||
|
}
|
||||||
|
|
||||||
|
const N: usize = 3;
|
||||||
|
|
||||||
|
mod m {
|
||||||
|
type X = u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<'a>(a: A<'a, m::X, N>) {}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mismatching_args() {
|
||||||
|
generic_param_name_hints_always(
|
||||||
|
r#"
|
||||||
|
struct A<X, const N: usize> {
|
||||||
|
x: [X; N]
|
||||||
|
}
|
||||||
|
|
||||||
|
type InvalidType = A<3, i32>;
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
//! fn max(x: i32, y: i32) -> i32 { x + y }
|
//! fn max(x: i32, y: i32) -> i32 { x + y }
|
||||||
//! _ = max(/*x*/4, /*y*/4);
|
//! _ = max(/*x*/4, /*y*/4);
|
||||||
//! ```
|
//! ```
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{Callable, Semantics};
|
use hir::{Callable, Semantics};
|
||||||
use ide_db::{base_db::FileRange, RootDatabase};
|
use ide_db::{base_db::FileRange, RootDatabase};
|
||||||
|
@ -46,9 +48,7 @@ pub(super) fn hints(
|
||||||
.map(|(param, param_name, _, FileRange { range, .. })| {
|
.map(|(param, param_name, _, FileRange { range, .. })| {
|
||||||
let linked_location = param.and_then(|name| sema.original_range_opt(name.syntax()));
|
let linked_location = param.and_then(|name| sema.original_range_opt(name.syntax()));
|
||||||
|
|
||||||
let colon = if config.render_colons { ":" } else { "" };
|
let label = render_label(¶m_name, config, linked_location);
|
||||||
let label =
|
|
||||||
InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location);
|
|
||||||
InlayHint {
|
InlayHint {
|
||||||
range,
|
range,
|
||||||
kind: InlayKind::Parameter,
|
kind: InlayKind::Parameter,
|
||||||
|
@ -64,6 +64,16 @@ pub(super) fn hints(
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn render_label(
|
||||||
|
param_name: impl Display,
|
||||||
|
config: &InlayHintsConfig,
|
||||||
|
linked_location: Option<FileRange>,
|
||||||
|
) -> InlayHintLabel {
|
||||||
|
let colon = if config.render_colons { ":" } else { "" };
|
||||||
|
|
||||||
|
InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_callable(
|
fn get_callable(
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
|
@ -113,7 +123,7 @@ fn should_hide_param_name_hint(
|
||||||
};
|
};
|
||||||
let fn_name = fn_name.as_deref();
|
let fn_name = fn_name.as_deref();
|
||||||
is_param_name_suffix_of_fn_name(param_name, callable, fn_name)
|
is_param_name_suffix_of_fn_name(param_name, callable, fn_name)
|
||||||
|| is_argument_similar_to_param_name(argument, param_name)
|
|| is_argument_expr_similar_to_param_name(argument, param_name)
|
||||||
|| param_name.starts_with("ra_fixture")
|
|| param_name.starts_with("ra_fixture")
|
||||||
|| (callable.n_params() == 1 && is_obvious_param(param_name))
|
|| (callable.n_params() == 1 && is_obvious_param(param_name))
|
||||||
|| is_adt_constructor_similar_to_param_name(sema, argument, param_name)
|
|| is_adt_constructor_similar_to_param_name(sema, argument, param_name)
|
||||||
|
@ -143,14 +153,17 @@ fn is_param_name_suffix_of_fn_name(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_argument_similar_to_param_name(argument: &ast::Expr, param_name: &str) -> bool {
|
fn is_argument_expr_similar_to_param_name(argument: &ast::Expr, param_name: &str) -> bool {
|
||||||
// check whether param_name and argument are the same or
|
|
||||||
// whether param_name is a prefix/suffix of argument(split at `_`)
|
|
||||||
let argument = match get_string_representation(argument) {
|
let argument = match get_string_representation(argument) {
|
||||||
Some(argument) => argument,
|
Some(argument) => argument,
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
is_argument_similar_to_param_name(&argument, param_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether param_name and argument are the same or
|
||||||
|
/// whether param_name is a prefix/suffix of argument(split at `_`).
|
||||||
|
pub(super) fn is_argument_similar_to_param_name(argument: &str, param_name: &str) -> bool {
|
||||||
// std is honestly too panic happy...
|
// std is honestly too panic happy...
|
||||||
let str_split_at = |str: &str, at| str.is_char_boundary(at).then(|| argument.split_at(at));
|
let str_split_at = |str: &str, at| str.is_char_boundary(at).then(|| argument.split_at(at));
|
||||||
|
|
||||||
|
|
|
@ -89,8 +89,8 @@ pub use crate::{
|
||||||
},
|
},
|
||||||
inlay_hints::{
|
inlay_hints::{
|
||||||
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
|
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
|
||||||
InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintPosition,
|
GenericParameterHints, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart,
|
||||||
InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
|
InlayHintPosition, InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
|
||||||
},
|
},
|
||||||
join_lines::JoinLinesConfig,
|
join_lines::JoinLinesConfig,
|
||||||
markup::Markup,
|
markup::Markup,
|
||||||
|
|
|
@ -131,6 +131,11 @@ impl StaticIndex<'_> {
|
||||||
discriminant_hints: crate::DiscriminantHints::Fieldless,
|
discriminant_hints: crate::DiscriminantHints::Fieldless,
|
||||||
type_hints: true,
|
type_hints: true,
|
||||||
parameter_hints: true,
|
parameter_hints: true,
|
||||||
|
generic_parameter_hints: crate::GenericParameterHints {
|
||||||
|
type_hints: false,
|
||||||
|
lifetime_hints: false,
|
||||||
|
const_hints: true,
|
||||||
|
},
|
||||||
chaining_hints: true,
|
chaining_hints: true,
|
||||||
closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock,
|
closure_return_type_hints: crate::ClosureReturnTypeHints::WithBlock,
|
||||||
lifetime_elision_hints: crate::LifetimeElisionHints::Never,
|
lifetime_elision_hints: crate::LifetimeElisionHints::Never,
|
||||||
|
|
|
@ -1008,6 +1008,11 @@ impl flags::AnalysisStats {
|
||||||
type_hints: true,
|
type_hints: true,
|
||||||
discriminant_hints: ide::DiscriminantHints::Always,
|
discriminant_hints: ide::DiscriminantHints::Always,
|
||||||
parameter_hints: true,
|
parameter_hints: true,
|
||||||
|
generic_parameter_hints: ide::GenericParameterHints {
|
||||||
|
type_hints: true,
|
||||||
|
lifetime_hints: true,
|
||||||
|
const_hints: true,
|
||||||
|
},
|
||||||
chaining_hints: true,
|
chaining_hints: true,
|
||||||
adjustment_hints: ide::AdjustmentHints::Always,
|
adjustment_hints: ide::AdjustmentHints::Always,
|
||||||
adjustment_hints_mode: ide::AdjustmentHintsMode::Postfix,
|
adjustment_hints_mode: ide::AdjustmentHintsMode::Postfix,
|
||||||
|
|
|
@ -10,9 +10,9 @@ use dirs::config_dir;
|
||||||
use flycheck::{CargoOptions, FlycheckConfig};
|
use flycheck::{CargoOptions, FlycheckConfig};
|
||||||
use ide::{
|
use ide::{
|
||||||
AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode,
|
AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode,
|
||||||
HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve,
|
GenericParameterHints, HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat,
|
||||||
InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind,
|
InlayFieldsToResolve, InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig,
|
||||||
Snippet, SnippetScope, SourceRootId,
|
MemoryLayoutHoverRenderKind, Snippet, SnippetScope, SourceRootId,
|
||||||
};
|
};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
|
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
|
||||||
|
@ -509,6 +509,12 @@ config_data! {
|
||||||
inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = false,
|
inlayHints_expressionAdjustmentHints_hideOutsideUnsafe: bool = false,
|
||||||
/// Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
|
/// Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
|
||||||
inlayHints_expressionAdjustmentHints_mode: AdjustmentHintsModeDef = AdjustmentHintsModeDef::Prefix,
|
inlayHints_expressionAdjustmentHints_mode: AdjustmentHintsModeDef = AdjustmentHintsModeDef::Prefix,
|
||||||
|
/// Whether to show const generic parameter name inlay hints.
|
||||||
|
inlayHints_genericParameterHints_const_enable: bool= false,
|
||||||
|
/// Whether to show generic lifetime parameter name inlay hints.
|
||||||
|
inlayHints_genericParameterHints_lifetime_enable: bool = true,
|
||||||
|
/// Whether to show generic type parameter name inlay hints.
|
||||||
|
inlayHints_genericParameterHints_type_enable: bool = false,
|
||||||
/// Whether to show implicit drop hints.
|
/// Whether to show implicit drop hints.
|
||||||
inlayHints_implicitDrops_enable: bool = false,
|
inlayHints_implicitDrops_enable: bool = false,
|
||||||
/// Whether to show inlay type hints for elided lifetimes in function signatures.
|
/// Whether to show inlay type hints for elided lifetimes in function signatures.
|
||||||
|
@ -1391,6 +1397,11 @@ impl Config {
|
||||||
render_colons: self.inlayHints_renderColons().to_owned(),
|
render_colons: self.inlayHints_renderColons().to_owned(),
|
||||||
type_hints: self.inlayHints_typeHints_enable().to_owned(),
|
type_hints: self.inlayHints_typeHints_enable().to_owned(),
|
||||||
parameter_hints: self.inlayHints_parameterHints_enable().to_owned(),
|
parameter_hints: self.inlayHints_parameterHints_enable().to_owned(),
|
||||||
|
generic_parameter_hints: GenericParameterHints {
|
||||||
|
type_hints: self.inlayHints_genericParameterHints_type_enable().to_owned(),
|
||||||
|
lifetime_hints: self.inlayHints_genericParameterHints_lifetime_enable().to_owned(),
|
||||||
|
const_hints: self.inlayHints_genericParameterHints_const_enable().to_owned(),
|
||||||
|
},
|
||||||
chaining_hints: self.inlayHints_chainingHints_enable().to_owned(),
|
chaining_hints: self.inlayHints_chainingHints_enable().to_owned(),
|
||||||
discriminant_hints: match self.inlayHints_discriminantHints_enable() {
|
discriminant_hints: match self.inlayHints_discriminantHints_enable() {
|
||||||
DiscriminantHintsDef::Always => ide::DiscriminantHints::Always,
|
DiscriminantHintsDef::Always => ide::DiscriminantHints::Always,
|
||||||
|
@ -2874,6 +2885,19 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
|
||||||
"Only show discriminant hints on fieldless enum variants."
|
"Only show discriminant hints on fieldless enum variants."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"GenericParameterHintsDef" => set! {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"always",
|
||||||
|
"never",
|
||||||
|
"const_only"
|
||||||
|
],
|
||||||
|
"enumDescriptions": [
|
||||||
|
"Always show generic parameter hints.",
|
||||||
|
"Never show generic parameter hints.",
|
||||||
|
"Only show const generic parameter hints."
|
||||||
|
]
|
||||||
|
},
|
||||||
"AdjustmentHintsModeDef" => set! {
|
"AdjustmentHintsModeDef" => set! {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
|
|
@ -501,7 +501,9 @@ pub(crate) fn inlay_hint(
|
||||||
padding_left: Some(inlay_hint.pad_left),
|
padding_left: Some(inlay_hint.pad_left),
|
||||||
padding_right: Some(inlay_hint.pad_right),
|
padding_right: Some(inlay_hint.pad_right),
|
||||||
kind: match inlay_hint.kind {
|
kind: match inlay_hint.kind {
|
||||||
InlayKind::Parameter => Some(lsp_types::InlayHintKind::PARAMETER),
|
InlayKind::Parameter | InlayKind::GenericParameter => {
|
||||||
|
Some(lsp_types::InlayHintKind::PARAMETER)
|
||||||
|
}
|
||||||
InlayKind::Type | InlayKind::Chaining => Some(lsp_types::InlayHintKind::TYPE),
|
InlayKind::Type | InlayKind::Chaining => Some(lsp_types::InlayHintKind::TYPE),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
|
|
@ -655,6 +655,21 @@ Whether to hide inlay hints for type adjustments outside of `unsafe` blocks.
|
||||||
--
|
--
|
||||||
Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
|
Whether to show inlay hints as postfix ops (`.*` instead of `*`, etc).
|
||||||
--
|
--
|
||||||
|
[[rust-analyzer.inlayHints.genericParameterHints.const.enable]]rust-analyzer.inlayHints.genericParameterHints.const.enable (default: `false`)::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
Whether to show const generic parameter name inlay hints.
|
||||||
|
--
|
||||||
|
[[rust-analyzer.inlayHints.genericParameterHints.lifetime.enable]]rust-analyzer.inlayHints.genericParameterHints.lifetime.enable (default: `true`)::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
Whether to show generic lifetime parameter name inlay hints.
|
||||||
|
--
|
||||||
|
[[rust-analyzer.inlayHints.genericParameterHints.type.enable]]rust-analyzer.inlayHints.genericParameterHints.type.enable (default: `false`)::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
Whether to show generic type parameter name inlay hints.
|
||||||
|
--
|
||||||
[[rust-analyzer.inlayHints.implicitDrops.enable]]rust-analyzer.inlayHints.implicitDrops.enable (default: `false`)::
|
[[rust-analyzer.inlayHints.implicitDrops.enable]]rust-analyzer.inlayHints.implicitDrops.enable (default: `false`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
|
|
|
@ -1909,6 +1909,36 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "inlayHints",
|
||||||
|
"properties": {
|
||||||
|
"rust-analyzer.inlayHints.genericParameterHints.const.enable": {
|
||||||
|
"markdownDescription": "Whether to show const generic parameter name inlay hints.",
|
||||||
|
"default": false,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "inlayHints",
|
||||||
|
"properties": {
|
||||||
|
"rust-analyzer.inlayHints.genericParameterHints.lifetime.enable": {
|
||||||
|
"markdownDescription": "Whether to show generic lifetime parameter name inlay hints.",
|
||||||
|
"default": true,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "inlayHints",
|
||||||
|
"properties": {
|
||||||
|
"rust-analyzer.inlayHints.genericParameterHints.type.enable": {
|
||||||
|
"markdownDescription": "Whether to show generic type parameter name inlay hints.",
|
||||||
|
"default": false,
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "inlayHints",
|
"title": "inlayHints",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
Loading…
Reference in a new issue