123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- /*
- * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
- * 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
- */
- #pragma once
- #include <AK/HashMap.h>
- #include <AK/NonnullRefPtr.h>
- #include <AK/NonnullRefPtrVector.h>
- #include <AK/SourceGenerator.h>
- #include <AK/String.h>
- #include <AK/StringBuilder.h>
- #include <AK/Tuple.h>
- #include <AK/TypeCasts.h>
- namespace IDL {
- template<typename FunctionType>
- static size_t get_function_shortest_length(FunctionType& function)
- {
- size_t length = 0;
- for (auto& parameter : function.parameters) {
- if (!parameter.optional && !parameter.variadic)
- length++;
- }
- return length;
- }
- enum class SequenceStorageType {
- Vector, // Used to safely store non-JS values
- MarkedVector, // Used to safely store JS::Value and anything that inherits JS::Cell, e.g. JS::Object
- };
- struct CppType {
- String name;
- SequenceStorageType sequence_storage_type;
- };
- class ParameterizedType;
- class UnionType;
- class Type : public RefCounted<Type> {
- public:
- enum class Kind {
- Plain, // AKA, Type.
- Parameterized,
- Union,
- };
- Type(String name, bool 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;
- Kind kind() const { return m_kind; }
- bool is_plain() const { return m_kind == Kind::Plain; }
- 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();
- String const& name() const { return m_name; }
- bool is_nullable() const { return m_nullable; }
- void set_nullable(bool value) { m_nullable = value; }
- // https://webidl.spec.whatwg.org/#dfn-includes-a-nullable-type
- bool includes_nullable_type() const;
- // -> https://webidl.spec.whatwg.org/#dfn-includes-undefined
- bool includes_undefined() const;
- Type const& innermost_type() const
- {
- // From step 4 of https://webidl.spec.whatwg.org/#dfn-distinguishable
- // "Consider the two "innermost" types derived by taking each type’s inner type if it is an annotated type, and then taking its inner type inner type if the result is a nullable type."
- // FIXME: Annotated types.
- VERIFY(!is_union());
- return *this;
- }
- // https://webidl.spec.whatwg.org/#idl-any
- bool is_any() const { return is_plain() && m_name == "any"; }
- // https://webidl.spec.whatwg.org/#idl-undefined
- bool is_undefined() const { return is_plain() && m_name == "undefined"; }
- // https://webidl.spec.whatwg.org/#idl-boolean
- bool is_boolean() const { return is_plain() && m_name == "boolean"; }
- // https://webidl.spec.whatwg.org/#idl-bigint
- bool is_bigint() const { return is_plain() && m_name == "bigint"; }
- // https://webidl.spec.whatwg.org/#idl-object
- bool is_object() const { return is_plain() && m_name == "object"; }
- // https://webidl.spec.whatwg.org/#idl-symbol
- bool is_symbol() const { return is_plain() && m_name == "symbol"; }
- bool is_string() const { return is_plain() && m_name.is_one_of("ByteString", "CSSOMString", "DOMString", "USVString"); }
- // https://webidl.spec.whatwg.org/#dfn-integer-type
- bool is_integer() const { return is_plain() && 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_plain() && (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_plain() && (is_numeric() || is_boolean() || m_name == "bigint"); }
- // https://webidl.spec.whatwg.org/#idl-sequence
- bool is_sequence() const { return is_parameterized() && m_name == "sequence"; }
- // https://webidl.spec.whatwg.org/#dfn-distinguishable
- bool is_distinguishable_from(Type const& other) const;
- private:
- Kind m_kind;
- String m_name;
- bool m_nullable { false };
- };
- struct Parameter {
- NonnullRefPtr<Type> type;
- String name;
- bool optional { false };
- Optional<String> optional_default_value;
- HashMap<String, String> extended_attributes;
- bool variadic { false };
- };
- struct Function {
- NonnullRefPtr<Type> return_type;
- String name;
- Vector<Parameter> parameters;
- HashMap<String, String> extended_attributes;
- size_t overload_index { 0 };
- bool is_overloaded { false };
- size_t shortest_length() const { return get_function_shortest_length(*this); }
- };
- struct Constructor {
- String name;
- Vector<Parameter> parameters;
- size_t shortest_length() const { return get_function_shortest_length(*this); }
- };
- struct Constant {
- NonnullRefPtr<Type> type;
- String name;
- String value;
- };
- struct Attribute {
- bool inherit { false };
- bool readonly { false };
- NonnullRefPtr<Type> type;
- String name;
- HashMap<String, String> extended_attributes;
- // Added for convenience after parsing
- String getter_callback_name;
- String setter_callback_name;
- };
- struct DictionaryMember {
- bool required { false };
- NonnullRefPtr<Type> type;
- String name;
- HashMap<String, String> extended_attributes;
- Optional<String> default_value;
- };
- struct Dictionary {
- String parent_name;
- Vector<DictionaryMember> members;
- };
- struct Typedef {
- HashMap<String, String> extended_attributes;
- NonnullRefPtr<Type> type;
- };
- struct Enumeration {
- HashTable<String> values;
- HashMap<String, String> translated_cpp_names;
- String first_member;
- bool is_original_definition { true };
- };
- struct CallbackFunction {
- NonnullRefPtr<Type> return_type;
- Vector<Parameter> parameters;
- bool is_legacy_treat_non_object_as_null { false };
- };
- class Interface;
- class ParameterizedType : public Type {
- public:
- ParameterizedType(String name, bool nullable, NonnullRefPtrVector<Type> parameters)
- : Type(Kind::Parameterized, move(name), nullable)
- , m_parameters(move(parameters))
- {
- }
- virtual ~ParameterizedType() override = default;
- 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)
- {
- size_t shortest_length = SIZE_MAX;
- for (auto const& function : overload_set)
- shortest_length = min(function.shortest_length(), shortest_length);
- return shortest_length;
- }
- class Interface {
- AK_MAKE_NONCOPYABLE(Interface);
- AK_MAKE_NONMOVABLE(Interface);
- public:
- explicit Interface() = default;
- String name;
- String parent_name;
- bool is_mixin { false };
- HashMap<String, String> extended_attributes;
- Vector<Attribute> attributes;
- Vector<Constant> constants;
- Vector<Constructor> constructors;
- Vector<Function> functions;
- Vector<Function> static_functions;
- bool has_stringifier { false };
- Optional<String> stringifier_attribute;
- bool has_unscopable_member { false };
- Optional<NonnullRefPtr<Type>> value_iterator_type;
- Optional<Tuple<NonnullRefPtr<Type>, NonnullRefPtr<Type>>> pair_iterator_types;
- Optional<Function> named_property_getter;
- Optional<Function> named_property_setter;
- Optional<Function> indexed_property_getter;
- Optional<Function> indexed_property_setter;
- Optional<Function> named_property_deleter;
- HashMap<String, Dictionary> dictionaries;
- HashMap<String, Enumeration> enumerations;
- HashMap<String, Typedef> typedefs;
- HashMap<String, Interface*> mixins;
- HashMap<String, CallbackFunction> callback_functions;
- // Added for convenience after parsing
- String fully_qualified_name;
- String constructor_class;
- String prototype_class;
- String prototype_base_class;
- HashMap<String, HashTable<String>> included_mixins;
- String module_own_path;
- HashTable<String> required_imported_paths;
- Vector<Interface&> imported_modules;
- HashMap<String, Vector<Function&>> overload_sets;
- HashMap<String, Vector<Function&>> static_overload_sets;
- // https://webidl.spec.whatwg.org/#dfn-support-indexed-properties
- bool supports_indexed_properties() const { return indexed_property_getter.has_value(); }
- // https://webidl.spec.whatwg.org/#dfn-support-named-properties
- bool supports_named_properties() const { return named_property_getter.has_value(); }
- // https://webidl.spec.whatwg.org/#dfn-legacy-platform-object
- bool is_legacy_platform_object() const { return !extended_attributes.contains("Global") && (supports_indexed_properties() || supports_named_properties()); }
- bool will_generate_code() const
- {
- return !name.is_empty() || any_of(enumerations, [](auto& entry) { return entry.value.is_original_definition; });
- }
- };
- class UnionType : public Type {
- public:
- UnionType(String name, bool nullable, NonnullRefPtrVector<Type> member_types)
- : Type(Kind::Union, move(name), nullable)
- , m_member_types(move(member_types))
- {
- }
- virtual ~UnionType() override = default;
- 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
- {
- // 1. Let T be the union type.
- // 2. Initialize S to ∅.
- NonnullRefPtrVector<Type> types;
- // 3. For each member type U of T:
- 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 (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.
- types.append(type);
- }
- }
- // 4. Return S.
- return types;
- }
- // https://webidl.spec.whatwg.org/#dfn-number-of-nullable-member-types
- size_t number_of_nullable_member_types() const
- {
- // 1. Let T be the union type.
- // 2. Initialize n to 0.
- size_t num_nullable_member_types = 0;
- // 3. For each member type U of T:
- for (auto& type : m_member_types) {
- // 1. If U is a nullable type, then:
- if (type.is_nullable()) {
- // 1. Set n to n + 1.
- ++num_nullable_member_types;
- // 2. Set U to be the inner type of U. (NOTE: Not necessary as nullable is stored with Type and not as a separate struct)
- }
- // 2. If U is a union type, then:
- 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.
- num_nullable_member_types += union_member_type.number_of_nullable_member_types();
- }
- }
- // 4. Return n.
- return num_nullable_member_types;
- }
- private:
- NonnullRefPtrVector<Type> m_member_types;
- };
- // https://webidl.spec.whatwg.org/#dfn-optionality-value
- enum class Optionality {
- Required,
- Optional,
- Variadic,
- };
- // https://webidl.spec.whatwg.org/#dfn-effective-overload-set
- class EffectiveOverloadSet {
- public:
- struct Item {
- int callable_id;
- NonnullRefPtrVector<Type> types;
- Vector<Optionality> optionality_values;
- };
- EffectiveOverloadSet(Vector<Item> items)
- : m_items(move(items))
- , m_argument_count(m_items.is_empty() ? 0 : m_items.first().types.size())
- {
- }
- Vector<Item>& items() { return m_items; }
- Vector<Item> const& items() const { return m_items; }
- Item const& only_item() const
- {
- VERIFY(m_items.size() == 1);
- return m_items[0];
- }
- bool is_empty() const { return m_items.is_empty(); }
- size_t size() const { return m_items.size(); }
- int distinguishing_argument_index();
- template<typename Matches>
- bool has_overload_with_matching_argument_at_index(size_t index, Matches matches)
- {
- for (auto const& item : m_items) {
- if (matches(item.types[index], item.optionality_values[index])) {
- m_last_matching_item = &item;
- return true;
- }
- }
- m_last_matching_item = nullptr;
- return false;
- }
- void remove_all_other_entries();
- private:
- // FIXME: This should be an "ordered set".
- Vector<Item> m_items;
- size_t m_argument_count;
- Item const* m_last_matching_item { nullptr };
- };
- }
|