X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=crates%2Fhir%2Fsrc%2Fsemantics.rs;h=1156dfe98e15b18a2972bc51da28afa2b544544b;hb=7b89d5ede23cbbbf4bef37b43e0d2d99752ddb51;hp=243ba63b8a0a8b52a583f0d8f14b6b4a35288b6e;hpb=1fe3b2edd68889489d2702507ac0ba22a5126adf;p=rust.git diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 243ba63b8a0..1156dfe98e1 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -5,7 +5,6 @@ use std::{cell::RefCell, fmt, iter}; use base_db::{FileId, FileRange}; -use either::Either; use hir_def::{ body, resolver::{self, HasResolver, Resolver, TypeNs}, @@ -19,17 +18,16 @@ use syntax::{ algo::skip_trivia_token, ast::{self, HasAttrs as _, HasGenericParams, HasLoopBody}, - match_ast, AstNode, AstToken, Direction, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, - TextSize, T, + match_ast, AstNode, Direction, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextSize, }; use crate::{ db::HirDatabase, semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, source_analyzer::{resolve_hir_path, SourceAnalyzer}, - Access, AssocItem, BuiltinAttr, Callable, ConstParam, Crate, Field, Function, HasAttrs as _, - HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, - Name, Path, ScopeDef, ToolModule, Trait, Type, TypeAlias, TypeParam, VariantDef, + Access, AssocItem, BuiltinAttr, Callable, ConstParam, Crate, Field, Function, HasSource, + HirFileId, Impl, InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, + ScopeDef, ToolModule, Trait, Type, TypeAlias, TypeParam, VariantDef, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -350,14 +348,6 @@ pub fn resolve_bind_pat_to_const(&self, pat: &ast::IdentPat) -> Option Option { - self.imp.resolve_derive_ident(derive, ident) - } - pub fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> { self.imp.record_literal_missing_fields(literal) } @@ -475,7 +465,7 @@ fn derive_macro_calls(&self, attr: &ast::Attr) -> Option let adt = InFile::new(file_id, &adt); let src = InFile::new(file_id, attr.clone()); self.with_ctx(|ctx| { - let (_, res) = ctx.attr_to_derive_macro_call(adt, src)?; + let (.., res) = ctx.attr_to_derive_macro_call(adt, src)?; Some(res.to_vec()) }) } @@ -668,7 +658,27 @@ fn descend_into_macros_impl( // FIXME replace map.while_some with take_while once stable token.value.ancestors().map(ast::TokenTree::cast).while_some().last() { - let macro_call = tt.syntax().parent().and_then(ast::MacroCall::cast)?; + let parent = tt.syntax().parent()?; + // check for derive attribute here + let macro_call = match_ast! { + match parent { + ast::MacroCall(mcall) => mcall, + // attribute we failed expansion for earlier, this might be a derive invocation + // so try downmapping the token into the pseudo derive expansion + ast::Meta(meta) => { + let attr = meta.parent_attr()?; + let adt = attr.syntax().parent().and_then(ast::Adt::cast)?; + let call_id = self.with_ctx(|ctx| { + let (_, call_id, _) = ctx.attr_to_derive_macro_call(token.with_value(&adt), token.with_value(attr))?; + Some(call_id) + })?; + let file_id = call_id.as_file(); + return process_expansion_for_token(&mut stack,file_id,Some(adt.into()),token.as_ref(),); + }, + _ => return None, + } + }; + if tt.left_delimiter_token().map_or(false, |it| it == token.value) { return None; } @@ -898,72 +908,6 @@ fn resolve_bind_pat_to_const(&self, pat: &ast::IdentPat) -> Option { self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) } - fn resolve_derive_ident( - &self, - derive: &ast::Attr, - ident: &ast::Ident, - ) -> Option { - 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), - } - } - fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> { self.analyze(literal.syntax()) .record_literal_missing_fields(self.db, literal)