mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 20: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:
parent
c4668053d1
commit
7c8ef79898
6 changed files with 288 additions and 217 deletions
|
@ -1,5 +1,6 @@
|
|||
set(SOURCES
|
||||
IDLParser.cpp
|
||||
Types.cpp
|
||||
)
|
||||
|
||||
serenity_lib(LibIDL idl)
|
||||
|
|
|
@ -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)
|
||||
|
|
31
Userland/Libraries/LibIDL/Types.cpp
Normal file
31
Userland/Libraries/LibIDL/Types.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue