瀏覽代碼

LibWeb: Add support for IDL typedefs

Idan Horowitz 3 年之前
父節點
當前提交
c14cb65215

+ 91 - 0
Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLParser.cpp

@@ -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);

+ 1 - 0
Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLParser.h

@@ -38,6 +38,7 @@ private:
     void parse_interface(Interface&);
     void parse_non_interface_entities(bool allow_interface, Interface&);
     void parse_enumeration(Interface&);
+    void parse_typedef(Interface&);
     void parse_interface_mixin(Interface&);
     void parse_dictionary(Interface&);
     void parse_constructor(Interface&);

+ 6 - 0
Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLTypes.h

@@ -121,6 +121,11 @@ struct Dictionary {
     Vector<DictionaryMember> members;
 };
 
+struct Typedef {
+    HashMap<String, String> extended_attributes;
+    NonnullRefPtr<Type> type;
+};
+
 struct Enumeration {
     HashTable<String> values;
     HashMap<String, String> translated_cpp_names;
@@ -184,6 +189,7 @@ struct Interface {
 
     HashMap<String, Dictionary> dictionaries;
     HashMap<String, Enumeration> enumerations;
+    HashMap<String, Typedef> typedefs;
     HashMap<String, NonnullOwnPtr<Interface>> mixins;
 
     // Added for convenience after parsing