mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
153 lines
4.4 KiB
Rust
153 lines
4.4 KiB
Rust
//! Implementation of trait bound hints.
|
|
//!
|
|
//! Currently this renders the implied `Sized` bound.
|
|
use ide_db::{famous_defs::FamousDefs, FileRange};
|
|
|
|
use span::EditionedFileId;
|
|
use syntax::ast::{self, AstNode, HasTypeBounds};
|
|
|
|
use crate::{
|
|
InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintPosition, InlayHintsConfig, InlayKind,
|
|
TryToNav,
|
|
};
|
|
|
|
pub(super) fn hints(
|
|
acc: &mut Vec<InlayHint>,
|
|
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
|
|
config: &InlayHintsConfig,
|
|
_file_id: EditionedFileId,
|
|
params: ast::GenericParamList,
|
|
) -> Option<()> {
|
|
if !config.sized_bound {
|
|
return None;
|
|
}
|
|
|
|
let linked_location =
|
|
famous_defs.core_marker_Sized().and_then(|it| it.try_to_nav(sema.db)).map(|it| {
|
|
let n = it.call_site();
|
|
FileRange { file_id: n.file_id, range: n.focus_or_full_range() }
|
|
});
|
|
|
|
for param in params.type_or_const_params() {
|
|
match param {
|
|
ast::TypeOrConstParam::Type(type_param) => {
|
|
let c = type_param.colon_token().map(|it| it.text_range());
|
|
let has_bounds =
|
|
type_param.type_bound_list().is_some_and(|it| it.bounds().next().is_some());
|
|
acc.push(InlayHint {
|
|
range: c.unwrap_or_else(|| type_param.syntax().text_range()),
|
|
kind: InlayKind::Type,
|
|
label: {
|
|
let mut hint = InlayHintLabel::default();
|
|
if c.is_none() {
|
|
hint.parts.push(InlayHintLabelPart {
|
|
text: ": ".to_owned(),
|
|
linked_location: None,
|
|
tooltip: None,
|
|
});
|
|
}
|
|
hint.parts.push(InlayHintLabelPart {
|
|
text: "Sized".to_owned(),
|
|
linked_location,
|
|
tooltip: None,
|
|
});
|
|
if has_bounds {
|
|
hint.parts.push(InlayHintLabelPart {
|
|
text: " +".to_owned(),
|
|
linked_location: None,
|
|
tooltip: None,
|
|
});
|
|
}
|
|
hint
|
|
},
|
|
text_edit: None,
|
|
position: InlayHintPosition::After,
|
|
pad_left: c.is_some(),
|
|
pad_right: has_bounds,
|
|
resolve_parent: Some(params.syntax().text_range()),
|
|
});
|
|
}
|
|
ast::TypeOrConstParam::Const(_) => (),
|
|
}
|
|
}
|
|
|
|
Some(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use expect_test::expect;
|
|
|
|
use crate::inlay_hints::InlayHintsConfig;
|
|
|
|
use crate::inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG};
|
|
|
|
#[track_caller]
|
|
fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
|
|
check_with_config(InlayHintsConfig { sized_bound: true, ..DISABLED_CONFIG }, ra_fixture);
|
|
}
|
|
|
|
#[test]
|
|
fn smoke() {
|
|
check(
|
|
r#"
|
|
fn foo<T>() {}
|
|
// ^ : Sized
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn with_colon() {
|
|
check(
|
|
r#"
|
|
fn foo<T:>() {}
|
|
// ^ Sized
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn with_colon_and_bounds() {
|
|
check(
|
|
r#"
|
|
fn foo<T: 'static>() {}
|
|
// ^ Sized +
|
|
"#,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn location_works() {
|
|
check_expect(
|
|
InlayHintsConfig { sized_bound: true, ..DISABLED_CONFIG },
|
|
r#"
|
|
//- minicore: sized
|
|
fn foo<T>() {}
|
|
"#,
|
|
expect![[r#"
|
|
[
|
|
(
|
|
7..8,
|
|
[
|
|
": ",
|
|
InlayHintLabelPart {
|
|
text: "Sized",
|
|
linked_location: Some(
|
|
FileRangeWrapper {
|
|
file_id: FileId(
|
|
1,
|
|
),
|
|
range: 135..140,
|
|
},
|
|
),
|
|
tooltip: "",
|
|
},
|
|
],
|
|
),
|
|
]
|
|
"#]],
|
|
);
|
|
}
|
|
}
|