Merge pull request #638 from afdw/master

Add applying of typedefs, remove generation of type aliases
This commit is contained in:
Sendil Kumar N 2018-08-04 13:50:23 +02:00 committed by GitHub
commit d66b834afd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 147 additions and 83 deletions

View File

@ -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,

View File

@ -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::*;

View File

@ -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);
}
}

View File

@ -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(())
}
}

View File

@ -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(),

View File

@ -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;