This commit is contained in:
Lukas Wirth 2023-12-06 14:36:39 +01:00
parent 9cb13b6efb
commit 634d588fd7
13 changed files with 137 additions and 176 deletions

View file

@ -18,7 +18,7 @@ use std::{iter, ops::Range, sync};
use base_db::{fixture::WithFixture, span::SpanData, ProcMacro, SourceDatabase}; use base_db::{fixture::WithFixture, span::SpanData, ProcMacro, SourceDatabase};
use expect_test::Expect; use expect_test::Expect;
use hir_expand::{db::ExpandDatabase, span::SpanMapRef, HirFileIdExt, InFile, MacroFileId}; use hir_expand::{db::ExpandDatabase, span::SpanMapRef, InFile, MacroFileId, MacroFileIdExt};
use stdx::format_to; use stdx::format_to;
use syntax::{ use syntax::{
ast::{self, edit::IndentLevel}, ast::{self, edit::IndentLevel},
@ -172,35 +172,41 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
}; };
if let Some(src) = src { if let Some(src) = src {
if src.file_id.is_attr_macro(&db) || src.file_id.is_custom_derive(&db) { if let Some(file_id) = src.file_id.macro_file() {
let call = src.file_id.call_node(&db).expect("macro file"); if file_id.is_attr_macro(&db) || file_id.is_custom_derive(&db) {
let mut show_spans = false; let call = file_id.call_node(&db);
let mut show_ctxt = false; let mut show_spans = false;
for comment in call.value.children_with_tokens().filter(|it| it.kind() == COMMENT) { let mut show_ctxt = false;
show_spans |= comment.to_string().contains("+spans"); for comment in
show_ctxt |= comment.to_string().contains("+syntaxctxt"); call.value.children_with_tokens().filter(|it| it.kind() == COMMENT)
{
show_spans |= comment.to_string().contains("+spans");
show_ctxt |= comment.to_string().contains("+syntaxctxt");
}
let pp = pretty_print_macro_expansion(
src.value,
db.span_map(src.file_id).as_ref(),
show_spans,
show_ctxt,
);
format_to!(expanded_text, "\n{}", pp)
} }
let pp = pretty_print_macro_expansion(
src.value,
db.span_map(src.file_id).as_ref(),
show_spans,
show_ctxt,
);
format_to!(expanded_text, "\n{}", pp)
} }
} }
} }
for impl_id in def_map[local_id].scope.impls() { for impl_id in def_map[local_id].scope.impls() {
let src = impl_id.lookup(&db).source(&db); let src = impl_id.lookup(&db).source(&db);
if src.file_id.is_builtin_derive(&db) { if let Some(macro_file) = src.file_id.macro_file() {
let pp = pretty_print_macro_expansion( if macro_file.is_builtin_derive(&db) {
src.value.syntax().clone(), let pp = pretty_print_macro_expansion(
db.span_map(src.file_id).as_ref(), src.value.syntax().clone(),
false, db.span_map(macro_file.into()).as_ref(),
false, false,
); false,
format_to!(expanded_text, "\n{}", pp) );
format_to!(expanded_text, "\n{}", pp)
}
} }
} }

View file

@ -1,7 +1,7 @@
//! This module resolves `mod foo;` declaration to file. //! This module resolves `mod foo;` declaration to file.
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use base_db::{AnchoredPath, FileId}; use base_db::{AnchoredPath, FileId};
use hir_expand::{name::Name, HirFileIdExt}; use hir_expand::{name::Name, HirFileIdExt, MacroFileIdExt};
use limit::Limit; use limit::Limit;
use syntax::SmolStr; use syntax::SmolStr;
@ -73,7 +73,7 @@ impl ModDir {
Some(attr_path) => { Some(attr_path) => {
candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner)) candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner))
} }
None if file_id.is_include_macro(db.upcast()) => { None if file_id.macro_file().map_or(false, |it| it.is_include_macro(db.upcast())) => {
candidate_files.push(format!("{}.rs", name.display(db.upcast()))); candidate_files.push(format!("{}.rs", name.display(db.upcast())));
candidate_files.push(format!("{}/mod.rs", name.display(db.upcast()))); candidate_files.push(format!("{}/mod.rs", name.display(db.upcast())));
} }

View file

@ -6,9 +6,9 @@ use base_db::{
FileId, FileRange, FileId, FileRange,
}; };
use either::Either; use either::Either;
use syntax::{AstNode, SyntaxNode, SyntaxToken, TextRange}; use syntax::{AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize};
use crate::{db, ExpansionInfo, HirFileIdExt as _}; use crate::{db, ExpansionInfo, MacroFileIdExt};
/// `InFile<T>` stores a value of `T` inside a particular file/syntax tree. /// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
/// ///
@ -119,16 +119,6 @@ impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
// region:specific impls // region:specific impls
impl InFile<&SyntaxNode> { impl InFile<&SyntaxNode> {
pub fn ancestors_with_macros(
self,
db: &dyn db::ExpandDatabase,
) -> impl Iterator<Item = InFile<SyntaxNode>> + Clone + '_ {
iter::successors(Some(self.cloned()), move |node| match node.value.parent() {
Some(parent) => Some(node.with_value(parent)),
None => node.file_id.call_node(db),
})
}
/// Skips the attributed item that caused the macro invocation we are climbing up /// Skips the attributed item that caused the macro invocation we are climbing up
pub fn ancestors_with_macros_skip_attr_item( pub fn ancestors_with_macros_skip_attr_item(
self, self,
@ -137,8 +127,9 @@ impl InFile<&SyntaxNode> {
let succ = move |node: &InFile<SyntaxNode>| match node.value.parent() { let succ = move |node: &InFile<SyntaxNode>| match node.value.parent() {
Some(parent) => Some(node.with_value(parent)), Some(parent) => Some(node.with_value(parent)),
None => { None => {
let parent_node = node.file_id.call_node(db)?; let macro_file_id = node.file_id.macro_file()?;
if node.file_id.is_attr_macro(db) { let parent_node = macro_file_id.call_node(db);
if macro_file_id.is_attr_macro(db) {
// macro call was an attributed item, skip it // macro call was an attributed item, skip it
// FIXME: does this fail if this is a direct expansion of another macro? // FIXME: does this fail if this is a direct expansion of another macro?
parent_node.map(|node| node.parent()).transpose() parent_node.map(|node| node.parent()).transpose()
@ -222,7 +213,7 @@ impl InFile<&SyntaxNode> {
} }
HirFileIdRepr::MacroFile(m) => m, HirFileIdRepr::MacroFile(m) => m,
}; };
if !self.file_id.is_attr_macro(db) { if !file_id.is_attr_macro(db) {
return None; return None;
} }
@ -243,21 +234,23 @@ impl InFile<&SyntaxNode> {
} }
} }
impl InFile<SyntaxToken> { impl InMacroFile<SyntaxToken> {
pub fn upmap_once( pub fn upmap_once(
self, self,
db: &dyn db::ExpandDatabase, db: &dyn db::ExpandDatabase,
) -> Option<InFile<smallvec::SmallVec<[TextRange; 1]>>> { ) -> InFile<smallvec::SmallVec<[TextRange; 1]>> {
Some(self.file_id.expansion_info(db)?.map_range_up_once(db, self.value.text_range())) self.file_id.expansion_info(db).map_range_up_once(db, self.value.text_range())
} }
}
impl InFile<SyntaxToken> {
/// Falls back to the macro call range if the node cannot be mapped up fully. /// Falls back to the macro call range if the node cannot be mapped up fully.
pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> FileRange { pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> FileRange {
match self.file_id.repr() { match self.file_id.repr() {
HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() }, HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
HirFileIdRepr::MacroFile(mac_file) => { HirFileIdRepr::MacroFile(mac_file) => {
let (range, ctxt) = ExpansionInfo::new(db, mac_file) let (range, ctxt) = ExpansionInfo::new(db, mac_file)
.map_token_range_up(db, self.value.text_range()); .span_for_offset(db, self.value.text_range().start());
// FIXME: Figure out an API that makes proper use of ctx, this only exists to // FIXME: Figure out an API that makes proper use of ctx, this only exists to
// keep pre-token map rewrite behaviour. // keep pre-token map rewrite behaviour.
@ -280,7 +273,7 @@ impl InFile<SyntaxToken> {
} }
HirFileIdRepr::MacroFile(mac_file) => { HirFileIdRepr::MacroFile(mac_file) => {
let (range, ctxt) = ExpansionInfo::new(db, mac_file) let (range, ctxt) = ExpansionInfo::new(db, mac_file)
.map_token_range_up(db, self.value.text_range()); .span_for_offset(db, self.value.text_range().start());
// FIXME: Figure out an API that makes proper use of ctx, this only exists to // FIXME: Figure out an API that makes proper use of ctx, this only exists to
// keep pre-token map rewrite behaviour. // keep pre-token map rewrite behaviour.
@ -294,20 +287,13 @@ impl InFile<SyntaxToken> {
} }
} }
impl InFile<TextRange> { impl InMacroFile<TextSize> {
/// Attempts to map the syntax node back up its macro calls. pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> (FileRange, SyntaxContextId) {
pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> FileRange { ExpansionInfo::new(db, self.file_id).span_for_offset(db, self.value)
let (range, _ctxt) = match self.file_id.repr() {
HirFileIdRepr::FileId(file_id) => {
(FileRange { file_id, range: self.value }, SyntaxContextId::ROOT)
}
HirFileIdRepr::MacroFile(m) => {
ExpansionInfo::new(db, m).map_token_range_up(db, self.value)
}
};
range
} }
}
impl InFile<TextRange> {
pub fn original_node_file_range( pub fn original_node_file_range(
self, self,
db: &dyn db::ExpandDatabase, db: &dyn db::ExpandDatabase,
@ -353,7 +339,7 @@ impl<N: AstNode> InFile<N> {
} }
HirFileIdRepr::MacroFile(m) => m, HirFileIdRepr::MacroFile(m) => m,
}; };
if !self.file_id.is_attr_macro(db) { if !file_id.is_attr_macro(db) {
return None; return None;
} }

View file

@ -179,9 +179,6 @@ pub trait HirFileIdExt {
/// one of the calls comes from an `include!``. /// one of the calls comes from an `include!``.
fn original_file_respecting_includes(self, db: &dyn db::ExpandDatabase) -> FileId; fn original_file_respecting_includes(self, db: &dyn db::ExpandDatabase) -> FileId;
/// If this is a macro call, returns the syntax node of the call.
fn call_node(self, db: &dyn db::ExpandDatabase) -> Option<InFile<SyntaxNode>>;
/// If this is a macro call, returns the syntax node of the very first macro call this file resides in. /// If this is a macro call, returns the syntax node of the very first macro call this file resides in.
fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<SyntaxNode>>; fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<SyntaxNode>>;
@ -190,19 +187,6 @@ pub trait HirFileIdExt {
fn as_builtin_derive_attr_node(&self, db: &dyn db::ExpandDatabase) fn as_builtin_derive_attr_node(&self, db: &dyn db::ExpandDatabase)
-> Option<InFile<ast::Attr>>; -> Option<InFile<ast::Attr>>;
fn is_builtin_derive(&self, db: &dyn db::ExpandDatabase) -> bool;
fn is_custom_derive(&self, db: &dyn db::ExpandDatabase) -> bool;
/// Return whether this file is an include macro
fn is_include_macro(&self, db: &dyn db::ExpandDatabase) -> bool;
fn is_eager(&self, db: &dyn db::ExpandDatabase) -> bool;
/// Return whether this file is an attr macro
fn is_attr_macro(&self, db: &dyn db::ExpandDatabase) -> bool;
/// Return whether this file is the pseudo expansion of the derive attribute.
/// See [`crate::builtin_attr_macro::derive_attr_expand`].
fn is_derive_attr_pseudo_expansion(&self, db: &dyn db::ExpandDatabase) -> bool;
} }
impl HirFileIdExt for HirFileId { impl HirFileIdExt for HirFileId {
@ -241,12 +225,6 @@ impl HirFileIdExt for HirFileId {
} }
} }
fn call_node(self, db: &dyn db::ExpandDatabase) -> Option<InFile<SyntaxNode>> {
let macro_file = self.macro_file()?;
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
Some(loc.to_node(db))
}
fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<SyntaxNode>> { fn original_call_node(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<SyntaxNode>> {
let mut call = db.lookup_intern_macro_call(self.macro_file()?.macro_call_id).to_node(db); let mut call = db.lookup_intern_macro_call(self.macro_file()?.macro_call_id).to_node(db);
loop { loop {
@ -278,77 +256,34 @@ impl HirFileIdExt for HirFileId {
}; };
Some(attr.with_value(ast::Attr::cast(attr.value.clone())?)) Some(attr.with_value(ast::Attr::cast(attr.value.clone())?))
} }
fn is_custom_derive(&self, db: &dyn db::ExpandDatabase) -> bool {
match self.macro_file() {
Some(macro_file) => {
matches!(
db.lookup_intern_macro_call(macro_file.macro_call_id).def.kind,
MacroDefKind::ProcMacro(_, ProcMacroKind::CustomDerive, _)
)
}
None => false,
}
}
fn is_builtin_derive(&self, db: &dyn db::ExpandDatabase) -> bool {
match self.macro_file() {
Some(macro_file) => {
matches!(
db.lookup_intern_macro_call(macro_file.macro_call_id).def.kind,
MacroDefKind::BuiltInDerive(..)
)
}
None => false,
}
}
fn is_include_macro(&self, db: &dyn db::ExpandDatabase) -> bool {
match self.macro_file() {
Some(macro_file) => {
db.lookup_intern_macro_call(macro_file.macro_call_id).def.is_include()
}
_ => false,
}
}
fn is_eager(&self, db: &dyn db::ExpandDatabase) -> bool {
match self.macro_file() {
Some(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
matches!(loc.def.kind, MacroDefKind::BuiltInEager(..))
}
_ => false,
}
}
fn is_attr_macro(&self, db: &dyn db::ExpandDatabase) -> bool {
match self.macro_file() {
Some(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
matches!(loc.kind, MacroCallKind::Attr { .. })
}
_ => false,
}
}
fn is_derive_attr_pseudo_expansion(&self, db: &dyn db::ExpandDatabase) -> bool {
match self.macro_file() {
Some(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
loc.def.is_attribute_derive()
}
None => false,
}
}
} }
pub trait MacroFileIdExt { pub trait MacroFileIdExt {
fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32; fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32;
/// If this is a macro call, returns the syntax node of the call.
fn call_node(self, db: &dyn db::ExpandDatabase) -> InFile<SyntaxNode>;
fn expansion_info(self, db: &dyn db::ExpandDatabase) -> ExpansionInfo; fn expansion_info(self, db: &dyn db::ExpandDatabase) -> ExpansionInfo;
fn is_builtin_derive(&self, db: &dyn db::ExpandDatabase) -> bool;
fn is_custom_derive(&self, db: &dyn db::ExpandDatabase) -> bool;
/// Return whether this file is an include macro
fn is_include_macro(&self, db: &dyn db::ExpandDatabase) -> bool;
fn is_eager(&self, db: &dyn db::ExpandDatabase) -> bool;
/// Return whether this file is an attr macro
fn is_attr_macro(&self, db: &dyn db::ExpandDatabase) -> bool;
/// Return whether this file is the pseudo expansion of the derive attribute.
/// See [`crate::builtin_attr_macro::derive_attr_expand`].
fn is_derive_attr_pseudo_expansion(&self, db: &dyn db::ExpandDatabase) -> bool;
} }
impl MacroFileIdExt for MacroFileId { impl MacroFileIdExt for MacroFileId {
fn call_node(self, db: &dyn db::ExpandDatabase) -> InFile<SyntaxNode> {
db.lookup_intern_macro_call(self.macro_call_id).to_node(db)
}
fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32 { fn expansion_level(self, db: &dyn db::ExpandDatabase) -> u32 {
let mut level = 0; let mut level = 0;
let mut macro_file = self; let mut macro_file = self;
@ -367,6 +302,39 @@ impl MacroFileIdExt for MacroFileId {
fn expansion_info(self, db: &dyn db::ExpandDatabase) -> ExpansionInfo { fn expansion_info(self, db: &dyn db::ExpandDatabase) -> ExpansionInfo {
ExpansionInfo::new(db, self) ExpansionInfo::new(db, self)
} }
fn is_custom_derive(&self, db: &dyn db::ExpandDatabase) -> bool {
matches!(
db.lookup_intern_macro_call(self.macro_call_id).def.kind,
MacroDefKind::ProcMacro(_, ProcMacroKind::CustomDerive, _)
)
}
fn is_builtin_derive(&self, db: &dyn db::ExpandDatabase) -> bool {
matches!(
db.lookup_intern_macro_call(self.macro_call_id).def.kind,
MacroDefKind::BuiltInDerive(..)
)
}
fn is_include_macro(&self, db: &dyn db::ExpandDatabase) -> bool {
db.lookup_intern_macro_call(self.macro_call_id).def.is_include()
}
fn is_eager(&self, db: &dyn db::ExpandDatabase) -> bool {
let loc: MacroCallLoc = db.lookup_intern_macro_call(self.macro_call_id);
matches!(loc.def.kind, MacroDefKind::BuiltInEager(..))
}
fn is_attr_macro(&self, db: &dyn db::ExpandDatabase) -> bool {
let loc: MacroCallLoc = db.lookup_intern_macro_call(self.macro_call_id);
matches!(loc.kind, MacroCallKind::Attr { .. })
}
fn is_derive_attr_pseudo_expansion(&self, db: &dyn db::ExpandDatabase) -> bool {
let loc: MacroCallLoc = db.lookup_intern_macro_call(self.macro_call_id);
loc.def.is_attribute_derive()
}
} }
impl MacroDefId { impl MacroDefId {
@ -653,14 +621,14 @@ impl ExpansionInfo {
Some(tokens.map(move |token| InMacroFile::new(self.expanded.file_id, token))) Some(tokens.map(move |token| InMacroFile::new(self.expanded.file_id, token)))
} }
/// Maps up the text range out of the expansion hierarchy back into the original file its from. /// Looks up the span at the given offset.
pub fn map_token_range_up( pub fn span_for_offset(
&self, &self,
db: &dyn db::ExpandDatabase, db: &dyn db::ExpandDatabase,
range: TextRange, offset: TextSize,
) -> (FileRange, SyntaxContextId) { ) -> (FileRange, SyntaxContextId) {
debug_assert!(self.expanded.value.text_range().contains_range(range)); debug_assert!(self.expanded.value.text_range().contains(offset));
let span = self.exp_map.span_at(range.start()); let span = self.exp_map.span_at(offset);
let anchor_offset = db let anchor_offset = db
.ast_id_map(span.anchor.file_id.into()) .ast_id_map(span.anchor.file_id.into())
.get_erased(span.anchor.ast_id) .get_erased(span.anchor.ast_id)

View file

@ -24,7 +24,7 @@ use hir_def::{
}; };
use hir_expand::{ use hir_expand::{
name::{AsName, Name}, name::{AsName, Name},
HirFileId, HirFileIdExt, HirFileId, MacroFileIdExt,
}; };
use stdx::{always, never}; use stdx::{always, never};
use syntax::{ use syntax::{
@ -196,7 +196,7 @@ impl<'a> DeclValidator<'a> {
AttrDefId::GenericParamId(_) => None, AttrDefId::GenericParamId(_) => None,
} }
.map_or(false, |file_id| { .map_or(false, |file_id| {
file_id.is_custom_derive(db.upcast()) || file_id.is_builtin_derive(db.upcast()) matches!(file_id.macro_file(), Some(file_id) if file_id.is_custom_derive(db.upcast()) || file_id.is_builtin_derive(db.upcast()))
}) })
}; };

View file

@ -128,6 +128,7 @@ pub use {
hygiene::{marks_rev, SyntaxContextExt}, hygiene::{marks_rev, SyntaxContextExt},
name::{known, Name}, name::{known, Name},
tt, ExpandResult, HirFileId, HirFileIdExt, InFile, InMacroFile, InRealFile, MacroFileId, tt, ExpandResult, HirFileId, HirFileIdExt, InFile, InMacroFile, InRealFile, MacroFileId,
MacroFileIdExt,
}, },
hir_ty::{ hir_ty::{
display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
@ -607,7 +608,7 @@ impl Module {
let tree = loc.id.item_tree(db.upcast()); let tree = loc.id.item_tree(db.upcast());
let node = &tree[loc.id.value]; let node = &tree[loc.id.value];
let file_id = loc.id.file_id(); let file_id = loc.id.file_id();
if file_id.is_builtin_derive(db.upcast()) { if file_id.macro_file().map_or(false, |it| it.is_builtin_derive(db.upcast())) {
// these expansion come from us, diagnosing them is a waste of resources // these expansion come from us, diagnosing them is a waste of resources
// FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow // FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
continue; continue;

View file

@ -20,8 +20,8 @@ use hir_def::{
AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId, AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId,
}; };
use hir_expand::{ use hir_expand::{
db::ExpandDatabase, files::InRealFile, name::AsName, ExpansionInfo, HirFileIdExt, MacroCallId, db::ExpandDatabase, files::InRealFile, name::AsName, ExpansionInfo, MacroCallId, MacroFileId,
MacroFileId, MacroFileIdExt, MacroFileIdExt,
}; };
use itertools::Itertools; use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
@ -865,7 +865,7 @@ impl<'db> SemanticsImpl<'db> {
Some(parent) => Some(InFile::new(file_id, parent)), Some(parent) => Some(InFile::new(file_id, parent)),
None => { None => {
self.cache(value.clone(), file_id); self.cache(value.clone(), file_id);
file_id.call_node(db) Some(file_id.macro_file()?.call_node(db))
} }
} }
}) })

View file

@ -29,7 +29,7 @@ use hir_expand::{
mod_path::path, mod_path::path,
name, name,
name::{AsName, Name}, name::{AsName, Name},
HirFileId, HirFileIdExt, InFile, MacroFileId, MacroFileIdExt, HirFileId, InFile, MacroFileId, MacroFileIdExt,
}; };
use hir_ty::{ use hir_ty::{
diagnostics::{ diagnostics::{
@ -939,11 +939,12 @@ fn scope_for_offset(
} }
// FIXME handle attribute expansion // FIXME handle attribute expansion
let source = iter::successors(file_id.call_node(db.upcast()), |it| { let source =
it.file_id.call_node(db.upcast()) iter::successors(file_id.macro_file().map(|it| it.call_node(db.upcast())), |it| {
}) Some(it.file_id.macro_file()?.call_node(db.upcast()))
.find(|it| it.file_id == from_file) })
.filter(|it| it.value.kind() == SyntaxKind::MACRO_CALL)?; .find(|it| it.file_id == from_file)
.filter(|it| it.value.kind() == SyntaxKind::MACRO_CALL)?;
Some((source.value.text_range(), scope)) Some((source.value.text_range(), scope))
}) })
.filter(|(expr_range, _scope)| expr_range.start() <= offset && offset <= expr_range.end()) .filter(|(expr_range, _scope)| expr_range.start() <= offset && offset <= expr_range.end())

View file

@ -49,10 +49,6 @@ impl DeclarationLocation {
let node = resolve_node(db, self.hir_file_id, &self.ptr); let node = resolve_node(db, self.hir_file_id, &self.ptr);
node.as_ref().original_file_range(db.upcast()) node.as_ref().original_file_range(db.upcast())
} }
pub fn original_name_range(&self, db: &dyn HirDatabase) -> FileRange {
InFile::new(self.hir_file_id, self.name_ptr.text_range()).original_file_range(db.upcast())
}
} }
fn resolve_node( fn resolve_node(

View file

@ -1,4 +1,4 @@
use hir::{HirFileIdExt, InFile, ModuleDef}; use hir::{InFile, MacroFileIdExt, ModuleDef};
use ide_db::{helpers::mod_path_to_ast, imports::import_assets::NameToImport, items_locator}; use ide_db::{helpers::mod_path_to_ast, imports::import_assets::NameToImport, items_locator};
use itertools::Itertools; use itertools::Itertools;
use syntax::{ use syntax::{
@ -43,12 +43,12 @@ pub(crate) fn replace_derive_with_manual_impl(
) -> Option<()> { ) -> Option<()> {
let attr = ctx.find_node_at_offset_with_descend::<ast::Attr>()?; let attr = ctx.find_node_at_offset_with_descend::<ast::Attr>()?;
let path = attr.path()?; let path = attr.path()?;
let hir_file = ctx.sema.hir_file_for(attr.syntax()); let macro_file = ctx.sema.hir_file_for(attr.syntax()).macro_file()?;
if !hir_file.is_derive_attr_pseudo_expansion(ctx.db()) { if !macro_file.is_derive_attr_pseudo_expansion(ctx.db()) {
return None; return None;
} }
let InFile { file_id, value } = hir_file.call_node(ctx.db())?; let InFile { file_id, value } = macro_file.call_node(ctx.db());
if file_id.is_macro() { if file_id.is_macro() {
// FIXME: make this work in macro files // FIXME: make this work in macro files
return None; return None;
@ -56,7 +56,7 @@ pub(crate) fn replace_derive_with_manual_impl(
// collect the derive paths from the #[derive] expansion // collect the derive paths from the #[derive] expansion
let current_derives = ctx let current_derives = ctx
.sema .sema
.parse_or_expand(hir_file) .parse_or_expand(macro_file.into())
.descendants() .descendants()
.filter_map(ast::Attr::cast) .filter_map(ast::Attr::cast)
.filter_map(|attr| attr.path()) .filter_map(|attr| attr.path())

View file

@ -1,4 +1,4 @@
use hir::{DescendPreference, HirFileIdExt, InFile, Semantics}; use hir::{DescendPreference, InFile, MacroFileIdExt, Semantics};
use ide_db::{ use ide_db::{
base_db::FileId, helpers::pick_best_token, base_db::FileId, helpers::pick_best_token,
syntax_helpers::insert_whitespace_into_node::insert_ws_into, RootDatabase, syntax_helpers::insert_whitespace_into_node::insert_ws_into, RootDatabase,
@ -44,15 +44,15 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
.descend_into_macros(DescendPreference::None, tok.clone()) .descend_into_macros(DescendPreference::None, tok.clone())
.into_iter() .into_iter()
.find_map(|descended| { .find_map(|descended| {
let hir_file = sema.hir_file_for(&descended.parent()?); let macro_file = sema.hir_file_for(&descended.parent()?).macro_file()?;
if !hir_file.is_derive_attr_pseudo_expansion(db) { if !macro_file.is_derive_attr_pseudo_expansion(db) {
return None; return None;
} }
let name = descended.parent_ancestors().filter_map(ast::Path::cast).last()?.to_string(); let name = descended.parent_ancestors().filter_map(ast::Path::cast).last()?.to_string();
// up map out of the #[derive] expansion // up map out of the #[derive] expansion
let InFile { file_id, value: tokens } = let InFile { file_id, value: tokens } =
hir::InFile::new(hir_file, descended).upmap_once(db)?; hir::InMacroFile::new(macro_file, descended).upmap_once(db);
let token = sema.parse_or_expand(file_id).covering_element(tokens[0]).into_token()?; let token = sema.parse_or_expand(file_id).covering_element(tokens[0]).into_token()?;
let attr = token.parent_ancestors().find_map(ast::Attr::cast)?; let attr = token.parent_ancestors().find_map(ast::Attr::cast)?;
let expansions = sema.expand_derive_macro(&attr)?; let expansions = sema.expand_derive_macro(&attr)?;

View file

@ -142,7 +142,7 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
Definition::Function(it) => it.source(db).map(|src| src.file_id), Definition::Function(it) => it.source(db).map(|src| src.file_id),
_ => None, _ => None,
}; };
if let Some(file_id) = file_id.filter(|file| file.call_node(db).is_some()) { if let Some(file_id) = file_id.filter(|file| file.macro_file().is_some()) {
in_macro_expansion.entry(file_id).or_default().push(runnable); in_macro_expansion.entry(file_id).or_default().push(runnable);
return; return;
} }

View file

@ -1,6 +1,6 @@
//! Computes color for a single element. //! Computes color for a single element.
use hir::{AsAssocItem, HasVisibility, HirFileIdExt, Semantics}; use hir::{AsAssocItem, HasVisibility, MacroFileIdExt, Semantics};
use ide_db::{ use ide_db::{
defs::{Definition, IdentClass, NameClass, NameRefClass}, defs::{Definition, IdentClass, NameClass, NameRefClass},
FxHashMap, RootDatabase, SymbolKind, FxHashMap, RootDatabase, SymbolKind,
@ -218,7 +218,10 @@ fn highlight_name_ref(
// We can fix this for derive attributes since derive helpers are recorded, but not for // We can fix this for derive attributes since derive helpers are recorded, but not for
// general attributes. // general attributes.
None if name_ref.syntax().ancestors().any(|it| it.kind() == ATTR) None if name_ref.syntax().ancestors().any(|it| it.kind() == ATTR)
&& !sema.hir_file_for(name_ref.syntax()).is_derive_attr_pseudo_expansion(sema.db) => && !sema
.hir_file_for(name_ref.syntax())
.macro_file()
.map_or(false, |it| it.is_derive_attr_pseudo_expansion(sema.db)) =>
{ {
return HlTag::Symbol(SymbolKind::Attribute).into(); return HlTag::Symbol(SymbolKind::Attribute).into();
} }