Auto merge of #15522 - SomeoneToIgnore:resolve-inlay-hints, r=Veykril
Resolve inlay hint data Part of https://github.com/rust-lang/rust-analyzer/issues/13962 Support https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#inlayHint_resolve better, by omitting all inlay hint fields specified in the client hint resolve capabilities. Current list of all capabilities possible to resolve later: ``` "textEdits" "tooltip" "label.tooltip" "label.location" "label.command" ``` and every one specified in the client capabilities is now resolved by r-a, being omitted in the initial response. -------------- When editing `inlay_hints.rs` file around line `457` with no resolve capabilities, I get <details> <summary>resolved json, 10803 characters</summary> ```json {"jsonrpc":"2.0","id":55,"result":[{"position":{"line":477,"character":1},"label":[{"value":"fn inlay_hints","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/ide/src/inlay_hints.rs","range":{"start":{"line":445,"character":14},"end":{"line":445,"character":25}}}}],"paddingLeft":true,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":451,"character":10},"label":[{"value":": "},{"value":"ProfileSpan","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/profile/src/hprof.rs","range":{"start":{"line":85,"character":11},"end":{"line":85,"character":22}}}},{"value":""}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":451,"character":27},"label":[{"value":"label:","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/profile/src/hprof.rs","range":{"start":{"line":60,"character":12},"end":{"line":60,"character":17}}}}],"kind":2,"paddingLeft":false,"paddingRight":true,"data":{"file_id":0}},{"position":{"line":452,"character":12},"label":[{"value":": "},{"value":"Semantics","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/hir/src/semantics.rs","range":{"start":{"line":108,"character":11},"end":{"line":108,"character":20}}}},{"value":"<'_, "},{"value":"RootDatabase","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/ide-db/src/lib.rs","range":{"start":{"line":75,"character":11},"end":{"line":75,"character":23}}}},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":453,"character":12},"label":[{"value":": "},{"value":"SourceFile","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs","range":{"start":{"line":223,"character":11},"end":{"line":223,"character":21}}}},{"value":""}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":454,"character":12},"label":[{"value":": &"},{"value":"SyntaxNode","location":{"uri":"file:///Users/someonetoignore/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rowan-0.15.11/src/api.rs","range":{"start":{"line":15,"character":11},"end":{"line":15,"character":21}}}},{"value":"<"},{"value":"RustLanguage","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/syntax/src/syntax_node.rs","range":{"start":{"line":15,"character":9},"end":{"line":15,"character":21}}}},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":456,"character":12},"label":": i32","kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":458,"character":15},"label":[{"value":": "},{"value":"Vec","location":{"uri":"file:///Users/someonetoignore/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs","range":{"start":{"line":395,"character":11},"end":{"line":395,"character":14}}}},{"value":"<"},{"value":"InlayHint","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/ide/src/inlay_hints.rs","range":{"start":{"line":149,"character":11},"end":{"line":149,"character":20}}}},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":460,"character":21},"label":[{"value":": "},{"value":"SemanticsScope","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/hir/src/semantics.rs","range":{"start":{"line":1651,"character":11},"end":{"line":1651,"character":25}}}},{"value":"<'_>"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":460,"character":36},"label":[{"value":"node:","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/hir/src/semantics.rs","range":{"start":{"line":482,"character":24},"end":{"line":482,"character":28}}}}],"kind":2,"paddingLeft":false,"paddingRight":true,"data":{"file_id":0}},{"position":{"line":461,"character":23},"label":[{"value":": "},{"value":"FamousDefs","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/ide-db/src/famous_defs.rs","range":{"start":{"line":20,"character":11},"end":{"line":20,"character":21}}}},{"value":"<'_, '_>"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":463,"character":17},"label":[{"value":": impl FnMut("},{"value":"SyntaxNode","location":{"uri":"file:///Users/someonetoignore/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rowan-0.15.11/src/api.rs","range":{"start":{"line":15,"character":11},"end":{"line":15,"character":21}}}},{"value":"<"},{"value":"RustLanguage","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/syntax/src/syntax_node.rs","range":{"start":{"line":15,"character":9},"end":{"line":15,"character":21}}}},{"value":">)"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":463,"character":25},"label":[{"value":": "},{"value":"SyntaxNode","location":{"uri":"file:///Users/someonetoignore/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rowan-0.15.11/src/api.rs","range":{"start":{"line":15,"character":11},"end":{"line":15,"character":21}}}},{"value":"<"},{"value":"RustLanguage","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/syntax/src/syntax_node.rs","range":{"start":{"line":15,"character":9},"end":{"line":15,"character":21}}}},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":463,"character":33},"label":[{"value":"hints:","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/ide/src/inlay_hints.rs","range":{"start":{"line":480,"character":4},"end":{"line":480,"character":9}}}}],"kind":2,"paddingLeft":false,"paddingRight":true,"data":{"file_id":0}},{"position":{"line":465,"character":22},"label":[{"value":": "},{"value":"TextRange","location":{"uri":"file:///Users/someonetoignore/.cargo/registry/src/index.crates.io-6f17d22bba15001f/text-size-1.1.0/src/range.rs","range":{"start":{"line":14,"character":11},"end":{"line":14,"character":20}}}},{"value":""}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":467,"character":35},"label":[{"value":": "},{"value":"SyntaxNode","location":{"uri":"file:///Users/someonetoignore/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rowan-0.15.11/src/api.rs","range":{"start":{"line":15,"character":11},"end":{"line":15,"character":21}}}},{"value":"<"},{"value":"RustLanguage","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/syntax/src/syntax_node.rs","range":{"start":{"line":15,"character":9},"end":{"line":15,"character":21}}}},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":469,"character":92},"label":[{"value":"impl "},{"value":"Iterator","location":{"uri":"file:///Users/someonetoignore/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs","range":{"start":{"line":72,"character":10},"end":{"line":72,"character":18}}}},{"value":"<"},{"value":"Item","location":{"uri":"file:///Users/someonetoignore/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs","range":{"start":{"line":76,"character":9},"end":{"line":76,"character":13}}}},{"value":" = "},{"value":"SyntaxNode","location":{"uri":"file:///Users/someonetoignore/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rowan-0.15.11/src/api.rs","range":{"start":{"line":15,"character":11},"end":{"line":15,"character":21}}}},{"value":"<"},{"value":"RustLanguage","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/syntax/src/syntax_node.rs","range":{"start":{"line":15,"character":9},"end":{"line":15,"character":21}}}},{"value":">>"}],"kind":1,"paddingLeft":true,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":468,"character":34},"label":[{"value":"impl "},{"value":"Iterator","location":{"uri":"file:///Users/someonetoignore/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs","range":{"start":{"line":72,"character":10},"end":{"line":72,"character":18}}}},{"value":"<"},{"value":"Item","location":{"uri":"file:///Users/someonetoignore/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs","range":{"start":{"line":76,"character":9},"end":{"line":76,"character":13}}}},{"value":" = "},{"value":"SyntaxNode","location":{"uri":"file:///Users/someonetoignore/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rowan-0.15.11/src/api.rs","range":{"start":{"line":15,"character":11},"end":{"line":15,"character":21}}}},{"value":"<"},{"value":"RustLanguage","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/syntax/src/syntax_node.rs","range":{"start":{"line":15,"character":9},"end":{"line":15,"character":21}}}},{"value":">>"},{"value":""}],"kind":1,"paddingLeft":true,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":467,"character":41},"label":[{"value":""},{"value":"SyntaxNode","location":{"uri":"file:///Users/someonetoignore/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rowan-0.15.11/src/api.rs","range":{"start":{"line":15,"character":11},"end":{"line":15,"character":21}}}},{"value":"<"},{"value":"RustLanguage","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/syntax/src/syntax_node.rs","range":{"start":{"line":15,"character":9},"end":{"line":15,"character":21}}}},{"value":">"}],"kind":1,"paddingLeft":true,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":469,"character":40},"label":" -> bool","kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":469,"character":39},"label":[{"value":": &"},{"value":"SyntaxNode","location":{"uri":"file:///Users/someonetoignore/.cargo/registry/src/index.crates.io-6f17d22bba15001f/rowan-0.15.11/src/api.rs","range":{"start":{"line":15,"character":11},"end":{"line":15,"character":21}}}},{"value":"<"},{"value":"RustLanguage","location":{"uri":"file:///Users/someonetoignore/work/rust-analyzer/crates/syntax/src/syntax_node.rs","range":{"start":{"line":15,"character":9},"end":{"line":15,"character":21}}}},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}}]} ``` </details> for the visible editor range alone, pretty much repeated on every consequent edit. With this patch and all inlay hint resolve capabilities enabled, for the same example I observe quite a footprint reduction: <details> <summary>unresolved json, 4142 characters</summary> ```json {"jsonrpc":"2.0","id":49,"result":[{"position":{"line":477,"character":1},"label":[{"value":"fn inlay_hints"}],"paddingLeft":true,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":451,"character":10},"label":[{"value":": "},{"value":"ProfileSpan"},{"value":""}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":451,"character":27},"label":[{"value":"label:"}],"kind":2,"paddingLeft":false,"paddingRight":true,"data":{"file_id":0}},{"position":{"line":452,"character":12},"label":[{"value":": "},{"value":"Semantics"},{"value":"<'_, "},{"value":"RootDatabase"},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":453,"character":12},"label":[{"value":": "},{"value":"SourceFile"},{"value":""}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":454,"character":12},"label":[{"value":": &"},{"value":"SyntaxNode"},{"value":"<"},{"value":"RustLanguage"},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":456,"character":12},"label":": i32","kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":458,"character":15},"label":[{"value":": "},{"value":"Vec"},{"value":"<"},{"value":"InlayHint"},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":460,"character":21},"label":[{"value":": "},{"value":"SemanticsScope"},{"value":"<'_>"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":460,"character":36},"label":[{"value":"node:"}],"kind":2,"paddingLeft":false,"paddingRight":true,"data":{"file_id":0}},{"position":{"line":461,"character":23},"label":[{"value":": "},{"value":"FamousDefs"},{"value":"<'_, '_>"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":463,"character":17},"label":[{"value":": impl FnMut("},{"value":"SyntaxNode"},{"value":"<"},{"value":"RustLanguage"},{"value":">)"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":463,"character":25},"label":[{"value":": "},{"value":"SyntaxNode"},{"value":"<"},{"value":"RustLanguage"},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":463,"character":33},"label":[{"value":"hints:"}],"kind":2,"paddingLeft":false,"paddingRight":true,"data":{"file_id":0}},{"position":{"line":465,"character":22},"label":[{"value":": "},{"value":"TextRange"},{"value":""}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":467,"character":35},"label":[{"value":": "},{"value":"SyntaxNode"},{"value":"<"},{"value":"RustLanguage"},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":469,"character":92},"label":[{"value":"impl "},{"value":"Iterator"},{"value":"<"},{"value":"Item"},{"value":" = "},{"value":"SyntaxNode"},{"value":"<"},{"value":"RustLanguage"},{"value":">>"}],"kind":1,"paddingLeft":true,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":468,"character":34},"label":[{"value":"impl "},{"value":"Iterator"},{"value":"<"},{"value":"Item"},{"value":" = "},{"value":"SyntaxNode"},{"value":"<"},{"value":"RustLanguage"},{"value":">>"},{"value":""}],"kind":1,"paddingLeft":true,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":467,"character":41},"label":[{"value":""},{"value":"SyntaxNode"},{"value":"<"},{"value":"RustLanguage"},{"value":">"}],"kind":1,"paddingLeft":true,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":469,"character":40},"label":" -> bool","kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}},{"position":{"line":469,"character":39},"label":[{"value":": &"},{"value":"SyntaxNode"},{"value":"<"},{"value":"RustLanguage"},{"value":">"}],"kind":1,"paddingLeft":false,"paddingRight":false,"data":{"file_id":0}}]} ``` </details> with all unresolved parts needing only for navigation, hover or applying the hint edit — dynamic parts that are made after mouse hover or similar events, that resolve the hint data.
This commit is contained in:
commit
70a6cf0ef7
@ -52,6 +52,28 @@ pub struct InlayHintsConfig {
|
||||
pub closure_style: ClosureStyle,
|
||||
pub max_length: Option<usize>,
|
||||
pub closing_brace_hints_min_lines: Option<usize>,
|
||||
pub fields_to_resolve: InlayFieldsToResolve,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct InlayFieldsToResolve {
|
||||
pub resolve_text_edits: bool,
|
||||
pub resolve_hint_tooltip: bool,
|
||||
pub resolve_label_tooltip: bool,
|
||||
pub resolve_label_location: bool,
|
||||
pub resolve_label_command: bool,
|
||||
}
|
||||
|
||||
impl InlayFieldsToResolve {
|
||||
pub const fn empty() -> Self {
|
||||
Self {
|
||||
resolve_text_edits: false,
|
||||
resolve_hint_tooltip: false,
|
||||
resolve_label_tooltip: false,
|
||||
resolve_label_location: false,
|
||||
resolve_label_command: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@ -123,11 +145,13 @@ pub struct InlayHint {
|
||||
pub label: InlayHintLabel,
|
||||
/// Text edit to apply when "accepting" this inlay hint.
|
||||
pub text_edit: Option<TextEdit>,
|
||||
pub needs_resolve: bool,
|
||||
}
|
||||
|
||||
impl InlayHint {
|
||||
fn closing_paren_after(kind: InlayKind, range: TextRange) -> InlayHint {
|
||||
InlayHint {
|
||||
needs_resolve: false,
|
||||
range,
|
||||
kind,
|
||||
label: InlayHintLabel::from(")"),
|
||||
@ -139,6 +163,7 @@ impl InlayHint {
|
||||
}
|
||||
fn opening_paren_before(kind: InlayKind, range: TextRange) -> InlayHint {
|
||||
InlayHint {
|
||||
needs_resolve: false,
|
||||
range,
|
||||
kind,
|
||||
label: InlayHintLabel::from("("),
|
||||
@ -196,6 +221,10 @@ impl InlayHintLabel {
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn needs_resolve(&self) -> bool {
|
||||
self.parts.iter().any(|part| part.linked_location.is_some() || part.tooltip.is_some())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for InlayHintLabel {
|
||||
@ -529,6 +558,7 @@ fn closure_has_block_body(closure: &ast::ClosureExpr) -> bool {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use expect_test::Expect;
|
||||
use hir::ClosureStyle;
|
||||
use itertools::Itertools;
|
||||
@ -538,7 +568,7 @@ mod tests {
|
||||
use crate::DiscriminantHints;
|
||||
use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
|
||||
|
||||
use super::ClosureReturnTypeHints;
|
||||
use super::{ClosureReturnTypeHints, InlayFieldsToResolve};
|
||||
|
||||
pub(super) const DISABLED_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
||||
discriminant_hints: DiscriminantHints::Never,
|
||||
@ -559,6 +589,7 @@ mod tests {
|
||||
param_names_for_lifetime_elision_hints: false,
|
||||
max_length: None,
|
||||
closing_brace_hints_min_lines: None,
|
||||
fields_to_resolve: InlayFieldsToResolve::empty(),
|
||||
};
|
||||
pub(super) const TEST_CONFIG: InlayHintsConfig = InlayHintsConfig {
|
||||
type_hints: true,
|
||||
|
@ -137,21 +137,23 @@ pub(super) fn hints(
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
let label = InlayHintLabel::simple(
|
||||
if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
|
||||
Some(InlayTooltip::Markdown(format!(
|
||||
"`{}` → `{}` ({coercion} coercion)",
|
||||
source.display(sema.db),
|
||||
target.display(sema.db),
|
||||
))),
|
||||
None,
|
||||
);
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: label.needs_resolve(),
|
||||
range: expr.syntax().text_range(),
|
||||
pad_left: false,
|
||||
pad_right: false,
|
||||
position: if postfix { InlayHintPosition::After } else { InlayHintPosition::Before },
|
||||
kind: InlayKind::Adjustment,
|
||||
label: InlayHintLabel::simple(
|
||||
if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() },
|
||||
Some(InlayTooltip::Markdown(format!(
|
||||
"`{}` → `{}` ({coercion} coercion)",
|
||||
source.display(sema.db),
|
||||
target.display(sema.db),
|
||||
))),
|
||||
None,
|
||||
),
|
||||
label,
|
||||
text_edit: None,
|
||||
});
|
||||
}
|
||||
|
@ -99,6 +99,7 @@ pub(super) fn hints(
|
||||
None => pat.syntax().text_range(),
|
||||
};
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: label.needs_resolve() || text_edit.is_some(),
|
||||
range: match type_ascriptable {
|
||||
Some(Some(t)) => text_range.cover(t.text_range()),
|
||||
_ => text_range,
|
||||
|
@ -50,9 +50,10 @@ pub(super) fn hints(
|
||||
_ => return,
|
||||
};
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: false,
|
||||
range,
|
||||
kind: InlayKind::BindingMode,
|
||||
label: r.to_string().into(),
|
||||
label: r.into(),
|
||||
text_edit: None,
|
||||
position: InlayHintPosition::Before,
|
||||
pad_left: false,
|
||||
@ -68,9 +69,10 @@ pub(super) fn hints(
|
||||
hir::BindingMode::Ref(Mutability::Shared) => "ref",
|
||||
};
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: false,
|
||||
range: pat.syntax().text_range(),
|
||||
kind: InlayKind::BindingMode,
|
||||
label: bm.to_string().into(),
|
||||
label: bm.into(),
|
||||
text_edit: None,
|
||||
position: InlayHintPosition::Before,
|
||||
pad_left: false,
|
||||
|
@ -57,10 +57,12 @@ pub(super) fn hints(
|
||||
}
|
||||
}
|
||||
}
|
||||
let label = label_of_ty(famous_defs, config, &ty)?;
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: label.needs_resolve(),
|
||||
range: expr.syntax().text_range(),
|
||||
kind: InlayKind::Chaining,
|
||||
label: label_of_ty(famous_defs, config, &ty)?,
|
||||
label,
|
||||
text_edit: None,
|
||||
position: InlayHintPosition::After,
|
||||
pad_left: true,
|
||||
@ -128,6 +130,7 @@ fn main() {
|
||||
"",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 147..154,
|
||||
@ -152,6 +155,7 @@ fn main() {
|
||||
"",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
@ -221,6 +225,7 @@ fn main() {
|
||||
"",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 143..179,
|
||||
@ -245,6 +250,7 @@ fn main() {
|
||||
"",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
@ -298,6 +304,7 @@ fn main() {
|
||||
"",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 143..179,
|
||||
@ -322,6 +329,7 @@ fn main() {
|
||||
"",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
@ -389,6 +397,7 @@ fn main() {
|
||||
"<i32, bool>>",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 246..265,
|
||||
@ -426,6 +435,7 @@ fn main() {
|
||||
"<i32, bool>>",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
@ -495,6 +505,7 @@ fn main() {
|
||||
" = ()>",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 174..224,
|
||||
@ -532,6 +543,7 @@ fn main() {
|
||||
" = ()>",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 174..206,
|
||||
@ -569,6 +581,7 @@ fn main() {
|
||||
" = ()>",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 174..189,
|
||||
@ -593,6 +606,7 @@ fn main() {
|
||||
"",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
@ -655,6 +669,7 @@ fn main() {
|
||||
],
|
||||
},
|
||||
),
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 145..185,
|
||||
@ -679,6 +694,7 @@ fn main() {
|
||||
"",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 145..168,
|
||||
@ -703,6 +719,7 @@ fn main() {
|
||||
"",
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
InlayHint {
|
||||
range: 222..228,
|
||||
@ -725,6 +742,7 @@ fn main() {
|
||||
},
|
||||
],
|
||||
text_edit: None,
|
||||
needs_resolve: true,
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
|
@ -109,6 +109,7 @@ pub(super) fn hints(
|
||||
|
||||
let linked_location = name_range.map(|range| FileRange { file_id, range });
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: linked_location.is_some(),
|
||||
range: closing_token.text_range(),
|
||||
kind: InlayKind::ClosingBrace,
|
||||
label: InlayHintLabel::simple(label, None, linked_location),
|
||||
|
@ -31,9 +31,10 @@ pub(super) fn hints(
|
||||
let range = closure.syntax().first_token()?.prev_token()?.text_range();
|
||||
let range = TextRange::new(range.end() - TextSize::from(1), range.end());
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: false,
|
||||
range,
|
||||
kind: InlayKind::ClosureCapture,
|
||||
label: InlayHintLabel::simple("move", None, None),
|
||||
label: InlayHintLabel::from("move"),
|
||||
text_edit: None,
|
||||
position: InlayHintPosition::After,
|
||||
pad_left: false,
|
||||
@ -43,6 +44,7 @@ pub(super) fn hints(
|
||||
}
|
||||
};
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: false,
|
||||
range: move_kw_range,
|
||||
kind: InlayKind::ClosureCapture,
|
||||
label: InlayHintLabel::from("("),
|
||||
@ -59,23 +61,25 @@ pub(super) fn hints(
|
||||
// force cache the source file, otherwise sema lookup will potentially panic
|
||||
_ = sema.parse_or_expand(source.file());
|
||||
|
||||
let label = InlayHintLabel::simple(
|
||||
format!(
|
||||
"{}{}",
|
||||
match capture.kind() {
|
||||
hir::CaptureKind::SharedRef => "&",
|
||||
hir::CaptureKind::UniqueSharedRef => "&unique ",
|
||||
hir::CaptureKind::MutableRef => "&mut ",
|
||||
hir::CaptureKind::Move => "",
|
||||
},
|
||||
capture.display_place(sema.db)
|
||||
),
|
||||
None,
|
||||
source.name().and_then(|name| name.syntax().original_file_range_opt(sema.db)),
|
||||
);
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: label.needs_resolve(),
|
||||
range: move_kw_range,
|
||||
kind: InlayKind::ClosureCapture,
|
||||
label: InlayHintLabel::simple(
|
||||
format!(
|
||||
"{}{}",
|
||||
match capture.kind() {
|
||||
hir::CaptureKind::SharedRef => "&",
|
||||
hir::CaptureKind::UniqueSharedRef => "&unique ",
|
||||
hir::CaptureKind::MutableRef => "&mut ",
|
||||
hir::CaptureKind::Move => "",
|
||||
},
|
||||
capture.display_place(sema.db)
|
||||
),
|
||||
None,
|
||||
source.name().and_then(|name| name.syntax().original_file_range_opt(sema.db)),
|
||||
),
|
||||
label,
|
||||
text_edit: None,
|
||||
position: InlayHintPosition::After,
|
||||
pad_left: false,
|
||||
@ -84,9 +88,10 @@ pub(super) fn hints(
|
||||
|
||||
if idx != last {
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: false,
|
||||
range: move_kw_range,
|
||||
kind: InlayKind::ClosureCapture,
|
||||
label: InlayHintLabel::simple(", ", None, None),
|
||||
label: InlayHintLabel::from(", "),
|
||||
text_edit: None,
|
||||
position: InlayHintPosition::After,
|
||||
pad_left: false,
|
||||
@ -95,6 +100,7 @@ pub(super) fn hints(
|
||||
}
|
||||
}
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: false,
|
||||
range: move_kw_range,
|
||||
kind: InlayKind::ClosureCapture,
|
||||
label: InlayHintLabel::from(")"),
|
||||
|
@ -64,6 +64,7 @@ pub(super) fn hints(
|
||||
};
|
||||
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: label.needs_resolve() || text_edit.is_some(),
|
||||
range: param_list.syntax().text_range(),
|
||||
kind: InlayKind::Type,
|
||||
label,
|
||||
|
@ -79,6 +79,7 @@ fn variant_hints(
|
||||
None,
|
||||
);
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: label.needs_resolve(),
|
||||
range: match eq_token {
|
||||
Some(t) => range.cover(t.text_range()),
|
||||
_ => range,
|
||||
|
@ -22,6 +22,7 @@ pub(super) fn hints(
|
||||
}
|
||||
|
||||
let mk_lt_hint = |t: SyntaxToken, label: String| InlayHint {
|
||||
needs_resolve: false,
|
||||
range: t.text_range(),
|
||||
kind: InlayKind::Lifetime,
|
||||
label: label.into(),
|
||||
@ -185,6 +186,7 @@ pub(super) fn hints(
|
||||
let angle_tok = gpl.l_angle_token()?;
|
||||
let is_empty = gpl.generic_params().next().is_none();
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: false,
|
||||
range: angle_tok.text_range(),
|
||||
kind: InlayKind::Lifetime,
|
||||
label: format!(
|
||||
@ -200,6 +202,7 @@ pub(super) fn hints(
|
||||
});
|
||||
}
|
||||
(None, allocated_lifetimes) => acc.push(InlayHint {
|
||||
needs_resolve: false,
|
||||
range: func.name()?.syntax().text_range(),
|
||||
kind: InlayKind::GenericParamList,
|
||||
label: format!("<{}>", allocated_lifetimes.iter().format(", "),).into(),
|
||||
|
@ -31,9 +31,10 @@ pub(super) fn hints(
|
||||
if ty.lifetime().is_none() {
|
||||
let t = ty.amp_token()?;
|
||||
acc.push(InlayHint {
|
||||
needs_resolve: false,
|
||||
range: t.text_range(),
|
||||
kind: InlayKind::Lifetime,
|
||||
label: "'static".to_owned().into(),
|
||||
label: "'static".into(),
|
||||
text_edit: None,
|
||||
position: InlayHintPosition::After,
|
||||
pad_left: false,
|
||||
|
@ -57,6 +57,7 @@ pub(super) fn hints(
|
||||
let label =
|
||||
InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location);
|
||||
InlayHint {
|
||||
needs_resolve: label.needs_resolve(),
|
||||
range,
|
||||
kind: InlayKind::Parameter,
|
||||
label,
|
||||
|
@ -91,9 +91,9 @@ pub use crate::{
|
||||
MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind,
|
||||
},
|
||||
inlay_hints::{
|
||||
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints, InlayHint,
|
||||
InlayHintLabel, InlayHintLabelPart, InlayHintPosition, InlayHintsConfig, InlayKind,
|
||||
InlayTooltip, LifetimeElisionHints,
|
||||
AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
|
||||
InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintPosition,
|
||||
InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
|
||||
},
|
||||
join_lines::JoinLinesConfig,
|
||||
markup::Markup,
|
||||
|
@ -12,6 +12,7 @@ use ide_db::{
|
||||
};
|
||||
use syntax::{AstNode, SyntaxKind::*, TextRange, T};
|
||||
|
||||
use crate::inlay_hints::InlayFieldsToResolve;
|
||||
use crate::{
|
||||
hover::hover_for_definition,
|
||||
inlay_hints::AdjustmentHintsMode,
|
||||
@ -125,6 +126,7 @@ impl StaticIndex<'_> {
|
||||
max_length: Some(25),
|
||||
closure_capture_hints: false,
|
||||
closing_brace_hints_min_lines: Some(25),
|
||||
fields_to_resolve: InlayFieldsToResolve::empty(),
|
||||
},
|
||||
file_id,
|
||||
None,
|
||||
|
@ -15,7 +15,10 @@ use hir_def::{
|
||||
hir::{ExprId, PatId},
|
||||
};
|
||||
use hir_ty::{Interner, Substitution, TyExt, TypeFlags};
|
||||
use ide::{Analysis, AnnotationConfig, DiagnosticsConfig, InlayHintsConfig, LineCol, RootDatabase};
|
||||
use ide::{
|
||||
Analysis, AnnotationConfig, DiagnosticsConfig, InlayFieldsToResolve, InlayHintsConfig, LineCol,
|
||||
RootDatabase,
|
||||
};
|
||||
use ide_db::{
|
||||
base_db::{
|
||||
salsa::{self, debug::DebugQueryTable, ParallelDatabase},
|
||||
@ -786,6 +789,7 @@ impl flags::AnalysisStats {
|
||||
closure_style: hir::ClosureStyle::ImplFn,
|
||||
max_length: Some(25),
|
||||
closing_brace_hints_min_lines: Some(20),
|
||||
fields_to_resolve: InlayFieldsToResolve::empty(),
|
||||
},
|
||||
file_id,
|
||||
None,
|
||||
|
@ -13,8 +13,9 @@ use cfg::{CfgAtom, CfgDiff};
|
||||
use flycheck::FlycheckConfig;
|
||||
use ide::{
|
||||
AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode,
|
||||
HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayHintsConfig,
|
||||
JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, Snippet, SnippetScope,
|
||||
HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, InlayFieldsToResolve,
|
||||
InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind,
|
||||
Snippet, SnippetScope,
|
||||
};
|
||||
use ide_db::{
|
||||
imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind},
|
||||
@ -1335,6 +1336,18 @@ impl Config {
|
||||
}
|
||||
|
||||
pub fn inlay_hints(&self) -> InlayHintsConfig {
|
||||
let client_capability_fields = self
|
||||
.caps
|
||||
.text_document
|
||||
.as_ref()
|
||||
.and_then(|text| text.inlay_hint.as_ref())
|
||||
.and_then(|inlay_hint_caps| inlay_hint_caps.resolve_support.as_ref())
|
||||
.map(|inlay_resolve| inlay_resolve.properties.iter())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.cloned()
|
||||
.collect::<FxHashSet<_>>();
|
||||
|
||||
InlayHintsConfig {
|
||||
render_colons: self.data.inlayHints_renderColons,
|
||||
type_hints: self.data.inlayHints_typeHints_enable,
|
||||
@ -1395,6 +1408,13 @@ impl Config {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
fields_to_resolve: InlayFieldsToResolve {
|
||||
resolve_text_edits: client_capability_fields.contains("textEdits"),
|
||||
resolve_hint_tooltip: client_capability_fields.contains("tooltip"),
|
||||
resolve_label_tooltip: client_capability_fields.contains("label.tooltip"),
|
||||
resolve_label_location: client_capability_fields.contains("label.location"),
|
||||
resolve_label_command: client_capability_fields.contains("label.command"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -498,6 +498,10 @@ impl GlobalStateSnapshot {
|
||||
pub(crate) fn vfs_memory_usage(&self) -> usize {
|
||||
self.vfs_read().memory_usage()
|
||||
}
|
||||
|
||||
pub(crate) fn file_exists(&self, file_id: FileId) -> bool {
|
||||
self.vfs.read().0.exists(file_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn file_id_to_url(vfs: &vfs::Vfs, id: FileId) -> Url {
|
||||
|
@ -11,8 +11,8 @@ use anyhow::Context;
|
||||
|
||||
use ide::{
|
||||
AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, FilePosition, FileRange,
|
||||
HoverAction, HoverGotoTypeData, Query, RangeInfo, ReferenceCategory, Runnable, RunnableKind,
|
||||
SingleResolve, SourceChange, TextEdit,
|
||||
HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query, RangeInfo, ReferenceCategory,
|
||||
Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit,
|
||||
};
|
||||
use ide_db::SymbolKind;
|
||||
use lsp_server::ErrorCode;
|
||||
@ -30,7 +30,7 @@ use serde_json::json;
|
||||
use stdx::{format_to, never};
|
||||
use syntax::{algo, ast, AstNode, TextRange, TextSize};
|
||||
use triomphe::Arc;
|
||||
use vfs::{AbsPath, AbsPathBuf, VfsPath};
|
||||
use vfs::{AbsPath, AbsPathBuf, FileId, VfsPath};
|
||||
|
||||
use crate::{
|
||||
cargo_target_spec::CargoTargetSpec,
|
||||
@ -1412,17 +1412,73 @@ pub(crate) fn handle_inlay_hints(
|
||||
snap.analysis
|
||||
.inlay_hints(&inlay_hints_config, file_id, Some(range))?
|
||||
.into_iter()
|
||||
.map(|it| to_proto::inlay_hint(&snap, &line_index, it))
|
||||
.map(|it| {
|
||||
to_proto::inlay_hint(
|
||||
&snap,
|
||||
&inlay_hints_config.fields_to_resolve,
|
||||
&line_index,
|
||||
file_id,
|
||||
it,
|
||||
)
|
||||
})
|
||||
.collect::<Cancellable<Vec<_>>>()?,
|
||||
))
|
||||
}
|
||||
|
||||
pub(crate) fn handle_inlay_hints_resolve(
|
||||
_snap: GlobalStateSnapshot,
|
||||
hint: InlayHint,
|
||||
snap: GlobalStateSnapshot,
|
||||
mut original_hint: InlayHint,
|
||||
) -> anyhow::Result<InlayHint> {
|
||||
let _p = profile::span("handle_inlay_hints_resolve");
|
||||
Ok(hint)
|
||||
|
||||
let data = match original_hint.data.take() {
|
||||
Some(it) => it,
|
||||
None => return Ok(original_hint),
|
||||
};
|
||||
|
||||
let resolve_data: lsp_ext::InlayHintResolveData = serde_json::from_value(data)?;
|
||||
let file_id = FileId(resolve_data.file_id);
|
||||
anyhow::ensure!(snap.file_exists(file_id), "Invalid LSP resolve data");
|
||||
|
||||
let line_index = snap.file_line_index(file_id)?;
|
||||
let range = from_proto::text_range(
|
||||
&line_index,
|
||||
lsp_types::Range { start: original_hint.position, end: original_hint.position },
|
||||
)?;
|
||||
let range_start = range.start();
|
||||
let range_end = range.end();
|
||||
let large_range = TextRange::new(
|
||||
range_start.checked_sub(1.into()).unwrap_or(range_start),
|
||||
range_end.checked_add(1.into()).unwrap_or(range_end),
|
||||
);
|
||||
let mut forced_resolve_inlay_hints_config = snap.config.inlay_hints();
|
||||
forced_resolve_inlay_hints_config.fields_to_resolve = InlayFieldsToResolve::empty();
|
||||
let resolve_hints = snap.analysis.inlay_hints(
|
||||
&forced_resolve_inlay_hints_config,
|
||||
file_id,
|
||||
Some(large_range),
|
||||
)?;
|
||||
|
||||
let mut resolved_hints = resolve_hints
|
||||
.into_iter()
|
||||
.filter_map(|it| {
|
||||
to_proto::inlay_hint(
|
||||
&snap,
|
||||
&forced_resolve_inlay_hints_config.fields_to_resolve,
|
||||
&line_index,
|
||||
file_id,
|
||||
it,
|
||||
)
|
||||
.ok()
|
||||
})
|
||||
.filter(|hint| hint.position == original_hint.position)
|
||||
.filter(|hint| hint.kind == original_hint.kind);
|
||||
if let Some(resolved_hint) = resolved_hints.next() {
|
||||
if resolved_hints.next().is_none() {
|
||||
return Ok(resolved_hint);
|
||||
}
|
||||
}
|
||||
Ok(original_hint)
|
||||
}
|
||||
|
||||
pub(crate) fn handle_call_hierarchy_prepare(
|
||||
|
@ -682,7 +682,9 @@ pub struct CompletionResolveData {
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InlayHintResolveData {}
|
||||
pub struct InlayHintResolveData {
|
||||
pub file_id: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CompletionImport {
|
||||
|
@ -8,10 +8,10 @@ use std::{
|
||||
use ide::{
|
||||
Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionItem,
|
||||
CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit,
|
||||
Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, InlayHint,
|
||||
InlayHintLabel, InlayHintLabelPart, InlayKind, Markup, NavigationTarget, ReferenceCategory,
|
||||
RenameError, Runnable, Severity, SignatureHelp, SnippetEdit, SourceChange, StructureNodeKind,
|
||||
SymbolKind, TextEdit, TextRange, TextSize,
|
||||
Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel,
|
||||
InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup,
|
||||
NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
|
||||
SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
|
||||
};
|
||||
use ide_db::rust_doc::format_docs;
|
||||
use itertools::Itertools;
|
||||
@ -438,10 +438,25 @@ pub(crate) fn signature_help(
|
||||
|
||||
pub(crate) fn inlay_hint(
|
||||
snap: &GlobalStateSnapshot,
|
||||
fields_to_resolve: &InlayFieldsToResolve,
|
||||
line_index: &LineIndex,
|
||||
file_id: FileId,
|
||||
inlay_hint: InlayHint,
|
||||
) -> Cancellable<lsp_types::InlayHint> {
|
||||
let (label, tooltip) = inlay_hint_label(snap, inlay_hint.label)?;
|
||||
let needs_resolve = inlay_hint.needs_resolve;
|
||||
let (label, tooltip, mut something_to_resolve) =
|
||||
inlay_hint_label(snap, fields_to_resolve, needs_resolve, inlay_hint.label)?;
|
||||
let text_edits = if needs_resolve && fields_to_resolve.resolve_text_edits {
|
||||
something_to_resolve |= inlay_hint.text_edit.is_some();
|
||||
None
|
||||
} else {
|
||||
inlay_hint.text_edit.map(|it| text_edit_vec(line_index, it))
|
||||
};
|
||||
let data = if needs_resolve && something_to_resolve {
|
||||
Some(to_value(lsp_ext::InlayHintResolveData { file_id: file_id.0 }).unwrap())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(lsp_types::InlayHint {
|
||||
position: match inlay_hint.position {
|
||||
@ -455,8 +470,8 @@ pub(crate) fn inlay_hint(
|
||||
InlayKind::Type | InlayKind::Chaining => Some(lsp_types::InlayHintKind::TYPE),
|
||||
_ => None,
|
||||
},
|
||||
text_edits: inlay_hint.text_edit.map(|it| text_edit_vec(line_index, it)),
|
||||
data: None,
|
||||
text_edits,
|
||||
data,
|
||||
tooltip,
|
||||
label,
|
||||
})
|
||||
@ -464,13 +479,18 @@ pub(crate) fn inlay_hint(
|
||||
|
||||
fn inlay_hint_label(
|
||||
snap: &GlobalStateSnapshot,
|
||||
fields_to_resolve: &InlayFieldsToResolve,
|
||||
needs_resolve: bool,
|
||||
mut label: InlayHintLabel,
|
||||
) -> Cancellable<(lsp_types::InlayHintLabel, Option<lsp_types::InlayHintTooltip>)> {
|
||||
let res = match &*label.parts {
|
||||
) -> Cancellable<(lsp_types::InlayHintLabel, Option<lsp_types::InlayHintTooltip>, bool)> {
|
||||
let mut something_to_resolve = false;
|
||||
let (label, tooltip) = match &*label.parts {
|
||||
[InlayHintLabelPart { linked_location: None, .. }] => {
|
||||
let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap();
|
||||
(
|
||||
lsp_types::InlayHintLabel::String(text),
|
||||
let hint_tooltip = if needs_resolve && fields_to_resolve.resolve_hint_tooltip {
|
||||
something_to_resolve |= tooltip.is_some();
|
||||
None
|
||||
} else {
|
||||
match tooltip {
|
||||
Some(ide::InlayTooltip::String(s)) => {
|
||||
Some(lsp_types::InlayHintTooltip::String(s))
|
||||
@ -482,41 +502,52 @@ fn inlay_hint_label(
|
||||
}))
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
)
|
||||
}
|
||||
};
|
||||
(lsp_types::InlayHintLabel::String(text), hint_tooltip)
|
||||
}
|
||||
_ => {
|
||||
let parts = label
|
||||
.parts
|
||||
.into_iter()
|
||||
.map(|part| {
|
||||
part.linked_location.map(|range| location(snap, range)).transpose().map(
|
||||
|location| lsp_types::InlayHintLabelPart {
|
||||
value: part.text,
|
||||
tooltip: match part.tooltip {
|
||||
Some(ide::InlayTooltip::String(s)) => {
|
||||
Some(lsp_types::InlayHintLabelPartTooltip::String(s))
|
||||
}
|
||||
Some(ide::InlayTooltip::Markdown(s)) => {
|
||||
Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent(
|
||||
lsp_types::MarkupContent {
|
||||
kind: lsp_types::MarkupKind::Markdown,
|
||||
value: s,
|
||||
},
|
||||
))
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
location,
|
||||
command: None,
|
||||
},
|
||||
)
|
||||
let tooltip = if needs_resolve && fields_to_resolve.resolve_label_tooltip {
|
||||
something_to_resolve |= part.tooltip.is_some();
|
||||
None
|
||||
} else {
|
||||
match part.tooltip {
|
||||
Some(ide::InlayTooltip::String(s)) => {
|
||||
Some(lsp_types::InlayHintLabelPartTooltip::String(s))
|
||||
}
|
||||
Some(ide::InlayTooltip::Markdown(s)) => {
|
||||
Some(lsp_types::InlayHintLabelPartTooltip::MarkupContent(
|
||||
lsp_types::MarkupContent {
|
||||
kind: lsp_types::MarkupKind::Markdown,
|
||||
value: s,
|
||||
},
|
||||
))
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
};
|
||||
let location = if needs_resolve && fields_to_resolve.resolve_label_location {
|
||||
something_to_resolve |= part.linked_location.is_some();
|
||||
None
|
||||
} else {
|
||||
part.linked_location.map(|range| location(snap, range)).transpose()?
|
||||
};
|
||||
Ok(lsp_types::InlayHintLabelPart {
|
||||
value: part.text,
|
||||
tooltip,
|
||||
location,
|
||||
command: None,
|
||||
})
|
||||
})
|
||||
.collect::<Cancellable<_>>()?;
|
||||
(lsp_types::InlayHintLabel::LabelParts(parts), None)
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
Ok((label, tooltip, something_to_resolve))
|
||||
}
|
||||
|
||||
static TOKEN_RESULT_COUNTER: AtomicU32 = AtomicU32::new(1);
|
||||
|
@ -184,6 +184,11 @@ impl Vfs {
|
||||
mem::take(&mut self.changes)
|
||||
}
|
||||
|
||||
/// Provides a panic-less way to verify file_id validity.
|
||||
pub fn exists(&self, file_id: FileId) -> bool {
|
||||
self.get(file_id).is_some()
|
||||
}
|
||||
|
||||
/// Returns the id associated with `path`
|
||||
///
|
||||
/// - If `path` does not exists in the `Vfs`, allocate a new id for it, associated with a
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!---
|
||||
lsp/ext.rs hash: 149a5be3c5e469d1
|
||||
lsp/ext.rs hash: 121482ee911854da
|
||||
|
||||
If you need to change the above hash to make the test pass, please check if you
|
||||
need to adjust this doc as well and ping this issue:
|
||||
@ -322,7 +322,7 @@ Position[]
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let x: Vec<()>/*cursor here*/ = vec![]
|
||||
let x: Vec<()>/*cursor here*/ = vec![];
|
||||
}
|
||||
```
|
||||
|
||||
@ -362,7 +362,7 @@ interface RunnablesParams {
|
||||
```typescript
|
||||
interface Runnable {
|
||||
label: string;
|
||||
/// If this Runnable is associated with a specific function/module, etc, the location of this item
|
||||
/// If this Runnable is associated with a specific function/module, etc., the location of this item
|
||||
location?: LocationLink;
|
||||
/// Running things is necessary technology specific, `kind` needs to be advertised via server capabilities,
|
||||
// the type of `args` is specific to `kind`. The actual running is handled by the client.
|
||||
|
Loading…
x
Reference in New Issue
Block a user