Skip to content

Commit 3024ddd

Browse files
committed
refactor: Remove fields from ItemTree
1 parent 96a2531 commit 3024ddd

File tree

8 files changed

+230
-200
lines changed

8 files changed

+230
-200
lines changed

crates/hir-def/src/attr.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,37 +94,45 @@ impl Attrs {
9494
v: VariantId,
9595
) -> Arc<ArenaMap<LocalFieldId, Attrs>> {
9696
let _p = tracing::info_span!("fields_attrs_query").entered();
97-
// FIXME: There should be some proper form of mapping between item tree field ids and hir field ids
9897
let mut res = ArenaMap::default();
9998
let item_tree;
100-
let (parent, fields, krate) = match v {
99+
let (parent, field_count, krate) = match v {
101100
VariantId::EnumVariantId(it) => {
102101
let loc = it.lookup(db);
103102
let krate = loc.parent.lookup(db).container.krate;
104103
item_tree = loc.id.item_tree(db);
105-
let variant = &item_tree[loc.id.value];
106-
(FieldParent::EnumVariant(loc.id.value), &variant.fields, krate)
104+
let node = loc.ast_ptr(db).to_node(db);
105+
let field_count = node.field_list().map_or(0, |it| match it {
106+
ast::FieldList::RecordFieldList(it) => it.fields().count(),
107+
ast::FieldList::TupleFieldList(it) => it.fields().count(),
108+
});
109+
(FieldParent::EnumVariant(loc.id.value), field_count, krate)
107110
}
108111
VariantId::StructId(it) => {
109112
let loc = it.lookup(db);
110113
let krate = loc.container.krate;
111114
item_tree = loc.id.item_tree(db);
112-
let struct_ = &item_tree[loc.id.value];
113-
(FieldParent::Struct(loc.id.value), &struct_.fields, krate)
115+
let node = loc.ast_ptr(db).to_node(db);
116+
let field_count = node.field_list().map_or(0, |it| match it {
117+
ast::FieldList::RecordFieldList(it) => it.fields().count(),
118+
ast::FieldList::TupleFieldList(it) => it.fields().count(),
119+
});
120+
(FieldParent::Struct(loc.id.value), field_count, krate)
114121
}
115122
VariantId::UnionId(it) => {
116123
let loc = it.lookup(db);
117124
let krate = loc.container.krate;
118125
item_tree = loc.id.item_tree(db);
119-
let union_ = &item_tree[loc.id.value];
120-
(FieldParent::Union(loc.id.value), &union_.fields, krate)
126+
let node = loc.ast_ptr(db).to_node(db);
127+
let field_count = node.record_field_list().map_or(0, |it| it.fields().count());
128+
(FieldParent::Union(loc.id.value), field_count, krate)
121129
}
122130
};
123131

124132
let cfg_options = krate.cfg_options(db);
125133

126134
let mut idx = 0;
127-
for (id, _field) in fields.iter().enumerate() {
135+
for id in 0..field_count {
128136
let attrs = item_tree.attrs(db, krate, AttrOwner::make_field_indexed(parent, id));
129137
if attrs.is_cfg_enabled(cfg_options) {
130138
res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);

crates/hir-def/src/item_tree.rs

Lines changed: 73 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,25 @@ use std::{
4444
};
4545

4646
use ast::{AstNode, StructKind};
47-
use base_db::Crate;
47+
use base_db::{Crate, EditionedFileId};
48+
use either::Either;
4849
use hir_expand::{
4950
ExpandTo, HirFileId, InFile,
5051
attrs::RawAttrs,
5152
mod_path::{ModPath, PathKind},
52-
name::Name,
53+
name::{AsName, Name},
5354
};
5455
use intern::{Interned, Symbol};
5556
use la_arena::{Arena, Idx, RawIdx};
5657
use rustc_hash::FxHashMap;
5758
use smallvec::SmallVec;
5859
use span::{AstIdNode, Edition, FileAstId, SyntaxContext};
5960
use stdx::never;
60-
use syntax::{SyntaxKind, ast, match_ast};
61+
use syntax::{
62+
SyntaxKind,
63+
ast::{self, HasName, HasVisibility},
64+
match_ast,
65+
};
6166
use triomphe::Arc;
6267

6368
use crate::{BlockId, Lookup, attr::Attrs, db::DefDatabase};
@@ -194,6 +199,57 @@ impl ItemTree {
194199
Attrs::expand_cfg_attr(db, krate, self.raw_attrs(of).clone())
195200
}
196201

202+
pub(crate) fn fields<'a>(
203+
&'a self,
204+
db: &'a dyn DefDatabase,
205+
file_id: HirFileId,
206+
parent: FieldParent,
207+
override_visibility: Option<RawVisibilityId>,
208+
) -> Option<Box<dyn Iterator<Item = (Name, RawVisibility, bool)> + 'a>> {
209+
let ast_fields = match parent {
210+
FieldParent::Struct(it) => {
211+
InFile::new(file_id, self[it].ast_id).to_node(db).field_list()
212+
}
213+
FieldParent::Union(it) => InFile::new(file_id, self[it].ast_id)
214+
.to_node(db)
215+
.record_field_list()
216+
.map(ast::FieldList::RecordFieldList),
217+
FieldParent::EnumVariant(it) => {
218+
InFile::new(file_id, self[it].ast_id).to_node(db).field_list()
219+
}
220+
}?;
221+
let override_or_span_map =
222+
override_visibility.map_or_else(|| Either::Right(db.span_map(file_id)), Either::Left);
223+
let lower_vis =
224+
move |field: Either<&ast::RecordField, &ast::TupleField>| match &override_or_span_map {
225+
Either::Left(id) => self[*id].clone(),
226+
Either::Right(span_map) => {
227+
let node = match field {
228+
Either::Left(it) => it.visibility(),
229+
Either::Right(it) => it.visibility(),
230+
};
231+
RawVisibility::from_ast(db, node, &mut |range| {
232+
span_map.span_for_range(range).ctx
233+
})
234+
}
235+
};
236+
let res: Box<dyn Iterator<Item = (Name, RawVisibility, bool)>> = match ast_fields {
237+
ast::FieldList::RecordFieldList(it) => Box::new(it.fields().map(move |f| {
238+
(
239+
f.name().map_or(Name::missing(), |n| n.as_name()),
240+
lower_vis(Either::Left(&f)),
241+
f.unsafe_token().is_some(),
242+
)
243+
})),
244+
ast::FieldList::TupleFieldList(it) => {
245+
Box::new(it.fields().enumerate().map(move |(idx, f)| {
246+
(Name::new_tuple_field(idx), lower_vis(Either::Right(&f)), false)
247+
}))
248+
}
249+
};
250+
Some(res)
251+
}
252+
197253
/// Returns a count of a few, expensive items.
198254
///
199255
/// For more detail, see [`ItemTreeDataStats`].
@@ -210,8 +266,8 @@ impl ItemTree {
210266
}
211267
}
212268

213-
pub fn pretty_print(&self, db: &dyn DefDatabase, edition: Edition) -> String {
214-
pretty::print_item_tree(db, self, edition)
269+
pub fn pretty_print(&self, db: &dyn DefDatabase, file_id: EditionedFileId) -> String {
270+
pretty::print_item_tree(db, self, file_id)
215271
}
216272

217273
fn data(&self) -> &ItemTreeData {
@@ -341,12 +397,12 @@ pub enum AttrOwner {
341397

342398
Variant(FileItemTreeId<Variant>),
343399
// while not relevant to early name resolution, fields can contain visibility
344-
Field(FieldParent, ItemTreeFieldId),
400+
Field(FieldParent, usize),
345401
}
346402

347403
impl AttrOwner {
348404
pub fn make_field_indexed(parent: FieldParent, idx: usize) -> Self {
349-
AttrOwner::Field(parent, ItemTreeFieldId::from_raw(RawIdx::from_u32(idx as u32)))
405+
AttrOwner::Field(parent, idx)
350406
}
351407
}
352408

@@ -357,8 +413,6 @@ pub enum FieldParent {
357413
EnumVariant(FileItemTreeId<Variant>),
358414
}
359415

360-
pub type ItemTreeFieldId = Idx<Field>;
361-
362416
macro_rules! from_attrs {
363417
( $( $var:ident($t:ty) ),+ $(,)? ) => {
364418
$(
@@ -725,7 +779,6 @@ pub struct Function {
725779
pub struct Struct {
726780
pub name: Name,
727781
pub visibility: RawVisibilityId,
728-
pub fields: Box<[Field]>,
729782
pub shape: FieldsShape,
730783
pub ast_id: FileAstId<ast::Struct>,
731784
}
@@ -734,7 +787,6 @@ pub struct Struct {
734787
pub struct Union {
735788
pub name: Name,
736789
pub visibility: RawVisibilityId,
737-
pub fields: Box<[Field]>,
738790
pub ast_id: FileAstId<ast::Union>,
739791
}
740792

@@ -749,7 +801,6 @@ pub struct Enum {
749801
#[derive(Debug, Clone, PartialEq, Eq)]
750802
pub struct Variant {
751803
pub name: Name,
752-
pub fields: Box<[Field]>,
753804
pub shape: FieldsShape,
754805
pub ast_id: FileAstId<ast::Variant>,
755806
}
@@ -771,6 +822,16 @@ pub enum RawVisibility {
771822
Public,
772823
}
773824

825+
impl RawVisibility {
826+
pub fn from_ast(
827+
db: &dyn DefDatabase,
828+
node: Option<ast::Visibility>,
829+
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext,
830+
) -> Self {
831+
lower::visibility_from_ast(db, node, span_for_range)
832+
}
833+
}
834+
774835
/// Whether the item was imported through an explicit `pub(crate) use` or just a `use` without
775836
/// visibility.
776837
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -785,16 +846,6 @@ impl VisibilityExplicitness {
785846
}
786847
}
787848

788-
// FIXME: Remove this from item tree?
789-
/// A single field of an enum variant or struct
790-
#[derive(Debug, Clone, PartialEq, Eq)]
791-
pub struct Field {
792-
pub name: Name,
793-
pub visibility: RawVisibilityId,
794-
// FIXME: Not an item tree property
795-
pub is_unsafe: bool,
796-
}
797-
798849
#[derive(Debug, Clone, Eq, PartialEq)]
799850
pub struct Const {
800851
/// `None` for `const _: () = ();`

crates/hir-def/src/item_tree/lower.rs

Lines changed: 20 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ use triomphe::Arc;
2020
use crate::{
2121
db::DefDatabase,
2222
item_tree::{
23-
AssocItem, AttrOwner, Const, Enum, ExternBlock, ExternCrate, Field, FieldParent,
24-
FieldsShape, FileItemTreeId, Function, Idx, Impl, ImportAlias, Interned, ItemTree,
25-
ItemTreeData, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, ModPath, Name, Range,
26-
RawAttrs, RawIdx, RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait,
27-
TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, Variant, VisibilityExplicitness,
23+
AssocItem, AttrOwner, Const, Enum, ExternBlock, ExternCrate, FieldParent, FieldsShape,
24+
FileItemTreeId, Function, Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData, Macro2,
25+
MacroCall, MacroRules, Mod, ModItem, ModKind, ModPath, Name, Range, RawAttrs, RawIdx,
26+
RawVisibility, RawVisibilityId, Static, Struct, StructKind, Trait, TraitAlias, TypeAlias,
27+
Union, Use, UseTree, UseTreeKind, Variant, VisibilityExplicitness,
2828
},
2929
};
3030

@@ -187,93 +187,59 @@ impl<'a> Ctx<'a> {
187187
let visibility = self.lower_visibility(strukt);
188188
let name = strukt.name()?.as_name();
189189
let ast_id = self.source_ast_id_map.ast_id(strukt);
190-
let (fields, kind, attrs) = self.lower_fields(&strukt.kind());
191-
let res = Struct { name, visibility, fields, shape: kind, ast_id };
190+
let (kind, attrs) = self.lower_fields(&strukt.kind());
191+
let res = Struct { name, visibility, shape: kind, ast_id };
192192
let id = id(self.data().structs.alloc(res));
193193

194194
for (idx, attr) in attrs {
195-
self.add_attrs(
196-
AttrOwner::Field(
197-
FieldParent::Struct(id),
198-
Idx::from_raw(RawIdx::from_u32(idx as u32)),
199-
),
200-
attr,
201-
);
195+
self.add_attrs(AttrOwner::Field(FieldParent::Struct(id), idx), attr);
202196
}
203197
Some(id)
204198
}
205199

206200
fn lower_fields(
207201
&mut self,
208202
strukt_kind: &ast::StructKind,
209-
) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) {
203+
) -> (FieldsShape, Vec<(usize, RawAttrs)>) {
210204
match strukt_kind {
211205
ast::StructKind::Record(it) => {
212-
let mut fields = vec![];
213206
let mut attrs = vec![];
214207

215208
for (i, field) in it.fields().enumerate() {
216-
let data = self.lower_record_field(&field);
217-
fields.push(data);
218209
let attr = RawAttrs::new(self.db, &field, self.span_map());
219210
if !attr.is_empty() {
220211
attrs.push((i, attr))
221212
}
222213
}
223-
(fields.into(), FieldsShape::Record, attrs)
214+
(FieldsShape::Record, attrs)
224215
}
225216
ast::StructKind::Tuple(it) => {
226-
let mut fields = vec![];
227217
let mut attrs = vec![];
228218

229219
for (i, field) in it.fields().enumerate() {
230-
let data = self.lower_tuple_field(i, &field);
231-
fields.push(data);
232220
let attr = RawAttrs::new(self.db, &field, self.span_map());
233221
if !attr.is_empty() {
234222
attrs.push((i, attr))
235223
}
236224
}
237-
(fields.into(), FieldsShape::Tuple, attrs)
225+
(FieldsShape::Tuple, attrs)
238226
}
239-
ast::StructKind::Unit => (Box::default(), FieldsShape::Unit, Vec::default()),
227+
ast::StructKind::Unit => (FieldsShape::Unit, Vec::default()),
240228
}
241229
}
242230

243-
fn lower_record_field(&mut self, field: &ast::RecordField) -> Field {
244-
let name = match field.name() {
245-
Some(name) => name.as_name(),
246-
None => Name::missing(),
247-
};
248-
let visibility = self.lower_visibility(field);
249-
250-
Field { name, visibility, is_unsafe: field.unsafe_token().is_some() }
251-
}
252-
253-
fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field {
254-
let name = Name::new_tuple_field(idx);
255-
let visibility = self.lower_visibility(field);
256-
Field { name, visibility, is_unsafe: false }
257-
}
258-
259231
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
260232
let visibility = self.lower_visibility(union);
261233
let name = union.name()?.as_name();
262234
let ast_id = self.source_ast_id_map.ast_id(union);
263-
let (fields, _, attrs) = match union.record_field_list() {
235+
let (_, attrs) = match union.record_field_list() {
264236
Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
265-
None => (Box::default(), FieldsShape::Record, Vec::default()),
237+
None => (FieldsShape::Record, Vec::default()),
266238
};
267-
let res = Union { name, visibility, fields, ast_id };
239+
let res = Union { name, visibility, ast_id };
268240
let id = id(self.data().unions.alloc(res));
269241
for (idx, attr) in attrs {
270-
self.add_attrs(
271-
AttrOwner::Field(
272-
FieldParent::Union(id),
273-
Idx::from_raw(RawIdx::from_u32(idx as u32)),
274-
),
275-
attr,
276-
);
242+
self.add_attrs(AttrOwner::Field(FieldParent::Union(id), idx), attr);
277243
}
278244
Some(id)
279245
}
@@ -308,16 +274,13 @@ impl<'a> Ctx<'a> {
308274
Some(name) => name.as_name(),
309275
None => Name::missing(),
310276
};
311-
let (fields, kind, attrs) = self.lower_fields(&variant.kind());
277+
let (kind, attrs) = self.lower_fields(&variant.kind());
312278
let ast_id = self.source_ast_id_map.ast_id(variant);
313-
let res = Variant { name, fields, shape: kind, ast_id };
279+
let res = Variant { name, shape: kind, ast_id };
314280
let id = self.data().variants.alloc(res);
315281
for (idx, attr) in attrs {
316282
self.add_attrs(
317-
AttrOwner::Field(
318-
FieldParent::EnumVariant(FileItemTreeId(id)),
319-
Idx::from_raw(RawIdx::from_u32(idx as u32)),
320-
),
283+
AttrOwner::Field(FieldParent::EnumVariant(FileItemTreeId(id)), idx),
321284
attr,
322285
);
323286
}
@@ -626,7 +589,7 @@ fn private_vis() -> RawVisibility {
626589
)
627590
}
628591

629-
fn visibility_from_ast(
592+
pub(super) fn visibility_from_ast(
630593
db: &dyn DefDatabase,
631594
node: Option<ast::Visibility>,
632595
span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContext,

0 commit comments

Comments
 (0)