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
//! be partial.
use std::cmp::Ordering;
use std::collections::{BTreeMap, BTreeSet};
use weedle::{DictionaryDefinition, PartialDictionaryDefinition};
@ -80,7 +81,7 @@ pub(crate) struct DictionaryData<'src> {
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub(crate) enum OperationId<'src> {
Constructor,
Constructor(IgnoreTraits<&'src str>),
Operation(Option<&'src str>),
IndexingGetter,
IndexingSetter,
@ -363,7 +364,7 @@ fn process_interface_attribute<'src>(
record,
FirstPassOperationType::Interface,
self_name,
&[OperationId::Constructor],
&[OperationId::Constructor(IgnoreTraits(self_name))],
&list.args.body.list,
&return_ty,
&None,
@ -381,7 +382,7 @@ fn process_interface_attribute<'src>(
record,
FirstPassOperationType::Interface,
self_name,
&[OperationId::Constructor],
&[OperationId::Constructor(IgnoreTraits(self_name))],
&[],
&return_ty,
&None,
@ -401,7 +402,7 @@ fn process_interface_attribute<'src>(
record,
FirstPassOperationType::Interface,
self_name,
&[OperationId::Constructor],
&[OperationId::Constructor(IgnoreTraits(list.rhs_identifier.0))],
&list.args.body.list,
&return_ty,
&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 {
OperationId::Operation(Some(name)) => name,
OperationId::Constructor |
OperationId::Constructor(_) |
OperationId::Operation(None) |
OperationId::IndexingGetter |
OperationId::IndexingSetter |
@ -404,13 +404,13 @@ impl<'src> FirstPassRecord<'src> {
}),
});
for (ctor_name, args) in data.constructors.iter() {
self.append_constructor(program, name, ctor_name, args);
}
// for (ctor_name, args) in data.constructors.iter() {
// self.append_constructor(program, name, ctor_name, args);
// }
for (id, op_data) in data.operations2.iter() {
if let OperationId::Constructor = id {
continue // TODO
}
// if let OperationId::Constructor = id {
// continue // TODO
// }
self.member_operation2(program, name, data, id, op_data);
}
for member in data.consts.iter() {
@ -453,61 +453,61 @@ impl<'src> FirstPassRecord<'src> {
}
}
fn append_constructor(
&self,
program: &mut backend::ast::Program,
iface_name: &'src str,
ctor_name: &'src str,
args: &[Argument<'src>],
) {
let (overloaded, same_argument_names) = self.get_operation_overloading(
args,
&::first_pass::OperationId::Constructor,
iface_name,
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
// 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**.
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 append_constructor(
// &self,
// program: &mut backend::ast::Program,
// iface_name: &'src str,
// ctor_name: &'src str,
// args: &[Argument<'src>],
// ) {
// let (overloaded, same_argument_names) = self.get_operation_overloading(
// args,
// &::first_pass::OperationId::Constructor,
// iface_name,
// 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
// // 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**.
// 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(
&self,
@ -571,28 +571,29 @@ impl<'src> FirstPassRecord<'src> {
id: &OperationId<'src>,
op_data: &OperationData2<'src>,
) {
let operation_kind = match id {
OperationId::Constructor => panic!("constructors are unsupported"),
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 import_function_kind = |opkind| {
self.import_function_kind(self_name, data.global, op_data.is_static, opkind)
};
let operation = backend::ast::Operation {
is_static: op_data.is_static,
kind: operation_kind,
};
let ty = ident_ty(rust_ident(camel_case_ident(&self_name).as_str()));
let kind = if data.global {
backend::ast::ImportFunctionKind::ScopedMethod {
ty,
operation,
let kind = match id {
OperationId::Constructor(ctor_name) => {
let self_ty = ident_ty(rust_ident(&camel_case_ident(self_name)));
backend::ast::ImportFunctionKind::Method {
class: ctor_name.0.to_string(),
ty: self_ty.clone(),
kind: backend::ast::MethodKind::Constructor,
}
}
} else {
backend::ast::ImportFunctionKind::Method {
class: self_name.to_string(),
ty,
kind: backend::ast::MethodKind::Operation(operation),
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) {

View File

@ -522,7 +522,7 @@ impl<'src> FirstPassRecord<'src> {
)
}
fn import_function_kind(
pub fn import_function_kind(
&self,
self_name: &str,
global: bool,
@ -630,16 +630,28 @@ impl<'src> FirstPassRecord<'src> {
}
}
let (name, force_structural) = match id {
OperationId::Constructor => ("new", false),
OperationId::Operation(Some(s)) => (*s, false),
let (name, force_structural, force_throws) = match id {
// 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
// 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) => {
warn!("unsupported unnamed operation");
return Vec::new()
}
OperationId::IndexingGetter => ("get", true),
OperationId::IndexingSetter => ("set", true),
OperationId::IndexingDeleter => ("delete", true),
OperationId::IndexingGetter => ("get", true, false),
OperationId::IndexingSetter => ("set", true, false),
OperationId::IndexingDeleter => ("delete", true, false),
};
let mut ret = Vec::new();
@ -707,7 +719,7 @@ impl<'src> FirstPassRecord<'src> {
&ret_ty,
kind.clone(),
force_structural || is_structural(&signature.orig.attrs),
throws(&signature.orig.attrs),
force_throws || throws(&signature.orig.attrs),
None,
));
}