Skip to content

Commit d98a5fa

Browse files
bors[bot]slyngbaek
andauthored
Merge #3543
3543: Parameter inlay hint separate from variable type inlay? #2876 r=matklad a=slyngbaek Add setting to allow enabling either type inlay hints or parameter inlay hints or both. Group the the max inlay hint length option into the object. - Add a new type for the inlayHint options. - Add tests to ensure the inlays don't happen on the server side Co-authored-by: Steffen Lyngbaek <steffenlyngbaek@gmail.com>
2 parents 944bd2c + a153b90 commit d98a5fa

File tree

12 files changed

+150
-43
lines changed

12 files changed

+150
-43
lines changed

crates/ra_ide/src/inlay_hints.rs

Lines changed: 95 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,20 @@ use ra_syntax::{
1010

1111
use crate::{FileId, FunctionSignature};
1212

13-
#[derive(Debug, PartialEq, Eq)]
13+
#[derive(Clone, Debug, PartialEq, Eq)]
14+
pub struct InlayConfig {
15+
pub type_hints: bool,
16+
pub parameter_hints: bool,
17+
pub max_length: Option<usize>,
18+
}
19+
20+
impl Default for InlayConfig {
21+
fn default() -> Self {
22+
Self { type_hints: true, parameter_hints: true, max_length: None }
23+
}
24+
}
25+
26+
#[derive(Clone, Debug, PartialEq, Eq)]
1427
pub enum InlayKind {
1528
TypeHint,
1629
ParameterHint,
@@ -26,7 +39,7 @@ pub struct InlayHint {
2639
pub(crate) fn inlay_hints(
2740
db: &RootDatabase,
2841
file_id: FileId,
29-
max_inlay_hint_length: Option<usize>,
42+
inlay_hint_opts: &InlayConfig,
3043
) -> Vec<InlayHint> {
3144
let _p = profile("inlay_hints");
3245
let sema = Semantics::new(db);
@@ -36,9 +49,9 @@ pub(crate) fn inlay_hints(
3649
for node in file.syntax().descendants() {
3750
match_ast! {
3851
match node {
39-
ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, ast::Expr::from(it)); },
40-
ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, ast::Expr::from(it)); },
41-
ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, max_inlay_hint_length, it); },
52+
ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, inlay_hint_opts, ast::Expr::from(it)); },
53+
ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, inlay_hint_opts, ast::Expr::from(it)); },
54+
ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, inlay_hint_opts, it); },
4255
_ => (),
4356
}
4457
}
@@ -49,8 +62,13 @@ pub(crate) fn inlay_hints(
4962
fn get_param_name_hints(
5063
acc: &mut Vec<InlayHint>,
5164
sema: &Semantics<RootDatabase>,
65+
inlay_hint_opts: &InlayConfig,
5266
expr: ast::Expr,
5367
) -> Option<()> {
68+
if !inlay_hint_opts.parameter_hints {
69+
return None;
70+
}
71+
5472
let args = match &expr {
5573
ast::Expr::CallExpr(expr) => expr.arg_list()?.args(),
5674
ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(),
@@ -84,9 +102,13 @@ fn get_param_name_hints(
84102
fn get_bind_pat_hints(
85103
acc: &mut Vec<InlayHint>,
86104
sema: &Semantics<RootDatabase>,
87-
max_inlay_hint_length: Option<usize>,
105+
inlay_hint_opts: &InlayConfig,
88106
pat: ast::BindPat,
89107
) -> Option<()> {
108+
if !inlay_hint_opts.type_hints {
109+
return None;
110+
}
111+
90112
let ty = sema.type_of_pat(&pat.clone().into())?;
91113

92114
if should_not_display_type_hint(sema.db, &pat, &ty) {
@@ -96,7 +118,7 @@ fn get_bind_pat_hints(
96118
acc.push(InlayHint {
97119
range: pat.syntax().text_range(),
98120
kind: InlayKind::TypeHint,
99-
label: ty.display_truncated(sema.db, max_inlay_hint_length).to_string().into(),
121+
label: ty.display_truncated(sema.db, inlay_hint_opts.max_length).to_string().into(),
100122
});
101123
Some(())
102124
}
@@ -202,10 +224,65 @@ fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<
202224

203225
#[cfg(test)]
204226
mod tests {
227+
use crate::inlay_hints::InlayConfig;
205228
use insta::assert_debug_snapshot;
206229

207230
use crate::mock_analysis::single_file;
208231

232+
#[test]
233+
fn param_hints_only() {
234+
let (analysis, file_id) = single_file(
235+
r#"
236+
fn foo(a: i32, b: i32) -> i32 { a + b }
237+
fn main() {
238+
let _x = foo(4, 4);
239+
}"#,
240+
);
241+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ parameter_hints: true, type_hints: false, max_length: None}).unwrap(), @r###"
242+
[
243+
InlayHint {
244+
range: [106; 107),
245+
kind: ParameterHint,
246+
label: "a",
247+
},
248+
InlayHint {
249+
range: [109; 110),
250+
kind: ParameterHint,
251+
label: "b",
252+
},
253+
]"###);
254+
}
255+
256+
#[test]
257+
fn hints_disabled() {
258+
let (analysis, file_id) = single_file(
259+
r#"
260+
fn foo(a: i32, b: i32) -> i32 { a + b }
261+
fn main() {
262+
let _x = foo(4, 4);
263+
}"#,
264+
);
265+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ type_hints: false, parameter_hints: false, max_length: None}).unwrap(), @r###"[]"###);
266+
}
267+
268+
#[test]
269+
fn type_hints_only() {
270+
let (analysis, file_id) = single_file(
271+
r#"
272+
fn foo(a: i32, b: i32) -> i32 { a + b }
273+
fn main() {
274+
let _x = foo(4, 4);
275+
}"#,
276+
);
277+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ type_hints: true, parameter_hints: false, max_length: None}).unwrap(), @r###"
278+
[
279+
InlayHint {
280+
range: [97; 99),
281+
kind: TypeHint,
282+
label: "i32",
283+
},
284+
]"###);
285+
}
209286
#[test]
210287
fn default_generic_types_should_not_be_displayed() {
211288
let (analysis, file_id) = single_file(
@@ -221,7 +298,7 @@ fn main() {
221298
}"#,
222299
);
223300

224-
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
301+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
225302
[
226303
InlayHint {
227304
range: [69; 71),
@@ -278,7 +355,7 @@ fn main() {
278355
}"#,
279356
);
280357

281-
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
358+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
282359
[
283360
InlayHint {
284361
range: [193; 197),
@@ -358,7 +435,7 @@ fn main() {
358435
}"#,
359436
);
360437

361-
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
438+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
362439
[
363440
InlayHint {
364441
range: [21; 30),
@@ -422,7 +499,7 @@ fn main() {
422499
}"#,
423500
);
424501

425-
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
502+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
426503
[
427504
InlayHint {
428505
range: [21; 30),
@@ -472,7 +549,7 @@ fn main() {
472549
}"#,
473550
);
474551

475-
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
552+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
476553
[
477554
InlayHint {
478555
range: [188; 192),
@@ -567,7 +644,7 @@ fn main() {
567644
}"#,
568645
);
569646

570-
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
647+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
571648
[
572649
InlayHint {
573650
range: [188; 192),
@@ -662,7 +739,7 @@ fn main() {
662739
}"#,
663740
);
664741

665-
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
742+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
666743
[
667744
InlayHint {
668745
range: [252; 256),
@@ -734,7 +811,7 @@ fn main() {
734811
}"#,
735812
);
736813

737-
assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###"
814+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
738815
[
739816
InlayHint {
740817
range: [74; 75),
@@ -822,7 +899,7 @@ fn main() {
822899
}"#,
823900
);
824901

825-
assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
902+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
826903
[
827904
InlayHint {
828905
range: [798; 809),
@@ -944,7 +1021,7 @@ fn main() {
9441021
}"#,
9451022
);
9461023

947-
assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###"
1024+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
9481025
[]
9491026
"###
9501027
);
@@ -970,7 +1047,7 @@ fn main() {
9701047
}"#,
9711048
);
9721049

973-
assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###"
1050+
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
9741051
[]
9751052
"###
9761053
);

crates/ra_ide/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub use crate::{
6868
expand_macro::ExpandedMacro,
6969
folding_ranges::{Fold, FoldKind},
7070
hover::HoverResult,
71-
inlay_hints::{InlayHint, InlayKind},
71+
inlay_hints::{InlayConfig, InlayHint, InlayKind},
7272
references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
7373
runnables::{Runnable, RunnableKind, TestId},
7474
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
@@ -319,9 +319,9 @@ impl Analysis {
319319
pub fn inlay_hints(
320320
&self,
321321
file_id: FileId,
322-
max_inlay_hint_length: Option<usize>,
322+
inlay_hint_opts: &InlayConfig,
323323
) -> Cancelable<Vec<InlayHint>> {
324-
self.with_db(|db| inlay_hints::inlay_hints(db, file_id, max_inlay_hint_length))
324+
self.with_db(|db| inlay_hints::inlay_hints(db, file_id, inlay_hint_opts))
325325
}
326326

327327
/// Returns the set of folding ranges.

crates/rust-analyzer/src/config.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
//! configure the server itself, feature flags are passed into analysis, and
88
//! tweak things like automatic insertion of `()` in completions.
99
10+
use crate::req::InlayConfigDef;
11+
use ra_ide::InlayConfig;
1012
use rustc_hash::FxHashMap;
1113

1214
use ra_project_model::CargoFeatures;
@@ -30,7 +32,8 @@ pub struct ServerConfig {
3032

3133
pub lru_capacity: Option<usize>,
3234

33-
pub max_inlay_hint_length: Option<usize>,
35+
#[serde(with = "InlayConfigDef")]
36+
pub inlay_hints: InlayConfig,
3437

3538
pub cargo_watch_enable: bool,
3639
pub cargo_watch_args: Vec<String>,
@@ -60,7 +63,7 @@ impl Default for ServerConfig {
6063
exclude_globs: Vec::new(),
6164
use_client_watching: false,
6265
lru_capacity: None,
63-
max_inlay_hint_length: None,
66+
inlay_hints: Default::default(),
6467
cargo_watch_enable: true,
6568
cargo_watch_args: Vec::new(),
6669
cargo_watch_command: "check".to_string(),

crates/rust-analyzer/src/main_loop.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ pub fn main_loop(
177177
.and_then(|it| it.folding_range.as_ref())
178178
.and_then(|it| it.line_folding_only)
179179
.unwrap_or(false),
180-
max_inlay_hint_length: config.max_inlay_hint_length,
180+
inlay_hints: config.inlay_hints,
181181
cargo_watch: CheckOptions {
182182
enable: config.cargo_watch_enable,
183183
args: config.cargo_watch_args,

crates/rust-analyzer/src/main_loop/handlers.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::{
3737
},
3838
diagnostics::DiagnosticTask,
3939
from_json,
40-
req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
40+
req::{self, Decoration, InlayHint, InlayHintsParams},
4141
semantic_tokens::SemanticTokensBuilder,
4242
world::WorldSnapshot,
4343
LspError, Result,
@@ -997,15 +997,12 @@ pub fn handle_inlay_hints(
997997
let analysis = world.analysis();
998998
let line_index = analysis.file_line_index(file_id)?;
999999
Ok(analysis
1000-
.inlay_hints(file_id, world.options.max_inlay_hint_length)?
1000+
.inlay_hints(file_id, &world.options.inlay_hints)?
10011001
.into_iter()
10021002
.map(|api_type| InlayHint {
10031003
label: api_type.label.to_string(),
10041004
range: api_type.range.conv_with(&line_index),
1005-
kind: match api_type.kind {
1006-
ra_ide::InlayKind::TypeHint => InlayKind::TypeHint,
1007-
ra_ide::InlayKind::ParameterHint => InlayKind::ParameterHint,
1008-
},
1005+
kind: api_type.kind,
10091006
})
10101007
.collect())
10111008
}

crates/rust-analyzer/src/req.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url};
44
use rustc_hash::FxHashMap;
55
use serde::{Deserialize, Serialize};
66

7+
use ra_ide::{InlayConfig, InlayKind};
8+
79
pub use lsp_types::{
810
notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens,
911
CodeLensParams, CompletionParams, CompletionResponse, DiagnosticTag,
@@ -196,14 +198,24 @@ pub struct InlayHintsParams {
196198
}
197199

198200
#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
199-
pub enum InlayKind {
201+
#[serde(remote = "InlayKind")]
202+
pub enum InlayKindDef {
200203
TypeHint,
201204
ParameterHint,
202205
}
203206

207+
#[derive(Deserialize)]
208+
#[serde(remote = "InlayConfig", rename_all = "camelCase")]
209+
pub struct InlayConfigDef {
210+
pub type_hints: bool,
211+
pub parameter_hints: bool,
212+
pub max_length: Option<usize>,
213+
}
214+
204215
#[derive(Debug, Deserialize, Serialize)]
205216
pub struct InlayHint {
206217
pub range: Range,
218+
#[serde(with = "InlayKindDef")]
207219
pub kind: InlayKind,
208220
pub label: String,
209221
}

crates/rust-analyzer/src/world.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use lsp_types::Url;
1313
use parking_lot::RwLock;
1414
use ra_cargo_watch::{url_from_path_with_drive_lowercasing, CheckOptions, CheckWatcher};
1515
use ra_ide::{
16-
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
16+
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, InlayConfig, LibraryData,
17+
SourceRootId,
1718
};
1819
use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace};
1920
use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch};
@@ -34,7 +35,7 @@ pub struct Options {
3435
pub publish_decorations: bool,
3536
pub supports_location_link: bool,
3637
pub line_folding_only: bool,
37-
pub max_inlay_hint_length: Option<usize>,
38+
pub inlay_hints: InlayConfig,
3839
pub rustfmt_args: Vec<String>,
3940
pub cargo_watch: CheckOptions,
4041
}

docs/user/features.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ Two types of inlay hints are displayed currently:
191191

192192
In VS Code, the following settings can be used to configure the inlay hints:
193193

194-
* `rust-analyzer.displayInlayHints` — toggles inlay hints display on or off
195-
* `rust-analyzer.maxInlayHintLength` — shortens the hints if their length exceeds the value specified. If no value is specified (`null`), no shortening is applied.
194+
* `rust-analyzer.inlayHintOpts.displayType` configure which types of inlay hints are shown.
195+
* `rust-analyzer.inlayHintOpts.maxLength` — shortens the hints if their length exceeds the value specified. If no value is specified (`null`), no shortening is applied.
196196

197197
**Note:** VS Code does not have native support for inlay hints [yet](https://github.com/microsoft/vscode/issues/16221) and the hints are implemented using decorations.
198198
This approach has limitations, the caret movement and bracket highlighting near the edges of the hint may be weird:

0 commit comments

Comments
 (0)