- fn resolve_derive_ident(
- &self,
- derive: &ast::Attr,
- ident: &ast::Ident,
- ) -> Option<PathResolution> {
- debug_assert!(ident.syntax().parent().and_then(ast::TokenTree::cast).is_some());
- debug_assert!(ident.syntax().ancestors().any(|anc| anc == *derive.syntax()));
- // derive macros are always at depth 2, tokentree -> meta -> attribute
- let syntax = ident.syntax();
-
- let tt = derive.token_tree()?;
- let file = self.find_file(derive.syntax());
- let adt = derive.syntax().parent().and_then(ast::Adt::cast)?;
- let adt_def = ToDef::to_def(self, file.with_value(adt.clone()))?;
- let res = self.with_ctx(|ctx| {
- let (attr_id, derives) = ctx.attr_to_derive_macro_call(
- file.with_value(&adt),
- file.with_value(derive.clone()),
- )?;
- let attrs = adt_def.attrs(self.db);
- let mut derive_paths = attrs.get(attr_id)?.parse_path_comma_token_tree()?;
-
- let derive_idx = tt
- .syntax()
- .children_with_tokens()
- .filter_map(SyntaxElement::into_token)
- .take_while(|tok| tok != syntax)
- .filter(|t| t.kind() == T![,])
- .count();
- let path_segment_idx = syntax
- .siblings_with_tokens(Direction::Prev)
- .filter_map(SyntaxElement::into_token)
- .take_while(|tok| matches!(tok.kind(), T![:] | T![ident]))
- .filter(|tok| tok.kind() == T![ident])
- .count();
-
- let mut mod_path = derive_paths.nth(derive_idx)?;
-
- if path_segment_idx < mod_path.len() {
- // the path for the given ident is a qualifier, resolve to module if possible
- while path_segment_idx < mod_path.len() {
- mod_path.pop_segment();
- }
- Some(Either::Left(mod_path))
- } else {
- // otherwise fetch the derive
- Some(Either::Right(derives[derive_idx]))
- }
- })?;
-
- match res {
- Either::Left(path) => {
- let len = path.len();
- resolve_hir_path(
- self.db,
- &self.scope(derive.syntax()).resolver,
- &Path::from_known_path(path, vec![None; len]),
- )
- .filter(|res| matches!(res, PathResolution::Def(ModuleDef::Module(_))))
- }
- Either::Right(derive) => derive
- .map(|call| MacroDef { id: self.db.lookup_intern_macro_call(call).def })
- .map(PathResolution::Macro),
- }
- }
-