Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify metadata filtering #2684

Merged
merged 3 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions crates/libs/bindgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,14 @@ where
let output = canonicalize(output)?;

let input = read_input(&input)?;
let reader = metadata::Reader::new(input);
let filter = metadata::Filter::new(&include, &exclude);
let reader = metadata::Reader::filter(input, &include, &exclude);

winmd::verify(reader, &filter)?;
winmd::verify(reader)?;

match extension(&output) {
"rdl" => rdl::from_reader(reader, &filter, config, &output)?,
"winmd" => winmd::from_reader(reader, &filter, config, &output)?,
"rs" => rust::from_reader(reader, &filter, config, &output)?,
"rdl" => rdl::from_reader(reader, config, &output)?,
"winmd" => winmd::from_reader(reader, config, &output)?,
"rs" => rust::from_reader(reader, config, &output)?,
_ => return Err(Error::new("output extension must be one of winmd/rdl/rs")),
}

Expand Down
135 changes: 68 additions & 67 deletions crates/libs/bindgen/src/metadata.rs

Large diffs are not rendered by default.

19 changes: 9 additions & 10 deletions crates/libs/bindgen/src/rdl/from_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ use crate::tokens::{quote, to_ident, TokenStream};
use crate::{rdl, Error, Result, Tree};
use metadata::*;

pub fn from_reader(reader: &metadata::Reader, filter: &metadata::Filter, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> {
pub fn from_reader(reader: &metadata::Reader, mut config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> {
let dialect = match config.remove("type") {
Some("winrt") => Dialect::WinRT,
Some("win32") => Dialect::Win32,
_ => return Err(Error::new("configuration value `type` must be `win32` or `winrt`")),
};

let mut writer = Writer::new(reader, filter, output, dialect);
let mut writer = Writer::new(reader, output, dialect);

// TODO: be sure to use the same "split" key for winmd splitting.
// May also want to support split=N similar to the way MIDLRT supports winmd splitting
Expand All @@ -29,7 +29,7 @@ pub fn from_reader(reader: &metadata::Reader, filter: &metadata::Filter, mut con
}

fn gen_split(writer: &Writer) -> Result<()> {
let tree = Tree::new(writer.reader, writer.filter);
let tree = Tree::new(writer.reader);
let directory = crate::directory(writer.output);

// TODO: parallelize
Expand All @@ -46,7 +46,7 @@ fn gen_split(writer: &Writer) -> Result<()> {
}

fn gen_file(writer: &Writer) -> Result<()> {
let tree = Tree::new(writer.reader, writer.filter);
let tree = Tree::new(writer.reader);
let tokens = writer.tree(&tree);
writer.write_to_file(writer.output, tokens)
}
Expand All @@ -59,20 +59,19 @@ enum Dialect {

struct Writer<'a> {
reader: &'a metadata::Reader,
filter: &'a metadata::Filter<'a>,
namespace: &'a str,
dialect: Dialect,
split: bool,
output: &'a str,
}

impl<'a> Writer<'a> {
fn new(reader: &'a metadata::Reader, filter: &'a metadata::Filter, output: &'a str, dialect: Dialect) -> Self {
Self { reader, filter, namespace: "", output, dialect, split: false }
fn new(reader: &'a metadata::Reader, output: &'a str, dialect: Dialect) -> Self {
Self { reader, namespace: "", output, dialect, split: false }
}

fn with_namespace(&self, namespace: &'a str) -> Self {
Self { reader: self.reader, filter: self.filter, namespace, dialect: self.dialect, output: self.output, split: self.split }
Self { reader: self.reader, namespace, dialect: self.dialect, output: self.output, split: self.split }
}

fn write_to_file(&self, output: &str, tokens: TokenStream) -> Result<()> {
Expand Down Expand Up @@ -135,7 +134,7 @@ impl<'a> Writer<'a> {
let mut types = vec![];

if !tree.namespace.is_empty() {
for item in self.reader.namespace_items(tree.namespace, self.filter).filter(|item| match item {
for item in self.reader.namespace_items(tree.namespace).filter(|item| match item {
metadata::Item::Type(def) => {
let winrt = def.flags().contains(metadata::TypeAttributes::WindowsRuntime);
match self.dialect {
Expand Down Expand Up @@ -246,7 +245,7 @@ impl<'a> Writer<'a> {
let name = to_ident(method.name());

// TODO: use reader.method_def_signature instead
let signature = metadata::method_def_signature(self.reader, def.namespace(), method, generics);
let signature = metadata::method_def_signature(def.namespace(), method, generics);

let return_type = self.return_type(&signature.return_type);

Expand Down
76 changes: 38 additions & 38 deletions crates/libs/bindgen/src/rust/cfg.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use super::*;

#[derive(Default, Clone)]
pub struct Cfg<'a> {
pub types: BTreeMap<&'a str, BTreeSet<TypeDef>>,
pub struct Cfg {
pub types: BTreeMap<&'static str, BTreeSet<TypeDef>>,
pub core_types: BTreeSet<Type>,
pub arches: BTreeSet<&'static str>,
pub implement: bool,
}

impl<'a> Cfg<'a> {
pub fn add_feature(&mut self, feature: &'a str) {
impl Cfg {
pub fn add_feature(&mut self, feature: &'static str) {
self.types.entry(feature).or_default();
}
pub fn union(&self, other: &Self) -> Self {
Expand All @@ -30,63 +30,63 @@ impl<'a> Cfg<'a> {
}
}

pub fn field_cfg(reader: &Reader, row: Field) -> Cfg {
pub fn field_cfg(row: Field) -> Cfg {
let mut cfg = Cfg::default();
field_cfg_combine(reader, row, None, &mut cfg);
field_cfg_combine(row, None, &mut cfg);
cfg
}
fn field_cfg_combine<'a>(reader: &'a Reader, row: Field, enclosing: Option<TypeDef>, cfg: &mut Cfg<'a>) {
type_cfg_combine(reader, &row.ty(enclosing), cfg)
fn field_cfg_combine(row: Field, enclosing: Option<TypeDef>, cfg: &mut Cfg) {
type_cfg_combine(&row.ty(enclosing), cfg)
}

pub fn type_def_cfg<'a>(reader: &'a Reader, row: TypeDef, generics: &[Type]) -> Cfg<'a> {
pub fn type_def_cfg(row: TypeDef, generics: &[Type]) -> Cfg {
let mut cfg = Cfg::default();
type_def_cfg_combine(reader, row, generics, &mut cfg);
type_def_cfg_combine(row, generics, &mut cfg);
cfg_add_attributes(&mut cfg, row);
cfg
}
pub fn type_def_cfg_impl<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type]) -> Cfg<'a> {
pub fn type_def_cfg_impl(def: TypeDef, generics: &[Type]) -> Cfg {
let mut cfg = Cfg { implement: true, ..Default::default() };

fn combine<'a>(reader: &'a Reader, def: TypeDef, generics: &[Type], cfg: &mut Cfg<'a>) {
type_def_cfg_combine(reader, def, generics, cfg);
fn combine(def: TypeDef, generics: &[Type], cfg: &mut Cfg) {
type_def_cfg_combine(def, generics, cfg);

for method in def.methods() {
signature_cfg_combine(reader, &method.signature(generics), cfg);
signature_cfg_combine(&method.signature(generics), cfg);
}
}

combine(reader, def, generics, &mut cfg);
combine(def, generics, &mut cfg);

for def in type_def_vtables(def) {
if let Type::TypeDef(def, generics) = def {
combine(reader, def, &generics, &mut cfg);
combine(def, &generics, &mut cfg);
}
}

if def.flags().contains(TypeAttributes::WindowsRuntime) {
for interface in type_def_interfaces(def, generics) {
if let Type::TypeDef(def, generics) = interface {
combine(reader, def, &generics, &mut cfg);
combine(def, &generics, &mut cfg);
}
}
}

cfg_add_attributes(&mut cfg, def);
cfg
}
pub fn type_def_cfg_combine<'a>(reader: &'a Reader, row: TypeDef, generics: &[Type], cfg: &mut Cfg<'a>) {
pub fn type_def_cfg_combine(row: TypeDef, generics: &[Type], cfg: &mut Cfg) {
let type_name = row.type_name();

for generic in generics {
type_cfg_combine(reader, generic, cfg);
type_cfg_combine(generic, cfg);
}

if cfg.types.entry(type_name.namespace).or_default().insert(row) {
match row.kind() {
TypeKind::Class => {
if let Some(default_interface) = type_def_default_interface(row) {
type_cfg_combine(reader, &default_interface, cfg);
type_cfg_combine(&default_interface, cfg);
}
}
TypeKind::Interface => {
Expand All @@ -99,30 +99,30 @@ pub fn type_def_cfg_combine<'a>(reader: &'a Reader, row: TypeDef, generics: &[Ty
}
}
TypeKind::Struct => {
row.fields().for_each(|field| field_cfg_combine(reader, field, Some(row), cfg));
row.fields().for_each(|field| field_cfg_combine(field, Some(row), cfg));
if !type_name.namespace.is_empty() {
for def in reader.get_type_def(type_name.namespace, type_name.name) {
for def in row.reader().get_type_def(type_name.namespace, type_name.name) {
if def != row {
type_def_cfg_combine(reader, def, &[], cfg);
type_def_cfg_combine(def, &[], cfg);
}
}
}
}
TypeKind::Delegate => signature_cfg_combine(reader, &type_def_invoke_method(row).signature(generics), cfg),
TypeKind::Delegate => signature_cfg_combine(&type_def_invoke_method(row).signature(generics), cfg),
_ => {}
}
}
}

pub fn signature_cfg(reader: &Reader, method: MethodDef) -> Cfg {
pub fn signature_cfg(method: MethodDef) -> Cfg {
let mut cfg = Cfg::default();
signature_cfg_combine(reader, &method.signature(&[]), &mut cfg);
signature_cfg_combine(&method.signature(&[]), &mut cfg);
cfg_add_attributes(&mut cfg, method);
cfg
}
fn signature_cfg_combine<'a>(reader: &'a Reader, signature: &MethodDefSig, cfg: &mut Cfg<'a>) {
type_cfg_combine(reader, &signature.return_type, cfg);
signature.params.iter().for_each(|param| type_cfg_combine(reader, param, cfg));
fn signature_cfg_combine(signature: &MethodDefSig, cfg: &mut Cfg) {
type_cfg_combine(&signature.return_type, cfg);
signature.params.iter().for_each(|param| type_cfg_combine(param, cfg));
}

fn cfg_add_attributes<R: AsRow + Into<HasAttribute>>(cfg: &mut Cfg, row: R) {
Expand Down Expand Up @@ -151,19 +151,19 @@ fn cfg_add_attributes<R: AsRow + Into<HasAttribute>>(cfg: &mut Cfg, row: R) {
}
}

pub fn type_cfg<'a>(reader: &'a Reader, ty: &Type) -> Cfg<'a> {
pub fn type_cfg(ty: &Type) -> Cfg {
let mut cfg = Cfg::default();
type_cfg_combine(reader, ty, &mut cfg);
type_cfg_combine(ty, &mut cfg);
cfg
}
fn type_cfg_combine<'a>(reader: &'a Reader, ty: &Type, cfg: &mut Cfg<'a>) {
fn type_cfg_combine(ty: &Type, cfg: &mut Cfg) {
match ty {
Type::TypeDef(row, generics) => type_def_cfg_combine(reader, *row, generics, cfg),
Type::Win32Array(ty, _) => type_cfg_combine(reader, ty, cfg),
Type::ConstPtr(ty, _) => type_cfg_combine(reader, ty, cfg),
Type::MutPtr(ty, _) => type_cfg_combine(reader, ty, cfg),
Type::WinrtArray(ty) => type_cfg_combine(reader, ty, cfg),
Type::WinrtArrayRef(ty) => type_cfg_combine(reader, ty, cfg),
Type::TypeDef(row, generics) => type_def_cfg_combine(*row, generics, cfg),
Type::Win32Array(ty, _) => type_cfg_combine(ty, cfg),
Type::ConstPtr(ty, _) => type_cfg_combine(ty, cfg),
Type::MutPtr(ty, _) => type_cfg_combine(ty, cfg),
Type::WinrtArray(ty) => type_cfg_combine(ty, cfg),
Type::WinrtArrayRef(ty) => type_cfg_combine(ty, cfg),
ty => _ = cfg.core_types.insert(ty.clone()),
}
}
12 changes: 6 additions & 6 deletions crates/libs/bindgen/src/rust/classes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ fn gen_class(writer: &Writer, def: TypeDef) -> TokenStream {
}

let name = to_ident(def.name());
let interfaces = type_interfaces(writer.reader, &Type::TypeDef(def, Vec::new()));
let interfaces = type_interfaces(&Type::TypeDef(def, Vec::new()));
let mut methods = quote! {};
let mut method_names = MethodNames::new();

let cfg = type_def_cfg(writer.reader, def, &[]);
let cfg = type_def_cfg(def, &[]);
let doc = writer.cfg_doc(&cfg);
let features = writer.cfg_features(&cfg);

Expand All @@ -44,7 +44,7 @@ fn gen_class(writer: &Writer, def: TypeDef) -> TokenStream {
if let Type::TypeDef(def, generics) = &interface.ty {
if def.methods().next().is_some() {
let interface_type = writer.type_name(&interface.ty);
let features = writer.cfg_features(&type_def_cfg(writer.reader, *def, generics));
let features = writer.cfg_features(&type_def_cfg(*def, generics));

return Some(quote! {
#[doc(hidden)]
Expand Down Expand Up @@ -138,17 +138,17 @@ fn gen_conversions(writer: &Writer, def: TypeDef, name: &TokenStream, interfaces
}

let into = writer.type_name(&interface.ty);
let features = writer.cfg_features(&cfg.union(&type_cfg(writer.reader, &interface.ty)));
let features = writer.cfg_features(&cfg.union(&type_cfg(&interface.ty)));

tokens.combine(&quote! {
#features
impl ::windows_core::CanTryInto<#into> for #name {}
});
}

for def in type_def_bases(writer.reader, def) {
for def in type_def_bases(def) {
let into = writer.type_def_name(def, &[]);
let features = writer.cfg_features(&cfg.union(&type_def_cfg(writer.reader, def, &[])));
let features = writer.cfg_features(&cfg.union(&type_def_cfg(def, &[])));

tokens.combine(&quote! {
#features
Expand Down
4 changes: 2 additions & 2 deletions crates/libs/bindgen/src/rust/com_methods.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use super::*;

pub fn writer(writer: &Writer, def: TypeDef, kind: InterfaceKind, method: MethodDef, method_names: &mut MethodNames, virtual_names: &mut MethodNames, base_count: usize) -> TokenStream {
let signature = method_def_signature(writer.reader, def.namespace(), method, &[]);
let signature = method_def_signature(def.namespace(), method, &[]);

let name = method_names.add(method);
let vname = virtual_names.add(method);
let generics = writer.constraint_generics(&signature.params);
let where_clause = writer.where_clause(&signature.params);
let mut cfg = signature_cfg(writer.reader, method);
let mut cfg = signature_cfg(method);
cfg.add_feature(def.namespace());
let doc = writer.cfg_method_doc(&cfg);
let features = writer.cfg_features(&cfg);
Expand Down
2 changes: 1 addition & 1 deletion crates/libs/bindgen/src/rust/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::*;
pub fn writer(writer: &Writer, def: Field) -> TokenStream {
let name = to_ident(def.name());
let ty = def.ty(None).to_const_type();
let cfg = field_cfg(writer.reader, def);
let cfg = field_cfg(def);
let doc = writer.cfg_doc(&cfg);
let features = writer.cfg_features(&cfg);

Expand Down
8 changes: 4 additions & 4 deletions crates/libs/bindgen/src/rust/delegates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ fn gen_callback(writer: &Writer, def: TypeDef) -> TokenStream {
let name = to_ident(def.name());
let method = type_def_invoke_method(def);

let signature = method_def_signature(writer.reader, def.namespace(), method, &[]);
let signature = method_def_signature(def.namespace(), method, &[]);

let return_type = writer.return_sig(&signature);
let cfg = type_def_cfg(writer.reader, def, &[]);
let cfg = type_def_cfg(def, &[]);
let doc = writer.cfg_doc(&cfg);
let features = writer.cfg_features(&cfg);

Expand Down Expand Up @@ -57,10 +57,10 @@ fn gen_win_delegate(writer: &Writer, def: TypeDef) -> TokenStream {
let ident = writer.type_def_name(def, generics);
let method = type_def_invoke_method(def);

let signature = method_def_signature(writer.reader, def.namespace(), method, generics);
let signature = method_def_signature(def.namespace(), method, generics);

let fn_constraint = gen_fn_constraint(writer, def, &signature);
let cfg = type_def_cfg(writer.reader, def, generics);
let cfg = type_def_cfg(def, generics);
let doc = writer.cfg_doc(&cfg);
let features = writer.cfg_features(&cfg);

Expand Down
4 changes: 2 additions & 2 deletions crates/libs/bindgen/src/rust/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream {
// TODO: unscoped enums should be removed from metadata
let is_scoped = def.flags().contains(TypeAttributes::WindowsRuntime) || def.has_attribute("ScopedEnumAttribute");

let cfg = type_def_cfg(writer.reader, def, &[]);
let cfg = type_def_cfg(def, &[]);
let doc = writer.cfg_doc(&cfg);
let features = writer.cfg_features(&cfg);

Expand Down Expand Up @@ -160,7 +160,7 @@ pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream {
}

if def.flags().contains(TypeAttributes::WindowsRuntime) {
let signature = Literal::byte_string(type_def_signature(writer.reader, def, &[]).as_bytes());
let signature = Literal::byte_string(type_def_signature(def, &[]).as_bytes());

tokens.combine(&quote! {
#features
Expand Down
Loading