diff options
| author | Jonas Schievink <jonas.schievink@ferrous-systems.com> | 2022-03-22 16:05:24 +0100 |
|---|---|---|
| committer | Jonas Schievink <jonas.schievink@ferrous-systems.com> | 2022-03-22 16:08:46 +0100 |
| commit | 4bb5df0ce54544df5cf89a08067f7b295b242020 (patch) | |
| tree | 86736bea4cefd32386dcb1aa03e07d660a8b04eb | |
| parent | c9cefb9916143abcba6c743a200b27b1a519d3ef (diff) | |
| download | rust-4bb5df0ce54544df5cf89a08067f7b295b242020.tar.gz rust-4bb5df0ce54544df5cf89a08067f7b295b242020.zip | |
Avoid signature help inside multiline expressions
Fixes #11768
| -rw-r--r-- | crates/ide/src/signature_help.rs | 89 | ||||
| -rw-r--r-- | crates/ide_db/src/active_parameter.rs | 10 |
2 files changed, 88 insertions, 11 deletions
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs index 030790e470e..06fdc641f84 100644 --- a/crates/ide/src/signature_help.rs +++ b/crates/ide/src/signature_help.rs @@ -4,11 +4,15 @@ use either::Either; use hir::{HasAttrs, HirDisplay, Semantics}; use ide_db::{ - active_parameter::{callable_for_token, generics_for_token}, + active_parameter::{callable_for_node, generics_for_token}, base_db::FilePosition, }; use stdx::format_to; -use syntax::{algo, AstNode, Direction, TextRange, TextSize}; +use syntax::{ + algo, + ast::{self, HasArgList}, + AstNode, Direction, SyntaxToken, TextRange, TextSize, +}; use crate::RootDatabase; @@ -65,8 +69,8 @@ pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Optio .and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?; let token = sema.descend_into_macros_single(token); - if let Some((callable, active_parameter)) = callable_for_token(&sema, token.clone()) { - return Some(signature_help_for_callable(db, callable, active_parameter)); + if let Some(help) = signature_help_for_call(&sema, &token) { + return Some(help); } if let Some((generic_def, active_parameter)) = generics_for_token(&sema, token.clone()) { @@ -76,14 +80,39 @@ pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Optio None } -fn signature_help_for_callable( - db: &RootDatabase, - callable: hir::Callable, - active_parameter: Option<usize>, -) -> SignatureHelp { +fn signature_help_for_call( + sema: &Semantics<RootDatabase>, + token: &SyntaxToken, +) -> Option<SignatureHelp> { + // Find the calling expression and its NameRef + let mut node = token.parent()?; + let calling_node = loop { + if let Some(callable) = ast::CallableExpr::cast(node.clone()) { + if callable + .arg_list() + .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start())) + { + break callable; + } + } + + // Stop at multi-line expressions, since the signature of the outer call is not very + // helpful inside them. + if let Some(expr) = ast::Expr::cast(node.clone()) { + if expr.syntax().text().contains_char('\n') { + return None; + } + } + + node = node.parent()?; + }; + + let (callable, active_parameter) = callable_for_node(sema, &calling_node, token)?; + let mut res = SignatureHelp { doc: None, signature: String::new(), parameters: vec![], active_parameter }; + let db = sema.db; match callable.kind() { hir::CallableKind::Function(func) => { res.doc = func.docs(db).map(|it| it.into()); @@ -134,7 +163,7 @@ fn signature_help_for_callable( } hir::CallableKind::TupleStruct(_) | hir::CallableKind::TupleEnumVariant(_) => {} } - res + Some(res) } fn signature_help_for_generics( @@ -787,6 +816,46 @@ fn main() { } #[test] + fn test_multiline_argument() { + check( + r#" +fn callee(a: u8, b: u8) {} +fn main() { + callee(match 0 { + 0 => 1,$0 + }) +}"#, + expect![[r#""#]], + ); + check( + r#" +fn callee(a: u8, b: u8) {} +fn main() { + callee(match 0 { + 0 => 1, + },$0) +}"#, + expect![[r#" + fn callee(a: u8, b: u8) + ----- ^^^^^ + "#]], + ); + check( + r#" +fn callee(a: u8, b: u8) {} +fn main() { + callee($0match 0 { + 0 => 1, + }) +}"#, + expect![[r#" + fn callee(a: u8, b: u8) + ^^^^^ ----- + "#]], + ); + } + + #[test] fn test_generics_simple() { check( r#" diff --git a/crates/ide_db/src/active_parameter.rs b/crates/ide_db/src/active_parameter.rs index 67b819c5a5d..ed0c010f836 100644 --- a/crates/ide_db/src/active_parameter.rs +++ b/crates/ide_db/src/active_parameter.rs @@ -43,13 +43,21 @@ pub fn callable_for_token( sema: &Semantics<RootDatabase>, token: SyntaxToken, ) -> Option<(hir::Callable, Option<usize>)> { - // Find the calling expression and it's NameRef + // Find the calling expression and its NameRef let parent = token.parent()?; let calling_node = parent.ancestors().filter_map(ast::CallableExpr::cast).find(|it| { it.arg_list() .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start())) })?; + callable_for_node(sema, &calling_node, &token) +} + +pub fn callable_for_node( + sema: &Semantics<RootDatabase>, + calling_node: &ast::CallableExpr, + token: &SyntaxToken, +) -> Option<(hir::Callable, Option<usize>)> { let callable = match &calling_node { ast::CallableExpr::Call(call) => { let expr = call.expr()?; |
