1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-10 12:27:35 +00:00

LibWeb: Add support for IDL typedefs

This commit is contained in:
Idan Horowitz 2022-03-30 23:32:44 +03:00 committed by Andreas Kling
parent f0cd28dedd
commit c14cb65215
3 changed files with 98 additions and 0 deletions

View file

@ -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, &parameter.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);