From 34055fce9dff58da547e896949e8b5aa0b5cf58c Mon Sep 17 00:00:00 2001 From: Eduardo Speroni Date: Mon, 4 May 2026 01:23:15 -0300 Subject: [PATCH] feat: add more null types for types the runtime accept or returns as null --- .../Binary/binaryTypeEncodingSerializer.cpp | 6 + .../src/Binary/binaryTypeEncodingSerializer.h | 3 + .../src/Meta/NameRetrieverVisitor.cpp | 5 + .../src/Meta/NameRetrieverVisitor.h | 2 + metadata-generator/src/Meta/TypeEntities.h | 13 +- metadata-generator/src/Meta/TypeFactory.cpp | 2 + metadata-generator/src/Meta/TypeVisitor.h | 3 + .../src/Meta/ValidateMetaTypeVisitor.cpp | 7 + .../src/Meta/ValidateMetaTypeVisitor.h | 2 + .../src/TypeScript/DefinitionWriter.cpp | 14 +- .../src/TypeScript/DefinitionWriter.h | 174 ++++++++++-------- 11 files changed, 152 insertions(+), 79 deletions(-) diff --git a/metadata-generator/src/Binary/binaryTypeEncodingSerializer.cpp b/metadata-generator/src/Binary/binaryTypeEncodingSerializer.cpp index 16032020..8589f759 100644 --- a/metadata-generator/src/Binary/binaryTypeEncodingSerializer.cpp +++ b/metadata-generator/src/Binary/binaryTypeEncodingSerializer.cpp @@ -292,6 +292,12 @@ binary::BinaryTypeEncodingSerializer::visitNullable( return type.innerType->visit(*this); } +unique_ptr +binary::BinaryTypeEncodingSerializer::visitNonNullable( + const ::Meta::NonNullableType& type) { + return type.innerType->visit(*this); +} + unique_ptr binary::BinaryTypeEncodingSerializer::serializeRecordEncoding( const binary::BinaryTypeEncodingType encodingType, diff --git a/metadata-generator/src/Binary/binaryTypeEncodingSerializer.h b/metadata-generator/src/Binary/binaryTypeEncodingSerializer.h index 9a53f307..6a275202 100644 --- a/metadata-generator/src/Binary/binaryTypeEncodingSerializer.h +++ b/metadata-generator/src/Binary/binaryTypeEncodingSerializer.h @@ -118,5 +118,8 @@ class BinaryTypeEncodingSerializer virtual unique_ptr visitNullable( const ::Meta::NullableType& type) override; + + virtual unique_ptr visitNonNullable( + const ::Meta::NonNullableType& type) override; }; } // namespace binary diff --git a/metadata-generator/src/Meta/NameRetrieverVisitor.cpp b/metadata-generator/src/Meta/NameRetrieverVisitor.cpp index a0257bc7..0e120b2b 100644 --- a/metadata-generator/src/Meta/NameRetrieverVisitor.cpp +++ b/metadata-generator/src/Meta/NameRetrieverVisitor.cpp @@ -178,6 +178,11 @@ std::string NameRetrieverVisitor::visitNullable( return type.innerType->visit(*this); } +std::string NameRetrieverVisitor::visitNonNullable( + const ::Meta::NonNullableType& type) { + return type.innerType->visit(*this); +} + std::string NameRetrieverVisitor::generateFixedArray(const Type* el_type, size_t size) { std::stringstream ss(el_type->visit(*this)); diff --git a/metadata-generator/src/Meta/NameRetrieverVisitor.h b/metadata-generator/src/Meta/NameRetrieverVisitor.h index 820427ee..416b85d9 100644 --- a/metadata-generator/src/Meta/NameRetrieverVisitor.h +++ b/metadata-generator/src/Meta/NameRetrieverVisitor.h @@ -99,6 +99,8 @@ class NameRetrieverVisitor : public ::Meta::TypeVisitor { virtual std::string visitNullable(const ::Meta::NullableType& type); + virtual std::string visitNonNullable(const ::Meta::NonNullableType& type); + private: NameRetrieverVisitor(bool tsNames) : tsNames(tsNames) {} diff --git a/metadata-generator/src/Meta/TypeEntities.h b/metadata-generator/src/Meta/TypeEntities.h index 2a345012..5f3b5d6a 100644 --- a/metadata-generator/src/Meta/TypeEntities.h +++ b/metadata-generator/src/Meta/TypeEntities.h @@ -50,7 +50,8 @@ enum TypeType { TypeEnum, TypeTypeArgument, TypeExtVector, - TypeNullable + TypeNullable, + TypeNonNullable }; class Type { @@ -150,6 +151,8 @@ class Type { return visitor.visitExtVector(as()); case TypeNullable: return visitor.visitNullable(as()); + case TypeNonNullable: + return visitor.visitNonNullable(as()); } } @@ -324,4 +327,12 @@ class NullableType : public Type { Type* innerType; }; + +class NonNullableType : public Type { + public: + NonNullableType(Type* innerType) + : Type(TypeType::TypeNonNullable), innerType(innerType) {} + + Type* innerType; +}; } // namespace Meta diff --git a/metadata-generator/src/Meta/TypeFactory.cpp b/metadata-generator/src/Meta/TypeFactory.cpp index 48aba440..0b3de2f5 100644 --- a/metadata-generator/src/Meta/TypeFactory.cpp +++ b/metadata-generator/src/Meta/TypeFactory.cpp @@ -508,6 +508,8 @@ shared_ptr TypeFactory::createFromAttributedType( if (auto nullability = type->getImmediateNullability()) { if (*nullability == clang::NullabilityKind::Nullable) { return make_shared(innerType.get()); + } else if (*nullability == clang::NullabilityKind::NonNull) { + return make_shared(innerType.get()); } } return innerType; diff --git a/metadata-generator/src/Meta/TypeVisitor.h b/metadata-generator/src/Meta/TypeVisitor.h index b2a77d3d..f81a9da0 100644 --- a/metadata-generator/src/Meta/TypeVisitor.h +++ b/metadata-generator/src/Meta/TypeVisitor.h @@ -19,6 +19,7 @@ class EnumType; class TypeArgumentType; class ExtVectorType; class NullableType; +class NonNullableType; /* * \class TypeVisitor @@ -107,5 +108,7 @@ class TypeVisitor { virtual T_RESULT visitTypeArgument(const ::Meta::TypeArgumentType& type) = 0; virtual T_RESULT visitNullable(const ::Meta::NullableType& type) = 0; + + virtual T_RESULT visitNonNullable(const ::Meta::NonNullableType& type) = 0; }; } // namespace Meta diff --git a/metadata-generator/src/Meta/ValidateMetaTypeVisitor.cpp b/metadata-generator/src/Meta/ValidateMetaTypeVisitor.cpp index af47a7bd..5d5f77c9 100644 --- a/metadata-generator/src/Meta/ValidateMetaTypeVisitor.cpp +++ b/metadata-generator/src/Meta/ValidateMetaTypeVisitor.cpp @@ -171,3 +171,10 @@ bool ValidateMetaTypeVisitor::visitNullable(const NullableType& typeDetails) { return true; } + +bool ValidateMetaTypeVisitor::visitNonNullable( + const NonNullableType& typeDetails) { + typeDetails.innerType->visit(*this); + + return true; +} diff --git a/metadata-generator/src/Meta/ValidateMetaTypeVisitor.h b/metadata-generator/src/Meta/ValidateMetaTypeVisitor.h index 83a26a66..a05aa193 100644 --- a/metadata-generator/src/Meta/ValidateMetaTypeVisitor.h +++ b/metadata-generator/src/Meta/ValidateMetaTypeVisitor.h @@ -93,6 +93,8 @@ class ValidateMetaTypeVisitor : public TypeVisitor { virtual bool visitNullable(const ::Meta::NullableType& type); + virtual bool visitNonNullable(const ::Meta::NonNullableType& type); + private: MetaFactory& _metaFactory; }; diff --git a/metadata-generator/src/TypeScript/DefinitionWriter.cpp b/metadata-generator/src/TypeScript/DefinitionWriter.cpp index 8976a031..766b43bc 100644 --- a/metadata-generator/src/TypeScript/DefinitionWriter.cpp +++ b/metadata-generator/src/TypeScript/DefinitionWriter.cpp @@ -949,7 +949,8 @@ bool DefinitionWriter::hasClosedGenerics(const Type& type) { } std::string DefinitionWriter::tsifyType(const Type& type, - const bool isFuncParam) { + const bool isFuncParam, + const bool suppressNull) { switch (type.getType()) { case TypeVoid: return "void"; @@ -1011,6 +1012,9 @@ std::string DefinitionWriter::tsifyType(const Type& type, if (isFuncParam) { result += " | ArrayBufferLike | ArrayBufferView"; } + if (!suppressNull) { + result += " | null"; + } return result; } case TypeBlock: @@ -1130,8 +1134,16 @@ std::string DefinitionWriter::tsifyType(const Type& type, return type.as().name; case TypeNullable: { const NullableType& nullableType = type.as(); + if (nullableType.innerType->is(TypePointer)) { + return tsifyType(*nullableType.innerType, isFuncParam); + } return tsifyType(*nullableType.innerType, isFuncParam) + " | null"; } + case TypeNonNullable: { + const NonNullableType& nonNullType = type.as(); + bool suppress = isFuncParam; + return tsifyType(*nonNullType.innerType, isFuncParam, suppress); + } case TypeVaList: case TypeInstancetype: default: diff --git a/metadata-generator/src/TypeScript/DefinitionWriter.h b/metadata-generator/src/TypeScript/DefinitionWriter.h index cec193ef..2a14adce 100644 --- a/metadata-generator/src/TypeScript/DefinitionWriter.h +++ b/metadata-generator/src/TypeScript/DefinitionWriter.h @@ -1,87 +1,107 @@ #pragma once -#include "DocSetManager.h" -#include "Meta/MetaEntities.h" #include + #include #include #include +#include "DocSetManager.h" +#include "Meta/MetaEntities.h" + namespace TypeScript { class DefinitionWriter : Meta::MetaVisitor { -public: - DefinitionWriter(std::pair >& module, Meta::TypeFactory& typeFactory, std::string docSetPath) - : _module(module) - , _typeFactory(typeFactory) - , _docSet(docSetPath) - { - } - - std::string write(); - - static bool applyManualChanges; - - virtual void visit(Meta::InterfaceMeta* meta) override; - - virtual void visit(Meta::ProtocolMeta* meta) override; - - virtual void visit(Meta::CategoryMeta* meta) override; - - virtual void visit(Meta::FunctionMeta* meta) override; - - virtual void visit(Meta::StructMeta* meta) override; - - virtual void visit(Meta::UnionMeta* meta) override; - - virtual void visit(Meta::EnumMeta* meta) override; - - virtual void visit(Meta::VarMeta* meta) override; - - virtual void visit(Meta::MethodMeta* meta) override; - - virtual void visit(Meta::PropertyMeta* meta) override; - - virtual void visit(Meta::EnumConstantMeta* meta) override; - -private: - template - using CompoundMemberMap = std::map >; - - void writeMembers(const std::vector& fields, std::vector fieldsComments); - void writeProperty(Meta::PropertyMeta* meta, Meta::BaseClassMeta* owner, Meta::InterfaceMeta* target, CompoundMemberMap compoundProperties); - - static void getInheritedMembersRecursive(Meta::InterfaceMeta* interface, - CompoundMemberMap* staticMethods, - CompoundMemberMap* instanceMethods, - CompoundMemberMap* staticProperties, - CompoundMemberMap* instanceProperties); - - static void getProtocolMembersRecursive(Meta::ProtocolMeta* protocol, - CompoundMemberMap* staticMethods, - CompoundMemberMap* instanceMethods, - CompoundMemberMap* staticProperties, - CompoundMemberMap* instanceProperties, - std::unordered_set& visitedProtocols); - - static std::string writeConstructor(const CompoundMemberMap::value_type& initializer, - const Meta::BaseClassMeta* owner); - static std::string writeMethod(Meta::MethodMeta* meta, Meta::BaseClassMeta* owner, bool canUseThisType = false); - static std::string writeMethod(CompoundMemberMap::value_type& method, Meta::BaseClassMeta* owner, - const std::unordered_set& protocols, bool canUseThisType = false); - static std::string writeProperty(Meta::PropertyMeta* meta, Meta::BaseClassMeta* owner, bool optOutTypeChecking); - static std::string writeFunctionProto(const std::vector& signature); - static std::string localizeReference(const std::string& jsName, std::string moduleName); - static std::string localizeReference(const Meta::Meta& meta); - static std::string tsifyType(const Meta::Type& type, const bool isParam = false); - static std::string computeMethodReturnType(const Meta::Type* retType, const Meta::BaseClassMeta* owner, bool canUseThisType = false); - std::string getTypeArgumentsStringOrEmpty(const clang::ObjCObjectType* objectType); - - static bool hasClosedGenerics(const Meta::Type& type); - - std::pair >& _module; - Meta::TypeFactory& _typeFactory; - DocSetManager _docSet; - std::unordered_set _importedModules; - std::ostringstream _buffer; + public: + DefinitionWriter(std::pair >& module, + Meta::TypeFactory& typeFactory, std::string docSetPath) + : _module(module), _typeFactory(typeFactory), _docSet(docSetPath) {} + + std::string write(); + + static bool applyManualChanges; + + virtual void visit(Meta::InterfaceMeta* meta) override; + + virtual void visit(Meta::ProtocolMeta* meta) override; + + virtual void visit(Meta::CategoryMeta* meta) override; + + virtual void visit(Meta::FunctionMeta* meta) override; + + virtual void visit(Meta::StructMeta* meta) override; + + virtual void visit(Meta::UnionMeta* meta) override; + + virtual void visit(Meta::EnumMeta* meta) override; + + virtual void visit(Meta::VarMeta* meta) override; + + virtual void visit(Meta::MethodMeta* meta) override; + + virtual void visit(Meta::PropertyMeta* meta) override; + + virtual void visit(Meta::EnumConstantMeta* meta) override; + + private: + template + using CompoundMemberMap = + std::map >; + + void writeMembers(const std::vector& fields, + std::vector fieldsComments); + void writeProperty(Meta::PropertyMeta* meta, Meta::BaseClassMeta* owner, + Meta::InterfaceMeta* target, + CompoundMemberMap compoundProperties); + + static void getInheritedMembersRecursive( + Meta::InterfaceMeta* interface, + CompoundMemberMap* staticMethods, + CompoundMemberMap* instanceMethods, + CompoundMemberMap* staticProperties, + CompoundMemberMap* instanceProperties); + + static void getProtocolMembersRecursive( + Meta::ProtocolMeta* protocol, + CompoundMemberMap* staticMethods, + CompoundMemberMap* instanceMethods, + CompoundMemberMap* staticProperties, + CompoundMemberMap* instanceProperties, + std::unordered_set& visitedProtocols); + + static std::string writeConstructor( + const CompoundMemberMap::value_type& initializer, + const Meta::BaseClassMeta* owner); + static std::string writeMethod(Meta::MethodMeta* meta, + Meta::BaseClassMeta* owner, + bool canUseThisType = false); + static std::string writeMethod( + CompoundMemberMap::value_type& method, + Meta::BaseClassMeta* owner, + const std::unordered_set& protocols, + bool canUseThisType = false); + static std::string writeProperty(Meta::PropertyMeta* meta, + Meta::BaseClassMeta* owner, + bool optOutTypeChecking); + static std::string writeFunctionProto( + const std::vector& signature); + static std::string localizeReference(const std::string& jsName, + std::string moduleName); + static std::string localizeReference(const Meta::Meta& meta); + static std::string tsifyType(const Meta::Type& type, + const bool isParam = false, + const bool suppressNull = false); + static std::string computeMethodReturnType(const Meta::Type* retType, + const Meta::BaseClassMeta* owner, + bool canUseThisType = false); + std::string getTypeArgumentsStringOrEmpty( + const clang::ObjCObjectType* objectType); + + static bool hasClosedGenerics(const Meta::Type& type); + + std::pair >& _module; + Meta::TypeFactory& _typeFactory; + DocSetManager _docSet; + std::unordered_set _importedModules; + std::ostringstream _buffer; }; -} +} // namespace TypeScript