1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 13:17:44 +00:00

LibIDL+WrapperGenerator: Make it easier to work with IDL::Type classes

Track the kind of Type it is, and use that to provide some convenient
`is_foo()` / `as_foo()` methods. While I was at it, made these all
classes instead of structs and made their data private.
This commit is contained in:
Sam Atkins 2022-08-24 17:22:09 +01:00 committed by Andreas Kling
parent c4668053d1
commit 7c8ef79898
6 changed files with 288 additions and 217 deletions

View file

@ -1,5 +1,6 @@
set(SOURCES
IDLParser.cpp
Types.cpp
)
serenity_lib(LibIDL idl)

View file

@ -403,7 +403,7 @@ void Parser::parse_getter(HashMap<String, String>& extended_attributes, Interfac
auto& identifier = function.parameters.first();
if (identifier.type->nullable)
if (identifier.type->is_nullable())
report_parsing_error("identifier's type must not be nullable."sv, filename, input, lexer.tell());
if (identifier.optional)
@ -411,18 +411,18 @@ void Parser::parse_getter(HashMap<String, String>& extended_attributes, Interfac
// FIXME: Disallow variadic functions once they're supported.
if (identifier.type->name == "DOMString") {
if (identifier.type->name() == "DOMString") {
if (interface.named_property_getter.has_value())
report_parsing_error("An interface can only have one named property getter."sv, filename, input, lexer.tell());
interface.named_property_getter = move(function);
} else if (identifier.type->name == "unsigned long") {
} else if (identifier.type->name() == "unsigned long") {
if (interface.indexed_property_getter.has_value())
report_parsing_error("An interface can only have one indexed property getter."sv, filename, input, lexer.tell());
interface.indexed_property_getter = move(function);
} else {
report_parsing_error(String::formatted("Named/indexed property getter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name), filename, input, lexer.tell());
report_parsing_error(String::formatted("Named/indexed property getter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name()), filename, input, lexer.tell());
}
}
@ -437,7 +437,7 @@ void Parser::parse_setter(HashMap<String, String>& extended_attributes, Interfac
auto& identifier = function.parameters.first();
if (identifier.type->nullable)
if (identifier.type->is_nullable())
report_parsing_error("identifier's type must not be nullable."sv, filename, input, lexer.tell());
if (identifier.optional)
@ -445,7 +445,7 @@ void Parser::parse_setter(HashMap<String, String>& extended_attributes, Interfac
// FIXME: Disallow variadic functions once they're supported.
if (identifier.type->name == "DOMString") {
if (identifier.type->name() == "DOMString") {
if (interface.named_property_setter.has_value())
report_parsing_error("An interface can only have one named property setter."sv, filename, input, lexer.tell());
@ -453,7 +453,7 @@ void Parser::parse_setter(HashMap<String, String>& extended_attributes, Interfac
report_parsing_error("A named property setter must be accompanied by a named property getter."sv, filename, input, lexer.tell());
interface.named_property_setter = move(function);
} else if (identifier.type->name == "unsigned long") {
} else if (identifier.type->name() == "unsigned long") {
if (interface.indexed_property_setter.has_value())
report_parsing_error("An interface can only have one indexed property setter."sv, filename, input, lexer.tell());
@ -462,7 +462,7 @@ void Parser::parse_setter(HashMap<String, String>& extended_attributes, Interfac
interface.indexed_property_setter = move(function);
} else {
report_parsing_error(String::formatted("Named/indexed property setter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name), filename, input, lexer.tell());
report_parsing_error(String::formatted("Named/indexed property setter's identifier's type must be either 'DOMString' or 'unsigned long', got '{}'.", identifier.type->name()), filename, input, lexer.tell());
}
}
@ -477,7 +477,7 @@ void Parser::parse_deleter(HashMap<String, String>& extended_attributes, Interfa
auto& identifier = function.parameters.first();
if (identifier.type->nullable)
if (identifier.type->is_nullable())
report_parsing_error("identifier's type must not be nullable."sv, filename, input, lexer.tell());
if (identifier.optional)
@ -485,7 +485,7 @@ void Parser::parse_deleter(HashMap<String, String>& extended_attributes, Interfa
// FIXME: Disallow variadic functions once they're supported.
if (identifier.type->name == "DOMString") {
if (identifier.type->name() == "DOMString") {
if (interface.named_property_deleter.has_value())
report_parsing_error("An interface can only have one named property deleter."sv, filename, input, lexer.tell());
@ -494,7 +494,7 @@ void Parser::parse_deleter(HashMap<String, String>& extended_attributes, Interfa
interface.named_property_deleter = move(function);
} else {
report_parsing_error(String::formatted("Named property deleter's identifier's type must be 'DOMString', got '{}'.", identifier.type->name), filename, input, lexer.tell());
report_parsing_error(String::formatted("Named property deleter's identifier's type must be 'DOMString', got '{}'.", identifier.type->name()), filename, input, lexer.tell());
}
}
@ -809,18 +809,18 @@ static void resolve_typedef(Interface& interface, NonnullRefPtr<Type>& type, Has
{
if (is<ParameterizedType>(*type)) {
auto parameterized_type = static_ptr_cast<ParameterizedType>(type);
auto& parameters = static_cast<Vector<NonnullRefPtr<Type>>&>(parameterized_type->parameters);
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);
auto it = interface.typedefs.find(type->name());
if (it == interface.typedefs.end())
return;
bool is_nullable = type->nullable;
bool nullable = type->is_nullable();
type = it->value.type;
type->nullable = is_nullable;
type->set_nullable(nullable);
if (!extended_attributes)
return;
for (auto& attribute : it->value.extended_attributes)

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibIDL/Types.h>
namespace IDL {
ParameterizedType const& Type::as_parameterized() const
{
return verify_cast<ParameterizedType const>(*this);
}
ParameterizedType& Type::as_parameterized()
{
return verify_cast<ParameterizedType>(*this);
}
UnionType const& Type::as_union() const
{
return verify_cast<UnionType const>(*this);
}
UnionType& Type::as_union()
{
return verify_cast<UnionType>(*this);
}
}

View file

@ -3,6 +3,7 @@
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Luke Wilde <lukew@serenityos.org>
* Copyright (c) 2022, Ali Mohammad Pur <mpfard@serenityos.org>
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -41,29 +42,63 @@ struct CppType {
SequenceStorageType sequence_storage_type;
};
struct Type : public RefCounted<Type> {
Type() = default;
class ParameterizedType;
class UnionType;
class Type : public RefCounted<Type> {
public:
enum class Kind {
Plain, // AKA, Type.
Parameterized,
Union,
};
Type(String name, bool nullable)
: name(move(name))
, nullable(nullable)
: m_kind(Kind::Plain)
, m_name(move(name))
, m_nullable(nullable)
{
}
Type(Kind kind, String name, bool nullable)
: m_kind(kind)
, m_name(move(name))
, m_nullable(nullable)
{
}
virtual ~Type() = default;
String name;
bool nullable { false };
bool is_string() const { return name.is_one_of("ByteString", "CSSOMString", "DOMString", "USVString"); }
Kind kind() const { return m_kind; }
String const& name() const { return m_name; }
bool is_nullable() const { return m_nullable; }
void set_nullable(bool value) { m_nullable = value; }
bool is_string() const { return m_name.is_one_of("ByteString", "CSSOMString", "DOMString", "USVString"); }
// https://webidl.spec.whatwg.org/#dfn-integer-type
bool is_integer() const { return name.is_one_of("byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long", "unsigned long long"); }
bool is_integer() const { return m_name.is_one_of("byte", "octet", "short", "unsigned short", "long", "unsigned long", "long long", "unsigned long long"); }
// https://webidl.spec.whatwg.org/#dfn-numeric-type
bool is_numeric() const { return is_integer() || name.is_one_of("float", "unrestricted float", "double", "unrestricted double"); }
bool is_numeric() const { return is_integer() || m_name.is_one_of("float", "unrestricted float", "double", "unrestricted double"); }
// https://webidl.spec.whatwg.org/#dfn-primitive-type
bool is_primitive() const { return is_numeric() || name.is_one_of("bigint", "boolean"); }
bool is_primitive() const { return is_numeric() || m_name.is_one_of("bigint", "boolean"); }
bool is_parameterized() const { return m_kind == Kind::Parameterized; }
ParameterizedType const& as_parameterized() const;
ParameterizedType& as_parameterized();
bool is_union() const { return m_kind == Kind::Union; }
UnionType const& as_union() const;
UnionType& as_union();
private:
Kind m_kind;
String m_name;
bool m_nullable { false };
};
struct Parameter {
@ -143,20 +178,23 @@ struct CallbackFunction {
class Interface;
struct ParameterizedType : public Type {
ParameterizedType() = default;
class ParameterizedType : public Type {
public:
ParameterizedType(String name, bool nullable, NonnullRefPtrVector<Type> parameters)
: Type(move(name), nullable)
, parameters(move(parameters))
: Type(Kind::Parameterized, move(name), nullable)
, m_parameters(move(parameters))
{
}
virtual ~ParameterizedType() override = default;
NonnullRefPtrVector<Type> parameters;
void generate_sequence_from_iterable(SourceGenerator& generator, String const& cpp_name, String const& iterable_cpp_name, String const& iterator_method_cpp_name, IDL::Interface const&, size_t recursion_depth) const;
NonnullRefPtrVector<Type> const& parameters() const { return m_parameters; }
NonnullRefPtrVector<Type>& parameters() { return m_parameters; }
private:
NonnullRefPtrVector<Type> m_parameters;
};
static inline size_t get_shortest_function_length(Vector<Function&> const& overload_set)
@ -238,18 +276,18 @@ public:
}
};
struct UnionType : public Type {
UnionType() = default;
class UnionType : public Type {
public:
UnionType(String name, bool nullable, NonnullRefPtrVector<Type> member_types)
: Type(move(name), nullable)
, member_types(move(member_types))
: Type(Kind::Union, move(name), nullable)
, m_member_types(move(member_types))
{
}
virtual ~UnionType() override = default;
NonnullRefPtrVector<Type> member_types;
NonnullRefPtrVector<Type> const& member_types() const { return m_member_types; }
NonnullRefPtrVector<Type>& member_types() { return m_member_types; }
// https://webidl.spec.whatwg.org/#dfn-flattened-union-member-types
NonnullRefPtrVector<Type> flattened_member_types() const
@ -260,14 +298,14 @@ struct UnionType : public Type {
NonnullRefPtrVector<Type> types;
// 3. For each member type U of T:
for (auto& type : member_types) {
for (auto& type : m_member_types) {
// FIXME: 1. If U is an annotated type, then set U to be the inner type of U.
// 2. If U is a nullable type, then set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct)
// 3. If U is a union type, then add to S the flattened member types of U.
if (is<UnionType>(type)) {
auto& union_member_type = verify_cast<UnionType>(type);
if (type.is_union()) {
auto& union_member_type = type.as_union();
types.extend(union_member_type.flattened_member_types());
} else {
// 4. Otherwise, U is not a union type. Add U to S.
@ -288,9 +326,9 @@ struct UnionType : public Type {
size_t num_nullable_member_types = 0;
// 3. For each member type U of T:
for (auto& type : member_types) {
for (auto& type : m_member_types) {
// 1. If U is a nullable type, then:
if (type.nullable) {
if (type.is_nullable()) {
// 1. Set n to n + 1.
++num_nullable_member_types;
@ -298,8 +336,8 @@ struct UnionType : public Type {
}
// 2. If U is a union type, then:
if (is<UnionType>(type)) {
auto& union_member_type = verify_cast<UnionType>(type);
if (type.is_union()) {
auto& union_member_type = type.as_union();
// 1. Let m be the number of nullable member types of U.
// 2. Set n to n + m.
@ -322,18 +360,18 @@ struct UnionType : public Type {
bool includes_undefined() const
{
// -> the type is a union type and one of its member types includes undefined.
for (auto& type : member_types) {
if (is<UnionType>(type)) {
auto& union_type = verify_cast<UnionType>(type);
if (union_type.includes_undefined())
return true;
}
for (auto& type : m_member_types) {
if (type.is_union() && type.as_union().includes_undefined())
return true;
if (type.name == "undefined"sv)
if (type.name() == "undefined"sv)
return true;
}
return false;
}
private:
NonnullRefPtrVector<Type> m_member_types;
};
}