-/// Parses and returns the derive path at the cursor position in the given attribute, if it is a derive.
-/// This special case is required because the derive macro is a compiler builtin that discards the input derives.
-///
-/// The returned path is synthesized from TokenTree tokens and as such cannot be used with the [`Semantics`].
-pub fn get_path_in_derive_attr(
- sema: &hir::Semantics<RootDatabase>,
- attr: &ast::Attr,
- cursor: &Ident,
-) -> Option<ast::Path> {
- let path = attr.path()?;
- let tt = attr.token_tree()?;
- if !tt.syntax().text_range().contains_range(cursor.syntax().text_range()) {
- return None;
- }
- let scope = sema.scope(attr.syntax());
- let resolved_attr = sema.resolve_path(&path)?;
- let derive = FamousDefs(sema, scope.krate()).core_macros_builtin_derive()?;
- if PathResolution::Macro(derive) != resolved_attr {
- return None;
- }
- get_path_at_cursor_in_tt(cursor)
-}
-
-/// Parses the path the identifier is part of inside a token tree.
-pub fn get_path_at_cursor_in_tt(cursor: &Ident) -> Option<ast::Path> {
- let cursor = cursor.syntax();
- let first = cursor
- .siblings_with_tokens(Direction::Prev)
- .filter_map(SyntaxElement::into_token)
- .take_while(|tok| tok.kind() != T!['('] && tok.kind() != T![,])
- .last()?;
- let path_tokens = first
- .siblings_with_tokens(Direction::Next)
- .filter_map(SyntaxElement::into_token)
- .take_while(|tok| tok != cursor);
-
- ast::Path::parse(&path_tokens.chain(iter::once(cursor.clone())).join("")).ok()
-}
-
-/// Parses and resolves the path at the cursor position in the given attribute, if it is a derive.
-/// This special case is required because the derive macro is a compiler builtin that discards the input derives.
-pub fn try_resolve_derive_input(
- sema: &hir::Semantics<RootDatabase>,
- attr: &ast::Attr,
- cursor: &Ident,
-) -> Option<PathResolution> {
- let path = get_path_in_derive_attr(sema, attr, cursor)?;
- let scope = sema.scope(attr.syntax());
- // FIXME: This double resolve shouldn't be necessary
- // It's only here so we prefer macros over other namespaces
- match scope.speculative_resolve_as_mac(&path) {
- Some(mac) if mac.kind() == hir::MacroKind::Derive => Some(PathResolution::Macro(mac)),
- Some(_) => return None,
- None => scope
- .speculative_resolve(&path)
- .filter(|res| matches!(res, PathResolution::Def(ModuleDef::Module(_)))),
- }
-}
-