Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/ide/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pulldown-cmark-to-cmark = "10.0.4"
pulldown-cmark = { version = "0.9.1", default-features = false }
url = "2.3.1"
dot = "0.1.4"
smallvec = "1.10.0"

stdx = { path = "../stdx", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }
Expand Down
117 changes: 76 additions & 41 deletions crates/ide/src/inlay_hints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ use either::Either;
use hir::{known, HasVisibility, HirDisplay, HirWrite, ModuleDef, ModuleDefId, Semantics};
use ide_db::{base_db::FileRange, famous_defs::FamousDefs, RootDatabase};
use itertools::Itertools;
use smallvec::{smallvec, SmallVec};
use stdx::never;
use syntax::{
ast::{self, AstNode},
match_ast, NodeOrToken, SyntaxNode, TextRange, TextSize,
match_ast, NodeOrToken, SyntaxNode, TextRange,
};

use crate::{navigation_target::TryToNav, FileId};
Expand Down Expand Up @@ -83,75 +84,108 @@ pub enum AdjustmentHintsMode {
PreferPostfix,
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InlayKind {
BindingModeHint,
ChainingHint,
ClosingBraceHint,
ClosureReturnTypeHint,
GenericParamListHint,
AdjustmentHint,
AdjustmentHintPostfix,
LifetimeHint,
ParameterHint,
TypeHint,
DiscriminantHint,
BindingMode,
Chaining,
ClosingBrace,
ClosureReturnType,
GenericParamList,
Adjustment,
AdjustmentPostfix,
Lifetime,
Parameter,
Type,
Discriminant,
OpeningParenthesis,
ClosingParenthesis,
}

#[derive(Debug)]
pub struct InlayHint {
/// The text range this inlay hint applies to.
pub range: TextRange,
/// The kind of this inlay hint. This is used to determine side and padding of the hint for
/// rendering purposes.
pub kind: InlayKind,
/// The actual label to show in the inlay hint.
pub label: InlayHintLabel,
pub tooltip: Option<InlayTooltip>,
}

impl InlayHint {
fn closing_paren(range: TextRange) -> InlayHint {
InlayHint { range, kind: InlayKind::ClosingParenthesis, label: InlayHintLabel::from(")") }
}
fn opening_paren(range: TextRange) -> InlayHint {
InlayHint { range, kind: InlayKind::OpeningParenthesis, label: InlayHintLabel::from("(") }
}
}

#[derive(Debug)]
pub enum InlayTooltip {
String(String),
HoverRanged(FileId, TextRange),
HoverOffset(FileId, TextSize),
Markdown(String),
}

#[derive(Default)]
pub struct InlayHintLabel {
pub parts: Vec<InlayHintLabelPart>,
pub parts: SmallVec<[InlayHintLabelPart; 1]>,
}

impl InlayHintLabel {
pub fn as_simple_str(&self) -> Option<&str> {
match &*self.parts {
[part] => part.as_simple_str(),
_ => None,
pub fn simple(
s: impl Into<String>,
tooltip: Option<InlayTooltip>,
linked_location: Option<FileRange>,
) -> InlayHintLabel {
InlayHintLabel {
parts: smallvec![InlayHintLabelPart { text: s.into(), linked_location, tooltip }],
}
}

pub fn prepend_str(&mut self, s: &str) {
match &mut *self.parts {
[part, ..] if part.as_simple_str().is_some() => part.text = format!("{s}{}", part.text),
_ => self.parts.insert(0, InlayHintLabelPart { text: s.into(), linked_location: None }),
[InlayHintLabelPart { text, linked_location: None, tooltip: None }, ..] => {
text.insert_str(0, s)
}
_ => self.parts.insert(
0,
InlayHintLabelPart { text: s.into(), linked_location: None, tooltip: None },
),
}
}

pub fn append_str(&mut self, s: &str) {
match &mut *self.parts {
[.., part] if part.as_simple_str().is_some() => part.text.push_str(s),
_ => self.parts.push(InlayHintLabelPart { text: s.into(), linked_location: None }),
[.., InlayHintLabelPart { text, linked_location: None, tooltip: None }] => {
text.push_str(s)
}
_ => self.parts.push(InlayHintLabelPart {
text: s.into(),
linked_location: None,
tooltip: None,
}),
}
}
}

impl From<String> for InlayHintLabel {
fn from(s: String) -> Self {
Self { parts: vec![InlayHintLabelPart { text: s, linked_location: None }] }
Self {
parts: smallvec![InlayHintLabelPart { text: s, linked_location: None, tooltip: None }],
}
}
}

impl From<&str> for InlayHintLabel {
fn from(s: &str) -> Self {
Self { parts: vec![InlayHintLabelPart { text: s.into(), linked_location: None }] }
Self {
parts: smallvec![InlayHintLabelPart {
text: s.into(),
linked_location: None,
tooltip: None
}],
}
}
}

Expand All @@ -175,25 +209,25 @@ pub struct InlayHintLabelPart {
/// When setting this, no tooltip must be set on the containing hint, or VS Code will display
/// them both.
pub linked_location: Option<FileRange>,
}

impl InlayHintLabelPart {
pub fn as_simple_str(&self) -> Option<&str> {
match self {
Self { text, linked_location: None } => Some(text),
_ => None,
}
}
/// The tooltip to show when hovering over the inlay hint, this may invoke other actions like
/// hover requests to show.
pub tooltip: Option<InlayTooltip>,
}

impl fmt::Debug for InlayHintLabelPart {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.as_simple_str() {
Some(string) => string.fmt(f),
None => f
match self {
Self { text, linked_location: None, tooltip: None } => text.fmt(f),
Self { text, linked_location, tooltip } => f
.debug_struct("InlayHintLabelPart")
.field("text", &self.text)
.field("linked_location", &self.linked_location)
.field("text", text)
.field("linked_location", linked_location)
.field(
"tooltip",
&tooltip.as_ref().map_or("", |it| match it {
InlayTooltip::String(it) | InlayTooltip::Markdown(it) => it,
}),
)
.finish(),
}
}
Expand Down Expand Up @@ -242,6 +276,7 @@ impl InlayHintLabelBuilder<'_> {
self.result.parts.push(InlayHintLabelPart {
text: take(&mut self.last_part),
linked_location: self.location.take(),
tooltip: None,
});
}

Expand Down
49 changes: 7 additions & 42 deletions crates/ide/src/inlay_hints/adjustment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,12 @@ pub(super) fn hints(
mode_and_needs_parens_for_adjustment_hints(expr, config.adjustment_hints_mode);

if needs_outer_parens {
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: InlayKind::OpeningParenthesis,
label: "(".into(),
tooltip: None,
});
acc.push(InlayHint::opening_paren(expr.syntax().text_range()));
}

if postfix && needs_inner_parens {
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: InlayKind::OpeningParenthesis,
label: "(".into(),
tooltip: None,
});
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: InlayKind::ClosingParenthesis,
label: ")".into(),
tooltip: None,
});
acc.push(InlayHint::opening_paren(expr.syntax().text_range()));
acc.push(InlayHint::closing_paren(expr.syntax().text_range()));
}

let (mut tmp0, mut tmp1);
Expand Down Expand Up @@ -112,36 +97,16 @@ pub(super) fn hints(
};
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: if postfix {
InlayKind::AdjustmentHintPostfix
} else {
InlayKind::AdjustmentHint
},
kind: if postfix { InlayKind::AdjustmentPostfix } else { InlayKind::Adjustment },
label: if postfix { format!(".{}", text.trim_end()).into() } else { text.into() },
tooltip: None,
});
}
if !postfix && needs_inner_parens {
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: InlayKind::OpeningParenthesis,
label: "(".into(),
tooltip: None,
});
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: InlayKind::ClosingParenthesis,
label: ")".into(),
tooltip: None,
});
acc.push(InlayHint::opening_paren(expr.syntax().text_range()));
acc.push(InlayHint::closing_paren(expr.syntax().text_range()));
}
if needs_outer_parens {
acc.push(InlayHint {
range: expr.syntax().text_range(),
kind: InlayKind::ClosingParenthesis,
label: ")".into(),
tooltip: None,
});
acc.push(InlayHint::closing_paren(expr.syntax().text_range()));
}
Some(())
}
Expand Down
34 changes: 7 additions & 27 deletions crates/ide/src/inlay_hints/bind_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,15 @@ use syntax::{
match_ast,
};

use crate::{
inlay_hints::closure_has_block_body, InlayHint, InlayHintsConfig, InlayKind, InlayTooltip,
};
use crate::{inlay_hints::closure_has_block_body, InlayHint, InlayHintsConfig, InlayKind};

use super::label_of_ty;

pub(super) fn hints(
acc: &mut Vec<InlayHint>,
famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
config: &InlayHintsConfig,
file_id: FileId,
_file_id: FileId,
pat: &ast::IdentPat,
) -> Option<()> {
if !config.type_hints {
Expand Down Expand Up @@ -50,12 +48,8 @@ pub(super) fn hints(
Some(name) => name.syntax().text_range(),
None => pat.syntax().text_range(),
},
kind: InlayKind::TypeHint,
kind: InlayKind::Type,
label,
tooltip: pat
.name()
.map(|it| it.syntax().text_range())
.map(|it| InlayTooltip::HoverRanged(file_id, it)),
});

Some(())
Expand Down Expand Up @@ -322,22 +316,14 @@ fn main(a: SliceIter<'_, Container>) {
[
InlayHint {
range: 484..554,
kind: ChainingHint,
kind: Chaining,
label: [
"impl Iterator<Item = impl Iterator<Item = &&str>>",
],
tooltip: Some(
HoverRanged(
FileId(
0,
),
484..554,
),
),
},
InlayHint {
range: 484..485,
kind: ChainingHint,
kind: Chaining,
label: [
"",
InlayHintLabelPart {
Expand All @@ -350,6 +336,7 @@ fn main(a: SliceIter<'_, Container>) {
range: 289..298,
},
),
tooltip: "",
},
"<",
InlayHintLabelPart {
Expand All @@ -362,17 +349,10 @@ fn main(a: SliceIter<'_, Container>) {
range: 238..247,
},
),
tooltip: "",
},
">",
],
tooltip: Some(
HoverRanged(
FileId(
0,
),
484..485,
),
),
},
]
"#]],
Expand Down
Loading