From 1da304f7b78da333a12ccd54b3abe915b175e9e9 Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Tue, 22 Jul 2025 12:54:35 +0200 Subject: [PATCH] LibIDL: Support partial interfaces Partial interfaces have the same name as the interface they extend, and can appear in any order. In practice, we import the partial interfaces into the main interface's IDL. --- Libraries/LibIDL/IDLParser.cpp | 18 ++++++++++++++++++ Libraries/LibIDL/IDLParser.h | 1 + Libraries/LibIDL/Types.cpp | 9 +++++++++ Libraries/LibIDL/Types.h | 3 +++ 4 files changed, 31 insertions(+) diff --git a/Libraries/LibIDL/IDLParser.cpp b/Libraries/LibIDL/IDLParser.cpp index 4f76b867896..3d6ddb087d8 100644 --- a/Libraries/LibIDL/IDLParser.cpp +++ b/Libraries/LibIDL/IDLParser.cpp @@ -813,6 +813,17 @@ void Parser::parse_interface(Interface& interface) consume_whitespace(); } +void Parser::parse_partial_interface(Interface& parent) +{ + assert_string("partial"sv); + consume_whitespace(); + assert_string("interface"sv); + + auto partial_interface = make(); + parse_interface(*partial_interface); + parent.partial_interfaces.append(move(partial_interface)); +} + void Parser::parse_namespace(Interface& interface) { consume_whitespace(); @@ -1051,6 +1062,8 @@ void Parser::parse_non_interface_entities(bool allow_interface, Interface& inter parse_enumeration(extended_attributes, interface); } else if (lexer.next_is("typedef")) { parse_typedef(interface); + } else if (lexer.next_is("partial interface"sv)) { + parse_partial_interface(interface); } else if (lexer.next_is("interface mixin")) { parse_interface_mixin(interface); } else if (lexer.next_is("callback")) { @@ -1183,6 +1196,11 @@ Interface& Parser::parse() for (auto& import : imports) { // FIXME: Instead of copying every imported entity into the current interface, query imports directly + for (auto& partial_interface : import.partial_interfaces) { + if (partial_interface->name == interface.name) + interface.extend_with_partial_interface(*partial_interface); + } + for (auto& dictionary : import.dictionaries) interface.dictionaries.set(dictionary.key, dictionary.value); diff --git a/Libraries/LibIDL/IDLParser.h b/Libraries/LibIDL/IDLParser.h index 9537162726b..3b2a6e818e7 100644 --- a/Libraries/LibIDL/IDLParser.h +++ b/Libraries/LibIDL/IDLParser.h @@ -45,6 +45,7 @@ private: HashMap parse_extended_attributes(); void parse_attribute(HashMap& extended_attributes, Interface&, IsStatic is_static = IsStatic::No); void parse_interface(Interface&); + void parse_partial_interface(Interface& parent); void parse_namespace(Interface&); void parse_non_interface_entities(bool allow_interface, Interface&); void parse_enumeration(HashMap, Interface&); diff --git a/Libraries/LibIDL/Types.cpp b/Libraries/LibIDL/Types.cpp index c9c58b0e3c1..aaaf21e86de 100644 --- a/Libraries/LibIDL/Types.cpp +++ b/Libraries/LibIDL/Types.cpp @@ -305,4 +305,13 @@ void EffectiveOverloadSet::remove_all_other_entries() m_items = move(new_items); } +void Interface::extend_with_partial_interface(Interface const& partial) +{ + attributes.extend(partial.attributes); + static_attributes.extend(partial.static_attributes); + constants.extend(partial.constants); + functions.extend(partial.functions); + static_functions.extend(partial.static_functions); +} + } diff --git a/Libraries/LibIDL/Types.h b/Libraries/LibIDL/Types.h index 8249219cad6..b53a27122d4 100644 --- a/Libraries/LibIDL/Types.h +++ b/Libraries/LibIDL/Types.h @@ -318,6 +318,7 @@ public: HashMap> included_mixins; ByteString module_own_path; + Vector> partial_interfaces; Vector imported_modules; HashMap> overload_sets; @@ -337,6 +338,8 @@ public: { return !name.is_empty() || any_of(enumerations, [](auto& entry) { return entry.value.is_original_definition; }); } + + void extend_with_partial_interface(Interface const&); }; class UnionType : public Type {