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.rs50
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
+ }
+}