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.
This commit is contained in:
Jelle Raaijmakers 2025-07-22 12:54:35 +02:00 committed by Sam Atkins
commit 1da304f7b7
Notes: github-actions[bot] 2025-07-22 12:08:36 +00:00
4 changed files with 31 additions and 0 deletions

View file

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

View file

@ -45,6 +45,7 @@ private:
HashMap<ByteString, ByteString> parse_extended_attributes();
void parse_attribute(HashMap<ByteString, ByteString>& 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<ByteString, ByteString>, Interface&);

View file

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

View file

@ -318,6 +318,7 @@ public:
HashMap<ByteString, HashTable<ByteString>> included_mixins;
ByteString module_own_path;
Vector<NonnullOwnPtr<Interface>> partial_interfaces;
Vector<Interface&> imported_modules;
HashMap<ByteString, Vector<Function&>> 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 {