use std::f64;
use super::ImmutableVisitor;
use parser::ast::*;
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
pub struct PrettyPrintVisitor {
output: String,
}
impl PrettyPrintVisitor {
pub fn new() -> Self {
PrettyPrintVisitor {
output: String::new(),
}
}
pub fn get_output(&self) -> &String {
&self.output
}
fn stringify_arguments(&mut self, arguments: &[Argument]) {
self.output.push('(');
for (index, argument) in arguments.iter().enumerate() {
if index != 0 {
self.output.push_str(", ");
}
self.visit_argument(argument);
}
self.output.push(')');
}
fn stringify_extended_attributes(&mut self, extended_attributes: &[ExtendedAttribute]) {
if extended_attributes.is_empty() {
return;
}
self.output.push('[');
for (index, extended_attribute) in extended_attributes.iter().enumerate() {
if index != 0 {
self.output.push_str(", ");
}
self.visit_extended_attribute(extended_attribute);
}
self.output.push(']');
}
fn stringify_namespace_members(&mut self, namespace_members: &[NamespaceMember]) {
let mut iterator = namespace_members.iter().peekable();
while let Some(member) = iterator.next() {
self.visit_namespace_member(member);
if let Some(next_member) = iterator.peek() {
match *member {
NamespaceMember::Attribute(_) => match **next_member {
NamespaceMember::Attribute(_) => (),
_ => self.output.push('\n'),
},
NamespaceMember::Operation(_) => match **next_member {
NamespaceMember::Operation(_) => (),
_ => self.output.push('\n'),
},
}
}
}
}
#[allow(unknown_lints)]
#[allow(clippy::float_cmp)]
fn stringify_float_literal(&mut self, float_literal: f64) {
if float_literal.is_nan() {
self.output.push_str("NaN");
} else if float_literal == f64::INFINITY {
self.output.push_str("Infinity");
} else if float_literal == f64::NEG_INFINITY {
self.output.push_str("-Infinity");
} else {
self.output.push_str(&*float_literal.to_string());
if float_literal.floor() == float_literal {
self.output.push_str(".0");
}
}
}
fn stringify_interface_members(&mut self, interface_members: &[InterfaceMember]) {
let mut iterator = interface_members.iter().peekable();
while let Some(member) = iterator.next() {
self.visit_interface_member(member);
if let Some(next_member) = iterator.peek() {
match *member {
InterfaceMember::Attribute(_) => match **next_member {
InterfaceMember::Attribute(_) => (),
_ => self.output.push('\n'),
},
InterfaceMember::Const(_) => match **next_member {
InterfaceMember::Const(_) => (),
_ => self.output.push('\n'),
},
InterfaceMember::Iterable(_) => match **next_member {
InterfaceMember::Iterable(_) => (),
_ => self.output.push('\n'),
},
InterfaceMember::Maplike(_) => match **next_member {
InterfaceMember::Maplike(_) => (),
_ => self.output.push('\n'),
},
InterfaceMember::Operation(_) => match **next_member {
InterfaceMember::Operation(_) => (),
_ => self.output.push('\n'),
},
InterfaceMember::Setlike(_) => match **next_member {
InterfaceMember::Setlike(_) => (),
_ => self.output.push('\n'),
},
}
}
}
}
fn stringify_mixin_members(&mut self, mixin_members: &[MixinMember]) {
let mut iterator = mixin_members.iter().peekable();
while let Some(member) = iterator.next() {
self.visit_mixin_member(member);
if let Some(next_member) = iterator.peek() {
match *member {
MixinMember::Attribute(_) => match **next_member {
MixinMember::Attribute(_) => (),
_ => self.output.push('\n'),
},
MixinMember::Const(_) => match **next_member {
MixinMember::Const(_) => (),
_ => self.output.push('\n'),
},
MixinMember::Operation(_) => match **next_member {
MixinMember::Operation(_) => (),
_ => self.output.push('\n'),
},
}
}
}
}
}
impl<'ast> ImmutableVisitor<'ast> for PrettyPrintVisitor {
fn visit(&mut self, definitions: &'ast [Definition]) {
let mut iterator = definitions.iter().peekable();
while let Some(definition) = iterator.next() {
self.visit_definition(definition);
if let Some(next_definition) = iterator.peek() {
match *definition {
Definition::Callback(_) => match **next_definition {
Definition::Callback(_) => (),
_ => self.output.push('\n'),
},
Definition::Implements(_) => match **next_definition {
Definition::Implements(_) => (),
_ => self.output.push('\n'),
},
Definition::Includes(_) => match **next_definition {
Definition::Includes(_) => (),
_ => self.output.push('\n'),
},
Definition::Typedef(_) => match **next_definition {
Definition::Typedef(_) => (),
_ => self.output.push('\n'),
},
_ => (),
}
}
}
}
fn visit_argument(&mut self, argument: &'ast Argument) {
self.stringify_extended_attributes(&argument.extended_attributes);
if !argument.extended_attributes.is_empty() {
self.output.push(' ');
}
if argument.optional && !argument.variadic {
self.output.push_str("optional ");
}
self.visit_type(&argument.type_);
if argument.variadic {
self.output.push_str("...");
}
self.output.push(' ');
self.visit_identifier(&argument.name);
if let Some(ref default_value) = argument.default {
self.output.push_str(" = ");
self.visit_default_value(default_value);
}
}
fn visit_argument_list_extended_attribute(&mut self, ex: &'ast ArgumentListExtendedAttribute) {
self.visit_identifier(&ex.name);
self.stringify_arguments(&ex.arguments);
}
fn visit_callback(&mut self, callback: &'ast Callback) {
if !callback.extended_attributes.is_empty() {
self.stringify_extended_attributes(&callback.extended_attributes);
self.output.push('\n');
}
self.output.push_str("callback ");
self.visit_identifier(&callback.name);
self.output.push_str(" = ");
self.visit_return_type(&callback.return_type);
self.output.push(' ');
self.stringify_arguments(&callback.arguments);
self.output.push_str(";\n");
}
fn visit_callback_interface(&mut self, callback_interface: &'ast CallbackInterface) {
if !callback_interface.extended_attributes.is_empty() {
self.stringify_extended_attributes(&callback_interface.extended_attributes);
self.output.push_str("\n");
}
self.output.push_str("callback interface ");
self.visit_identifier(&callback_interface.name);
if let Some(ref inherit) = callback_interface.inherits {
self.output.push_str(" : ");
self.output.push_str(inherit);
}
self.output.push_str(" {\n");
self.stringify_interface_members(&callback_interface.members);
self.output.push_str("};\n\n");
}
fn visit_const(&mut self, const_: &'ast Const) {
if !const_.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&const_.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" const ");
self.visit_const_type(&const_.type_);
if const_.nullable {
self.output.push('?');
}
self.output.push(' ');
self.visit_identifier(&const_.name);
self.output.push_str(" = ");
self.visit_const_value(&const_.value);
self.output.push_str(";\n");
}
fn visit_const_type(&mut self, const_type: &'ast ConstType) {
match *const_type {
ConstType::Boolean => self.output.push_str("boolean"),
ConstType::Byte => self.output.push_str("byte"),
ConstType::Identifier(ref identifier) => self.visit_identifier(identifier),
ConstType::Octet => self.output.push_str("octet"),
ConstType::RestrictedDouble => self.output.push_str("double"),
ConstType::RestrictedFloat => self.output.push_str("float"),
ConstType::SignedLong => self.output.push_str("long"),
ConstType::SignedLongLong => self.output.push_str("long long"),
ConstType::SignedShort => self.output.push_str("short"),
ConstType::UnrestrictedDouble => self.output.push_str("unrestricted double"),
ConstType::UnrestrictedFloat => self.output.push_str("unrestricted float"),
ConstType::UnsignedLong => self.output.push_str("unsigned long"),
ConstType::UnsignedLongLong => self.output.push_str("unsigned long long"),
ConstType::UnsignedShort => self.output.push_str("unsigned short"),
}
}
fn visit_const_value(&mut self, const_value: &'ast ConstValue) {
match *const_value {
ConstValue::BooleanLiteral(boolean_literal) => {
self.output.push_str(&*boolean_literal.to_string());
}
ConstValue::FloatLiteral(float_literal) => {
self.stringify_float_literal(float_literal);
}
ConstValue::Null => self.output.push_str("null"),
ConstValue::SignedIntegerLiteral(integer_literal) => {
self.output.push_str(&*integer_literal.to_string());
}
ConstValue::UnsignedIntegerLiteral(integer_literal) => {
self.output.push_str(&*integer_literal.to_string());
}
}
}
fn visit_default_value(&mut self, default_value: &'ast DefaultValue) {
match *default_value {
DefaultValue::ConstValue(ref const_value) => self.visit_const_value(const_value),
DefaultValue::EmptySequence => self.output.push_str("[]"),
DefaultValue::StringLiteral(ref string_literal) => {
self.output.push('"');
self.output.push_str(&*string_literal);
self.output.push('"');
}
}
}
fn visit_dictionary_member(&mut self, dictionary_member: &'ast DictionaryMember) {
if !dictionary_member.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&dictionary_member.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" ");
if dictionary_member.required {
self.output.push_str("required ");
}
self.visit_type(&dictionary_member.type_);
self.output.push(' ');
self.visit_identifier(&dictionary_member.name);
if let Some(ref default_value) = dictionary_member.default {
self.output.push_str(" = ");
self.visit_default_value(default_value);
}
self.output.push_str(";\n");
}
fn visit_enum(&mut self, enum_: &'ast Enum) {
if !enum_.extended_attributes.is_empty() {
self.stringify_extended_attributes(&enum_.extended_attributes);
self.output.push('\n');
}
self.output.push_str("enum ");
self.visit_identifier(&enum_.name);
self.output.push_str(" {\n");
for (index, variant) in enum_.variants.iter().enumerate() {
if index != 0 {
self.output.push_str(",\n");
}
self.output.push_str(" \"");
self.output.push_str(&*variant);
self.output.push('"');
}
self.output.push_str("\n};\n\n");
}
fn visit_explicit_stringifier_operation(
&mut self,
operation: &'ast ExplicitStringifierOperation,
) {
if !operation.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&operation.extended_attributes);
self.output.push('\n');
}
self.stringify_extended_attributes(&operation.extended_attributes);
self.output.push_str(" stringifier ");
self.visit_return_type(&operation.return_type);
self.output.push(' ');
if let Some(ref name) = operation.name {
self.visit_identifier(name);
self.output.push(' ');
}
self.stringify_arguments(&operation.arguments);
self.output.push_str(";\n");
}
fn visit_identifier(&mut self, identifier: &'ast str) {
let identifier = match identifier {
"any" => "_any",
"ArrayBuffer" => "_ArrayBuffer",
"attribute" => "_attribute",
"boolean" => "_boolean",
"byte" => "_byte",
"ByteString" => "_ByteString",
"callback" => "_callback",
"const" => "_const",
"DataView" => "_DataView",
"deleter" => "_deleter",
"dictionary" => "_dictionary",
"DOMString" => "_DOMString",
"double" => "_double",
"enum" => "_enum",
"Error" => "_Error",
"false" => "_false",
"float" => "_float",
"Float32Array" => "_Float32Array",
"Float64Array" => "_Float64Array",
"FrozenArray" => "_FrozenArray",
"getter" => "_getter",
"implements" => "_implements",
"includes" => "_includes",
"inherit" => "_inherit",
"Int16Array" => "_Int16Array",
"Int32Array" => "_Int32Array",
"Int8Array" => "_Int8Array",
"interface" => "_interface",
"iterable" => "_iterable",
"legacycaller" => "_legacycaller",
"long" => "_long",
"maplike" => "_maplike",
"namespace" => "_namespace",
"NaN" => "_NaN",
"null" => "_null",
"object" => "_object",
"octet" => "_octet",
"optional" => "_optional",
"or" => "_or",
"partial" => "_partial",
"Infinity" => "_Infinity",
"Promise" => "_Promise",
"readonly" => "_readonly",
"record" => "_record",
"required" => "_required",
"sequence" => "_sequence",
"setlike" => "_setlike",
"setter" => "_setter",
"short" => "_short",
"static" => "_static",
"stringifier" => "_stringifier",
"symbol" => "_symbol",
"true" => "_true",
"typedef" => "_typedef",
"USVString" => "_USVString",
"Uint16Array" => "_Uint16Array",
"Uint32Array" => "_Uint32Array",
"Uint8Array" => "_Uint8Array",
"Uint8ClampedArray" => "_Uint8ClampedArray",
"unrestricted" => "_unrestricted",
"unsigned" => "_unsigned",
"void" => "_void",
identifier => identifier,
};
self.output.push_str(identifier);
}
fn visit_identifier_extended_attribute(
&mut self,
extended_attribute: &'ast IdentifierExtendedAttribute,
) {
self.visit_identifier(&extended_attribute.lhs);
self.output.push('=');
self.visit_other(&extended_attribute.rhs);
}
fn visit_identifier_list_extended_attribute(
&mut self,
ex: &'ast IdentifierListExtendedAttribute,
) {
self.visit_identifier(&ex.lhs);
self.output.push_str("=(");
for (index, identifier) in ex.rhs.iter().enumerate() {
if index != 0 {
self.output.push_str(", ");
}
self.visit_identifier(identifier);
}
self.output.push(')');
}
fn visit_implicit_stringifier_operation(
&mut self,
operation: &'ast ImplicitStringifierOperation,
) {
if !operation.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&operation.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" stringifier;\n");
}
fn visit_implements(&mut self, implements: &'ast Implements) {
if !implements.extended_attributes.is_empty() {
self.stringify_extended_attributes(&implements.extended_attributes);
self.output.push('\n');
}
self.visit_identifier(&implements.implementer);
self.output.push_str(" implements ");
self.visit_identifier(&implements.implementee);
self.output.push_str(";\n");
}
fn visit_includes(&mut self, includes: &'ast Includes) {
if !includes.extended_attributes.is_empty() {
self.stringify_extended_attributes(&includes.extended_attributes);
self.output.push('\n');
}
self.visit_identifier(&includes.includer);
self.output.push_str(" includes ");
self.visit_identifier(&includes.includee);
self.output.push_str(";\n");
}
fn visit_iterable(&mut self, iterable: &'ast Iterable) {
if !iterable.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&iterable.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" iterable<");
if let Some(ref key_type) = iterable.key_type {
self.visit_type(key_type);
self.output.push_str(", ");
}
self.visit_type(&iterable.value_type);
self.output.push_str(">;\n");
}
fn visit_maplike(&mut self, maplike: &'ast Maplike) {
if !maplike.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&maplike.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" ");
if maplike.read_only {
self.output.push_str("readonly ");
}
self.output.push_str("maplike<");
self.visit_type(&maplike.key_type);
self.output.push_str(", ");
self.visit_type(&maplike.value_type);
self.output.push_str(">;\n");
}
fn visit_named_argument_list_extended_attribute(
&mut self,
ex: &'ast NamedArgumentListExtendedAttribute,
) {
self.visit_identifier(&ex.lhs_name);
self.output.push('=');
self.visit_identifier(&ex.rhs_name);
self.stringify_arguments(&ex.rhs_arguments);
}
fn visit_non_partial_dictionary(&mut self, non_partial_dictionary: &'ast NonPartialDictionary) {
if !non_partial_dictionary.extended_attributes.is_empty() {
self.stringify_extended_attributes(&non_partial_dictionary.extended_attributes);
self.output.push('\n');
}
self.output.push_str("dictionary ");
self.visit_identifier(&non_partial_dictionary.name);
if let Some(ref inherit) = non_partial_dictionary.inherits {
self.output.push_str(" : ");
self.output.push_str(inherit);
}
self.output.push_str(" {\n");
for member in &non_partial_dictionary.members {
self.visit_dictionary_member(member);
}
self.output.push_str("};\n\n");
}
fn visit_non_partial_interface(&mut self, non_partial_interface: &'ast NonPartialInterface) {
if !non_partial_interface.extended_attributes.is_empty() {
self.stringify_extended_attributes(&non_partial_interface.extended_attributes);
self.output.push('\n');
}
self.output.push_str("interface ");
self.visit_identifier(&non_partial_interface.name);
if let Some(ref inherit) = non_partial_interface.inherits {
self.output.push_str(" : ");
self.output.push_str(inherit);
}
self.output.push_str(" {\n");
self.stringify_interface_members(&non_partial_interface.members);
self.output.push_str("};\n\n");
}
fn visit_non_partial_mixin(&mut self, non_partial_mixin: &'ast NonPartialMixin) {
if !non_partial_mixin.extended_attributes.is_empty() {
self.stringify_extended_attributes(&non_partial_mixin.extended_attributes);
self.output.push('\n');
}
self.output.push_str("interface mixin ");
self.visit_identifier(&non_partial_mixin.name);
self.output.push_str(" {\n");
self.stringify_mixin_members(&non_partial_mixin.members);
self.output.push_str("};\n\n");
}
fn visit_non_partial_namespace(&mut self, non_partial_namespace: &'ast NonPartialNamespace) {
if !non_partial_namespace.extended_attributes.is_empty() {
self.stringify_extended_attributes(&non_partial_namespace.extended_attributes);
self.output.push('\n');
}
self.output.push_str("namespace ");
self.visit_identifier(&non_partial_namespace.name);
self.output.push_str(" {\n");
self.stringify_namespace_members(&non_partial_namespace.members);
self.output.push_str("};\n\n");
}
fn visit_other(&mut self, other: &'ast Other) {
match *other {
Other::Any => self.output.push_str("any"),
Other::ArrayBuffer => self.output.push_str("ArrayBuffer"),
Other::Attribute => self.output.push_str("attribute"),
Other::Boolean => self.output.push_str("boolean"),
Other::Byte => self.output.push_str("byte"),
Other::ByteString => self.output.push_str("ByteString"),
Other::Callback => self.output.push_str("callback"),
Other::Const => self.output.push_str("const"),
Other::DOMString => self.output.push_str("DOMString"),
Other::DataView => self.output.push_str("DataView"),
Other::Deleter => self.output.push_str("deleter"),
Other::Dictionary => self.output.push_str("dictionary"),
Other::Double => self.output.push_str("double"),
Other::Enum => self.output.push_str("enum"),
Other::False => self.output.push_str("false"),
Other::Float => self.output.push_str("float"),
Other::Float32Array => self.output.push_str("Float32Array"),
Other::Float64Array => self.output.push_str("Float64Array"),
Other::FrozenArray => self.output.push_str("FrozenArray"),
Other::Getter => self.output.push_str("getter"),
Other::Implements => self.output.push_str("implements"),
Other::Includes => self.output.push_str("includes"),
Other::Inherit => self.output.push_str("inherit"),
Other::Int16Array => self.output.push_str("Int16Array"),
Other::Int32Array => self.output.push_str("Int32Array"),
Other::Int8Array => self.output.push_str("Int8Array"),
Other::Interface => self.output.push_str("interface"),
Other::Iterable => self.output.push_str("iterable"),
Other::LegacyCaller => self.output.push_str("legacycaller"),
Other::Long => self.output.push_str("long"),
Other::Maplike => self.output.push_str("maplike"),
Other::Namespace => self.output.push_str("namespace"),
Other::NegativeInfinity => self.output.push_str("-Infinity"),
Other::NaN => self.output.push_str("NaN"),
Other::Null => self.output.push_str("null"),
Other::Object => self.output.push_str("object"),
Other::Octet => self.output.push_str("octet"),
Other::Optional => self.output.push_str("optional"),
Other::Or => self.output.push_str("or"),
Other::Partial => self.output.push_str("partial"),
Other::PositiveInfinity => self.output.push_str("Infinity"),
Other::Required => self.output.push_str("required"),
Other::Sequence => self.output.push_str("sequence"),
Other::Setlike => self.output.push_str("setlike"),
Other::Setter => self.output.push_str("setter"),
Other::Short => self.output.push_str("short"),
Other::Static => self.output.push_str("static"),
Other::Stringifier => self.output.push_str("stringifier"),
Other::True => self.output.push_str("true"),
Other::Typedef => self.output.push_str("typedef"),
Other::USVString => self.output.push_str("USVString"),
Other::Uint16Array => self.output.push_str("Uint16Array"),
Other::Uint32Array => self.output.push_str("Uint32Array"),
Other::Uint8Array => self.output.push_str("Uint8Array"),
Other::Uint8ClampedArray => self.output.push_str("Uint8ClampedArray"),
Other::Unrestricted => self.output.push_str("unrestricted"),
Other::Unsigned => self.output.push_str("unsigned"),
Other::Void => self.output.push_str("void"),
Other::FloatLiteral(float_literal) => {
self.stringify_float_literal(float_literal);
}
Other::Identifier(ref identifier) => self.visit_identifier(identifier),
Other::OtherLiteral(other_literal) => self.output.push(other_literal),
Other::SignedIntegerLiteral(integer_literal) => {
self.output.push_str(&*integer_literal.to_string());
}
Other::StringLiteral(ref string_literal) => {
self.output.push('"');
self.output.push_str(&*string_literal);
self.output.push('"');
}
Other::UnsignedIntegerLiteral(integer_literal) => {
self.output.push_str(&*integer_literal.to_string());
}
Other::Colon => self.output.push(':'),
Other::Ellipsis => self.output.push_str("..."),
Other::Equals => self.output.push('='),
Other::GreaterThan => self.output.push('>'),
Other::Hyphen => self.output.push('-'),
Other::LessThan => self.output.push('<'),
Other::Period => self.output.push('.'),
Other::QuestionMark => self.output.push('?'),
Other::Semicolon => self.output.push(';'),
}
}
fn visit_other_extended_attribute(&mut self, extended_attribute: &'ast OtherExtendedAttribute) {
match *extended_attribute {
OtherExtendedAttribute::Nested {
ref group_type,
ref inner,
ref rest,
} => {
let end_group_char = match *group_type {
OtherExtendedAttributeGroupType::Brace => {
self.output.push('{');
'}'
}
OtherExtendedAttributeGroupType::Bracket => {
self.output.push('[');
']'
}
OtherExtendedAttributeGroupType::Parenthesis => {
self.output.push('(');
')'
}
};
if let Some(ref extended_attribute) = *inner {
self.visit_extended_attribute(extended_attribute);
}
self.output.push(end_group_char);
if let Some(ref extended_attribute) = *rest {
self.visit_extended_attribute(extended_attribute);
}
}
OtherExtendedAttribute::Other {
ref other,
ref rest,
} => {
if let Some(ref other) = *other {
self.visit_other(other);
}
if let Some(ref extended_attribute) = *rest {
self.visit_extended_attribute(extended_attribute);
}
}
}
}
fn visit_partial_dictionary(&mut self, partial_dictionary: &'ast PartialDictionary) {
if !partial_dictionary.extended_attributes.is_empty() {
self.stringify_extended_attributes(&partial_dictionary.extended_attributes);
self.output.push('\n');
}
self.output.push_str("partial dictionary ");
self.visit_identifier(&partial_dictionary.name);
self.output.push_str(" {\n");
for member in &partial_dictionary.members {
self.visit_dictionary_member(member);
}
self.output.push_str("};\n\n");
}
fn visit_partial_interface(&mut self, partial_interface: &'ast PartialInterface) {
if !partial_interface.extended_attributes.is_empty() {
self.stringify_extended_attributes(&partial_interface.extended_attributes);
self.output.push('\n');
}
self.output.push_str("partial interface ");
self.visit_identifier(&partial_interface.name);
self.output.push_str(" {\n");
self.stringify_interface_members(&partial_interface.members);
self.output.push_str("};\n\n");
}
fn visit_partial_mixin(&mut self, partial_mixin: &'ast PartialMixin) {
if !partial_mixin.extended_attributes.is_empty() {
self.stringify_extended_attributes(&partial_mixin.extended_attributes);
self.output.push('\n');
}
self.output.push_str("partial interface mixin ");
self.visit_identifier(&partial_mixin.name);
self.output.push_str(" {\n");
self.stringify_mixin_members(&partial_mixin.members);
self.output.push_str("};\n\n");
}
fn visit_partial_namespace(&mut self, partial_namespace: &'ast PartialNamespace) {
if !partial_namespace.extended_attributes.is_empty() {
self.stringify_extended_attributes(&partial_namespace.extended_attributes);
self.output.push('\n');
}
self.output.push_str("partial namespace ");
self.visit_identifier(&partial_namespace.name);
self.output.push_str(" {\n");
self.stringify_namespace_members(&partial_namespace.members);
self.output.push_str("};\n\n");
}
fn visit_regular_attribute(&mut self, regular_attribute: &'ast RegularAttribute) {
if !regular_attribute.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(®ular_attribute.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" ");
if regular_attribute.inherits {
self.output.push_str("inherit ");
}
if regular_attribute.read_only {
self.output.push_str("readonly ");
}
self.output.push_str("attribute ");
self.visit_type(®ular_attribute.type_);
self.output.push(' ');
self.visit_identifier(®ular_attribute.name);
self.output.push_str(";\n");
}
fn visit_regular_operation(&mut self, regular_operation: &'ast RegularOperation) {
if !regular_operation.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(®ular_operation.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" ");
self.visit_return_type(®ular_operation.return_type);
self.output.push(' ');
if let Some(ref name) = regular_operation.name {
self.visit_identifier(name);
}
self.stringify_arguments(®ular_operation.arguments);
self.output.push_str(";\n");
}
fn visit_return_type(&mut self, return_type: &'ast ReturnType) {
match *return_type {
ReturnType::NonVoid(ref type_) => self.visit_type(type_),
ReturnType::Void => self.output.push_str("void"),
}
}
fn visit_setlike(&mut self, setlike: &'ast Setlike) {
if !setlike.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&setlike.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" ");
if setlike.read_only {
self.output.push_str("readonly ");
}
self.output.push_str("setlike<");
self.visit_type(&setlike.type_);
self.output.push_str(">;\n");
}
fn visit_special(&mut self, special: &'ast Special) {
match *special {
Special::Deleter => self.output.push_str("deleter"),
Special::Getter => self.output.push_str("getter"),
Special::LegacyCaller => self.output.push_str("legacycaller"),
Special::Setter => self.output.push_str("setter"),
}
}
fn visit_special_operation(&mut self, special_operation: &'ast SpecialOperation) {
if !special_operation.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&special_operation.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" ");
for special_keyword in &special_operation.special_keywords {
self.visit_special(special_keyword);
self.output.push(' ');
}
self.visit_return_type(&special_operation.return_type);
self.output.push(' ');
if let Some(ref name) = special_operation.name {
self.visit_identifier(name);
}
self.stringify_arguments(&special_operation.arguments);
self.output.push_str(";\n");
}
fn visit_static_attribute(&mut self, static_attribute: &'ast StaticAttribute) {
if !static_attribute.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&static_attribute.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" static ");
if static_attribute.read_only {
self.output.push_str("readonly ");
}
self.output.push_str("attribute ");
self.visit_type(&static_attribute.type_);
self.output.push(' ');
self.visit_identifier(&static_attribute.name);
self.output.push_str(";\n");
}
fn visit_static_operation(&mut self, static_operation: &'ast StaticOperation) {
if !static_operation.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&static_operation.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" static ");
self.visit_return_type(&static_operation.return_type);
self.output.push(' ');
if let Some(ref name) = static_operation.name {
self.visit_identifier(name);
}
self.stringify_arguments(&static_operation.arguments);
self.output.push_str(";\n");
}
fn visit_string_type(&mut self, string_type: &'ast StringType) {
match *string_type {
StringType::ByteString => self.output.push_str("ByteString"),
StringType::DOMString => self.output.push_str("DOMString"),
StringType::USVString => self.output.push_str("USVString"),
}
}
fn visit_stringifier_attribute(&mut self, stringifier_attribute: &'ast StringifierAttribute) {
if !stringifier_attribute.extended_attributes.is_empty() {
self.output.push_str(" ");
self.stringify_extended_attributes(&stringifier_attribute.extended_attributes);
self.output.push('\n');
}
self.output.push_str(" stringifier ");
if stringifier_attribute.read_only {
self.output.push_str("readonly ");
}
self.output.push_str("attribute ");
self.visit_type(&stringifier_attribute.type_);
self.output.push(' ');
self.visit_identifier(&stringifier_attribute.name);
self.output.push_str(";\n");
}
fn visit_type(&mut self, type_: &'ast Type) {
self.stringify_extended_attributes(&type_.extended_attributes);
if !type_.extended_attributes.is_empty() {
self.output.push(' ');
}
self.visit_type_kind(&type_.kind);
if type_.nullable {
self.output.push_str("?");
}
}
fn visit_type_kind(&mut self, type_kind: &'ast TypeKind) {
match *type_kind {
TypeKind::Any => self.output.push_str("any"),
TypeKind::ArrayBuffer => self.output.push_str("ArrayBuffer"),
TypeKind::Boolean => self.output.push_str("boolean"),
TypeKind::Byte => self.output.push_str("byte"),
TypeKind::ByteString => self.output.push_str("ByteString"),
TypeKind::DOMString => self.output.push_str("DOMString"),
TypeKind::DataView => self.output.push_str("DataView"),
TypeKind::Error => self.output.push_str("Error"),
TypeKind::Float32Array => self.output.push_str("Float32Array"),
TypeKind::Float64Array => self.output.push_str("Float64Array"),
TypeKind::FrozenArray(ref type_) => {
self.output.push_str("FrozenArray<");
self.visit_type(type_);
self.output.push('>');
}
TypeKind::Identifier(ref identifier) => self.visit_identifier(identifier),
TypeKind::Int16Array => self.output.push_str("Int16Array"),
TypeKind::Int32Array => self.output.push_str("Int32Array"),
TypeKind::Int8Array => self.output.push_str("Int8Array"),
TypeKind::Octet => self.output.push_str("octet"),
TypeKind::Object => self.output.push_str("object"),
TypeKind::Promise(ref return_type) => {
self.output.push_str("Promise<");
self.visit_return_type(return_type);
self.output.push('>');
}
TypeKind::Record(ref string_type, ref value_type) => {
self.output.push_str("record<");
self.visit_string_type(string_type);
self.output.push_str(", ");
self.visit_type(value_type);
self.output.push('>');
}
TypeKind::RestrictedDouble => self.output.push_str("double"),
TypeKind::RestrictedFloat => self.output.push_str("float"),
TypeKind::Sequence(ref type_) => {
self.output.push_str("sequence<");
self.visit_type(type_);
self.output.push('>');
}
TypeKind::SignedLong => self.output.push_str("long"),
TypeKind::SignedLongLong => self.output.push_str("long long"),
TypeKind::SignedShort => self.output.push_str("short"),
TypeKind::Symbol => self.output.push_str("symbol"),
TypeKind::USVString => self.output.push_str("USVString"),
TypeKind::Uint16Array => self.output.push_str("Uint16Array"),
TypeKind::Uint32Array => self.output.push_str("Uint32Array"),
TypeKind::Uint8Array => self.output.push_str("Uint8Array"),
TypeKind::Uint8ClampedArray => self.output.push_str("Uint8ClampedArray"),
TypeKind::Union(ref types) => {
self.output.push('(');
for (index, type_) in types.iter().enumerate() {
if index != 0 {
self.output.push_str(" or ");
}
self.visit_type(type_);
}
self.output.push(')');
}
TypeKind::UnrestrictedDouble => self.output.push_str("unrestricted double"),
TypeKind::UnrestrictedFloat => self.output.push_str("unrestricted float"),
TypeKind::UnsignedLong => self.output.push_str("unsigned long"),
TypeKind::UnsignedLongLong => self.output.push_str("unsigned long long"),
TypeKind::UnsignedShort => self.output.push_str("unsigned short"),
}
}
fn visit_typedef(&mut self, typedef: &'ast Typedef) {
if !typedef.extended_attributes.is_empty() {
self.stringify_extended_attributes(&typedef.extended_attributes);
self.output.push('\n');
}
self.output.push_str("typedef ");
self.visit_type(&typedef.type_);
self.output.push(' ');
self.visit_identifier(&typedef.name);
self.output.push_str(";\n");
}
}