Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameter inlay hint separate from variable type inlay? #2876 #3543

Merged
merged 5 commits into from
Mar 12, 2020
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
113 changes: 95 additions & 18 deletions crates/ra_ide/src/inlay_hints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,20 @@ use ra_syntax::{

use crate::{FileId, FunctionSignature};

#[derive(Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct InlayConfig {
pub type_hints: bool,
pub parameter_hints: bool,
pub max_length: Option<usize>,
}

impl Default for InlayConfig {
fn default() -> Self {
Self { type_hints: true, parameter_hints: true, max_length: None }
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum InlayKind {
TypeHint,
ParameterHint,
Expand All @@ -26,7 +39,7 @@ pub struct InlayHint {
pub(crate) fn inlay_hints(
db: &RootDatabase,
file_id: FileId,
max_inlay_hint_length: Option<usize>,
inlay_hint_opts: &InlayConfig,
) -> Vec<InlayHint> {
let _p = profile("inlay_hints");
let sema = Semantics::new(db);
Expand All @@ -36,9 +49,9 @@ pub(crate) fn inlay_hints(
for node in file.syntax().descendants() {
match_ast! {
match node {
ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, ast::Expr::from(it)); },
ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, ast::Expr::from(it)); },
ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, max_inlay_hint_length, it); },
ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, inlay_hint_opts, ast::Expr::from(it)); },
ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, inlay_hint_opts, ast::Expr::from(it)); },
ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, inlay_hint_opts, it); },
_ => (),
}
}
Expand All @@ -49,8 +62,13 @@ pub(crate) fn inlay_hints(
fn get_param_name_hints(
acc: &mut Vec<InlayHint>,
sema: &Semantics<RootDatabase>,
inlay_hint_opts: &InlayConfig,
expr: ast::Expr,
) -> Option<()> {
if !inlay_hint_opts.parameter_hints {
return None;
}

let args = match &expr {
ast::Expr::CallExpr(expr) => expr.arg_list()?.args(),
ast::Expr::MethodCallExpr(expr) => expr.arg_list()?.args(),
Expand Down Expand Up @@ -84,9 +102,13 @@ fn get_param_name_hints(
fn get_bind_pat_hints(
acc: &mut Vec<InlayHint>,
sema: &Semantics<RootDatabase>,
max_inlay_hint_length: Option<usize>,
inlay_hint_opts: &InlayConfig,
pat: ast::BindPat,
) -> Option<()> {
if !inlay_hint_opts.type_hints {
return None;
}

let ty = sema.type_of_pat(&pat.clone().into())?;

if should_not_display_type_hint(sema.db, &pat, &ty) {
Expand All @@ -96,7 +118,7 @@ fn get_bind_pat_hints(
acc.push(InlayHint {
range: pat.syntax().text_range(),
kind: InlayKind::TypeHint,
label: ty.display_truncated(sema.db, max_inlay_hint_length).to_string().into(),
label: ty.display_truncated(sema.db, inlay_hint_opts.max_length).to_string().into(),
});
Some(())
}
Expand Down Expand Up @@ -202,10 +224,65 @@ fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<

#[cfg(test)]
mod tests {
use crate::inlay_hints::InlayConfig;
use insta::assert_debug_snapshot;

use crate::mock_analysis::single_file;

#[test]
fn param_hints_only() {
let (analysis, file_id) = single_file(
r#"
fn foo(a: i32, b: i32) -> i32 { a + b }
fn main() {
let _x = foo(4, 4);
}"#,
);
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ parameter_hints: true, type_hints: false, max_length: None}).unwrap(), @r###"
[
InlayHint {
range: [106; 107),
kind: ParameterHint,
label: "a",
},
InlayHint {
range: [109; 110),
kind: ParameterHint,
label: "b",
},
]"###);
}

#[test]
fn hints_disabled() {
let (analysis, file_id) = single_file(
r#"
fn foo(a: i32, b: i32) -> i32 { a + b }
fn main() {
let _x = foo(4, 4);
}"#,
);
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ type_hints: false, parameter_hints: false, max_length: None}).unwrap(), @r###"[]"###);
}

#[test]
fn type_hints_only() {
let (analysis, file_id) = single_file(
r#"
fn foo(a: i32, b: i32) -> i32 { a + b }
fn main() {
let _x = foo(4, 4);
}"#,
);
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ type_hints: true, parameter_hints: false, max_length: None}).unwrap(), @r###"
[
InlayHint {
range: [97; 99),
kind: TypeHint,
label: "i32",
},
]"###);
}
#[test]
fn default_generic_types_should_not_be_displayed() {
let (analysis, file_id) = single_file(
Expand All @@ -221,7 +298,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
[
InlayHint {
range: [69; 71),
Expand Down Expand Up @@ -278,7 +355,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
[
InlayHint {
range: [193; 197),
Expand Down Expand Up @@ -358,7 +435,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
[
InlayHint {
range: [21; 30),
Expand Down Expand Up @@ -422,7 +499,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
[
InlayHint {
range: [21; 30),
Expand Down Expand Up @@ -472,7 +549,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
[
InlayHint {
range: [188; 192),
Expand Down Expand Up @@ -567,7 +644,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
[
InlayHint {
range: [188; 192),
Expand Down Expand Up @@ -662,7 +739,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
[
InlayHint {
range: [252; 256),
Expand Down Expand Up @@ -734,7 +811,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
[
InlayHint {
range: [74; 75),
Expand Down Expand Up @@ -822,7 +899,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig::default()).unwrap(), @r###"
[
InlayHint {
range: [798; 809),
Expand Down Expand Up @@ -944,7 +1021,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
[]
"###
);
Expand All @@ -970,7 +1047,7 @@ fn main() {
}"#,
);

assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###"
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
[]
"###
);
Expand Down
6 changes: 3 additions & 3 deletions crates/ra_ide/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub use crate::{
expand_macro::ExpandedMacro,
folding_ranges::{Fold, FoldKind},
hover::HoverResult,
inlay_hints::{InlayHint, InlayKind},
inlay_hints::{InlayConfig, InlayHint, InlayKind},
references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
runnables::{Runnable, RunnableKind, TestId},
source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
Expand Down Expand Up @@ -318,9 +318,9 @@ impl Analysis {
pub fn inlay_hints(
&self,
file_id: FileId,
max_inlay_hint_length: Option<usize>,
inlay_hint_opts: &InlayConfig,
) -> Cancelable<Vec<InlayHint>> {
self.with_db(|db| inlay_hints::inlay_hints(db, file_id, max_inlay_hint_length))
self.with_db(|db| inlay_hints::inlay_hints(db, file_id, inlay_hint_opts))
}

/// Returns the set of folding ranges.
Expand Down
7 changes: 5 additions & 2 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
//! configure the server itself, feature flags are passed into analysis, and
//! tweak things like automatic insertion of `()` in completions.

use crate::req::InlayConfigDef;
use ra_ide::InlayConfig;
use rustc_hash::FxHashMap;

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

pub lru_capacity: Option<usize>,

pub max_inlay_hint_length: Option<usize>,
#[serde(with = "InlayConfigDef")]
pub inlay_hints: InlayConfig,

pub cargo_watch_enable: bool,
pub cargo_watch_args: Vec<String>,
Expand All @@ -57,7 +60,7 @@ impl Default for ServerConfig {
exclude_globs: Vec::new(),
use_client_watching: false,
lru_capacity: None,
max_inlay_hint_length: None,
inlay_hints: Default::default(),
cargo_watch_enable: true,
cargo_watch_args: Vec::new(),
cargo_watch_command: "check".to_string(),
Expand Down
2 changes: 1 addition & 1 deletion crates/rust-analyzer/src/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ pub fn main_loop(
.and_then(|it| it.folding_range.as_ref())
.and_then(|it| it.line_folding_only)
.unwrap_or(false),
max_inlay_hint_length: config.max_inlay_hint_length,
inlay_hints: config.inlay_hints,
cargo_watch: CheckOptions {
enable: config.cargo_watch_enable,
args: config.cargo_watch_args,
Expand Down
9 changes: 3 additions & 6 deletions crates/rust-analyzer/src/main_loop/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::{
},
diagnostics::DiagnosticTask,
from_json,
req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
req::{self, Decoration, InlayHint, InlayHintsParams},
semantic_tokens::SemanticTokensBuilder,
world::WorldSnapshot,
LspError, Result,
Expand Down Expand Up @@ -997,15 +997,12 @@ pub fn handle_inlay_hints(
let analysis = world.analysis();
let line_index = analysis.file_line_index(file_id)?;
Ok(analysis
.inlay_hints(file_id, world.options.max_inlay_hint_length)?
.inlay_hints(file_id, &world.options.inlay_hints)?
.into_iter()
.map(|api_type| InlayHint {
label: api_type.label.to_string(),
range: api_type.range.conv_with(&line_index),
kind: match api_type.kind {
ra_ide::InlayKind::TypeHint => InlayKind::TypeHint,
ra_ide::InlayKind::ParameterHint => InlayKind::ParameterHint,
},
kind: api_type.kind,
})
.collect())
}
Expand Down
14 changes: 13 additions & 1 deletion crates/rust-analyzer/src/req.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};

use ra_ide::{InlayConfig, InlayKind};

pub use lsp_types::{
notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens,
CodeLensParams, CompletionParams, CompletionResponse, DiagnosticTag,
Expand Down Expand Up @@ -196,14 +198,24 @@ pub struct InlayHintsParams {
}

#[derive(Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum InlayKind {
#[serde(remote = "InlayKind")]
pub enum InlayKindDef {
TypeHint,
ParameterHint,
}

#[derive(Deserialize)]
#[serde(remote = "InlayConfig", rename_all = "camelCase")]
pub struct InlayConfigDef {
pub type_hints: bool,
pub parameter_hints: bool,
pub max_length: Option<usize>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct InlayHint {
pub range: Range,
#[serde(with = "InlayKindDef")]
pub kind: InlayKind,
pub label: String,
}
Expand Down
5 changes: 3 additions & 2 deletions crates/rust-analyzer/src/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use lsp_types::Url;
use parking_lot::RwLock;
use ra_cargo_watch::{url_from_path_with_drive_lowercasing, CheckOptions, CheckWatcher};
use ra_ide::{
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, InlayConfig, LibraryData,
SourceRootId,
};
use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace};
use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch};
Expand All @@ -32,7 +33,7 @@ pub struct Options {
pub publish_decorations: bool,
pub supports_location_link: bool,
pub line_folding_only: bool,
pub max_inlay_hint_length: Option<usize>,
pub inlay_hints: InlayConfig,
pub rustfmt_args: Vec<String>,
pub cargo_watch: CheckOptions,
}
Expand Down
4 changes: 2 additions & 2 deletions docs/user/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ Two types of inlay hints are displayed currently:

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

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

**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.
This approach has limitations, the caret movement and bracket highlighting near the edges of the hint may be weird:
Expand Down
Loading