Switch from Vec<InlayKind> to object with props

- Instead of a single object type, use several individual nested types
  to allow toggling from the settings GUI
- Remove unused struct definitions
- Install and test that the toggles work
This commit is contained in:
Steffen Lyngbaek 2020-03-11 20:14:39 -07:00
parent 974ed7155a
commit 58248e24cd
11 changed files with 41 additions and 85 deletions

View file

@ -12,13 +12,14 @@ use crate::{FileId, FunctionSignature};
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct InlayConfig { pub struct InlayConfig {
pub display_type: Vec<InlayKind>, pub type_hints: bool,
pub parameter_hints: bool,
pub max_length: Option<usize>, pub max_length: Option<usize>,
} }
impl Default for InlayConfig { impl Default for InlayConfig {
fn default() -> Self { fn default() -> Self {
Self { display_type: vec![InlayKind::TypeHint, InlayKind::ParameterHint], max_length: None } Self { type_hints: true, parameter_hints: true, max_length: None }
} }
} }
@ -64,7 +65,7 @@ fn get_param_name_hints(
inlay_hint_opts: &InlayConfig, inlay_hint_opts: &InlayConfig,
expr: ast::Expr, expr: ast::Expr,
) -> Option<()> { ) -> Option<()> {
if !inlay_hint_opts.display_type.contains(&InlayKind::ParameterHint) { if !inlay_hint_opts.parameter_hints {
return None; return None;
} }
@ -104,7 +105,7 @@ fn get_bind_pat_hints(
inlay_hint_opts: &InlayConfig, inlay_hint_opts: &InlayConfig,
pat: ast::BindPat, pat: ast::BindPat,
) -> Option<()> { ) -> Option<()> {
if !inlay_hint_opts.display_type.contains(&InlayKind::TypeHint) { if !inlay_hint_opts.type_hints {
return None; return None;
} }
@ -223,7 +224,7 @@ fn get_fn_signature(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::inlay_hints::{InlayConfig, InlayKind}; use crate::inlay_hints::InlayConfig;
use insta::assert_debug_snapshot; use insta::assert_debug_snapshot;
use crate::mock_analysis::single_file; use crate::mock_analysis::single_file;
@ -237,7 +238,7 @@ mod tests {
let _x = foo(4, 4); let _x = foo(4, 4);
}"#, }"#,
); );
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ display_type: vec![InlayKind::ParameterHint], max_length: None}).unwrap(), @r###" assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ parameter_hints: true, type_hints: false, max_length: None}).unwrap(), @r###"
[ [
InlayHint { InlayHint {
range: [106; 107), range: [106; 107),
@ -261,7 +262,7 @@ mod tests {
let _x = foo(4, 4); let _x = foo(4, 4);
}"#, }"#,
); );
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ display_type: vec![], max_length: None}).unwrap(), @r###"[]"###); assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ type_hints: false, parameter_hints: false, max_length: None}).unwrap(), @r###"[]"###);
} }
#[test] #[test]
@ -273,7 +274,7 @@ mod tests {
let _x = foo(4, 4); let _x = foo(4, 4);
}"#, }"#,
); );
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ display_type: vec![InlayKind::TypeHint], max_length: None}).unwrap(), @r###" assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig{ type_hints: true, parameter_hints: false, max_length: None}).unwrap(), @r###"
[ [
InlayHint { InlayHint {
range: [97; 99), range: [97; 99),
@ -810,7 +811,7 @@ fn main() {
}"#, }"#,
); );
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { display_type: vec![InlayKind::TypeHint, InlayKind::ParameterHint], max_length: Some(8) }).unwrap(), @r###" assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
[ [
InlayHint { InlayHint {
range: [74; 75), range: [74; 75),
@ -1020,7 +1021,7 @@ fn main() {
}"#, }"#,
); );
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { display_type: vec![InlayKind::TypeHint, InlayKind::ParameterHint], max_length: Some(8) }).unwrap(), @r###" assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
[] []
"### "###
); );
@ -1046,7 +1047,7 @@ fn main() {
}"#, }"#,
); );
assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { display_type: vec![InlayKind::TypeHint, InlayKind::ParameterHint], max_length: Some(8) }).unwrap(), @r###" assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayConfig { max_length: Some(8), ..Default::default() }).unwrap(), @r###"
[] []
"### "###
); );

View file

@ -16,7 +16,6 @@ use anyhow::{bail, Context, Result};
use ra_cfg::CfgOptions; use ra_cfg::CfgOptions;
use ra_db::{CrateGraph, CrateName, Edition, Env, FileId}; use ra_db::{CrateGraph, CrateName, Edition, Env, FileId};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use serde::Deserialize;
use serde_json::from_reader; use serde_json::from_reader;
pub use crate::{ pub use crate::{
@ -25,28 +24,6 @@ pub use crate::{
sysroot::Sysroot, sysroot::Sysroot,
}; };
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum InlayHintDisplayType {
Off,
TypeHints,
ParameterHints,
Full,
}
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase", default)]
pub struct InlayHintOptions {
pub display_type: InlayHintDisplayType,
pub max_length: Option<usize>,
}
impl Default for InlayHintOptions {
fn default() -> Self {
Self { display_type: InlayHintDisplayType::Full, max_length: None }
}
}
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct CargoTomlNotFoundError { pub struct CargoTomlNotFoundError {
pub searched_at: PathBuf, pub searched_at: PathBuf,

View file

@ -33,7 +33,7 @@ pub struct ServerConfig {
pub lru_capacity: Option<usize>, pub lru_capacity: Option<usize>,
#[serde(with = "InlayConfigDef")] #[serde(with = "InlayConfigDef")]
pub inlay_hint_opts: InlayConfig, pub inlay_hints: InlayConfig,
pub cargo_watch_enable: bool, pub cargo_watch_enable: bool,
pub cargo_watch_args: Vec<String>, pub cargo_watch_args: Vec<String>,
@ -60,7 +60,7 @@ impl Default for ServerConfig {
exclude_globs: Vec::new(), exclude_globs: Vec::new(),
use_client_watching: false, use_client_watching: false,
lru_capacity: None, lru_capacity: None,
inlay_hint_opts: Default::default(), inlay_hints: Default::default(),
cargo_watch_enable: true, cargo_watch_enable: true,
cargo_watch_args: Vec::new(), cargo_watch_args: Vec::new(),
cargo_watch_command: "check".to_string(), cargo_watch_command: "check".to_string(),

View file

@ -177,7 +177,7 @@ pub fn main_loop(
.and_then(|it| it.folding_range.as_ref()) .and_then(|it| it.folding_range.as_ref())
.and_then(|it| it.line_folding_only) .and_then(|it| it.line_folding_only)
.unwrap_or(false), .unwrap_or(false),
inlay_hint_opts: config.inlay_hint_opts, inlay_hints: config.inlay_hints,
cargo_watch: CheckOptions { cargo_watch: CheckOptions {
enable: config.cargo_watch_enable, enable: config.cargo_watch_enable,
args: config.cargo_watch_args, args: config.cargo_watch_args,

View file

@ -997,7 +997,7 @@ pub fn handle_inlay_hints(
let analysis = world.analysis(); let analysis = world.analysis();
let line_index = analysis.file_line_index(file_id)?; let line_index = analysis.file_line_index(file_id)?;
Ok(analysis Ok(analysis
.inlay_hints(file_id, &world.options.inlay_hint_opts)? .inlay_hints(file_id, &world.options.inlay_hints)?
.into_iter() .into_iter()
.map(|api_type| InlayHint { .map(|api_type| InlayHint {
label: api_type.label.to_string(), label: api_type.label.to_string(),

View file

@ -2,7 +2,7 @@
use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url}; use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Serialize};
use ra_ide::{InlayConfig, InlayKind}; use ra_ide::{InlayConfig, InlayKind};
@ -204,24 +204,11 @@ pub enum InlayKindDef {
ParameterHint, ParameterHint,
} }
// Work-around until better serde support is added
// https://github.com/serde-rs/serde/issues/723#issuecomment-382501277
fn vec_inlay_kind<'de, D>(deserializer: D) -> Result<Vec<InlayKind>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)] #[derive(Deserialize)]
struct Wrapper(#[serde(with = "InlayKindDef")] InlayKind); #[serde(remote = "InlayConfig", rename_all = "camelCase")]
let v = Vec::deserialize(deserializer)?;
Ok(v.into_iter().map(|Wrapper(a)| a).collect())
}
#[derive(Deserialize)]
#[serde(remote = "InlayConfig")]
pub struct InlayConfigDef { pub struct InlayConfigDef {
#[serde(deserialize_with = "vec_inlay_kind")] pub type_hints: bool,
pub display_type: Vec<InlayKind>, pub parameter_hints: bool,
pub max_length: Option<usize>, pub max_length: Option<usize>,
} }

View file

@ -33,7 +33,7 @@ pub struct Options {
pub publish_decorations: bool, pub publish_decorations: bool,
pub supports_location_link: bool, pub supports_location_link: bool,
pub line_folding_only: bool, pub line_folding_only: bool,
pub inlay_hint_opts: InlayConfig, pub inlay_hints: InlayConfig,
pub rustfmt_args: Vec<String>, pub rustfmt_args: Vec<String>,
pub cargo_watch: CheckOptions, pub cargo_watch: CheckOptions,
} }

View file

@ -307,28 +307,18 @@
"exclusiveMinimum": true, "exclusiveMinimum": true,
"description": "Number of syntax trees rust-analyzer keeps in memory" "description": "Number of syntax trees rust-analyzer keeps in memory"
}, },
"rust-analyzer.inlayHintOpts.displayType": { "rust-analyzer.inlayHints.typeHints": {
"type": "string", "type": "boolean",
"enum": [ "default": true,
"off", "description": "Whether to show inlay type hints"
"typeHints",
"parameterHints",
"full"
],
"enumDescriptions": [
"No type inlay hints",
"Type inlays hints only",
"Parameter inlays hints only",
"All inlay hints types"
],
"default": "full",
"description": "Display additional type and parameter information in the editor"
}, },
"rust-analyzer.inlayHintOpts.maxLength": { "rust-analyzer.inlayHints.parameterHints": {
"type": [ "type": "boolean",
"null", "default": true,
"integer" "description": "Whether to show function parameter name inlay hints at the call site"
], },
"rust-analyzer.inlayHints.maxLength": {
"type": "integer",
"default": 20, "default": 20,
"minimum": 0, "minimum": 0,
"exclusiveMinimum": true, "exclusiveMinimum": true,

View file

@ -29,7 +29,7 @@ export async function createClient(config: Config, serverPath: string): Promise<
initializationOptions: { initializationOptions: {
publishDecorations: !config.highlightingSemanticTokens, publishDecorations: !config.highlightingSemanticTokens,
lruCapacity: config.lruCapacity, lruCapacity: config.lruCapacity,
inlayHintOpts: config.inlayHintOpts, inlayHints: config.inlayHints,
cargoWatchEnable: cargoWatchOpts.enable, cargoWatchEnable: cargoWatchOpts.enable,
cargoWatchArgs: cargoWatchOpts.arguments, cargoWatchArgs: cargoWatchOpts.arguments,
cargoWatchCommand: cargoWatchOpts.command, cargoWatchCommand: cargoWatchOpts.command,

View file

@ -6,7 +6,8 @@ import { log } from "./util";
const RA_LSP_DEBUG = process.env.__RA_LSP_SERVER_DEBUG; const RA_LSP_DEBUG = process.env.__RA_LSP_SERVER_DEBUG;
export interface InlayHintOptions { export interface InlayHintOptions {
displayType: string; typeHints: boolean;
parameterHints: boolean;
maxLength: number; maxLength: number;
} }
@ -28,8 +29,7 @@ export class Config {
"cargoFeatures", "cargoFeatures",
"cargo-watch", "cargo-watch",
"highlighting.semanticTokens", "highlighting.semanticTokens",
"inlayHintOpts.maxLength", "inlayHints",
"inlayHintOpts.displayType",
] ]
.map(opt => `${Config.rootSection}.${opt}`); .map(opt => `${Config.rootSection}.${opt}`);
@ -156,10 +156,11 @@ export class Config {
get highlightingOn() { return this.cfg.get("highlightingOn") as boolean; } get highlightingOn() { return this.cfg.get("highlightingOn") as boolean; }
get rainbowHighlightingOn() { return this.cfg.get("rainbowHighlightingOn") as boolean; } get rainbowHighlightingOn() { return this.cfg.get("rainbowHighlightingOn") as boolean; }
get lruCapacity() { return this.cfg.get("lruCapacity") as null | number; } get lruCapacity() { return this.cfg.get("lruCapacity") as null | number; }
get inlayHintOpts(): InlayHintOptions { get inlayHints(): InlayHintOptions {
return { return {
displayType: this.cfg.get("inlayHintOpts.displayType") as string, typeHints: this.cfg.get("inlayHints.typeHints") as boolean,
maxLength: this.cfg.get("inlayHintOpts.maxLength") as number, parameterHints: this.cfg.get("inlayHints.parameterHints") as boolean,
maxLength: this.cfg.get("inlayHints.maxLength") as number,
}; };
} }
get excludeGlobs() { return this.cfg.get("excludeGlobs") as string[]; } get excludeGlobs() { return this.cfg.get("excludeGlobs") as string[]; }

View file

@ -10,7 +10,7 @@ export function activateInlayHints(ctx: Ctx) {
const maybeUpdater = { const maybeUpdater = {
updater: null as null | HintsUpdater, updater: null as null | HintsUpdater,
onConfigChange() { onConfigChange() {
if (ctx.config.inlayHintOpts.displayType === 'off') { if (!ctx.config.inlayHints.typeHints && !ctx.config.inlayHints.parameterHints) {
return this.dispose(); return this.dispose();
} }
if (!this.updater) this.updater = new HintsUpdater(ctx); if (!this.updater) this.updater = new HintsUpdater(ctx);