mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-12-29 21:11:33 +03:00
Merge pull request #638 from afdw/master
Add applying of typedefs, remove generation of type aliases
This commit is contained in:
commit
d66b834afd
@ -17,8 +17,6 @@ pub struct Program {
|
||||
pub enums: Vec<Enum>,
|
||||
/// rust structs
|
||||
pub structs: Vec<Struct>,
|
||||
/// rust type aliases
|
||||
pub type_aliases: Vec<TypeAlias>,
|
||||
/// rust consts
|
||||
pub consts: Vec<Const>,
|
||||
}
|
||||
@ -198,13 +196,6 @@ pub enum TypeLocation {
|
||||
ExportRet,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
pub struct TypeAlias {
|
||||
pub vis: syn::Visibility,
|
||||
pub dest: Ident,
|
||||
pub src: syn::Type,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
||||
pub struct Const {
|
||||
pub vis: syn::Visibility,
|
||||
|
@ -64,9 +64,6 @@ impl TryToTokens for ast::Program {
|
||||
for e in self.enums.iter() {
|
||||
e.to_tokens(tokens);
|
||||
}
|
||||
for a in self.type_aliases.iter() {
|
||||
a.to_tokens(tokens);
|
||||
}
|
||||
for c in self.consts.iter() {
|
||||
c.to_tokens(tokens);
|
||||
}
|
||||
@ -983,18 +980,6 @@ impl ToTokens for ast::ImportStatic {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::TypeAlias {
|
||||
fn to_tokens(&self, into: &mut TokenStream) {
|
||||
let vis = &self.vis;
|
||||
let dest = &self.dest;
|
||||
let src = &self.src;
|
||||
(quote! {
|
||||
#[allow(non_camel_case_types)]
|
||||
#vis type #dest = #src;
|
||||
}).to_tokens(into);
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ast::Const {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
use ast::ConstValue::*;
|
||||
|
@ -83,7 +83,6 @@ impl ImportedTypes for ast::Program {
|
||||
F: FnMut(&Ident, ImportedTypeKind),
|
||||
{
|
||||
self.imports.imported_types(f);
|
||||
self.type_aliases.imported_types(f);
|
||||
self.consts.imported_types(f);
|
||||
}
|
||||
}
|
||||
@ -290,15 +289,6 @@ impl ImportedTypes for ast::ImportEnum {
|
||||
}
|
||||
}
|
||||
|
||||
impl ImportedTypes for ast::TypeAlias {
|
||||
fn imported_types<F>(&self, f: &mut F)
|
||||
where
|
||||
F: FnMut(&Ident, ImportedTypeKind),
|
||||
{
|
||||
f(&self.dest, ImportedTypeKind::Reference);
|
||||
}
|
||||
}
|
||||
|
||||
impl ImportedTypes for ast::Const {
|
||||
fn imported_types<F>(&self, f: &mut F)
|
||||
where
|
||||
@ -322,7 +312,6 @@ impl RemoveUndefinedImports for ast::Program {
|
||||
F: Fn(&Ident) -> bool,
|
||||
{
|
||||
self.imports.remove_undefined_imports(is_defined);
|
||||
self.type_aliases.remove_undefined_imports(is_defined);
|
||||
self.consts.remove_undefined_imports(is_defined);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ pub(crate) struct FirstPassRecord<'a> {
|
||||
pub(crate) enums: BTreeSet<String>,
|
||||
/// The mixins, mapping their name to the webidl ast node for the mixin.
|
||||
pub(crate) mixins: BTreeMap<String, MixinData<'a>>,
|
||||
pub(crate) typedefs: BTreeMap<String, webidl::ast::Type>,
|
||||
}
|
||||
|
||||
/// We need to collect interface data during the first pass, to be used later.
|
||||
@ -82,6 +83,7 @@ impl FirstPass<()> for webidl::ast::Definition {
|
||||
Enum(enum_) => enum_.first_pass(record, ()),
|
||||
Interface(interface) => interface.first_pass(record, ()),
|
||||
Mixin(mixin) => mixin.first_pass(record, ()),
|
||||
Typedef(typedef) => typedef.first_pass(record, ()),
|
||||
_ => {
|
||||
// Other definitions aren't currently used in the first pass
|
||||
Ok(())
|
||||
@ -356,3 +358,17 @@ impl FirstPass<()> for webidl::ast::PartialMixin {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl FirstPass<()> for webidl::ast::Typedef {
|
||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
||||
if ::util::is_chrome_only(&self.extended_attributes) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if record.typedefs.insert(self.name.clone(), *self.type_.clone()).is_some() {
|
||||
warn!("Encountered multiple declarations of {}", self.name);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ use failure::{ResultExt, Fail};
|
||||
use heck::{ShoutySnakeCase};
|
||||
|
||||
use first_pass::{FirstPass, FirstPassRecord};
|
||||
use util::{public, webidl_const_ty_to_syn_ty, webidl_const_v_to_backend_const_v, TypePosition, camel_case_ident, mdn_doc};
|
||||
use util::{ApplyTypedefs, public, webidl_const_ty_to_syn_ty, webidl_const_v_to_backend_const_v, camel_case_ident, mdn_doc};
|
||||
|
||||
pub use error::{Error, ErrorKind, Result};
|
||||
|
||||
@ -159,9 +159,6 @@ impl WebidlParse<()> for webidl::ast::Definition {
|
||||
webidl::ast::Definition::Interface(interface) => {
|
||||
interface.webidl_parse(program, first_pass, ())?
|
||||
}
|
||||
webidl::ast::Definition::Typedef(typedef) => {
|
||||
typedef.webidl_parse(program, first_pass, ())?
|
||||
}
|
||||
// TODO
|
||||
webidl::ast::Definition::Callback(..)
|
||||
| webidl::ast::Definition::Dictionary(..)
|
||||
@ -169,7 +166,8 @@ impl WebidlParse<()> for webidl::ast::Definition {
|
||||
| webidl::ast::Definition::Namespace(..) => {
|
||||
warn!("Unsupported WebIDL definition: {:?}", self)
|
||||
}
|
||||
webidl::ast::Definition::Mixin(_) => {
|
||||
webidl::ast::Definition::Mixin(_)
|
||||
| webidl::ast::Definition::Typedef(_) => {
|
||||
// handled in the first pass
|
||||
}
|
||||
}
|
||||
@ -226,39 +224,6 @@ impl WebidlParse<()> for webidl::ast::Interface {
|
||||
}
|
||||
}
|
||||
|
||||
impl WebidlParse<()> for webidl::ast::Typedef {
|
||||
fn webidl_parse(
|
||||
&self,
|
||||
program: &mut backend::ast::Program,
|
||||
first_pass: &FirstPassRecord<'_>,
|
||||
(): (),
|
||||
) -> Result<()> {
|
||||
if util::is_chrome_only(&self.extended_attributes) {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let dest = rust_ident(camel_case_ident(&self.name).as_str());
|
||||
let src = match first_pass.webidl_ty_to_syn_ty(&self.type_, TypePosition::Return) {
|
||||
Some(src) => src,
|
||||
None => {
|
||||
warn!(
|
||||
"typedef's source type is not yet supported: {:?}. Skipping typedef {:?}",
|
||||
*self.type_, self
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
program.type_aliases.push(backend::ast::TypeAlias {
|
||||
vis: public(),
|
||||
dest,
|
||||
src,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl WebidlParse<()> for webidl::ast::NonPartialInterface {
|
||||
fn webidl_parse(
|
||||
&self,
|
||||
@ -334,6 +299,11 @@ impl<'a> WebidlParse<&'a webidl::ast::NonPartialInterface> for webidl::ast::Exte
|
||||
interface: &'a webidl::ast::NonPartialInterface,
|
||||
) -> Result<()> {
|
||||
let mut add_constructor = |arguments: &[webidl::ast::Argument], class: &str| {
|
||||
let arguments = &arguments
|
||||
.iter()
|
||||
.map(|argument| argument.apply_typedefs(first_pass))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let (overloaded, same_argument_names) = first_pass.get_operation_overloading(
|
||||
arguments,
|
||||
::first_pass::OperationId::Constructor,
|
||||
@ -530,7 +500,7 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::RegularAttribute {
|
||||
first_pass
|
||||
.create_getter(
|
||||
&self.name,
|
||||
&self.type_,
|
||||
&self.type_.apply_typedefs(first_pass),
|
||||
self_name,
|
||||
false,
|
||||
is_structural,
|
||||
@ -543,7 +513,7 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::RegularAttribute {
|
||||
first_pass
|
||||
.create_setter(
|
||||
&self.name,
|
||||
&self.type_,
|
||||
&self.type_.apply_typedefs(first_pass),
|
||||
self_name,
|
||||
false,
|
||||
is_structural,
|
||||
@ -618,7 +588,7 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::StaticAttribute {
|
||||
first_pass
|
||||
.create_getter(
|
||||
&self.name,
|
||||
&self.type_,
|
||||
&self.type_.apply_typedefs(first_pass),
|
||||
self_name,
|
||||
true,
|
||||
is_structural,
|
||||
@ -631,7 +601,7 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::StaticAttribute {
|
||||
first_pass
|
||||
.create_setter(
|
||||
&self.name,
|
||||
&self.type_,
|
||||
&self.type_.apply_typedefs(first_pass),
|
||||
self_name,
|
||||
true,
|
||||
is_structural,
|
||||
@ -660,9 +630,13 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::RegularOperation {
|
||||
|
||||
first_pass
|
||||
.create_basic_method(
|
||||
&self.arguments,
|
||||
&self
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|argument| argument.apply_typedefs(first_pass))
|
||||
.collect::<Vec<_>>(),
|
||||
self.name.as_ref(),
|
||||
&self.return_type,
|
||||
&self.return_type.apply_typedefs(first_pass),
|
||||
self_name,
|
||||
false,
|
||||
throws,
|
||||
@ -689,9 +663,13 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::StaticOperation {
|
||||
|
||||
first_pass
|
||||
.create_basic_method(
|
||||
&self.arguments,
|
||||
&self
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|argument| argument.apply_typedefs(first_pass))
|
||||
.collect::<Vec<_>>(),
|
||||
self.name.as_ref(),
|
||||
&self.return_type,
|
||||
&self.return_type.apply_typedefs(first_pass),
|
||||
self_name,
|
||||
true,
|
||||
throws,
|
||||
@ -741,10 +719,10 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::Const {
|
||||
fn webidl_parse(
|
||||
&self,
|
||||
program: &mut backend::ast::Program,
|
||||
_: &FirstPassRecord<'_>,
|
||||
first_pass: &FirstPassRecord<'_>,
|
||||
self_name: &'a str,
|
||||
) -> Result<()> {
|
||||
let ty = webidl_const_ty_to_syn_ty(&self.type_);
|
||||
let ty = webidl_const_ty_to_syn_ty(&self.type_.apply_typedefs(first_pass));
|
||||
|
||||
program.consts.push(backend::ast::Const {
|
||||
vis: public(),
|
||||
|
@ -142,6 +142,111 @@ pub enum TypePosition {
|
||||
Return,
|
||||
}
|
||||
|
||||
fn type_kind_to_const_type(type_kind: &webidl::ast::TypeKind) -> webidl::ast::ConstType {
|
||||
match type_kind {
|
||||
webidl::ast::TypeKind::Boolean => webidl::ast::ConstType::Boolean,
|
||||
webidl::ast::TypeKind::Byte => webidl::ast::ConstType::Byte,
|
||||
webidl::ast::TypeKind::Identifier(identifier) => webidl::ast::ConstType::Identifier(identifier.clone()),
|
||||
webidl::ast::TypeKind::Octet => webidl::ast::ConstType::Octet,
|
||||
webidl::ast::TypeKind::RestrictedDouble => webidl::ast::ConstType::RestrictedDouble,
|
||||
webidl::ast::TypeKind::RestrictedFloat => webidl::ast::ConstType::RestrictedFloat,
|
||||
webidl::ast::TypeKind::SignedLong => webidl::ast::ConstType::SignedLong,
|
||||
webidl::ast::TypeKind::SignedLongLong => webidl::ast::ConstType::SignedLongLong,
|
||||
webidl::ast::TypeKind::SignedShort => webidl::ast::ConstType::SignedShort,
|
||||
webidl::ast::TypeKind::UnrestrictedDouble => webidl::ast::ConstType::UnrestrictedDouble,
|
||||
webidl::ast::TypeKind::UnrestrictedFloat => webidl::ast::ConstType::UnrestrictedFloat,
|
||||
webidl::ast::TypeKind::UnsignedLong => webidl::ast::ConstType::UnsignedLong,
|
||||
webidl::ast::TypeKind::UnsignedLongLong => webidl::ast::ConstType::UnsignedLongLong,
|
||||
webidl::ast::TypeKind::UnsignedShort => webidl::ast::ConstType::UnsignedShort,
|
||||
_ => panic!("can not convert TypeKind to ConstType: {:#?}", type_kind),
|
||||
}
|
||||
}
|
||||
|
||||
/// Implemented on an AST type node to apply typedefs.
|
||||
pub(crate) trait ApplyTypedefs {
|
||||
fn apply_typedefs<'a>(&self, record: &FirstPassRecord<'a>) -> Self;
|
||||
}
|
||||
|
||||
impl ApplyTypedefs for webidl::ast::Type {
|
||||
fn apply_typedefs<'a>(&self, record: &FirstPassRecord<'a>) -> Self {
|
||||
webidl::ast::Type {
|
||||
extended_attributes: self.extended_attributes.clone(),
|
||||
kind: self.kind.apply_typedefs(record),
|
||||
nullable: self.nullable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplyTypedefs for webidl::ast::ReturnType {
|
||||
fn apply_typedefs<'a>(&self, record: &FirstPassRecord<'a>) -> Self {
|
||||
match self {
|
||||
webidl::ast::ReturnType::NonVoid(ty) =>
|
||||
webidl::ast::ReturnType::NonVoid(Box::new(ty.apply_typedefs(record))),
|
||||
_ => self.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplyTypedefs for webidl::ast::StringType {
|
||||
fn apply_typedefs<'a>(&self, _: &FirstPassRecord<'a>) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplyTypedefs for webidl::ast::ConstType {
|
||||
fn apply_typedefs<'a>(&self, record: &FirstPassRecord<'a>) -> Self {
|
||||
match self {
|
||||
webidl::ast::ConstType::Identifier(identifier) =>
|
||||
record
|
||||
.typedefs
|
||||
.get(identifier)
|
||||
.map(|ty| type_kind_to_const_type(&ty.kind))
|
||||
.unwrap_or(self.clone()),
|
||||
_ => self.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplyTypedefs for webidl::ast::TypeKind {
|
||||
fn apply_typedefs<'a>(&self, record: &FirstPassRecord<'a>) -> Self {
|
||||
match self {
|
||||
webidl::ast::TypeKind::FrozenArray(ty) =>
|
||||
webidl::ast::TypeKind::FrozenArray(Box::new(ty.apply_typedefs(record))),
|
||||
webidl::ast::TypeKind::Identifier(identifier) => record
|
||||
.typedefs
|
||||
.get(identifier)
|
||||
.map(|ty| ty.kind.clone())
|
||||
.unwrap_or(self.clone()),
|
||||
webidl::ast::TypeKind::Promise(ty) =>
|
||||
webidl::ast::TypeKind::Promise(ty.apply_typedefs(record)),
|
||||
webidl::ast::TypeKind::Record(string_type, ty) => webidl::ast::TypeKind::Record(
|
||||
string_type.apply_typedefs(record),
|
||||
Box::new(ty.apply_typedefs(record)),
|
||||
),
|
||||
webidl::ast::TypeKind::Union(types) => webidl::ast::TypeKind::Union(
|
||||
types
|
||||
.iter()
|
||||
.map(|ty| Box::new(ty.apply_typedefs(record)))
|
||||
.collect(),
|
||||
),
|
||||
_ => self.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplyTypedefs for webidl::ast::Argument {
|
||||
fn apply_typedefs<'a>(&self, record: &FirstPassRecord<'a>) -> Self {
|
||||
webidl::ast::Argument {
|
||||
extended_attributes: self.extended_attributes.clone(),
|
||||
default: self.default.clone(),
|
||||
name: self.name.clone(),
|
||||
optional: self.optional,
|
||||
type_: Box::new(self.type_.apply_typedefs(record)),
|
||||
variadic: self.variadic,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implemented on an AST type node to generate a snake case name.
|
||||
trait TypeToString {
|
||||
fn type_to_string(&self) -> String;
|
||||
|
Loading…
Reference in New Issue
Block a user