about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-02-13 11:25:45 +0100
committerLukas Wirth <lukastw97@gmail.com>2023-02-13 11:25:45 +0100
commit244a48d13d697dd4f8ba9a3e9084ec1aec9db06c (patch)
tree75b5989ddaab7a83f233e5895340423b4377e7a8
parent9738f97f8c7542d84f1996e1f857ecd77adda160 (diff)
downloadrust-244a48d13d697dd4f8ba9a3e9084ec1aec9db06c.tar.gz
rust-244a48d13d697dd4f8ba9a3e9084ec1aec9db06c.zip
Cleanup signature help a bit
-rw-r--r--crates/ide-db/src/active_parameter.rs63
-rw-r--r--crates/ide/src/signature_help.rs81
2 files changed, 79 insertions, 65 deletions
diff --git a/crates/ide-db/src/active_parameter.rs b/crates/ide-db/src/active_parameter.rs
index f12d4744974..2b6b60547b3 100644
--- a/crates/ide-db/src/active_parameter.rs
+++ b/crates/ide-db/src/active_parameter.rs
@@ -5,7 +5,7 @@ use hir::{Semantics, Type};
 use parser::T;
 use syntax::{
     ast::{self, HasArgList, HasName},
-    AstNode, NodeOrToken, SyntaxToken,
+    match_ast, AstNode, NodeOrToken, SyntaxToken,
 };
 
 use crate::RootDatabase;
@@ -81,3 +81,64 @@ pub fn callable_for_node(
     };
     Some((callable, active_param))
 }
+
+pub fn generic_def_for_node(
+    sema: &Semantics<'_, RootDatabase>,
+    generic_arg_list: &ast::GenericArgList,
+    token: &SyntaxToken,
+) -> Option<(hir::GenericDef, usize, bool)> {
+    let parent = generic_arg_list.syntax().parent()?;
+    let def = match_ast! {
+        match parent {
+            ast::PathSegment(ps) => {
+                let res = sema.resolve_path(&ps.parent_path())?;
+                let generic_def: hir::GenericDef = match res {
+                    hir::PathResolution::Def(hir::ModuleDef::Adt(it)) => it.into(),
+                    hir::PathResolution::Def(hir::ModuleDef::Function(it)) => it.into(),
+                    hir::PathResolution::Def(hir::ModuleDef::Trait(it)) => it.into(),
+                    hir::PathResolution::Def(hir::ModuleDef::TypeAlias(it)) => it.into(),
+                    hir::PathResolution::Def(hir::ModuleDef::Variant(it)) => it.into(),
+                    hir::PathResolution::Def(hir::ModuleDef::BuiltinType(_))
+                    | hir::PathResolution::Def(hir::ModuleDef::Const(_))
+                    | hir::PathResolution::Def(hir::ModuleDef::Macro(_))
+                    | hir::PathResolution::Def(hir::ModuleDef::Module(_))
+                    | hir::PathResolution::Def(hir::ModuleDef::Static(_)) => return None,
+                    hir::PathResolution::BuiltinAttr(_)
+                    | hir::PathResolution::ToolModule(_)
+                    | hir::PathResolution::Local(_)
+                    | hir::PathResolution::TypeParam(_)
+                    | hir::PathResolution::ConstParam(_)
+                    | hir::PathResolution::SelfType(_)
+                    | hir::PathResolution::DeriveHelper(_) => return None,
+                };
+
+                generic_def
+            },
+            ast::AssocTypeArg(_) => {
+                // FIXME: We don't record the resolutions for this anywhere atm
+                return None;
+            },
+            ast::MethodCallExpr(mcall) => {
+                // recv.method::<$0>()
+                let method = sema.resolve_method_call(&mcall)?;
+                method.into()
+            },
+            _ => return None,
+        }
+    };
+
+    let active_param = generic_arg_list
+        .syntax()
+        .children_with_tokens()
+        .filter_map(NodeOrToken::into_token)
+        .filter(|t| t.kind() == T![,])
+        .take_while(|t| t.text_range().start() <= token.text_range().start())
+        .count();
+
+    let first_arg_is_non_lifetime = generic_arg_list
+        .generic_args()
+        .next()
+        .map_or(false, |arg| !matches!(arg, ast::GenericArg::LifetimeArg(_)));
+
+    Some((def, active_param, first_arg_is_non_lifetime))
+}
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index 26e45acff10..f70ca55a508 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -7,7 +7,11 @@ use either::Either;
 use hir::{
     AssocItem, GenericParam, HasAttrs, HirDisplay, ModuleDef, PathResolution, Semantics, Trait,
 };
-use ide_db::{active_parameter::callable_for_node, base_db::FilePosition, FxIndexMap};
+use ide_db::{
+    active_parameter::{callable_for_node, generic_def_for_node},
+    base_db::FilePosition,
+    FxIndexMap,
+};
 use stdx::format_to;
 use syntax::{
     algo,
@@ -214,59 +218,11 @@ fn signature_help_for_call(
 
 fn signature_help_for_generics(
     sema: &Semantics<'_, RootDatabase>,
-    garg_list: ast::GenericArgList,
+    arg_list: ast::GenericArgList,
     token: SyntaxToken,
 ) -> Option<SignatureHelp> {
-    let arg_list = garg_list
-        .syntax()
-        .ancestors()
-        .filter_map(ast::GenericArgList::cast)
-        .find(|list| list.syntax().text_range().contains(token.text_range().start()))?;
-
-    let mut active_parameter = arg_list
-        .generic_args()
-        .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
-        .count();
-
-    let first_arg_is_non_lifetime = arg_list
-        .generic_args()
-        .next()
-        .map_or(false, |arg| !matches!(arg, ast::GenericArg::LifetimeArg(_)));
-
-    let mut generics_def = if let Some(path) =
-        arg_list.syntax().ancestors().find_map(ast::Path::cast)
-    {
-        let res = sema.resolve_path(&path)?;
-        let generic_def: hir::GenericDef = match res {
-            hir::PathResolution::Def(hir::ModuleDef::Adt(it)) => it.into(),
-            hir::PathResolution::Def(hir::ModuleDef::Function(it)) => it.into(),
-            hir::PathResolution::Def(hir::ModuleDef::Trait(it)) => it.into(),
-            hir::PathResolution::Def(hir::ModuleDef::TypeAlias(it)) => it.into(),
-            hir::PathResolution::Def(hir::ModuleDef::Variant(it)) => it.into(),
-            hir::PathResolution::Def(hir::ModuleDef::BuiltinType(_))
-            | hir::PathResolution::Def(hir::ModuleDef::Const(_))
-            | hir::PathResolution::Def(hir::ModuleDef::Macro(_))
-            | hir::PathResolution::Def(hir::ModuleDef::Module(_))
-            | hir::PathResolution::Def(hir::ModuleDef::Static(_)) => return None,
-            hir::PathResolution::BuiltinAttr(_)
-            | hir::PathResolution::ToolModule(_)
-            | hir::PathResolution::Local(_)
-            | hir::PathResolution::TypeParam(_)
-            | hir::PathResolution::ConstParam(_)
-            | hir::PathResolution::SelfType(_)
-            | hir::PathResolution::DeriveHelper(_) => return None,
-        };
-
-        generic_def
-    } else if let Some(method_call) = arg_list.syntax().parent().and_then(ast::MethodCallExpr::cast)
-    {
-        // recv.method::<$0>()
-        let method = sema.resolve_method_call(&method_call)?;
-        method.into()
-    } else {
-        return None;
-    };
-
+    let (mut generics_def, mut active_parameter, first_arg_is_non_lifetime) =
+        generic_def_for_node(sema, &arg_list, &token)?;
     let mut res = SignatureHelp {
         doc: None,
         signature: String::new(),
@@ -305,9 +261,9 @@ fn signature_help_for_generics(
             // eg. `None::<u8>`
             // We'll use the signature of the enum, but include the docs of the variant.
             res.doc = it.docs(db).map(|it| it.into());
-            let it = it.parent_enum(db);
-            format_to!(res.signature, "enum {}", it.name(db));
-            generics_def = it.into();
+            let enum_ = it.parent_enum(db);
+            format_to!(res.signature, "enum {}", enum_.name(db));
+            generics_def = enum_.into();
         }
         // These don't have generic args that can be specified
         hir::GenericDef::Impl(_) | hir::GenericDef::Const(_) => return None,
@@ -386,16 +342,13 @@ fn signature_help_for_record_lit(
     record: ast::RecordExpr,
     token: SyntaxToken,
 ) -> Option<SignatureHelp> {
-    let arg_list = record
-        .syntax()
-        .ancestors()
-        .filter_map(ast::RecordExpr::cast)
-        .find(|list| list.syntax().text_range().contains(token.text_range().start()))?;
-
-    let active_parameter = arg_list
+    let active_parameter = record
         .record_expr_field_list()?
-        .fields()
-        .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start())
+        .syntax()
+        .children_with_tokens()
+        .filter_map(syntax::NodeOrToken::into_token)
+        .filter(|t| t.kind() == syntax::T![,])
+        .take_while(|t| t.text_range().start() <= token.text_range().start())
         .count();
 
     let mut res = SignatureHelp {