|
@@ -612,6 +612,25 @@ void Parser::parse_enumeration(Interface& interface)
|
|
|
consume_whitespace();
|
|
|
}
|
|
|
|
|
|
+void Parser::parse_typedef(Interface& interface)
|
|
|
+{
|
|
|
+ assert_string("typedef");
|
|
|
+ consume_whitespace();
|
|
|
+
|
|
|
+ HashMap<String, String> extended_attributes;
|
|
|
+ if (lexer.consume_specific('['))
|
|
|
+ extended_attributes = parse_extended_attributes();
|
|
|
+
|
|
|
+ auto type = parse_type();
|
|
|
+ consume_whitespace();
|
|
|
+
|
|
|
+ auto name = lexer.consume_until(';');
|
|
|
+ assert_specific(';');
|
|
|
+
|
|
|
+ interface.typedefs.set(name, Typedef { move(extended_attributes), move(type) });
|
|
|
+ consume_whitespace();
|
|
|
+}
|
|
|
+
|
|
|
void Parser::parse_dictionary(Interface& interface)
|
|
|
{
|
|
|
assert_string("dictionary");
|
|
@@ -710,6 +729,8 @@ void Parser::parse_non_interface_entities(bool allow_interface, Interface& inter
|
|
|
parse_dictionary(interface);
|
|
|
} else if (lexer.next_is("enum")) {
|
|
|
parse_enumeration(interface);
|
|
|
+ } else if (lexer.next_is("typedef")) {
|
|
|
+ parse_typedef(interface);
|
|
|
} else if (lexer.next_is("interface mixin")) {
|
|
|
parse_interface_mixin(interface);
|
|
|
} else if ((allow_interface && !lexer.next_is("interface")) || !allow_interface) {
|
|
@@ -732,6 +753,37 @@ void Parser::parse_non_interface_entities(bool allow_interface, Interface& inter
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void resolve_typedef(Interface& interface, NonnullRefPtr<Type>& type, HashMap<String, String>* extended_attributes = {})
|
|
|
+{
|
|
|
+ if (is<ParameterizedType>(*type)) {
|
|
|
+ auto parameterized_type = static_ptr_cast<ParameterizedType>(type);
|
|
|
+ auto& parameters = static_cast<Vector<NonnullRefPtr<Type>>&>(parameterized_type->parameters);
|
|
|
+ for (auto& parameter : parameters)
|
|
|
+ resolve_typedef(interface, parameter);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ auto it = interface.typedefs.find(type->name);
|
|
|
+ if (it == interface.typedefs.end())
|
|
|
+ return;
|
|
|
+ type = it->value.type;
|
|
|
+ if (!extended_attributes)
|
|
|
+ return;
|
|
|
+ for (auto& attribute : it->value.extended_attributes)
|
|
|
+ extended_attributes->set(attribute.key, attribute.value);
|
|
|
+}
|
|
|
+void resolve_parameters_typedefs(Interface& interface, Vector<Parameter>& parameters)
|
|
|
+{
|
|
|
+ for (auto& parameter : parameters)
|
|
|
+ resolve_typedef(interface, parameter.type, ¶meter.extended_attributes);
|
|
|
+}
|
|
|
+template<typename FunctionType>
|
|
|
+void resolve_function_typedefs(Interface& interface, FunctionType& function)
|
|
|
+{
|
|
|
+ resolve_typedef(interface, function.return_type);
|
|
|
+ resolve_parameters_typedefs(interface, function.parameters);
|
|
|
+}
|
|
|
+
|
|
|
NonnullOwnPtr<Interface> Parser::parse()
|
|
|
{
|
|
|
auto this_module = Core::File::real_path_for(filename);
|
|
@@ -780,6 +832,9 @@ NonnullOwnPtr<Interface> Parser::parse()
|
|
|
interface->enumerations.set(enumeration.key, move(enumeration_copy));
|
|
|
}
|
|
|
|
|
|
+ for (auto& typedef_ : import.typedefs)
|
|
|
+ interface->typedefs.set(typedef_.key, move(typedef_.value));
|
|
|
+
|
|
|
for (auto& mixin : import.mixins) {
|
|
|
if (interface->mixins.contains(mixin.key))
|
|
|
report_parsing_error(String::formatted("Mixin '{}' was already defined in {}", mixin.key, mixin.value->module_own_path), filename, input, lexer.tell());
|
|
@@ -809,6 +864,42 @@ NonnullOwnPtr<Interface> Parser::parse()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Resolve typedefs
|
|
|
+ for (auto& attribute : interface->attributes)
|
|
|
+ resolve_typedef(*interface, attribute.type, &attribute.extended_attributes);
|
|
|
+ for (auto& constant : interface->constants)
|
|
|
+ resolve_typedef(*interface, constant.type);
|
|
|
+ for (auto& constructor : interface->constructors)
|
|
|
+ resolve_parameters_typedefs(*interface, constructor.parameters);
|
|
|
+ for (auto& function : interface->functions)
|
|
|
+ resolve_function_typedefs(*interface, function);
|
|
|
+ for (auto& static_function : interface->static_functions)
|
|
|
+ resolve_function_typedefs(*interface, static_function);
|
|
|
+ if (interface->value_iterator_type.has_value())
|
|
|
+ resolve_typedef(*interface, *interface->value_iterator_type);
|
|
|
+ if (interface->pair_iterator_types.has_value()) {
|
|
|
+ resolve_typedef(*interface, interface->pair_iterator_types->get<0>());
|
|
|
+ resolve_typedef(*interface, interface->pair_iterator_types->get<1>());
|
|
|
+ }
|
|
|
+ if (interface->named_property_getter.has_value())
|
|
|
+ resolve_function_typedefs(*interface, *interface->named_property_getter);
|
|
|
+ if (interface->named_property_setter.has_value())
|
|
|
+ resolve_function_typedefs(*interface, *interface->named_property_setter);
|
|
|
+ if (interface->indexed_property_getter.has_value())
|
|
|
+ resolve_function_typedefs(*interface, *interface->indexed_property_getter);
|
|
|
+ if (interface->indexed_property_setter.has_value())
|
|
|
+ resolve_function_typedefs(*interface, *interface->indexed_property_setter);
|
|
|
+ if (interface->named_property_deleter.has_value())
|
|
|
+ resolve_function_typedefs(*interface, *interface->named_property_deleter);
|
|
|
+ if (interface->named_property_getter.has_value())
|
|
|
+ resolve_function_typedefs(*interface, *interface->named_property_getter);
|
|
|
+ for (auto& dictionary : interface->dictionaries) {
|
|
|
+ for (auto& dictionary_member : dictionary.value.members)
|
|
|
+ resolve_typedef(*interface, dictionary_member.type, &dictionary_member.extended_attributes);
|
|
|
+ }
|
|
|
+ for (auto& callback_function : interface->callback_functions)
|
|
|
+ resolve_function_typedefs(*interface, callback_function.value);
|
|
|
+
|
|
|
// Create overload sets
|
|
|
for (auto& function : interface->functions) {
|
|
|
auto& overload_set = interface->overload_sets.ensure(function.name);
|