Refactor attributes API to allow handling cfg_attr

This commit is contained in:
Jonas Schievink 2020-12-18 00:23:46 +01:00
parent a4e17a5a96
commit 4f07d8dd58
8 changed files with 196 additions and 123 deletions

View File

@ -3,6 +3,7 @@
use std::sync::Arc;
use arena::{map::ArenaMap, Arena};
use base_db::CrateId;
use either::Either;
use hir_expand::{
name::{AsName, Name},
@ -66,8 +67,13 @@ pub enum ReprKind {
Other,
}
fn repr_from_value(item_tree: &ItemTree, of: AttrOwner) -> Option<ReprKind> {
item_tree.attrs(of).by_key("repr").tt_values().find_map(parse_repr_tt)
fn repr_from_value(
db: &dyn DefDatabase,
krate: CrateId,
item_tree: &ItemTree,
of: AttrOwner,
) -> Option<ReprKind> {
item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
}
fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
@ -86,12 +92,13 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
impl StructData {
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
let loc = id.lookup(db);
let krate = loc.container.module(db).krate;
let item_tree = db.item_tree(loc.id.file_id);
let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into());
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
let strukt = &item_tree[loc.id.value];
let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields, None);
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
Arc::new(StructData {
name: strukt.name.clone(),
variant_data: Arc::new(variant_data),
@ -100,12 +107,13 @@ pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<Struc
}
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
let loc = id.lookup(db);
let krate = loc.container.module(db).krate;
let item_tree = db.item_tree(loc.id.file_id);
let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into());
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
let union = &item_tree[loc.id.value];
let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields, None);
let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
Arc::new(StructData {
name: union.name.clone(),
@ -118,16 +126,23 @@ pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructD
impl EnumData {
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
let loc = e.lookup(db);
let krate = loc.container.module(db).krate;
let item_tree = db.item_tree(loc.id.file_id);
let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
let enum_ = &item_tree[loc.id.value];
let mut variants = Arena::new();
for var_id in enum_.variants.clone() {
if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) {
if item_tree.attrs(db, krate, var_id.into()).is_cfg_enabled(&cfg_options) {
let var = &item_tree[var_id];
let var_data =
lower_fields(&item_tree, &cfg_options, &var.fields, Some(enum_.visibility));
let var_data = lower_fields(
db,
krate,
&item_tree,
&cfg_options,
&var.fields,
Some(enum_.visibility),
);
variants.alloc(EnumVariantData {
name: var.name.clone(),
@ -170,7 +185,7 @@ fn lower_enum(
.variant_list()
.into_iter()
.flat_map(|it| it.variants())
.filter(|var| expander.is_cfg_enabled(var));
.filter(|var| expander.is_cfg_enabled(db, var));
for var in variants {
trace.alloc(
|| var.clone(),
@ -262,7 +277,7 @@ fn lower_struct(
match &ast.value {
ast::StructKind::Tuple(fl) => {
for (i, fd) in fl.fields().enumerate() {
if !expander.is_cfg_enabled(&fd) {
if !expander.is_cfg_enabled(db, &fd) {
continue;
}
@ -279,7 +294,7 @@ fn lower_struct(
}
ast::StructKind::Record(fl) => {
for fd in fl.fields() {
if !expander.is_cfg_enabled(&fd) {
if !expander.is_cfg_enabled(db, &fd) {
continue;
}
@ -299,6 +314,8 @@ fn lower_struct(
}
fn lower_fields(
db: &dyn DefDatabase,
krate: CrateId,
item_tree: &ItemTree,
cfg_options: &CfgOptions,
fields: &Fields,
@ -308,7 +325,7 @@ fn lower_fields(
Fields::Record(flds) => {
let mut arena = Arena::new();
for field_id in flds.clone() {
if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
}
}
@ -317,7 +334,7 @@ fn lower_fields(
Fields::Tuple(flds) => {
let mut arena = Arena::new();
for field_id in flds.clone() {
if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
}
}

View File

@ -2,6 +2,7 @@
use std::{ops, sync::Arc};
use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use either::Either;
use hir_expand::{hygiene::Hygiene, AstId, InFile};
@ -38,12 +39,16 @@ fn from(Documentation(string): Documentation) -> Self {
}
}
/// Syntactical attributes, without filtering of `cfg_attr`s.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Attrs {
pub struct RawAttrs {
entries: Option<Arc<[Attr]>>,
}
impl ops::Deref for Attrs {
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Attrs(RawAttrs);
impl ops::Deref for RawAttrs {
type Target = [Attr];
fn deref(&self) -> &[Attr] {
@ -54,62 +59,21 @@ fn deref(&self) -> &[Attr] {
}
}
impl Attrs {
pub const EMPTY: Attrs = Attrs { entries: None };
impl ops::Deref for Attrs {
type Target = [Attr];
pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
match def {
AttrDefId::ModuleId(module) => {
let def_map = db.crate_def_map(module.krate);
let mod_data = &def_map[module.local_id];
match mod_data.declaration_source(db) {
Some(it) => {
Attrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner))
}
None => Attrs::from_attrs_owner(
db,
mod_data.definition_source(db).as_ref().map(|src| match src {
ModuleSource::SourceFile(file) => file as &dyn AttrsOwner,
ModuleSource::Module(module) => module as &dyn AttrsOwner,
}),
),
}
}
AttrDefId::FieldId(it) => {
let src = it.parent.child_source(db);
match &src.value[it.local_id] {
Either::Left(_tuple) => Attrs::default(),
Either::Right(record) => Attrs::from_attrs_owner(db, src.with_value(record)),
}
}
AttrDefId::EnumVariantId(var_id) => {
let src = var_id.parent.child_source(db);
let src = src.as_ref().map(|it| &it[var_id.local_id]);
Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
}
AttrDefId::AdtId(it) => match it {
AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
},
AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::MacroDefId(it) => {
it.ast_id.map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db))
}
AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
fn deref(&self) -> &[Attr] {
match &self.0.entries {
Some(it) => &*it,
None => &[],
}
}
}
fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs {
let hygiene = Hygiene::new(db.upcast(), owner.file_id);
Attrs::new(owner.value, &hygiene)
}
impl RawAttrs {
pub const EMPTY: Self = Self { entries: None };
pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Self {
let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
.map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs))));
@ -137,17 +101,93 @@ pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
} else {
Some(attrs.into_iter().flat_map(|(_, attr)| attr).collect())
};
Attrs { entries }
Self { entries }
}
fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Self {
let hygiene = Hygiene::new(db.upcast(), owner.file_id);
Self::new(owner.value, &hygiene)
}
pub(crate) fn merge(&self, other: Self) -> Self {
match (&self.entries, &other.entries) {
(None, None) => Self::EMPTY,
(Some(entries), None) | (None, Some(entries)) => {
Self { entries: Some(entries.clone()) }
}
(Some(a), Some(b)) => {
Self { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }
}
}
}
/// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
pub(crate) fn filter(self, _db: &dyn DefDatabase, _krate: CrateId) -> Attrs {
// FIXME actually implement this
Attrs(self)
}
}
impl Attrs {
pub const EMPTY: Self = Self(RawAttrs::EMPTY);
pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
let raw_attrs = match def {
AttrDefId::ModuleId(module) => {
let def_map = db.crate_def_map(module.krate);
let mod_data = &def_map[module.local_id];
match mod_data.declaration_source(db) {
Some(it) => {
RawAttrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner))
}
None => RawAttrs::from_attrs_owner(
db,
mod_data.definition_source(db).as_ref().map(|src| match src {
ModuleSource::SourceFile(file) => file as &dyn AttrsOwner,
ModuleSource::Module(module) => module as &dyn AttrsOwner,
}),
),
}
}
AttrDefId::FieldId(it) => {
let src = it.parent.child_source(db);
match &src.value[it.local_id] {
Either::Left(_tuple) => RawAttrs::default(),
Either::Right(record) => RawAttrs::from_attrs_owner(db, src.with_value(record)),
}
}
AttrDefId::EnumVariantId(var_id) => {
let src = var_id.parent.child_source(db);
let src = src.as_ref().map(|it| &it[var_id.local_id]);
RawAttrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
}
AttrDefId::AdtId(it) => match it {
AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
},
AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::MacroDefId(it) => {
it.ast_id.map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db))
}
AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
};
raw_attrs.filter(db, def.krate(db))
}
pub fn merge(&self, other: Attrs) -> Attrs {
match (&self.entries, &other.entries) {
(None, None) => Attrs { entries: None },
match (&self.0.entries, &other.0.entries) {
(None, None) => Attrs::EMPTY,
(Some(entries), None) | (None, Some(entries)) => {
Attrs { entries: Some(entries.clone()) }
Attrs(RawAttrs { entries: Some(entries.clone()) })
}
(Some(a), Some(b)) => {
Attrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }
Attrs(RawAttrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) })
}
}
}
@ -291,16 +331,16 @@ fn attrs(self) -> impl Iterator<Item = &'a Attr> {
}
}
fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> Attrs
fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> RawAttrs
where
N: ast::AttrsOwner,
{
let src = InFile::new(src.file_id, src.to_node(db.upcast()));
Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
RawAttrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
}
fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> Attrs {
fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> RawAttrs {
let tree = db.item_tree(id.file_id);
let mod_item = N::id_to_mod_item(id.value);
tree.attrs(mod_item.into()).clone()
tree.raw_attrs(mod_item.into()).clone()
}

View File

@ -24,7 +24,7 @@
pub(crate) use lower::LowerCtx;
use crate::{
attr::Attrs,
attr::{Attrs, RawAttrs},
db::DefDatabase,
expr::{Expr, ExprId, Pat, PatId},
item_scope::BuiltinShadowMode,
@ -40,6 +40,7 @@
pub(crate) struct CfgExpander {
cfg_options: CfgOptions,
hygiene: Hygiene,
krate: CrateId,
}
pub(crate) struct Expander {
@ -65,15 +66,15 @@ pub(crate) fn new(
) -> CfgExpander {
let hygiene = Hygiene::new(db.upcast(), current_file_id);
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
CfgExpander { cfg_options, hygiene }
CfgExpander { cfg_options, hygiene, krate }
}
pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
Attrs::new(owner, &self.hygiene)
pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
RawAttrs::new(owner, &self.hygiene).filter(db, self.krate)
}
pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool {
let attrs = self.parse_attrs(owner);
pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> bool {
let attrs = self.parse_attrs(db, owner);
attrs.is_cfg_enabled(&self.cfg_options)
}
}
@ -189,8 +190,8 @@ pub(crate) fn to_source<T>(&self, value: T) -> InFile<T> {
InFile { file_id: self.current_file_id, value }
}
pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
self.cfg_expander.parse_attrs(owner)
pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
self.cfg_expander.parse_attrs(db, owner)
}
pub(crate) fn cfg_options(&self) -> &CfgOptions {

View File

@ -963,7 +963,7 @@ fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Opt
/// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
/// not.
fn check_cfg(&mut self, owner: &dyn ast::AttrsOwner) -> Option<()> {
match self.expander.parse_attrs(owner).cfg() {
match self.expander.parse_attrs(self.db, owner).cfg() {
Some(cfg) => {
if self.expander.cfg_options().check(&cfg) != Some(false) {
return Some(());

View File

@ -35,6 +35,7 @@ pub struct FunctionData {
impl FunctionData {
pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> {
let loc = func.lookup(db);
let krate = loc.container.module(db).krate;
let item_tree = db.item_tree(loc.id.file_id);
let func = &item_tree[loc.id.value];
@ -42,7 +43,7 @@ pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<Funct
name: func.name.clone(),
params: func.params.to_vec(),
ret_type: func.ret_type.clone(),
attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(),
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(),
has_self_param: func.has_self_param,
has_body: func.has_body,
is_unsafe: func.is_unsafe,
@ -233,7 +234,7 @@ fn collect_items(
match item {
AssocItem::Function(id) => {
let item = &item_tree[id];
let attrs = item_tree.attrs(ModItem::from(id).into());
let attrs = item_tree.attrs(db, module.krate, ModItem::from(id).into());
if !attrs.is_cfg_enabled(&cfg_options) {
continue;
}

View File

@ -13,6 +13,7 @@
use arena::{Arena, Idx, RawId};
use ast::{AstNode, AttrsOwner, NameOwner, StructKind};
use base_db::CrateId;
use either::Either;
use hir_expand::{
ast_id_map::FileAstId,
@ -26,7 +27,7 @@
use test_utils::mark;
use crate::{
attr::Attrs,
attr::{Attrs, RawAttrs},
db::DefDatabase,
generics::GenericParams,
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
@ -67,7 +68,7 @@ impl GenericParamsId {
#[derive(Debug, Eq, PartialEq)]
pub struct ItemTree {
top_level: SmallVec<[ModItem; 1]>,
attrs: FxHashMap<AttrOwner, Attrs>,
attrs: FxHashMap<AttrOwner, RawAttrs>,
inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>,
data: Option<Box<ItemTreeData>>,
@ -88,7 +89,7 @@ pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree
let mut item_tree = match_ast! {
match syntax {
ast::SourceFile(file) => {
top_attrs = Some(Attrs::new(&file, &hygiene));
top_attrs = Some(RawAttrs::new(&file, &hygiene));
ctx.lower_module_items(&file)
},
ast::MacroItems(items) => {
@ -180,12 +181,16 @@ pub fn top_level_items(&self) -> &[ModItem] {
}
/// Returns the inner attributes of the source file.
pub fn top_level_attrs(&self) -> &Attrs {
self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&Attrs::EMPTY)
pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone().filter(db, krate)
}
pub fn attrs(&self, of: AttrOwner) -> &Attrs {
self.attrs.get(&of).unwrap_or(&Attrs::EMPTY)
pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs {
self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY)
}
pub fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs {
self.raw_attrs(of).clone().filter(db, krate)
}
/// Returns the lowered inner items that `ast` corresponds to.

View File

@ -10,7 +10,6 @@
};
use crate::{
attr::Attrs,
generics::{GenericParams, TypeParamData, TypeParamProvenance},
type_ref::LifetimeRef,
};
@ -105,7 +104,7 @@ fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems>
| ast::Item::MacroDef(_) => {}
};
let attrs = Attrs::new(item, &self.hygiene);
let attrs = RawAttrs::new(item, &self.hygiene);
let items = match item {
ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into),
ast::Item::Union(ast) => self.lower_union(ast).map(Into::into),
@ -138,7 +137,7 @@ fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems>
items
}
fn add_attrs(&mut self, item: AttrOwner, attrs: Attrs) {
fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) {
match self.tree.attrs.entry(item) {
Entry::Occupied(mut entry) => {
*entry.get_mut() = entry.get().merge(attrs);
@ -205,7 +204,7 @@ fn lower_record_fields(&mut self, fields: &ast::RecordFieldList) -> IdRange<Fiel
for field in fields.fields() {
if let Some(data) = self.lower_record_field(&field) {
let idx = self.data().fields.alloc(data);
self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene));
self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
}
}
let end = self.next_field_idx();
@ -225,7 +224,7 @@ fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldList) -> IdRange<Field>
for (i, field) in fields.fields().enumerate() {
let data = self.lower_tuple_field(i, &field);
let idx = self.data().fields.alloc(data);
self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene));
self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
}
let end = self.next_field_idx();
IdRange::new(start..end)
@ -270,7 +269,7 @@ fn lower_variants(&mut self, variants: &ast::VariantList) -> IdRange<Variant> {
for variant in variants.variants() {
if let Some(data) = self.lower_variant(&variant) {
let idx = self.data().variants.alloc(data);
self.add_attrs(idx.into(), Attrs::new(&variant, &self.hygiene));
self.add_attrs(idx.into(), RawAttrs::new(&variant, &self.hygiene));
}
}
let end = self.next_variant_idx();
@ -438,7 +437,7 @@ fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option<FileItemTreeId<Trait
self.with_inherited_visibility(visibility, |this| {
list.assoc_items()
.filter_map(|item| {
let attrs = Attrs::new(&item, &this.hygiene);
let attrs = RawAttrs::new(&item, &this.hygiene);
this.collect_inner_items(item.syntax());
this.lower_assoc_item(&item).map(|item| {
this.add_attrs(ModItem::from(item).into(), attrs);
@ -475,7 +474,7 @@ fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
.filter_map(|item| {
self.collect_inner_items(item.syntax());
let assoc = self.lower_assoc_item(&item)?;
let attrs = Attrs::new(&item, &self.hygiene);
let attrs = RawAttrs::new(&item, &self.hygiene);
self.add_attrs(ModItem::from(assoc).into(), attrs);
Some(assoc)
})
@ -560,7 +559,7 @@ fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
list.extern_items()
.filter_map(|item| {
self.collect_inner_items(item.syntax());
let attrs = Attrs::new(&item, &self.hygiene);
let attrs = RawAttrs::new(&item, &self.hygiene);
let id: ModItem = match item {
ast::ExternItem::Fn(ast) => {
let func_id = self.lower_function(&ast)?;

View File

@ -221,17 +221,20 @@ fn collect(&mut self) {
let item_tree = self.db.item_tree(file_id.into());
let module_id = self.def_map.root;
self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
let mut root_collector = ModCollector {
def_collector: &mut *self,
macro_depth: 0,
module_id,
file_id: file_id.into(),
item_tree: &item_tree,
mod_dir: ModDir::root(),
};
if item_tree.top_level_attrs().cfg().map_or(true, |cfg| root_collector.is_cfg_enabled(&cfg))
if item_tree
.top_level_attrs(self.db, self.def_map.krate)
.cfg()
.map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false))
{
root_collector.collect(item_tree.top_level_items());
ModCollector {
def_collector: &mut *self,
macro_depth: 0,
module_id,
file_id: file_id.into(),
item_tree: &item_tree,
mod_dir: ModDir::root(),
}
.collect(item_tree.top_level_items());
}
// main name resolution fixed-point loop.
@ -905,6 +908,8 @@ struct ModCollector<'a, 'b> {
impl ModCollector<'_, '_> {
fn collect(&mut self, items: &[ModItem]) {
let krate = self.def_collector.def_map.krate;
// Note: don't assert that inserted value is fresh: it's simply not true
// for macros.
self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
@ -921,7 +926,7 @@ fn collect(&mut self, items: &[ModItem]) {
// `#[macro_use] extern crate` is hoisted to imports macros before collecting
// any other items.
for item in items {
let attrs = self.item_tree.attrs((*item).into());
let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into());
if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
if let ModItem::ExternCrate(id) = item {
let import = self.item_tree[*id].clone();
@ -933,7 +938,7 @@ fn collect(&mut self, items: &[ModItem]) {
}
for &item in items {
let attrs = self.item_tree.attrs(item.into());
let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
if let Some(cfg) = attrs.cfg() {
if !self.is_cfg_enabled(&cfg) {
self.emit_unconfigured_diagnostic(item, &cfg);
@ -946,7 +951,7 @@ fn collect(&mut self, items: &[ModItem]) {
let mut def = None;
match item {
ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs),
ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs),
ModItem::Import(import_id) => {
self.def_collector.unresolved_imports.push(ImportDirective {
module_id: self.module_id,
@ -975,7 +980,11 @@ fn collect(&mut self, items: &[ModItem]) {
// "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it
// to define builtin macros, so we support at least that part.
let attrs = self.item_tree.attrs(ModItem::from(id).into());
let attrs = self.item_tree.attrs(
self.def_collector.db,
krate,
ModItem::from(id).into(),
);
if attrs.by_key("rustc_builtin_macro").exists() {
let krate = self.def_collector.def_map.krate;
let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
@ -1012,7 +1021,7 @@ fn collect(&mut self, items: &[ModItem]) {
ModItem::Function(id) => {
let func = &self.item_tree[id];
self.collect_proc_macro_def(&func.name, attrs);
self.collect_proc_macro_def(&func.name, &attrs);
def = Some(DefData {
id: FunctionLoc {
@ -1032,7 +1041,7 @@ fn collect(&mut self, items: &[ModItem]) {
// FIXME: check attrs to see if this is an attribute macro invocation;
// in which case we don't add the invocation, just a single attribute
// macro invocation
self.collect_derives(attrs, it.ast_id.upcast());
self.collect_derives(&attrs, it.ast_id.upcast());
def = Some(DefData {
id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) }
@ -1049,7 +1058,7 @@ fn collect(&mut self, items: &[ModItem]) {
// FIXME: check attrs to see if this is an attribute macro invocation;
// in which case we don't add the invocation, just a single attribute
// macro invocation
self.collect_derives(attrs, it.ast_id.upcast());
self.collect_derives(&attrs, it.ast_id.upcast());
def = Some(DefData {
id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) }
@ -1066,7 +1075,7 @@ fn collect(&mut self, items: &[ModItem]) {
// FIXME: check attrs to see if this is an attribute macro invocation;
// in which case we don't add the invocation, just a single attribute
// macro invocation
self.collect_derives(attrs, it.ast_id.upcast());
self.collect_derives(&attrs, it.ast_id.upcast());
def = Some(DefData {
id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) }
@ -1303,8 +1312,9 @@ fn collect_proc_macro_def(&mut self, func_name: &Name, attrs: &Attrs) {
}
fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
let krate = self.def_collector.def_map.krate;
let mac = &self.item_tree[id];
let attrs = self.item_tree.attrs(ModItem::from(id).into());
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
let export_attr = attrs.by_key("macro_export");