Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-db/src/active_parameter.rs')
| -rw-r--r-- | crates/ide-db/src/active_parameter.rs | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/crates/ide-db/src/active_parameter.rs b/crates/ide-db/src/active_parameter.rs index f12d474497..2b6b60547b 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)) +} |