generator: Generate push_next function for all extended structs (#305)

* push_next and Extends traits are generated for all root structs.
root structs are now all structs that are extended by other structs!
root structs used to be all structs that don't extend any other structs.

* the root_structs local variable that is passed around is now a set of Ident (and no String).

fixes https://github.com/MaikKlein/ash/issues/229
This commit is contained in:
Philippe Renon 2021-06-16 23:44:51 +02:00 committed by GitHub
parent d6e049f340
commit a0b9eddd0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 434 additions and 2818 deletions

File diff suppressed because it is too large Load diff

View file

@ -1778,7 +1778,7 @@ pub fn derive_debug(
pub fn derive_setters( pub fn derive_setters(
_struct: &vkxml::Struct, _struct: &vkxml::Struct,
root_struct_names: &HashSet<String, impl BuildHasher>, root_structs: &HashSet<Ident, impl BuildHasher>,
) -> Option<TokenStream> { ) -> Option<TokenStream> {
if &_struct.name == "VkBaseInStructure" if &_struct.name == "VkBaseInStructure"
|| &_struct.name == "VkBaseOutStructure" || &_struct.name == "VkBaseOutStructure"
@ -1979,19 +1979,7 @@ pub fn derive_setters(
let extends_name = format_ident!("Extends{}", name); let extends_name = format_ident!("Extends{}", name);
let root_structs: Vec<Ident> = _struct let is_root_struct = has_next && root_structs.contains(&name);
.extends
.as_ref()
.map(|extends| {
extends
.split(',')
.filter(|extend| root_struct_names.contains(*extend))
.map(|extends| format_ident!("Extends{}", name_to_tokens(extends)))
.collect()
})
.unwrap_or_else(Vec::new);
let is_root_struct = has_next && root_structs.is_empty();
// We only implement a next methods for root structs with a `pnext` field. // We only implement a next methods for root structs with a `pnext` field.
let next_function = if is_root_struct { let next_function = if is_root_struct {
@ -2032,8 +2020,13 @@ pub fn derive_setters(
quote!() quote!()
}; };
// If the struct extends something we need to implement the trait. // If the struct extends something we need to implement the traits.
let impl_extend_trait = root_structs.iter().map(|extends| { let impl_extend_trait = _struct
.extends
.iter()
.flat_map(|extends| extends.split(','))
.map(|extends| format_ident!("Extends{}", name_to_tokens(extends)))
.map(|extends| {
quote! { quote! {
unsafe impl #extends for #name_builder<'_> {} unsafe impl #extends for #name_builder<'_> {}
unsafe impl #extends for #name {} unsafe impl #extends for #name {}
@ -2104,7 +2097,7 @@ pub fn manual_derives(_struct: &vkxml::Struct) -> TokenStream {
} }
pub fn generate_struct( pub fn generate_struct(
_struct: &vkxml::Struct, _struct: &vkxml::Struct,
root_struct_names: &HashSet<String, impl BuildHasher>, root_structs: &HashSet<Ident, impl BuildHasher>,
union_types: &HashSet<&str, impl BuildHasher>, union_types: &HashSet<&str, impl BuildHasher>,
) -> TokenStream { ) -> TokenStream {
let name = name_to_tokens(&_struct.name); let name = name_to_tokens(&_struct.name);
@ -2150,7 +2143,7 @@ pub fn generate_struct(
let debug_tokens = derive_debug(_struct, union_types); let debug_tokens = derive_debug(_struct, union_types);
let default_tokens = derive_default(_struct); let default_tokens = derive_default(_struct);
let setter_tokens = derive_setters(_struct, root_struct_names); let setter_tokens = derive_setters(_struct, root_structs);
let manual_derive_tokens = manual_derives(_struct); let manual_derive_tokens = manual_derives(_struct);
let dbg_str = if debug_tokens.is_none() { let dbg_str = if debug_tokens.is_none() {
quote!(Debug,) quote!(Debug,)
@ -2248,26 +2241,23 @@ fn generate_union(union: &vkxml::Union) -> TokenStream {
} }
} }
} }
pub fn root_struct_names(definitions: &[&vkxml::DefinitionsElement]) -> HashSet<String> { /// Root structs are all structs that are extended by other structs.
definitions pub fn root_structs(definitions: &[&vkxml::DefinitionsElement]) -> HashSet<Ident> {
.iter() let mut root_structs = HashSet::new();
.filter_map(|definition| match *definition { // Loop over all structs and collect their extends
vkxml::DefinitionsElement::Struct(ref _struct) => { for definition in definitions {
let is_root_struct = _struct.extends.is_none(); if let vkxml::DefinitionsElement::Struct(ref _struct) = definition {
if is_root_struct { if let Some(extends) = &_struct.extends {
Some(_struct.name.clone()) root_structs.extend(extends.split(',').map(name_to_tokens));
} else {
None
} }
};
} }
_ => None, root_structs
})
.collect()
} }
pub fn generate_definition( pub fn generate_definition(
definition: &vkxml::DefinitionsElement, definition: &vkxml::DefinitionsElement,
union_types: &HashSet<&str, impl BuildHasher>, union_types: &HashSet<&str, impl BuildHasher>,
root_structs: &HashSet<String, impl BuildHasher>, root_structs: &HashSet<Ident, impl BuildHasher>,
bitflags_cache: &mut HashSet<Ident, impl BuildHasher>, bitflags_cache: &mut HashSet<Ident, impl BuildHasher>,
const_values: &mut BTreeMap<Ident, ConstantTypeInfo>, const_values: &mut BTreeMap<Ident, ConstantTypeInfo>,
identifier_renames: &mut BTreeMap<String, Ident>, identifier_renames: &mut BTreeMap<String, Ident>,
@ -2731,14 +2721,14 @@ pub fn write_source_code<P: AsRef<Path>>(vk_headers_dir: &Path, src_dir: P) {
let mut identifier_renames = BTreeMap::new(); let mut identifier_renames = BTreeMap::new();
let root_names = root_struct_names(&definitions); let root_structs = root_structs(&definitions);
let definition_code: Vec<_> = definitions let definition_code: Vec<_> = definitions
.into_iter() .into_iter()
.filter_map(|def| { .filter_map(|def| {
generate_definition( generate_definition(
def, def,
&union_types, &union_types,
&root_names, &root_structs,
&mut bitflags_cache, &mut bitflags_cache,
&mut const_values, &mut const_values,
&mut identifier_renames, &mut identifier_renames,