mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +00:00 
			
		
		
		
	feat: Implement default-field-values
				
					
				
			This commit is contained in:
		
							parent
							
								
									35b55fd67f
								
							
						
					
					
						commit
						7de0b2e75a
					
				
					 33 changed files with 647 additions and 31 deletions
				
			
		|  | @ -122,6 +122,9 @@ impl Body { | |||
|                     src.map(|it| it.expr()) | ||||
|                 } | ||||
|                 DefWithBodyId::InTypeConstId(c) => c.lookup(db).id.map(|_| c.source(db).expr()), | ||||
|                 DefWithBodyId::FieldId(f) => { | ||||
|                     f.record_field_source(db).map(|it| it.and_then(|it| it.expr())) | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|         let module = def.module(db); | ||||
|  |  | |||
|  | @ -90,6 +90,7 @@ pub(super) fn lower_body( | |||
|         DefWithBodyId::ConstId(it) => db.attrs(it.into()), | ||||
|         DefWithBodyId::InTypeConstId(_) => Attrs::EMPTY, | ||||
|         DefWithBodyId::VariantId(it) => db.attrs(it.into()), | ||||
|         DefWithBodyId::FieldId(it) => db.attrs(it.into()), | ||||
|     } | ||||
|     .rust_analyzer_tool() | ||||
|     .any(|attr| *attr.path() == tool_path![skip]); | ||||
|  | @ -168,6 +169,7 @@ pub(super) fn lower_body( | |||
|                     Awaitable::No("constant") | ||||
|                 } | ||||
|                 DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"), | ||||
|                 DefWithBodyId::FieldId(..) => Awaitable::No("field"), | ||||
|             } | ||||
|         }, | ||||
|     ); | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ use crate::{ | |||
|         Statement, | ||||
|     }, | ||||
|     pretty::{print_generic_args, print_path, print_type_ref}, | ||||
|     VariantId, | ||||
| }; | ||||
| 
 | ||||
| use super::*; | ||||
|  | @ -56,6 +57,32 @@ pub(super) fn print_body_hir( | |||
|                 loc.id.item_tree(db)[loc.id.value].name.display(db.upcast(), edition), | ||||
|             ) | ||||
|         } | ||||
|         DefWithBodyId::FieldId(it) => { | ||||
|             let parent_name: String = match it.parent { | ||||
|                 VariantId::EnumVariantId(it) => { | ||||
|                     let loc = it.lookup(db); | ||||
|                     let enum_loc = loc.parent.lookup(db); | ||||
|                     format!( | ||||
|                         "{}::{}", | ||||
|                         enum_loc.id.item_tree(db)[enum_loc.id.value] | ||||
|                             .name | ||||
|                             .display(db.upcast(), edition), | ||||
|                         loc.id.item_tree(db)[loc.id.value].name.display(db.upcast(), edition), | ||||
|                     ) | ||||
|                 } | ||||
|                 VariantId::StructId(it) => it | ||||
|                     .lookup(db) | ||||
|                     .id | ||||
|                     .resolved(db, |it| it.name.display(db.upcast(), edition).to_string()), | ||||
|                 VariantId::UnionId(it) => it | ||||
|                     .lookup(db) | ||||
|                     .id | ||||
|                     .resolved(db, |it| it.name.display(db.upcast(), edition).to_string()), | ||||
|             }; | ||||
|             let variant_data = it.parent.variant_data(db); | ||||
|             let field_name = &variant_data.fields()[it.local_id].name; | ||||
|             format!("field {}.{}", parent_name, field_name.display(db.upcast(), edition),) | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     let mut p = Printer { | ||||
|  |  | |||
|  | @ -55,6 +55,7 @@ pub mod visibility; | |||
| 
 | ||||
| use intern::Interned; | ||||
| pub use rustc_abi as layout; | ||||
| use src::HasSource; | ||||
| use triomphe::Arc; | ||||
| 
 | ||||
| #[cfg(test)] | ||||
|  | @ -77,6 +78,7 @@ use hir_expand::{ | |||
|     builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander}, | ||||
|     db::ExpandDatabase, | ||||
|     eager::expand_eager_macro_input, | ||||
|     files::InFileWrapper, | ||||
|     impl_intern_lookup, | ||||
|     name::Name, | ||||
|     proc_macro::{CustomProcMacroExpander, ProcMacroKind}, | ||||
|  | @ -519,6 +521,41 @@ pub struct FieldId { | |||
|     pub local_id: LocalFieldId, | ||||
| } | ||||
| 
 | ||||
| impl FieldId { | ||||
|     pub fn record_field_source( | ||||
|         &self, | ||||
|         db: &dyn DefDatabase, | ||||
|     ) -> InFileWrapper<HirFileId, Option<ast::RecordField>> { | ||||
|         let field_list = match self.parent { | ||||
|             crate::VariantId::EnumVariantId(it) => { | ||||
|                 let s = it.lookup(db); | ||||
|                 s.source(db).map(|it| { | ||||
|                     it.field_list().and_then(|it| match it { | ||||
|                         ast::FieldList::RecordFieldList(it) => Some(it), | ||||
|                         _ => None, | ||||
|                     }) | ||||
|                 }) | ||||
|             } | ||||
|             crate::VariantId::StructId(it) => { | ||||
|                 let s = it.lookup(db); | ||||
|                 s.source(db).map(|it| { | ||||
|                     it.field_list().and_then(|it| match it { | ||||
|                         ast::FieldList::RecordFieldList(it) => Some(it), | ||||
|                         _ => None, | ||||
|                     }) | ||||
|                 }) | ||||
|             } | ||||
|             crate::VariantId::UnionId(it) => { | ||||
|                 let s = it.lookup(db); | ||||
|                 s.source(db).map(|it| it.record_field_list()) | ||||
|             } | ||||
|         }; | ||||
|         field_list.map(|it| { | ||||
|             it.and_then(|it| it.fields().nth(self.local_id.into_raw().into_u32() as usize)) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub type LocalFieldId = Idx<data::adt::FieldData>; | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||||
|  | @ -686,6 +723,7 @@ pub enum TypeOwnerId { | |||
|     TypeAliasId(TypeAliasId), | ||||
|     ImplId(ImplId), | ||||
|     EnumVariantId(EnumVariantId), | ||||
|     FieldId(FieldId), | ||||
| } | ||||
| 
 | ||||
| impl TypeOwnerId { | ||||
|  | @ -703,6 +741,11 @@ impl TypeOwnerId { | |||
|                 GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent)) | ||||
|             } | ||||
|             TypeOwnerId::InTypeConstId(_) => return None, | ||||
|             TypeOwnerId::FieldId(it) => GenericDefId::AdtId(match it.parent { | ||||
|                 VariantId::EnumVariantId(it) => AdtId::EnumId(it.lookup(db).parent), | ||||
|                 VariantId::StructId(it) => it.into(), | ||||
|                 VariantId::UnionId(it) => it.into(), | ||||
|             }), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | @ -717,7 +760,8 @@ impl_from!( | |||
|     TraitAliasId, | ||||
|     TypeAliasId, | ||||
|     ImplId, | ||||
|     EnumVariantId | ||||
|     EnumVariantId, | ||||
|     FieldId | ||||
|     for TypeOwnerId | ||||
| ); | ||||
| 
 | ||||
|  | @ -730,6 +774,7 @@ impl From<DefWithBodyId> for TypeOwnerId { | |||
|             DefWithBodyId::ConstId(it) => it.into(), | ||||
|             DefWithBodyId::InTypeConstId(it) => it.into(), | ||||
|             DefWithBodyId::VariantId(it) => it.into(), | ||||
|             DefWithBodyId::FieldId(it) => it.into(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -885,6 +930,7 @@ pub enum DefWithBodyId { | |||
|     ConstId(ConstId), | ||||
|     InTypeConstId(InTypeConstId), | ||||
|     VariantId(EnumVariantId), | ||||
|     FieldId(FieldId), | ||||
| } | ||||
| 
 | ||||
| impl_from!(FunctionId, ConstId, StaticId, InTypeConstId for DefWithBodyId); | ||||
|  | @ -905,6 +951,7 @@ impl DefWithBodyId { | |||
|             // FIXME: stable rust doesn't allow generics in constants, but we should
 | ||||
|             // use `TypeOwnerId::as_generic_def_id` when it does.
 | ||||
|             DefWithBodyId::InTypeConstId(_) => None, | ||||
|             DefWithBodyId::FieldId(_) => None, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1332,6 +1379,11 @@ impl HasModule for TypeOwnerId { | |||
|             TypeOwnerId::ImplId(it) => it.module(db), | ||||
|             TypeOwnerId::EnumVariantId(it) => it.module(db), | ||||
|             TypeOwnerId::InTypeConstId(it) => it.lookup(db).owner.module(db), | ||||
|             TypeOwnerId::FieldId(it) => match it.parent { | ||||
|                 VariantId::EnumVariantId(it) => it.module(db), | ||||
|                 VariantId::StructId(it) => it.module(db), | ||||
|                 VariantId::UnionId(it) => it.module(db), | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1344,6 +1396,11 @@ impl HasModule for DefWithBodyId { | |||
|             DefWithBodyId::ConstId(it) => it.module(db), | ||||
|             DefWithBodyId::VariantId(it) => it.module(db), | ||||
|             DefWithBodyId::InTypeConstId(it) => it.lookup(db).owner.module(db), | ||||
|             DefWithBodyId::FieldId(it) => match it.parent { | ||||
|                 VariantId::EnumVariantId(it) => it.module(db), | ||||
|                 VariantId::StructId(it) => it.module(db), | ||||
|                 VariantId::UnionId(it) => it.module(db), | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -211,6 +211,20 @@ enum Bar { | |||
|     #[default] | ||||
|     Bar, | ||||
| } | ||||
| #[derive(Default)] | ||||
| struct Baz { | ||||
|     field1: i32 = 2, | ||||
|     field2: bool = { false }, | ||||
| } | ||||
| #[derive(Default)] | ||||
| enum Qux { | ||||
|     #[default] | ||||
|     Foo { | ||||
|         field1: i32, | ||||
|         field2: bool = true, | ||||
|         field3: (), | ||||
|     } | ||||
| } | ||||
| "#,
 | ||||
|         expect![[r#" | ||||
| #[derive(Default)] | ||||
|  | @ -224,6 +238,20 @@ enum Bar { | |||
|     #[default] | ||||
|     Bar, | ||||
| } | ||||
| #[derive(Default)] | ||||
| struct Baz { | ||||
|     field1: i32 = 2, | ||||
|     field2: bool = { false }, | ||||
| } | ||||
| #[derive(Default)] | ||||
| enum Qux { | ||||
|     #[default] | ||||
|     Foo { | ||||
|         field1: i32, | ||||
|         field2: bool = true, | ||||
|         field3: (), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl <> $crate::default::Default for Foo< > where { | ||||
|     fn default() -> Self { | ||||
|  | @ -236,6 +264,20 @@ impl <> $crate::default::Default for Bar< > where { | |||
|     fn default() -> Self { | ||||
|         Bar::Bar | ||||
|     } | ||||
| } | ||||
| impl <> $crate::default::Default for Baz< > where { | ||||
|     fn default() -> Self { | ||||
|         Baz { | ||||
|             .. | ||||
|         } | ||||
|     } | ||||
| } | ||||
| impl <> $crate::default::Default for Qux< > where { | ||||
|     fn default() -> Self { | ||||
|         Qux::Foo { | ||||
|             field1: $crate::default::Default::default(), field3: $crate::default::Default::default(), .. | ||||
|         } | ||||
|     } | ||||
| }"#]],
 | ||||
|     ); | ||||
| } | ||||
|  |  | |||
|  | @ -1227,6 +1227,11 @@ impl HasResolver for TypeOwnerId { | |||
|             TypeOwnerId::TypeAliasId(it) => it.resolver(db), | ||||
|             TypeOwnerId::ImplId(it) => it.resolver(db), | ||||
|             TypeOwnerId::EnumVariantId(it) => it.resolver(db), | ||||
|             TypeOwnerId::FieldId(it) => match it.parent { | ||||
|                 VariantId::EnumVariantId(it) => it.resolver(db), | ||||
|                 VariantId::StructId(it) => it.resolver(db), | ||||
|                 VariantId::UnionId(it) => it.resolver(db), | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -1239,6 +1244,11 @@ impl HasResolver for DefWithBodyId { | |||
|             DefWithBodyId::StaticId(s) => s.resolver(db), | ||||
|             DefWithBodyId::VariantId(v) => v.resolver(db), | ||||
|             DefWithBodyId::InTypeConstId(c) => c.lookup(db).owner.resolver(db), | ||||
|             DefWithBodyId::FieldId(f) => match f.parent { | ||||
|                 VariantId::EnumVariantId(it) => it.resolver(db), | ||||
|                 VariantId::StructId(it) => it.resolver(db), | ||||
|                 VariantId::UnionId(it) => it.resolver(db), | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Shoyu Vanilla
						Shoyu Vanilla