From a197abbc7aed53c42cac7e9e86787e44a5026291 Mon Sep 17 00:00:00 2001 From: Matt Hooper Date: Mon, 23 Mar 2020 20:32:05 +0100 Subject: Added new inlay hint kind and rules for method chaining --- crates/ra_ide/src/inlay_hints.rs | 97 +++++++++++++++++++++++++++++++++-- crates/rust-analyzer/src/config.rs | 3 ++ crates/rust-analyzer/src/conv.rs | 1 + crates/rust-analyzer/src/main_loop.rs | 1 + crates/rust-analyzer/src/req.rs | 1 + 5 files changed, 98 insertions(+), 5 deletions(-) diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index ecd615cf4..2353ad71f 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -5,7 +5,7 @@ use ra_ide_db::RootDatabase; use ra_prof::profile; use ra_syntax::{ ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, - match_ast, SmolStr, TextRange, + match_ast, SmolStr, TextRange, NodeOrToken, SyntaxKind, Direction }; use crate::{FileId, FunctionSignature}; @@ -14,12 +14,18 @@ use crate::{FileId, FunctionSignature}; pub struct InlayHintsOptions { pub type_hints: bool, pub parameter_hints: bool, + pub chaining_hints: bool, pub max_length: Option, } impl Default for InlayHintsOptions { fn default() -> Self { - Self { type_hints: true, parameter_hints: true, max_length: None } + Self { + type_hints: true, + parameter_hints: true, + chaining_hints: true, + max_length: None + } } } @@ -27,6 +33,7 @@ impl Default for InlayHintsOptions { pub enum InlayKind { TypeHint, ParameterHint, + ChainingHint, } #[derive(Debug)] @@ -47,6 +54,10 @@ pub(crate) fn inlay_hints( let mut res = Vec::new(); for node in file.syntax().descendants() { + if let Some(expr) = ast::Expr::cast(node.clone()) { + get_chaining_hints(&mut res, &sema, options, expr); + } + match_ast! { match node { ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, options, ast::Expr::from(it)); }, @@ -222,6 +233,45 @@ fn get_fn_signature(sema: &Semantics, expr: &ast::Expr) -> Option< } } +fn get_chaining_hints( + acc: &mut Vec, + sema: &Semantics, + options: &InlayHintsOptions, + expr: ast::Expr, +) -> Option<()> { + if !options.chaining_hints { + return None; + } + + let ty = sema.type_of_expr(&expr)?; + let label = ty.display_truncated(sema.db, options.max_length).to_string(); + if ty.is_unknown() { + return None; + } + + let mut tokens = expr.syntax() + .siblings_with_tokens(Direction::Next) + .filter_map(NodeOrToken::into_token) + .filter(|t| match t.kind() { + SyntaxKind::WHITESPACE if !t.text().contains('\n') => false, + SyntaxKind::COMMENT => false, + _ => true, + }); + + // Chaining can be defined as an expression whose next sibling tokens are newline and dot + // Ignoring extra whitespace and comments + let next = tokens.next()?.kind(); + let next_next = tokens.next()?.kind(); + if next == SyntaxKind::WHITESPACE && next_next == SyntaxKind::DOT { + acc.push(InlayHint { + range: expr.syntax().text_range(), + kind: InlayKind::ChainingHint, + label: label.into(), + }); + } + Some(()) +} + #[cfg(test)] mod tests { use crate::inlay_hints::InlayHintsOptions; @@ -229,6 +279,43 @@ mod tests { use crate::mock_analysis::single_file; + #[test] + fn generic_chaining_hints() { + let (analysis, file_id) = single_file( + r#" + struct A(T); + struct B(T); + struct C(T); + struct X(T, R); + + impl A { + fn new(t: T) -> Self { A(t) } + fn into_b(self) -> B { B(self.0) } + } + impl B { + fn into_c(self) -> C { C(self.0) } + } + fn test() { + let c = A::new(X(42, true)) + .into_b() // All the from A -> B -> C + .into_c(); + }"#, + ); + assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" + [ + InlayHint { + range: [416; 465), + kind: ChainingHint, + label: "B>", + }, + InlayHint { + range: [416; 435), + kind: ChainingHint, + label: "A>", + }, + ]"###); + } + #[test] fn param_hints_only() { let (analysis, file_id) = single_file( @@ -238,7 +325,7 @@ mod tests { let _x = foo(4, 4); }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: true, type_hints: false, max_length: None}).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: true, type_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###" [ InlayHint { range: [106; 107), @@ -262,7 +349,7 @@ mod tests { let _x = foo(4, 4); }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ type_hints: false, parameter_hints: false, max_length: None}).unwrap(), @r###"[]"###); + assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ type_hints: false, parameter_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###"[]"###); } #[test] @@ -274,7 +361,7 @@ mod tests { let _x = foo(4, 4); }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ type_hints: true, parameter_hints: false, max_length: None}).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ type_hints: true, parameter_hints: false, chaining_hints: false, max_length: None}).unwrap(), @r###" [ InlayHint { range: [97; 99), diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 103b2b53c..628ed107e 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -34,6 +34,8 @@ pub struct ServerConfig { pub inlay_hints_type: bool, #[serde(deserialize_with = "nullable_bool_true")] pub inlay_hints_parameter: bool, + #[serde(deserialize_with = "nullable_bool_true")] + pub inlay_hints_chaining: bool, pub inlay_hints_max_length: Option, pub cargo_watch_enable: bool, @@ -66,6 +68,7 @@ impl Default for ServerConfig { lru_capacity: None, inlay_hints_type: true, inlay_hints_parameter: true, + inlay_hints_chaining: true, inlay_hints_max_length: None, cargo_watch_enable: true, cargo_watch_args: Vec::new(), diff --git a/crates/rust-analyzer/src/conv.rs b/crates/rust-analyzer/src/conv.rs index fd4657d7e..6edc03fe0 100644 --- a/crates/rust-analyzer/src/conv.rs +++ b/crates/rust-analyzer/src/conv.rs @@ -332,6 +332,7 @@ impl ConvWith<&LineIndex> for InlayHint { kind: match self.kind { InlayKind::ParameterHint => req::InlayKind::ParameterHint, InlayKind::TypeHint => req::InlayKind::TypeHint, + InlayKind::ChainingHint => req::InlayKind::ChainingHint, }, } } diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index a8a5894d2..7825b0077 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -183,6 +183,7 @@ pub fn main_loop( inlay_hints: InlayHintsOptions { type_hints: config.inlay_hints_type, parameter_hints: config.inlay_hints_parameter, + chaining_hints: config.inlay_hints_chaining, max_length: config.inlay_hints_max_length, }, cargo_watch: CheckOptions { diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/req.rs index 9e27d3f1c..8557294f6 100644 --- a/crates/rust-analyzer/src/req.rs +++ b/crates/rust-analyzer/src/req.rs @@ -200,6 +200,7 @@ pub struct InlayHintsParams { pub enum InlayKind { TypeHint, ParameterHint, + ChainingHint, } #[derive(Debug, Deserialize, Serialize)] -- cgit v1.2.3 From 6f239a581a0acf8d1c3f26da68146c5c1ea7d4f2 Mon Sep 17 00:00:00 2001 From: Matt Hooper Date: Mon, 23 Mar 2020 23:32:50 +0100 Subject: Extension types and rendering --- editors/code/package.json | 5 +++++ editors/code/src/client.ts | 1 + editors/code/src/config.ts | 1 + editors/code/src/inlay_hints.ts | 32 +++++++++++++++++++++++++++++--- editors/code/src/rust-analyzer-api.ts | 4 +++- 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index 1d113ebb6..37e083220 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -333,6 +333,11 @@ "default": true, "description": "Whether to show inlay type hints" }, + "rust-analyzer.inlayHints.chainingHints": { + "type": "boolean", + "default": true, + "description": "Whether to show inlay type hints for method chains" + }, "rust-analyzer.inlayHints.parameterHints": { "type": "boolean", "default": true, diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 82ca749f3..98f2f232f 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -32,6 +32,7 @@ export async function createClient(config: Config, serverPath: string): Promise< inlayHintsType: config.inlayHints.typeHints, inlayHintsParameter: config.inlayHints.parameterHints, + inlayHintsChaining: config.inlayHints.chainingHints, inlayHintsMaxLength: config.inlayHints.maxLength, cargoWatchEnable: cargoWatchOpts.enable, diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 7668c20b7..637aea27d 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -88,6 +88,7 @@ export class Config { return { typeHints: this.cfg.get("inlayHints.typeHints")!, parameterHints: this.cfg.get("inlayHints.parameterHints")!, + chainingHints: this.cfg.get("inlayHints.chainingHints")!, maxLength: this.cfg.get("inlayHints.maxLength")!, }; } diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts index 17d0dfa33..542d1f367 100644 --- a/editors/code/src/inlay_hints.ts +++ b/editors/code/src/inlay_hints.ts @@ -10,7 +10,11 @@ export function activateInlayHints(ctx: Ctx) { const maybeUpdater = { updater: null as null | HintsUpdater, onConfigChange() { - if (!ctx.config.inlayHints.typeHints && !ctx.config.inlayHints.parameterHints) { + if ( + !ctx.config.inlayHints.typeHints && + !ctx.config.inlayHints.parameterHints && + !ctx.config.inlayHints.chainingHints + ) { return this.dispose(); } if (!this.updater) this.updater = new HintsUpdater(ctx); @@ -63,6 +67,22 @@ const paramHints = { } }; +const chainingHints = { + decorationType: vscode.window.createTextEditorDecorationType({ + after: { + color: new vscode.ThemeColor('rust_analyzer.inlayHint'), + fontStyle: "normal", + } + }), + + toDecoration(hint: ra.InlayHint.ChainingHint, conv: lc.Protocol2CodeConverter): vscode.DecorationOptions { + return { + range: conv.asRange(hint.range), + renderOptions: { after: { contentText: ` ${hint.label}` } } + }; + } +}; + class HintsUpdater implements Disposable { private sourceFiles = new Map(); // map Uri -> RustSourceFile private readonly disposables: Disposable[] = []; @@ -95,7 +115,7 @@ class HintsUpdater implements Disposable { dispose() { this.sourceFiles.forEach(file => file.inlaysRequest?.cancel()); - this.ctx.visibleRustEditors.forEach(editor => this.renderDecorations(editor, { param: [], type: [] })); + this.ctx.visibleRustEditors.forEach(editor => this.renderDecorations(editor, { param: [], type: [], chaining: [] })); this.disposables.forEach(d => d.dispose()); } @@ -154,10 +174,11 @@ class HintsUpdater implements Disposable { private renderDecorations(editor: RustEditor, decorations: InlaysDecorations) { editor.setDecorations(typeHints.decorationType, decorations.type); editor.setDecorations(paramHints.decorationType, decorations.param); + editor.setDecorations(chainingHints.decorationType, decorations.chaining); } private hintsToDecorations(hints: ra.InlayHint[]): InlaysDecorations { - const decorations: InlaysDecorations = { type: [], param: [] }; + const decorations: InlaysDecorations = { type: [], param: [], chaining: [] }; const conv = this.ctx.client.protocol2CodeConverter; for (const hint of hints) { @@ -170,6 +191,10 @@ class HintsUpdater implements Disposable { decorations.param.push(paramHints.toDecoration(hint, conv)); continue; } + case ra.InlayHint.Kind.ChainingHint: { + decorations.chaining.push(chainingHints.toDecoration(hint, conv)); + continue; + } } } return decorations; @@ -196,6 +221,7 @@ class HintsUpdater implements Disposable { interface InlaysDecorations { type: vscode.DecorationOptions[]; param: vscode.DecorationOptions[]; + chaining: vscode.DecorationOptions[]; } interface RustSourceFile { diff --git a/editors/code/src/rust-analyzer-api.ts b/editors/code/src/rust-analyzer-api.ts index 9846f7343..400ac3714 100644 --- a/editors/code/src/rust-analyzer-api.ts +++ b/editors/code/src/rust-analyzer-api.ts @@ -86,12 +86,13 @@ export interface Runnable { } export const runnables = request>("runnables"); -export type InlayHint = InlayHint.TypeHint | InlayHint.ParamHint; +export type InlayHint = InlayHint.TypeHint | InlayHint.ParamHint | InlayHint.ChainingHint; export namespace InlayHint { export const enum Kind { TypeHint = "TypeHint", ParamHint = "ParameterHint", + ChainingHint = "ChainingHint", } interface Common { range: lc.Range; @@ -99,6 +100,7 @@ export namespace InlayHint { } export type TypeHint = Common & { kind: Kind.TypeHint }; export type ParamHint = Common & { kind: Kind.ParamHint }; + export type ChainingHint = Common & { kind: Kind.ChainingHint }; } export interface InlayHintsParams { textDocument: lc.TextDocumentIdentifier; -- cgit v1.2.3 From c1f9a1a1c5f32f9fb311e6e91033e1811c5acc47 Mon Sep 17 00:00:00 2001 From: Matt Hooper Date: Tue, 24 Mar 2020 01:10:03 +0100 Subject: Updated docs --- docs/user/features.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/user/features.md b/docs/user/features.md index 45360c633..56d2969fd 100644 --- a/docs/user/features.md +++ b/docs/user/features.md @@ -185,6 +185,7 @@ These contain extended information on the hovered language item. Two types of inlay hints are displayed currently: * type hints, displaying the minimal information on the type of the expression (if the information is available) +* method chaining hints, type information for multi-line method chains * parameter name hints, displaying the names of the parameters in the corresponding methods #### VS Code @@ -192,6 +193,7 @@ Two types of inlay hints are displayed currently: In VS Code, the following settings can be used to configure the inlay hints: * `rust-analyzer.inlayHints.typeHints` - enable hints for inferred types. +* `rust-analyzer.inlayHints.chainingHints` - enable hints for inferred types on method chains. * `rust-analyzer.inlayHints.parameterHints` - enable hints for function parameters. * `rust-analyzer.inlayHints.maxLength` — shortens the hints if their length exceeds the value specified. If no value is specified (`null`), no shortening is applied. -- cgit v1.2.3 From b70ce559b8d3102c3fed3ecef8edef3038a5ceed Mon Sep 17 00:00:00 2001 From: Matt Hooper Date: Tue, 24 Mar 2020 19:33:00 +0100 Subject: Added more unit tests --- crates/ra_ide/src/inlay_hints.rs | 235 ++++++++++++++++++++++++++------------- 1 file changed, 159 insertions(+), 76 deletions(-) diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 2353ad71f..293944206 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -70,6 +70,45 @@ pub(crate) fn inlay_hints( res } +fn get_chaining_hints( + acc: &mut Vec, + sema: &Semantics, + options: &InlayHintsOptions, + expr: ast::Expr, +) -> Option<()> { + if !options.chaining_hints { + return None; + } + + let ty = sema.type_of_expr(&expr)?; + let label = ty.display_truncated(sema.db, options.max_length).to_string(); + if ty.is_unknown() { + return None; + } + + let mut tokens = expr.syntax() + .siblings_with_tokens(Direction::Next) + .filter_map(NodeOrToken::into_token) + .filter(|t| match t.kind() { + SyntaxKind::WHITESPACE if !t.text().contains('\n') => false, + SyntaxKind::COMMENT => false, + _ => true, + }); + + // Chaining can be defined as an expression whose next sibling tokens are newline and dot + // Ignoring extra whitespace and comments + let next = tokens.next()?.kind(); + let next_next = tokens.next()?.kind(); + if next == SyntaxKind::WHITESPACE && next_next == SyntaxKind::DOT { + acc.push(InlayHint { + range: expr.syntax().text_range(), + kind: InlayKind::ChainingHint, + label: label.into(), + }); + } + Some(()) +} + fn get_param_name_hints( acc: &mut Vec, sema: &Semantics, @@ -233,45 +272,6 @@ fn get_fn_signature(sema: &Semantics, expr: &ast::Expr) -> Option< } } -fn get_chaining_hints( - acc: &mut Vec, - sema: &Semantics, - options: &InlayHintsOptions, - expr: ast::Expr, -) -> Option<()> { - if !options.chaining_hints { - return None; - } - - let ty = sema.type_of_expr(&expr)?; - let label = ty.display_truncated(sema.db, options.max_length).to_string(); - if ty.is_unknown() { - return None; - } - - let mut tokens = expr.syntax() - .siblings_with_tokens(Direction::Next) - .filter_map(NodeOrToken::into_token) - .filter(|t| match t.kind() { - SyntaxKind::WHITESPACE if !t.text().contains('\n') => false, - SyntaxKind::COMMENT => false, - _ => true, - }); - - // Chaining can be defined as an expression whose next sibling tokens are newline and dot - // Ignoring extra whitespace and comments - let next = tokens.next()?.kind(); - let next_next = tokens.next()?.kind(); - if next == SyntaxKind::WHITESPACE && next_next == SyntaxKind::DOT { - acc.push(InlayHint { - range: expr.syntax().text_range(), - kind: InlayKind::ChainingHint, - label: label.into(), - }); - } - Some(()) -} - #[cfg(test)] mod tests { use crate::inlay_hints::InlayHintsOptions; @@ -279,43 +279,6 @@ mod tests { use crate::mock_analysis::single_file; - #[test] - fn generic_chaining_hints() { - let (analysis, file_id) = single_file( - r#" - struct A(T); - struct B(T); - struct C(T); - struct X(T, R); - - impl A { - fn new(t: T) -> Self { A(t) } - fn into_b(self) -> B { B(self.0) } - } - impl B { - fn into_c(self) -> C { C(self.0) } - } - fn test() { - let c = A::new(X(42, true)) - .into_b() // All the from A -> B -> C - .into_c(); - }"#, - ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" - [ - InlayHint { - range: [416; 465), - kind: ChainingHint, - label: "B>", - }, - InlayHint { - range: [416; 435), - kind: ChainingHint, - label: "A>", - }, - ]"###); - } - #[test] fn param_hints_only() { let (analysis, file_id) = single_file( @@ -1139,4 +1102,124 @@ fn main() { "### ); } + + #[test] + fn chaining_hints_ignore_comments() { + let (analysis, file_id) = single_file( + r#" + struct A(B); + impl A { fn into_b(self) -> B { self.0 } } + struct B(C) + impl B { fn into_c(self) -> C { self.0 } } + struct C; + + fn main() { + let c = A(B(C)) + .into_b() // This is a comment + .into_c(); + }"#, + ); + assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" + [ + InlayHint { + range: [231; 268), + kind: ChainingHint, + label: "B", + }, + InlayHint { + range: [231; 238), + kind: ChainingHint, + label: "A", + }, + ]"###); + } + + #[test] + fn chaining_hints_without_newlines() { + let (analysis, file_id) = single_file( + r#" + struct A(B); + impl A { fn into_b(self) -> B { self.0 } } + struct B(C) + impl B { fn into_c(self) -> C { self.0 } } + struct C; + + fn main() { + let c = A(B(C)).into_b().into_c(); + }"#, + ); + assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###"[]"###); + } + + #[test] + fn struct_access_chaining_hints() { + let (analysis, file_id) = single_file( + r#" + struct A { pub b: B } + struct B { pub c: C } + struct C(pub bool); + + fn main() { + let x = A { b: B { c: C(true) } } + .b + .c + .0; + }"#, + ); + assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" + [ + InlayHint { + range: [150; 221), + kind: ChainingHint, + label: "C", + }, + InlayHint { + range: [150; 198), + kind: ChainingHint, + label: "B", + }, + InlayHint { + range: [150; 175), + kind: ChainingHint, + label: "A", + }, + ]"###); + } + + #[test] + fn generic_chaining_hints() { + let (analysis, file_id) = single_file( + r#" + struct A(T); + struct B(T); + struct C(T); + struct X(T, R); + + impl A { + fn new(t: T) -> Self { A(t) } + fn into_b(self) -> B { B(self.0) } + } + impl B { + fn into_c(self) -> C { C(self.0) } + } + fn main() { + let c = A::new(X(42, true)) + .into_b() + .into_c(); + }"#, + ); + assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" + [ + InlayHint { + range: [416; 465), + kind: ChainingHint, + label: "B>", + }, + InlayHint { + range: [416; 435), + kind: ChainingHint, + label: "A>", + }, + ]"###); + } } -- cgit v1.2.3 From 9d298115a62343e207992bbceb0279522324bf75 Mon Sep 17 00:00:00 2001 From: Matt Hooper Date: Tue, 24 Mar 2020 20:31:02 +0100 Subject: Fmt corrections --- crates/ra_ide/src/inlay_hints.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 293944206..07aab45ee 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -5,7 +5,7 @@ use ra_ide_db::RootDatabase; use ra_prof::profile; use ra_syntax::{ ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner}, - match_ast, SmolStr, TextRange, NodeOrToken, SyntaxKind, Direction + match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, }; use crate::{FileId, FunctionSignature}; @@ -20,12 +20,7 @@ pub struct InlayHintsOptions { impl Default for InlayHintsOptions { fn default() -> Self { - Self { - type_hints: true, - parameter_hints: true, - chaining_hints: true, - max_length: None - } + Self { type_hints: true, parameter_hints: true, chaining_hints: true, max_length: None } } } @@ -86,7 +81,8 @@ fn get_chaining_hints( return None; } - let mut tokens = expr.syntax() + let mut tokens = expr + .syntax() .siblings_with_tokens(Direction::Next) .filter_map(NodeOrToken::into_token) .filter(|t| match t.kind() { @@ -99,7 +95,7 @@ fn get_chaining_hints( // Ignoring extra whitespace and comments let next = tokens.next()?.kind(); let next_next = tokens.next()?.kind(); - if next == SyntaxKind::WHITESPACE && next_next == SyntaxKind::DOT { + if next == SyntaxKind::WHITESPACE && next_next == SyntaxKind::DOT { acc.push(InlayHint { range: expr.syntax().text_range(), kind: InlayKind::ChainingHint, @@ -1190,11 +1186,11 @@ fn main() { fn generic_chaining_hints() { let (analysis, file_id) = single_file( r#" - struct A(T); + struct A(T); struct B(T); struct C(T); struct X(T, R); - + impl A { fn new(t: T) -> Self { A(t) } fn into_b(self) -> B { B(self.0) } @@ -1211,12 +1207,12 @@ fn main() { assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" [ InlayHint { - range: [416; 465), + range: [403; 452), kind: ChainingHint, label: "B>", }, InlayHint { - range: [416; 435), + range: [403; 422), kind: ChainingHint, label: "A>", }, -- cgit v1.2.3 From 7b35da04bf56a5461321a6dca515dcd29f44b57f Mon Sep 17 00:00:00 2001 From: Matt Hooper Date: Tue, 24 Mar 2020 23:50:25 +0100 Subject: Improvements based on code review feedback --- crates/ra_ide/src/inlay_hints.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 07aab45ee..f4f0751c0 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -76,7 +76,6 @@ fn get_chaining_hints( } let ty = sema.type_of_expr(&expr)?; - let label = ty.display_truncated(sema.db, options.max_length).to_string(); if ty.is_unknown() { return None; } @@ -96,6 +95,7 @@ fn get_chaining_hints( let next = tokens.next()?.kind(); let next_next = tokens.next()?.kind(); if next == SyntaxKind::WHITESPACE && next_next == SyntaxKind::DOT { + let label = ty.display_truncated(sema.db, options.max_length).to_string(); acc.push(InlayHint { range: expr.syntax().text_range(), kind: InlayKind::ChainingHint, @@ -1105,7 +1105,7 @@ fn main() { r#" struct A(B); impl A { fn into_b(self) -> B { self.0 } } - struct B(C) + struct B(C); impl B { fn into_c(self) -> C { self.0 } } struct C; @@ -1118,12 +1118,12 @@ fn main() { assert_debug_snapshot!(analysis.inlay_hints(file_id, &InlayHintsOptions{ parameter_hints: false, type_hints: false, chaining_hints: true, max_length: None}).unwrap(), @r###" [ InlayHint { - range: [231; 268), + range: [232; 269), kind: ChainingHint, label: "B", }, InlayHint { - range: [231; 238), + range: [232; 239), kind: ChainingHint, label: "A", }, @@ -1136,7 +1136,7 @@ fn main() { r#" struct A(B); impl A { fn into_b(self) -> B { self.0 } } - struct B(C) + struct B(C); impl B { fn into_c(self) -> C { self.0 } } struct C; -- cgit v1.2.3