Migrate constructors to new naming scheme

This commit is contained in:
Alex Crichton
2018-08-29 18:27:49 -07:00
parent 5a4a34d4a1
commit 923abc7d85
3 changed files with 129 additions and 94 deletions

View File

@ -7,6 +7,7 @@
//! Only `interface`s, `dictionary`s, `enum`s and `mixin`s can //! Only `interface`s, `dictionary`s, `enum`s and `mixin`s can
//! be partial. //! be partial.
use std::cmp::Ordering;
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use weedle::{DictionaryDefinition, PartialDictionaryDefinition}; use weedle::{DictionaryDefinition, PartialDictionaryDefinition};
@ -80,7 +81,7 @@ pub(crate) struct DictionaryData<'src> {
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub(crate) enum OperationId<'src> { pub(crate) enum OperationId<'src> {
Constructor, Constructor(IgnoreTraits<&'src str>),
Operation(Option<&'src str>), Operation(Option<&'src str>),
IndexingGetter, IndexingGetter,
IndexingSetter, IndexingSetter,
@ -363,7 +364,7 @@ fn process_interface_attribute<'src>(
record, record,
FirstPassOperationType::Interface, FirstPassOperationType::Interface,
self_name, self_name,
&[OperationId::Constructor], &[OperationId::Constructor(IgnoreTraits(self_name))],
&list.args.body.list, &list.args.body.list,
&return_ty, &return_ty,
&None, &None,
@ -381,7 +382,7 @@ fn process_interface_attribute<'src>(
record, record,
FirstPassOperationType::Interface, FirstPassOperationType::Interface,
self_name, self_name,
&[OperationId::Constructor], &[OperationId::Constructor(IgnoreTraits(self_name))],
&[], &[],
&return_ty, &return_ty,
&None, &None,
@ -401,7 +402,7 @@ fn process_interface_attribute<'src>(
record, record,
FirstPassOperationType::Interface, FirstPassOperationType::Interface,
self_name, self_name,
&[OperationId::Constructor], &[OperationId::Constructor(IgnoreTraits(list.rhs_identifier.0))],
&list.args.body.list, &list.args.body.list,
&return_ty, &return_ty,
&None, &None,
@ -784,3 +785,24 @@ impl<'a> FirstPassRecord<'a> {
} }
} }
} }
#[derive(Copy, Clone, Debug)]
pub struct IgnoreTraits<T>(pub T);
impl<T> PartialEq for IgnoreTraits<T> {
fn eq(&self, _other: &IgnoreTraits<T>) -> bool { true }
}
impl<T> Eq for IgnoreTraits<T> {}
impl<T> PartialOrd for IgnoreTraits<T> {
fn partial_cmp(&self, _other: &IgnoreTraits<T>) -> Option<Ordering> {
Some(Ordering::Equal)
}
}
impl<T> Ord for IgnoreTraits<T> {
fn cmp(&self, _other: &IgnoreTraits<T>) -> Ordering {
Ordering::Equal
}
}

View File

@ -314,7 +314,7 @@ impl<'src> FirstPassRecord<'src> {
) { ) {
let name = match id { let name = match id {
OperationId::Operation(Some(name)) => name, OperationId::Operation(Some(name)) => name,
OperationId::Constructor | OperationId::Constructor(_) |
OperationId::Operation(None) | OperationId::Operation(None) |
OperationId::IndexingGetter | OperationId::IndexingGetter |
OperationId::IndexingSetter | OperationId::IndexingSetter |
@ -404,13 +404,13 @@ impl<'src> FirstPassRecord<'src> {
}), }),
}); });
for (ctor_name, args) in data.constructors.iter() { // for (ctor_name, args) in data.constructors.iter() {
self.append_constructor(program, name, ctor_name, args); // self.append_constructor(program, name, ctor_name, args);
} // }
for (id, op_data) in data.operations2.iter() { for (id, op_data) in data.operations2.iter() {
if let OperationId::Constructor = id { // if let OperationId::Constructor = id {
continue // TODO // continue // TODO
} // }
self.member_operation2(program, name, data, id, op_data); self.member_operation2(program, name, data, id, op_data);
} }
for member in data.consts.iter() { for member in data.consts.iter() {
@ -453,61 +453,61 @@ impl<'src> FirstPassRecord<'src> {
} }
} }
fn append_constructor( // fn append_constructor(
&self, // &self,
program: &mut backend::ast::Program, // program: &mut backend::ast::Program,
iface_name: &'src str, // iface_name: &'src str,
ctor_name: &'src str, // ctor_name: &'src str,
args: &[Argument<'src>], // args: &[Argument<'src>],
) { // ) {
let (overloaded, same_argument_names) = self.get_operation_overloading( // let (overloaded, same_argument_names) = self.get_operation_overloading(
args, // args,
&::first_pass::OperationId::Constructor, // &::first_pass::OperationId::Constructor,
iface_name, // iface_name,
false, // false,
); // );
let self_ty = ident_ty(rust_ident(camel_case_ident(iface_name).as_str()));
let kind = backend::ast::ImportFunctionKind::Method {
class: ctor_name.to_string(),
ty: self_ty.clone(),
kind: backend::ast::MethodKind::Constructor,
};
let structural = false;
// Constructors aren't annotated with `[Throws]` extended attributes
// (how could they be, since they themselves are extended
// attributes?) so we must conservatively assume that they can
// always throw.
// //
// From https://heycam.github.io/webidl/#Constructor (emphasis // let self_ty = ident_ty(rust_ident(camel_case_ident(iface_name).as_str()));
// mine):
// //
// > The prose definition of a constructor must either return an IDL // let kind = backend::ast::ImportFunctionKind::Method {
// > value of a type corresponding to the interface the // class: ctor_name.to_string(),
// > `[Constructor]` extended attribute appears on, **or throw an // ty: self_ty.clone(),
// > exception**. // kind: backend::ast::MethodKind::Constructor,
let throws = true; // };
//
for import_function in self.create_function( // let structural = false;
"new", //
overloaded, // // Constructors aren't annotated with `[Throws]` extended attributes
same_argument_names, // // (how could they be, since they themselves are extended
&match self.convert_arguments(args) { // // attributes?) so we must conservatively assume that they can
Some(arguments) => arguments, // // always throw.
None => return, // //
}, // // From https://heycam.github.io/webidl/#Constructor (emphasis
IdlType::Interface(iface_name), // // mine):
kind, // //
structural, // // > The prose definition of a constructor must either return an IDL
throws, // // > value of a type corresponding to the interface the
None, // // > `[Constructor]` extended attribute appears on, **or throw an
) { // // > exception**.
program.imports.push(wrap_import_function(import_function)); // let throws = true;
} //
} // for import_function in self.create_function(
// "new",
// overloaded,
// same_argument_names,
// &match self.convert_arguments(args) {
// Some(arguments) => arguments,
// None => return,
// },
// IdlType::Interface(iface_name),
// kind,
// structural,
// throws,
// None,
// ) {
// program.imports.push(wrap_import_function(import_function));
// }
// }
fn member_attribute( fn member_attribute(
&self, &self,
@ -571,28 +571,29 @@ impl<'src> FirstPassRecord<'src> {
id: &OperationId<'src>, id: &OperationId<'src>,
op_data: &OperationData2<'src>, op_data: &OperationData2<'src>,
) { ) {
let operation_kind = match id { let import_function_kind = |opkind| {
OperationId::Constructor => panic!("constructors are unsupported"), self.import_function_kind(self_name, data.global, op_data.is_static, opkind)
OperationId::Operation(_) => backend::ast::OperationKind::Regular,
OperationId::IndexingGetter => backend::ast::OperationKind::IndexingGetter,
OperationId::IndexingSetter => backend::ast::OperationKind::IndexingSetter,
OperationId::IndexingDeleter => backend::ast::OperationKind::IndexingDeleter,
}; };
let operation = backend::ast::Operation { let kind = match id {
is_static: op_data.is_static, OperationId::Constructor(ctor_name) => {
kind: operation_kind, let self_ty = ident_ty(rust_ident(&camel_case_ident(self_name)));
};
let ty = ident_ty(rust_ident(camel_case_ident(&self_name).as_str()));
let kind = if data.global {
backend::ast::ImportFunctionKind::ScopedMethod {
ty,
operation,
}
} else {
backend::ast::ImportFunctionKind::Method { backend::ast::ImportFunctionKind::Method {
class: self_name.to_string(), class: ctor_name.0.to_string(),
ty, ty: self_ty.clone(),
kind: backend::ast::MethodKind::Operation(operation), kind: backend::ast::MethodKind::Constructor,
}
}
OperationId::Operation(_) => {
import_function_kind(backend::ast::OperationKind::Regular)
}
OperationId::IndexingGetter => {
import_function_kind(backend::ast::OperationKind::IndexingGetter)
}
OperationId::IndexingSetter => {
import_function_kind(backend::ast::OperationKind::IndexingSetter)
}
OperationId::IndexingDeleter => {
import_function_kind(backend::ast::OperationKind::IndexingDeleter)
} }
}; };
for method in self.create_imports(kind, id, op_data) { for method in self.create_imports(kind, id, op_data) {

View File

@ -522,7 +522,7 @@ impl<'src> FirstPassRecord<'src> {
) )
} }
fn import_function_kind( pub fn import_function_kind(
&self, &self,
self_name: &str, self_name: &str,
global: bool, global: bool,
@ -630,16 +630,28 @@ impl<'src> FirstPassRecord<'src> {
} }
} }
let (name, force_structural) = match id { let (name, force_structural, force_throws) = match id {
OperationId::Constructor => ("new", false), // Constructors aren't annotated with `[Throws]` extended attributes
OperationId::Operation(Some(s)) => (*s, false), // (how could they be, since they themselves are extended
// attributes?) so we must conservatively assume that they can
// always throw.
//
// From https://heycam.github.io/webidl/#Constructor (emphasis
// mine):
//
// > The prose definition of a constructor must either return an IDL
// > value of a type corresponding to the interface the
// > `[Constructor]` extended attribute appears on, **or throw an
// > exception**.
OperationId::Constructor(_) => ("new", false, true),
OperationId::Operation(Some(s)) => (*s, false, false),
OperationId::Operation(None) => { OperationId::Operation(None) => {
warn!("unsupported unnamed operation"); warn!("unsupported unnamed operation");
return Vec::new() return Vec::new()
} }
OperationId::IndexingGetter => ("get", true), OperationId::IndexingGetter => ("get", true, false),
OperationId::IndexingSetter => ("set", true), OperationId::IndexingSetter => ("set", true, false),
OperationId::IndexingDeleter => ("delete", true), OperationId::IndexingDeleter => ("delete", true, false),
}; };
let mut ret = Vec::new(); let mut ret = Vec::new();
@ -707,7 +719,7 @@ impl<'src> FirstPassRecord<'src> {
&ret_ty, &ret_ty,
kind.clone(), kind.clone(),
force_structural || is_structural(&signature.orig.attrs), force_structural || is_structural(&signature.orig.attrs),
throws(&signature.orig.attrs), force_throws || throws(&signature.orig.attrs),
None, None,
)); ));
} }