diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs index ee8bff34678..8f68bd5fb13 100644 --- a/crates/ra_assists/src/assists/add_new.rs +++ b/crates/ra_assists/src/assists/add_new.rs @@ -35,8 +35,8 @@ pub(crate) fn add_new(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { let strukt = ctx.find_node_at_offset::<ast::StructDef>()?; // We want to only apply this to non-union structs with named fields - let field_list = match (strukt.kind(), strukt.is_union()) { - (StructKind::Record(named), false) => named, + let field_list = match strukt.kind() { + StructKind::Record(named) => named, _ => return None, }; diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 534f1f8e982..ae730beb51a 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -320,7 +320,7 @@ pub struct Struct { impl Struct { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.0.module(db) } + Module { id: self.id.module(db) } } pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { @@ -369,11 +369,11 @@ pub struct Union { impl Union { pub fn name(self, db: &impl DefDatabase) -> Option<Name> { - db.struct_data(self.id.into()).name.clone() + db.union_data(self.id).name.clone() } pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.0.module(db) } + Module { id: self.id.module(db) } } pub fn ty(self, db: &impl HirDatabase) -> Ty { diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index a4e317c203c..076d86f2b9c 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -51,13 +51,13 @@ impl HasSource for StructField { impl HasSource for Struct { type Ast = ast::StructDef; fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> { - self.id.0.source(db) + self.id.source(db) } } impl HasSource for Union { - type Ast = ast::StructDef; - fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> { - self.id.0.source(db) + type Ast = ast::UnionDef; + fn source(self, db: &impl DefDatabase) -> Source<ast::UnionDef> { + self.id.source(db) } } impl HasSource for Enum { diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 1e7c22774d1..95db7161bf8 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use hir_def::{AstItemDef, LocationCtx, ModuleId, StructId, StructOrUnionId, UnionId}; +use hir_def::{AstItemDef, LocationCtx, ModuleId}; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ ast::{self, AstNode, NameOwner}, @@ -19,19 +19,18 @@ pub trait FromSource: Sized { fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>; } -// FIXIME: these two impls are wrong, `ast::StructDef` might produce either a struct or a union impl FromSource for Struct { type Ast = ast::StructDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { - let id: StructOrUnionId = from_source(db, src)?; - Some(Struct { id: StructId(id) }) + let id = from_source(db, src)?; + Some(Struct { id }) } } impl FromSource for Union { - type Ast = ast::StructDef; + type Ast = ast::UnionDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { - let id: StructOrUnionId = from_source(db, src)?; - Some(Union { id: UnionId(id) }) + let id = from_source(db, src)?; + Some(Union { id }) } } impl FromSource for Enum { diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 8c045aaef29..3cbcbd1d01b 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -858,7 +858,7 @@ impl HirDisplay for ApplicationTy { let name = match def { CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(), CallableDef::StructId(s) => { - f.db.struct_data(s.0).name.clone().unwrap_or_else(Name::missing) + f.db.struct_data(s).name.clone().unwrap_or_else(Name::missing) } CallableDef::EnumVariantId(e) => { let enum_data = f.db.enum_data(e.parent); diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs index 4b53bba73b4..bb9a2e427ef 100644 --- a/crates/ra_hir/src/ty/infer/coerce.rs +++ b/crates/ra_hir/src/ty/infer/coerce.rs @@ -246,7 +246,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), ) if struct1 == struct2 => { let field_tys = self.db.field_types(struct1.id.into()); - let struct_data = self.db.struct_data(struct1.id.0); + let struct_data = self.db.struct_data(struct1.id); let mut fields = struct_data.variant_data.fields().iter(); let (last_field_id, _data) = fields.next_back()?; diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 27cfe00c11a..89bc4b9aebb 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -560,7 +560,7 @@ pub(crate) fn field_types_query( variant_id: VariantId, ) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { let (resolver, var_data) = match variant_id { - VariantId::StructId(it) => (it.resolver(db), db.struct_data(it.0).variant_data.clone()), + VariantId::StructId(it) => (it.resolver(db), db.struct_data(it).variant_data.clone()), VariantId::EnumVariantId(it) => ( it.parent.resolver(db), db.enum_data(it.parent).variants[it.local_id].variant_data.clone(), @@ -818,7 +818,7 @@ impl CallableDef { pub fn krate(self, db: &impl HirDatabase) -> CrateId { match self { CallableDef::FunctionId(f) => f.lookup(db).module(db).krate, - CallableDef::StructId(s) => s.0.module(db).krate, + CallableDef::StructId(s) => s.module(db).krate, CallableDef::EnumVariantId(e) => e.parent.module(db).krate, } } diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index c9f30923ee6..71014826ef7 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -12,7 +12,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; use crate::{ db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource, - LocalEnumVariantId, LocalStructFieldId, StructOrUnionId, VariantId, + LocalEnumVariantId, LocalStructFieldId, StructId, UnionId, VariantId, }; /// Note that we use `StructData` for unions as well! @@ -49,13 +49,25 @@ pub struct StructFieldData { } impl StructData { - pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructOrUnionId) -> Arc<StructData> { + pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> { let src = id.source(db); let name = src.value.name().map(|n| n.as_name()); let variant_data = VariantData::new(src.value.kind()); let variant_data = Arc::new(variant_data); Arc::new(StructData { name, variant_data }) } + pub(crate) fn union_data_query(db: &impl DefDatabase, id: UnionId) -> Arc<StructData> { + let src = id.source(db); + let name = src.value.name().map(|n| n.as_name()); + let variant_data = VariantData::new( + src.value + .record_field_def_list() + .map(ast::StructKind::Record) + .unwrap_or(ast::StructKind::Unit), + ); + let variant_data = Arc::new(variant_data); + Arc::new(StructData { name, variant_data }) + } } impl EnumData { @@ -137,7 +149,7 @@ impl HasChildSource for VariantId { let src = it.parent.child_source(db); src.map(|map| map[it.local_id].kind()) } - VariantId::StructId(it) => it.0.source(db).map(|it| it.kind()), + VariantId::StructId(it) => it.source(db).map(|it| it.kind()), }; let mut trace = Trace::new_for_map(); lower_struct(&mut trace, &src.value); diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 53456fc0850..298608e27cd 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -54,9 +54,9 @@ impl Attrs { Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) } AttrDefId::AdtId(it) => match it { - AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), + AdtId::StructId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), - AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), + AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), }, AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db), diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 32adb11bdc4..ef5611ffc0d 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -18,8 +18,8 @@ use crate::{ CrateDefMap, }, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId, - ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructOrUnionId, TraitId, TypeAliasId, - TypeAliasLoc, + ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TypeAliasId, TypeAliasLoc, + UnionId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -27,7 +27,9 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_function(&self, loc: FunctionLoc) -> FunctionId; #[salsa::interned] - fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> StructOrUnionId; + fn intern_struct(&self, loc: ItemLoc<ast::StructDef>) -> StructId; + #[salsa::interned] + fn intern_union(&self, loc: ItemLoc<ast::UnionDef>) -> UnionId; #[salsa::interned] fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId; #[salsa::interned] @@ -57,7 +59,9 @@ pub trait DefDatabase: InternDatabase + AstDatabase { fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>; #[salsa::invoke(StructData::struct_data_query)] - fn struct_data(&self, id: StructOrUnionId) -> Arc<StructData>; + fn struct_data(&self, id: StructId) -> Arc<StructData>; + #[salsa::invoke(StructData::union_data_query)] + fn union_data(&self, id: UnionId) -> Arc<StructData>; #[salsa::invoke(EnumData::enum_data_query)] fn enum_data(&self, e: EnumId) -> Arc<EnumData>; diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs index 90a8627bc69..4749b642f0d 100644 --- a/crates/ra_hir_def/src/docs.rs +++ b/crates/ra_hir_def/src/docs.rs @@ -47,9 +47,9 @@ impl Documentation { } } AttrDefId::AdtId(it) => match it { - AdtId::StructId(it) => docs_from_ast(&it.0.source(db).value), + AdtId::StructId(it) => docs_from_ast(&it.source(db).value), AdtId::EnumId(it) => docs_from_ast(&it.source(db).value), - AdtId::UnionId(it) => docs_from_ast(&it.0.source(db).value), + AdtId::UnionId(it) => docs_from_ast(&it.source(db).value), }, AttrDefId::EnumVariantId(it) => { let src = it.parent.child_source(db); diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 015fe772e54..3f94e40e4f4 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -60,10 +60,8 @@ impl GenericParams { // FIXME: add `: Sized` bound for everything except for `Self` in traits match def { GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), - GenericDefId::AdtId(AdtId::StructId(it)) => { - generics.fill(&it.0.source(db).value, start) - } - GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.0.source(db).value, start), + GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start), + GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start), GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), GenericDefId::TraitId(it) => { // traits get the Self type as an implicit first type parameter diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 8e8c2d74908..5f11be1143a 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -141,30 +141,26 @@ impl Lookup for FunctionId { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct StructOrUnionId(salsa::InternId); -impl_intern_key!(StructOrUnionId); -impl AstItemDef<ast::StructDef> for StructOrUnionId { +pub struct StructId(salsa::InternId); +impl_intern_key!(StructId); +impl AstItemDef<ast::StructDef> for StructId { fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self { - db.intern_struct_or_union(loc) + db.intern_struct(loc) } fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> { - db.lookup_intern_struct_or_union(self) + db.lookup_intern_struct(self) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct StructId(pub StructOrUnionId); -impl From<StructId> for StructOrUnionId { - fn from(id: StructId) -> StructOrUnionId { - id.0 +pub struct UnionId(salsa::InternId); +impl_intern_key!(UnionId); +impl AstItemDef<ast::UnionDef> for UnionId { + fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::UnionDef>) -> Self { + db.intern_union(loc) } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct UnionId(pub StructOrUnionId); -impl From<UnionId> for StructOrUnionId { - fn from(id: UnionId) -> StructOrUnionId { - id.0 + fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::UnionDef> { + db.lookup_intern_union(self) } } @@ -485,8 +481,8 @@ impl HasModule for ConstLoc { impl HasModule for AdtId { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { match self { - AdtId::StructId(it) => it.0.module(db), - AdtId::UnionId(it) => it.0.module(db), + AdtId::StructId(it) => it.module(db), + AdtId::UnionId(it) => it.module(db), AdtId::EnumId(it) => it.module(db), } } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 41becf8dffd..4ff6f72cfba 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -25,7 +25,7 @@ use crate::{ per_ns::PerNs, AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId, Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId, - StructOrUnionId, TraitId, TypeAliasLoc, UnionId, + TraitId, TypeAliasLoc, UnionId, }; pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { @@ -698,14 +698,12 @@ where PerNs::values(def.into()) } raw::DefKind::Struct(ast_id) => { - let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); - let s = StructId(id).into(); - PerNs::both(s, s) + let id = StructId::from_ast_id(ctx, ast_id).into(); + PerNs::both(id, id) } raw::DefKind::Union(ast_id) => { - let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); - let u = UnionId(id).into(); - PerNs::both(u, u) + let id = UnionId::from_ast_id(ctx, ast_id).into(); + PerNs::both(id, id) } raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()), raw::DefKind::Const(ast_id) => { diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 401af031cc8..6eb106094cf 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -176,7 +176,7 @@ pub(super) struct DefData { pub(super) enum DefKind { Function(FileAstId<ast::FnDef>), Struct(FileAstId<ast::StructDef>), - Union(FileAstId<ast::StructDef>), + Union(FileAstId<ast::UnionDef>), Enum(FileAstId<ast::EnumDef>), Const(FileAstId<ast::ConstDef>), Static(FileAstId<ast::StaticDef>), @@ -246,11 +246,12 @@ impl RawItemsCollector { ast::ModuleItem::StructDef(it) => { let id = self.source_ast_id_map.ast_id(&it); let name = it.name(); - if it.is_union() { - (DefKind::Union(id), name) - } else { - (DefKind::Struct(id), name) - } + (DefKind::Struct(id), name) + } + ast::ModuleItem::UnionDef(it) => { + let id = self.source_ast_id_map.ast_id(&it); + let name = it.name(); + (DefKind::Union(id), name) } ast::ModuleItem::EnumDef(it) => { (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name()) diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index f502f1cb30e..87fcd617c52 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs @@ -82,6 +82,12 @@ fn crate_def_map_smoke_test() { //- /foo/bar.rs pub struct Baz; + + union U { + to_be: bool, + not_to_be: u8, + } + enum E { V } ", ); @@ -99,6 +105,7 @@ fn crate_def_map_smoke_test() { ⋮crate::foo::bar ⋮Baz: t v ⋮E: t + ⋮U: t v "###) } diff --git a/crates/ra_ide_api/src/display/short_label.rs b/crates/ra_ide_api/src/display/short_label.rs index 5d2bce3d292..9ffc9b98014 100644 --- a/crates/ra_ide_api/src/display/short_label.rs +++ b/crates/ra_ide_api/src/display/short_label.rs @@ -19,6 +19,12 @@ impl ShortLabel for ast::StructDef { } } +impl ShortLabel for ast::UnionDef { + fn short_label(&self) -> Option<String> { + short_label_from_node(self, "union ") + } +} + impl ShortLabel for ast::EnumDef { fn short_label(&self) -> Option<String> { short_label_from_node(self, "enum ") diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs index 3e3012559bb..2b3100fc366 100644 --- a/crates/ra_ide_api/src/impls.rs +++ b/crates/ra_ide_api/src/impls.rs @@ -49,6 +49,10 @@ fn impls_for_def( let src = hir::Source { file_id: position.file_id.into(), value: def.clone() }; hir::Enum::from_source(db, src)?.ty(db) } + ast::NominalDef::UnionDef(def) => { + let src = hir::Source { file_id: position.file_id.into(), value: def.clone() }; + hir::Union::from_source(db, src)?.ty(db) + } }; let krate = module.krate(); diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 630e6ce64fb..370990e21fd 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -6,8 +6,8 @@ mod traits; mod use_item; pub(crate) use self::{ - expressions::{match_arm_list, record_field_list}, adt::{enum_variant_list, record_field_def_list}, + expressions::{match_arm_list, record_field_list}, traits::{impl_item_list, trait_item_list}, use_item::use_tree_list, }; diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index 513ed7920f9..a8f62517629 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs @@ -196,17 +196,6 @@ impl StructKind { } impl ast::StructDef { - pub fn is_union(&self) -> bool { - for child in self.syntax().children_with_tokens() { - match child.kind() { - T![struct] => return false, - T![union] => return true, - _ => (), - } - } - false - } - pub fn kind(&self) -> StructKind { StructKind::from_node(self) } diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 1a03ae56c4b..c06076e3d7a 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -1856,6 +1856,7 @@ impl Module { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum ModuleItem { StructDef(StructDef), + UnionDef(UnionDef), EnumDef(EnumDef), FnDef(FnDef), TraitDef(TraitDef), @@ -1872,6 +1873,11 @@ impl From<StructDef> for ModuleItem { ModuleItem::StructDef(node) } } +impl From<UnionDef> for ModuleItem { + fn from(node: UnionDef) -> ModuleItem { + ModuleItem::UnionDef(node) + } +} impl From<EnumDef> for ModuleItem { fn from(node: EnumDef) -> ModuleItem { ModuleItem::EnumDef(node) @@ -1925,14 +1931,15 @@ impl From<Module> for ModuleItem { impl AstNode for ModuleItem { fn can_cast(kind: SyntaxKind) -> bool { match kind { - STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF | IMPL_BLOCK | USE_ITEM - | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE => true, + STRUCT_DEF | UNION_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF + | IMPL_BLOCK | USE_ITEM | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE => true, _ => false, } } fn cast(syntax: SyntaxNode) -> Option<Self> { let res = match syntax.kind() { STRUCT_DEF => ModuleItem::StructDef(StructDef { syntax }), + UNION_DEF => ModuleItem::UnionDef(UnionDef { syntax }), ENUM_DEF => ModuleItem::EnumDef(EnumDef { syntax }), FN_DEF => ModuleItem::FnDef(FnDef { syntax }), TRAIT_DEF => ModuleItem::TraitDef(TraitDef { syntax }), @@ -1950,6 +1957,7 @@ impl AstNode for ModuleItem { fn syntax(&self) -> &SyntaxNode { match self { ModuleItem::StructDef(it) => &it.syntax, + ModuleItem::UnionDef(it) => &it.syntax, ModuleItem::EnumDef(it) => &it.syntax, ModuleItem::FnDef(it) => &it.syntax, ModuleItem::TraitDef(it) => &it.syntax, @@ -2038,6 +2046,7 @@ impl NeverType {} pub enum NominalDef { StructDef(StructDef), EnumDef(EnumDef), + UnionDef(UnionDef), } impl From<StructDef> for NominalDef { fn from(node: StructDef) -> NominalDef { @@ -2049,10 +2058,15 @@ impl From<EnumDef> for NominalDef { NominalDef::EnumDef(node) } } +impl From<UnionDef> for NominalDef { + fn from(node: UnionDef) -> NominalDef { + NominalDef::UnionDef(node) + } +} impl AstNode for NominalDef { fn can_cast(kind: SyntaxKind) -> bool { match kind { - STRUCT_DEF | ENUM_DEF => true, + STRUCT_DEF | ENUM_DEF | UNION_DEF => true, _ => false, } } @@ -2060,6 +2074,7 @@ impl AstNode for NominalDef { let res = match syntax.kind() { STRUCT_DEF => NominalDef::StructDef(StructDef { syntax }), ENUM_DEF => NominalDef::EnumDef(EnumDef { syntax }), + UNION_DEF => NominalDef::UnionDef(UnionDef { syntax }), _ => return None, }; Some(res) @@ -2068,6 +2083,7 @@ impl AstNode for NominalDef { match self { NominalDef::StructDef(it) => &it.syntax, NominalDef::EnumDef(it) => &it.syntax, + NominalDef::UnionDef(it) => &it.syntax, } } } @@ -3815,7 +3831,11 @@ impl ast::NameOwner for UnionDef {} impl ast::TypeParamsOwner for UnionDef {} impl ast::AttrsOwner for UnionDef {} impl ast::DocCommentsOwner for UnionDef {} -impl UnionDef {} +impl UnionDef { + pub fn record_field_def_list(&self) -> Option<RecordFieldDefList> { + AstChildren::new(&self.syntax).next() + } +} #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UseItem { pub(crate) syntax: SyntaxNode, diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index c16bed89156..d1be40abeb9 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -293,7 +293,8 @@ Grammar( "TypeParamsOwner", "AttrsOwner", "DocCommentsOwner" - ] + ], + options: ["RecordFieldDefList"], ), "RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]), "RecordFieldDef": ( @@ -398,7 +399,7 @@ Grammar( ]), "NominalDef": ( - enum: ["StructDef", "EnumDef"], + enum: ["StructDef", "EnumDef", "UnionDef"], traits: [ "NameOwner", "TypeParamsOwner", @@ -406,9 +407,9 @@ Grammar( ], ), "ModuleItem": ( - enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock", + enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock", "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ], - traits: ["AttrsOwner"] + traits: ["AttrsOwner"], ), "ImplItem": ( enum: ["FnDef", "TypeAliasDef", "ConstDef"],