mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-17 23:11:23 +00:00
Add initial support for unions in return types, add more fixes for case of identifiers
This commit is contained in:
@ -1,12 +1,11 @@
|
|||||||
use backend::util::{ident_ty, leading_colon_path_ty, raw_ident, rust_ident};
|
use backend::util::{ident_ty, leading_colon_path_ty, raw_ident, rust_ident};
|
||||||
use heck::SnakeCase;
|
|
||||||
use syn;
|
use syn;
|
||||||
use weedle::common::Identifier;
|
use weedle::common::Identifier;
|
||||||
use weedle::term;
|
use weedle::term;
|
||||||
use weedle::types::*;
|
use weedle::types::*;
|
||||||
|
|
||||||
use first_pass::FirstPassRecord;
|
use first_pass::FirstPassRecord;
|
||||||
use util::{TypePosition, camel_case_ident, shared_ref, option_ty, array};
|
use util::{TypePosition, camel_case_ident, snake_case_ident, shared_ref, option_ty, array};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
|
||||||
pub(crate) enum IdlType<'a> {
|
pub(crate) enum IdlType<'a> {
|
||||||
@ -336,8 +335,88 @@ terms_to_idl_type! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IdlType<'a> {
|
impl<'a> IdlType<'a> {
|
||||||
|
/// Generates a camel case type name.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(crate) fn push_camel_case_name(&self, dst: &mut String) {
|
||||||
|
match self {
|
||||||
|
IdlType::Boolean => dst.push_str("Bool"),
|
||||||
|
IdlType::Byte => dst.push_str("I8"),
|
||||||
|
IdlType::Octet => dst.push_str("U8"),
|
||||||
|
IdlType::Short => dst.push_str("I16"),
|
||||||
|
IdlType::UnsignedShort => dst.push_str("U16"),
|
||||||
|
IdlType::Long => dst.push_str("I32"),
|
||||||
|
IdlType::UnsignedLong => dst.push_str("U32"),
|
||||||
|
IdlType::LongLong => dst.push_str("I64"),
|
||||||
|
IdlType::UnsignedLongLong => dst.push_str("U64"),
|
||||||
|
| IdlType::Float
|
||||||
|
| IdlType::UnrestrictedFloat => dst.push_str("F32"),
|
||||||
|
| IdlType::Double
|
||||||
|
| IdlType::UnrestrictedDouble => dst.push_str("F64"),
|
||||||
|
| IdlType::DomString
|
||||||
|
| IdlType::ByteString
|
||||||
|
| IdlType::UsvString => dst.push_str("Str"),
|
||||||
|
IdlType::Object => dst.push_str("Object"),
|
||||||
|
IdlType::Symbol => dst.push_str("Symbol"),
|
||||||
|
IdlType::Error => dst.push_str("Error"),
|
||||||
|
|
||||||
|
IdlType::ArrayBuffer => dst.push_str("ArrayBuffer"),
|
||||||
|
IdlType::DataView => dst.push_str("DataView"),
|
||||||
|
IdlType::Int8Array => dst.push_str("I8Array"),
|
||||||
|
IdlType::Uint8Array => dst.push_str("U8Array"),
|
||||||
|
IdlType::Uint8ClampedArray => dst.push_str("U8ClampedArray"),
|
||||||
|
IdlType::Int16Array => dst.push_str("I16Array"),
|
||||||
|
IdlType::Uint16Array => dst.push_str("U16Array"),
|
||||||
|
IdlType::Int32Array => dst.push_str("I32Array"),
|
||||||
|
IdlType::Uint32Array => dst.push_str("U32Array"),
|
||||||
|
IdlType::Float32Array => dst.push_str("F32Array"),
|
||||||
|
IdlType::Float64Array => dst.push_str("F64Array"),
|
||||||
|
|
||||||
|
IdlType::Interface(name) => dst.push_str(&camel_case_ident(name)),
|
||||||
|
IdlType::Dictionary(name) => dst.push_str(&camel_case_ident(name)),
|
||||||
|
IdlType::Enum(name) => dst.push_str(&camel_case_ident(name)),
|
||||||
|
|
||||||
|
IdlType::Nullable(idl_type) => {
|
||||||
|
dst.push_str("Opt");
|
||||||
|
idl_type.push_snake_case_name(dst);
|
||||||
|
},
|
||||||
|
IdlType::FrozenArray(idl_type) => {
|
||||||
|
idl_type.push_snake_case_name(dst);
|
||||||
|
dst.push_str("FrozenArray");
|
||||||
|
},
|
||||||
|
IdlType::Sequence(idl_type) => {
|
||||||
|
idl_type.push_snake_case_name(dst);
|
||||||
|
dst.push_str("Sequence");
|
||||||
|
},
|
||||||
|
IdlType::Promise(idl_type) => {
|
||||||
|
idl_type.push_snake_case_name(dst);
|
||||||
|
dst.push_str("Promise");
|
||||||
|
},
|
||||||
|
IdlType::Record(idl_type_from, idl_type_to) => {
|
||||||
|
dst.push_str("RecordFrom");
|
||||||
|
idl_type_from.push_snake_case_name(dst);
|
||||||
|
dst.push_str("To");
|
||||||
|
idl_type_to.push_snake_case_name(dst);
|
||||||
|
},
|
||||||
|
IdlType::Union(idl_types) => {
|
||||||
|
dst.push_str("UnionOf");
|
||||||
|
let mut first = true;
|
||||||
|
for idl_type in idl_types {
|
||||||
|
if first {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
dst.push_str("And");
|
||||||
|
}
|
||||||
|
idl_type.push_snake_case_name(dst);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
IdlType::Any => dst.push_str("Any"),
|
||||||
|
IdlType::Void => dst.push_str("Void"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generates a snake case type name.
|
/// Generates a snake case type name.
|
||||||
pub(crate) fn push_type_name(&self, dst: &mut String) {
|
pub(crate) fn push_snake_case_name(&self, dst: &mut String) {
|
||||||
match self {
|
match self {
|
||||||
IdlType::Boolean => dst.push_str("bool"),
|
IdlType::Boolean => dst.push_str("bool"),
|
||||||
IdlType::Byte => dst.push_str("i8"),
|
IdlType::Byte => dst.push_str("i8"),
|
||||||
@ -348,13 +427,13 @@ impl<'a> IdlType<'a> {
|
|||||||
IdlType::UnsignedLong => dst.push_str("u32"),
|
IdlType::UnsignedLong => dst.push_str("u32"),
|
||||||
IdlType::LongLong => dst.push_str("i64"),
|
IdlType::LongLong => dst.push_str("i64"),
|
||||||
IdlType::UnsignedLongLong => dst.push_str("u64"),
|
IdlType::UnsignedLongLong => dst.push_str("u64"),
|
||||||
IdlType::Float |
|
| IdlType::Float
|
||||||
IdlType::UnrestrictedFloat => dst.push_str("f32"),
|
| IdlType::UnrestrictedFloat => dst.push_str("f32"),
|
||||||
IdlType::Double |
|
| IdlType::Double
|
||||||
IdlType::UnrestrictedDouble => dst.push_str("f64"),
|
| IdlType::UnrestrictedDouble => dst.push_str("f64"),
|
||||||
IdlType::DomString |
|
| IdlType::DomString
|
||||||
IdlType::ByteString |
|
| IdlType::ByteString
|
||||||
IdlType::UsvString => dst.push_str("str"),
|
| IdlType::UsvString => dst.push_str("str"),
|
||||||
IdlType::Object => dst.push_str("object"),
|
IdlType::Object => dst.push_str("object"),
|
||||||
IdlType::Symbol => dst.push_str("symbol"),
|
IdlType::Symbol => dst.push_str("symbol"),
|
||||||
IdlType::Error => dst.push_str("error"),
|
IdlType::Error => dst.push_str("error"),
|
||||||
@ -371,31 +450,31 @@ impl<'a> IdlType<'a> {
|
|||||||
IdlType::Float32Array => dst.push_str("f32_array"),
|
IdlType::Float32Array => dst.push_str("f32_array"),
|
||||||
IdlType::Float64Array => dst.push_str("f64_array"),
|
IdlType::Float64Array => dst.push_str("f64_array"),
|
||||||
|
|
||||||
IdlType::Interface(name) => dst.push_str(&name.to_snake_case()),
|
IdlType::Interface(name) => dst.push_str(&snake_case_ident(name)),
|
||||||
IdlType::Dictionary(name) => dst.push_str(&name.to_snake_case()),
|
IdlType::Dictionary(name) => dst.push_str(&snake_case_ident(name)),
|
||||||
IdlType::Enum(name) => dst.push_str(&name.to_snake_case()),
|
IdlType::Enum(name) => dst.push_str(&snake_case_ident(name)),
|
||||||
|
|
||||||
IdlType::Nullable(idl_type) => {
|
IdlType::Nullable(idl_type) => {
|
||||||
dst.push_str("opt_");
|
dst.push_str("opt_");
|
||||||
idl_type.push_type_name(dst);
|
idl_type.push_snake_case_name(dst);
|
||||||
},
|
},
|
||||||
IdlType::FrozenArray(idl_type) => {
|
IdlType::FrozenArray(idl_type) => {
|
||||||
idl_type.push_type_name(dst);
|
idl_type.push_snake_case_name(dst);
|
||||||
dst.push_str("_frozen_array");
|
dst.push_str("_frozen_array");
|
||||||
},
|
},
|
||||||
IdlType::Sequence(idl_type) => {
|
IdlType::Sequence(idl_type) => {
|
||||||
idl_type.push_type_name(dst);
|
idl_type.push_snake_case_name(dst);
|
||||||
dst.push_str("_sequence");
|
dst.push_str("_sequence");
|
||||||
},
|
},
|
||||||
IdlType::Promise(idl_type) => {
|
IdlType::Promise(idl_type) => {
|
||||||
idl_type.push_type_name(dst);
|
idl_type.push_snake_case_name(dst);
|
||||||
dst.push_str("_promise");
|
dst.push_str("_promise");
|
||||||
},
|
},
|
||||||
IdlType::Record(idl_type_from, idl_type_to) => {
|
IdlType::Record(idl_type_from, idl_type_to) => {
|
||||||
dst.push_str("record_from_");
|
dst.push_str("record_from_");
|
||||||
idl_type_from.push_type_name(dst);
|
idl_type_from.push_snake_case_name(dst);
|
||||||
dst.push_str("_to_");
|
dst.push_str("_to_");
|
||||||
idl_type_to.push_type_name(dst);
|
idl_type_to.push_snake_case_name(dst);
|
||||||
},
|
},
|
||||||
IdlType::Union(idl_types) => {
|
IdlType::Union(idl_types) => {
|
||||||
dst.push_str("union_of_");
|
dst.push_str("union_of_");
|
||||||
@ -406,7 +485,7 @@ impl<'a> IdlType<'a> {
|
|||||||
} else {
|
} else {
|
||||||
dst.push_str("_and_");
|
dst.push_str("_and_");
|
||||||
}
|
}
|
||||||
idl_type.push_type_name(dst);
|
idl_type.push_snake_case_name(dst);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -415,14 +494,6 @@ impl<'a> IdlType<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a snake case type name.
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub(crate) fn get_type_name(&self) -> String {
|
|
||||||
let mut string = String::new();
|
|
||||||
self.push_type_name(&mut string);
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts to syn type if possible.
|
/// Converts to syn type if possible.
|
||||||
pub(crate) fn to_syn_type(&self, pos: TypePosition) -> Option<syn::Type> {
|
pub(crate) fn to_syn_type(&self, pos: TypePosition) -> Option<syn::Type> {
|
||||||
match self {
|
match self {
|
||||||
@ -467,8 +538,8 @@ impl<'a> IdlType<'a> {
|
|||||||
IdlType::Float32Array => Some(array("f32", pos)),
|
IdlType::Float32Array => Some(array("f32", pos)),
|
||||||
IdlType::Float64Array => Some(array("f64", pos)),
|
IdlType::Float64Array => Some(array("f64", pos)),
|
||||||
|
|
||||||
IdlType::Interface(name) |
|
| IdlType::Interface(name)
|
||||||
IdlType::Dictionary(name) => {
|
| IdlType::Dictionary(name) => {
|
||||||
let ty = ident_ty(rust_ident(camel_case_ident(name).as_str()));
|
let ty = ident_ty(rust_ident(camel_case_ident(name).as_str()));
|
||||||
if pos == TypePosition::Argument {
|
if pos == TypePosition::Argument {
|
||||||
Some(shared_ref(ty))
|
Some(shared_ref(ty))
|
||||||
@ -491,7 +562,12 @@ impl<'a> IdlType<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
IdlType::Record(_idl_type_from, _idl_type_to) => None,
|
IdlType::Record(_idl_type_from, _idl_type_to) => None,
|
||||||
IdlType::Union(_idl_types) => None,
|
IdlType::Union(_idl_types) => {
|
||||||
|
// Handles union types in all places except operation argument types
|
||||||
|
// TODO: add better support for union types here?
|
||||||
|
let path = vec![rust_ident("wasm_bindgen"), rust_ident("JsValue")];
|
||||||
|
Some(leading_colon_path_ty(path))
|
||||||
|
},
|
||||||
|
|
||||||
IdlType::Any => {
|
IdlType::Any => {
|
||||||
let path = vec![rust_ident("wasm_bindgen"), rust_ident("JsValue")];
|
let path = vec![rust_ident("wasm_bindgen"), rust_ident("JsValue")];
|
||||||
@ -552,7 +628,7 @@ impl<'a> IdlType<'a> {
|
|||||||
.flat_map(|idl_type| idl_type.flatten())
|
.flat_map(|idl_type| idl_type.flatten())
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|
||||||
idl_type @ _ => vec![idl_type.clone()]
|
idl_type @ _ => vec![idl_type.clone()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,14 +41,13 @@ use backend::defined::{ImportedTypeDefinitions, RemoveUndefinedImports};
|
|||||||
use backend::defined::ImportedTypeReferences;
|
use backend::defined::ImportedTypeReferences;
|
||||||
use backend::util::{ident_ty, rust_ident, raw_ident, wrap_import_function};
|
use backend::util::{ident_ty, rust_ident, raw_ident, wrap_import_function};
|
||||||
use failure::ResultExt;
|
use failure::ResultExt;
|
||||||
use heck::{ShoutySnakeCase, SnakeCase};
|
|
||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
use weedle::attribute::{ExtendedAttributeList};
|
use weedle::attribute::{ExtendedAttributeList};
|
||||||
use weedle::dictionary::DictionaryMember;
|
use weedle::dictionary::DictionaryMember;
|
||||||
|
|
||||||
use first_pass::{FirstPass, FirstPassRecord, OperationId, InterfaceData};
|
use first_pass::{FirstPass, FirstPassRecord, OperationId, InterfaceData};
|
||||||
use first_pass::OperationData;
|
use first_pass::OperationData;
|
||||||
use util::{public, webidl_const_v_to_backend_const_v, TypePosition, camel_case_ident, mdn_doc};
|
use util::{public, webidl_const_v_to_backend_const_v, TypePosition, camel_case_ident, shouty_snake_case_ident, snake_case_ident, mdn_doc};
|
||||||
use idl_type::ToIdlType;
|
use idl_type::ToIdlType;
|
||||||
|
|
||||||
pub use error::{Error, ErrorKind, Result};
|
pub use error::{Error, ErrorKind, Result};
|
||||||
@ -280,7 +279,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
|
|
||||||
Some(ast::DictionaryField {
|
Some(ast::DictionaryField {
|
||||||
required: field.required.is_some(),
|
required: field.required.is_some(),
|
||||||
name: rust_ident(&field.identifier.0.to_snake_case()),
|
name: rust_ident(&snake_case_ident(field.identifier.0)),
|
||||||
ty,
|
ty,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -293,7 +292,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
) {
|
) {
|
||||||
let mut module = backend::ast::Module {
|
let mut module = backend::ast::Module {
|
||||||
vis: public(),
|
vis: public(),
|
||||||
name: rust_ident(name.to_snake_case().as_str()),
|
name: rust_ident(snake_case_ident(name).as_str()),
|
||||||
imports: Default::default(),
|
imports: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -368,7 +367,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
|
|
||||||
program.consts.push(backend::ast::Const {
|
program.consts.push(backend::ast::Const {
|
||||||
vis: public(),
|
vis: public(),
|
||||||
name: rust_ident(member.identifier.0.to_shouty_snake_case().as_str()),
|
name: rust_ident(shouty_snake_case_ident(member.identifier.0).as_str()),
|
||||||
class: Some(rust_ident(camel_case_ident(&self_name).as_str())),
|
class: Some(rust_ident(camel_case_ident(&self_name).as_str())),
|
||||||
ty,
|
ty,
|
||||||
value: webidl_const_v_to_backend_const_v(&member.const_value),
|
value: webidl_const_v_to_backend_const_v(&member.const_value),
|
||||||
|
@ -3,7 +3,7 @@ use std::ptr;
|
|||||||
|
|
||||||
use backend;
|
use backend;
|
||||||
use backend::util::{ident_ty, leading_colon_path_ty, raw_ident, rust_ident};
|
use backend::util::{ident_ty, leading_colon_path_ty, raw_ident, rust_ident};
|
||||||
use heck::{CamelCase, SnakeCase};
|
use heck::{CamelCase, ShoutySnakeCase, SnakeCase};
|
||||||
use proc_macro2::Ident;
|
use proc_macro2::Ident;
|
||||||
use syn;
|
use syn;
|
||||||
use weedle;
|
use weedle;
|
||||||
@ -23,9 +23,28 @@ pub(crate) fn shared_ref(ty: syn::Type) -> syn::Type {
|
|||||||
}.into()
|
}.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fix camelcase of identifiers like HTMLBRElement
|
/// Fix case of identifiers like `HTMLBRElement` or `texImage2D`
|
||||||
|
fn fix_ident(identifier: &str) -> String {
|
||||||
|
identifier
|
||||||
|
.replace("HTML", "HTML_")
|
||||||
|
.replace("1D", "_1d")
|
||||||
|
.replace("2D", "_2d")
|
||||||
|
.replace("3D", "_3d")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert an identifier to camel case
|
||||||
pub fn camel_case_ident(identifier: &str) -> String {
|
pub fn camel_case_ident(identifier: &str) -> String {
|
||||||
identifier.replace("HTML", "HTML_").to_camel_case()
|
fix_ident(identifier).to_camel_case()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert an identifier to shouty snake case
|
||||||
|
pub fn shouty_snake_case_ident(identifier: &str) -> String {
|
||||||
|
fix_ident(identifier).to_shouty_snake_case()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert an identifier to snake case
|
||||||
|
pub fn snake_case_ident(identifier: &str) -> String {
|
||||||
|
fix_ident(identifier).to_snake_case()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a link to MDN
|
// Returns a link to MDN
|
||||||
@ -308,7 +327,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
let ret = ty.to_idl_type(self)?;
|
let ret = ty.to_idl_type(self)?;
|
||||||
self.create_one_function(
|
self.create_one_function(
|
||||||
&name,
|
&name,
|
||||||
&name.to_snake_case(),
|
&snake_case_ident(name),
|
||||||
None.into_iter(),
|
None.into_iter(),
|
||||||
&ret,
|
&ret,
|
||||||
kind,
|
kind,
|
||||||
@ -492,7 +511,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rust_name = name.to_snake_case();
|
let mut rust_name = snake_case_ident(name);
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for (i, arg) in signature.args.iter().enumerate() {
|
for (i, arg) in signature.args.iter().enumerate() {
|
||||||
// Find out if any other known signature either has the same
|
// Find out if any other known signature either has the same
|
||||||
@ -539,9 +558,9 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
// then we can't use that if the types are also the same because
|
// then we can't use that if the types are also the same because
|
||||||
// otherwise it could be ambiguous.
|
// otherwise it could be ambiguous.
|
||||||
if any_same_name && any_different_type {
|
if any_same_name && any_different_type {
|
||||||
arg.push_type_name(&mut rust_name);
|
arg.push_snake_case_name(&mut rust_name);
|
||||||
} else {
|
} else {
|
||||||
rust_name.push_str(&arg_name.to_snake_case());
|
rust_name.push_str(&snake_case_ident(arg_name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret.extend(self.create_one_function(
|
ret.extend(self.create_one_function(
|
||||||
|
Reference in New Issue
Block a user