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 | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/crates/ide_db/src/active_parameter.rs b/crates/ide_db/src/active_parameter.rs index 47bd7aa979..67b819c5a5 100644 --- a/crates/ide_db/src/active_parameter.rs +++ b/crates/ide_db/src/active_parameter.rs @@ -68,3 +68,53 @@ pub fn callable_for_token( }; Some((callable, active_param)) } + +pub fn generics_for_token( + sema: &Semantics<RootDatabase>, + token: SyntaxToken, +) -> Option<(hir::GenericDef, usize)> { + let parent = token.parent()?; + let arg_list = parent + .ancestors() + .filter_map(ast::GenericArgList::cast) + .find(|list| list.syntax().text_range().contains(token.text_range().start()))?; + + let active_param = arg_list + .generic_args() + .take_while(|arg| arg.syntax().text_range().end() <= token.text_range().start()) + .count(); + + 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::AssocItem(hir::AssocItem::Function(it)) => it.into(), + hir::PathResolution::AssocItem(hir::AssocItem::TypeAlias(it)) => it.into(), + hir::PathResolution::AssocItem(hir::AssocItem::Const(_)) => return None, + hir::PathResolution::BuiltinAttr(_) + | hir::PathResolution::ToolModule(_) + | hir::PathResolution::Local(_) + | hir::PathResolution::TypeParam(_) + | hir::PathResolution::ConstParam(_) + | hir::PathResolution::SelfType(_) => return None, + }; + + Some((generic_def, active_param)) + } 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)?; + Some((method.into(), active_param)) + } else { + None + } +} |