diff --git a/metadata-generator/src/Binary/binaryTypeEncodingSerializer.cpp b/metadata-generator/src/Binary/binaryTypeEncodingSerializer.cpp index 34481127..16032020 100644 --- a/metadata-generator/src/Binary/binaryTypeEncodingSerializer.cpp +++ b/metadata-generator/src/Binary/binaryTypeEncodingSerializer.cpp @@ -1,265 +1,320 @@ #include "binaryTypeEncodingSerializer.h" -#include "../Meta/MetaEntities.h" + #include -binary::MetaFileOffset binary::BinaryTypeEncodingSerializer::visit(std::vector< ::Meta::Type*>& types) -{ - vector > binaryEncodings; - for (::Meta::Type* type : types) { - unique_ptr binaryEncoding = type->visit(*this); - binaryEncodings.push_back(std::move(binaryEncoding)); - } +#include "../Meta/MetaEntities.h" - binary::MetaFileOffset offset = this->_heapWriter.push_arrayCount(types.size()); - for (unique_ptr& binaryEncoding : binaryEncodings) { - binaryEncoding->save(this->_heapWriter); - } - return offset; -} +binary::MetaFileOffset binary::BinaryTypeEncodingSerializer::visit( + std::vector< ::Meta::Type*>& types) { + vector > binaryEncodings; + for (::Meta::Type* type : types) { + unique_ptr binaryEncoding = type->visit(*this); + binaryEncodings.push_back(std::move(binaryEncoding)); + } -unique_ptr binary::BinaryTypeEncodingSerializer::visitVoid() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Void); + binary::MetaFileOffset offset = + this->_heapWriter.push_arrayCount(types.size()); + for (unique_ptr& binaryEncoding : binaryEncodings) { + binaryEncoding->save(this->_heapWriter); + } + return offset; } -unique_ptr binary::BinaryTypeEncodingSerializer::visitBool() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Bool); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitVoid() { + return std::make_unique( + binary::BinaryTypeEncodingType::Void); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitShort() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Short); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitBool() { + return std::make_unique( + binary::BinaryTypeEncodingType::Bool); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitUShort() -{ - return std::make_unique(binary::BinaryTypeEncodingType::UShort); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitShort() { + return std::make_unique( + binary::BinaryTypeEncodingType::Short); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitInt() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Int); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitUShort() { + return std::make_unique( + binary::BinaryTypeEncodingType::UShort); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitUInt() -{ - return std::make_unique(binary::BinaryTypeEncodingType::UInt); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitInt() { + return std::make_unique( + binary::BinaryTypeEncodingType::Int); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitLong() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Long); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitUInt() { + return std::make_unique( + binary::BinaryTypeEncodingType::UInt); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitUlong() -{ - return std::make_unique(binary::BinaryTypeEncodingType::ULong); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitLong() { + return std::make_unique( + binary::BinaryTypeEncodingType::Long); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitLongLong() -{ - return std::make_unique(binary::BinaryTypeEncodingType::LongLong); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitUlong() { + return std::make_unique( + binary::BinaryTypeEncodingType::ULong); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitULongLong() -{ - return std::make_unique(binary::BinaryTypeEncodingType::ULongLong); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitLongLong() { + return std::make_unique( + binary::BinaryTypeEncodingType::LongLong); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitSignedChar() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Char); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitULongLong() { + return std::make_unique( + binary::BinaryTypeEncodingType::ULongLong); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitUnsignedChar() -{ - return std::make_unique(binary::BinaryTypeEncodingType::UChar); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitSignedChar() { + return std::make_unique( + binary::BinaryTypeEncodingType::Char); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitUnichar() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Unichar); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitUnsignedChar() { + return std::make_unique( + binary::BinaryTypeEncodingType::UChar); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitCString() -{ - return std::make_unique(binary::BinaryTypeEncodingType::CString); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitUnichar() { + return std::make_unique( + binary::BinaryTypeEncodingType::Unichar); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitFloat() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Float); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitCString() { + return std::make_unique( + binary::BinaryTypeEncodingType::CString); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitDouble() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Double); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitFloat() { + return std::make_unique( + binary::BinaryTypeEncodingType::Float); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitVaList() -{ - return std::make_unique(binary::BinaryTypeEncodingType::VaList); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitDouble() { + return std::make_unique( + binary::BinaryTypeEncodingType::Double); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitSelector() -{ - return std::make_unique(binary::BinaryTypeEncodingType::Selector); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitVaList() { + return std::make_unique( + binary::BinaryTypeEncodingType::VaList); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitInstancetype() -{ - return std::make_unique(binary::BinaryTypeEncodingType::InstanceType); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitSelector() { + return std::make_unique( + binary::BinaryTypeEncodingType::Selector); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitClass(const ::Meta::ClassType& type) -{ - return std::make_unique(binary::BinaryTypeEncodingType::Class); // TODO: Add protocols +unique_ptr +binary::BinaryTypeEncodingSerializer::visitInstancetype() { + return std::make_unique( + binary::BinaryTypeEncodingType::InstanceType); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitProtocol() -{ - return std::make_unique(binary::BinaryTypeEncodingType::ProtocolType); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitClass( + const ::Meta::ClassType& type) { + return std::make_unique( + binary::BinaryTypeEncodingType::Class); // TODO: Add protocols } -unique_ptr binary::BinaryTypeEncodingSerializer::visitId(const ::Meta::IdType& type) -{ - auto s = std::make_unique(); - std::vector offsets; - for (auto protocol : type.protocols) { - offsets.push_back(this->_heapWriter.push_string(protocol->name)); - } - s->_protocols = this->_heapWriter.push_binaryArray(offsets); - - return unique_ptr(s.release()); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitProtocol() { + return std::make_unique( + binary::BinaryTypeEncodingType::ProtocolType); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitConstantArray(const ::Meta::ConstantArrayType& type) -{ - binary::ConstantArrayEncoding* s = new binary::ConstantArrayEncoding(); - s->_size = type.size; - s->_elementType = type.innerType->visit(*this); - return unique_ptr(s); -} +unique_ptr binary::BinaryTypeEncodingSerializer::visitId( + const ::Meta::IdType& type) { + auto s = std::make_unique(); + std::vector offsets; + for (auto protocol : type.protocols) { + offsets.push_back(this->_heapWriter.push_string(protocol->name)); + } + s->_protocols = this->_heapWriter.push_binaryArray(offsets); -unique_ptr binary::BinaryTypeEncodingSerializer::visitIncompleteArray(const ::Meta::IncompleteArrayType& type) -{ - binary::IncompleteArrayEncoding* s = new binary::IncompleteArrayEncoding(); - s->_elementType = type.innerType->visit(*this); - return unique_ptr(s); + return unique_ptr(s.release()); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitInterface(const ::Meta::InterfaceType& type) -{ - auto* s = new binary::InterfaceDeclarationReferenceEncoding(); - s->_name = this->_heapWriter.push_string(type.interface->name); - - std::vector offsets; - for (auto protocol : type.protocols) { - offsets.push_back(this->_heapWriter.push_string(protocol->name)); - } - s->_protocols = this->_heapWriter.push_binaryArray(offsets); - - return unique_ptr(s); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitConstantArray( + const ::Meta::ConstantArrayType& type) { + binary::ConstantArrayEncoding* s = new binary::ConstantArrayEncoding(); + s->_size = type.size; + s->_elementType = type.innerType->visit(*this); + return unique_ptr(s); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitBridgedInterface(const ::Meta::BridgedInterfaceType& type) -{ - if (type.isId()) { - return this->visitId(::Meta::IdType()); - } - if (type.bridgedInterface == nullptr) { - throw logic_error(std::string("Unresolved bridged interface for BridgedInterfaceType with name '") + type.name + "'."); - } - auto s = new binary::InterfaceDeclarationReferenceEncoding(); - s->_name = this->_heapWriter.push_string(type.bridgedInterface->name); - - std::vector offsets; - s->_protocols = this->_heapWriter.push_binaryArray(offsets); - - return unique_ptr(s); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitIncompleteArray( + const ::Meta::IncompleteArrayType& type) { + binary::IncompleteArrayEncoding* s = new binary::IncompleteArrayEncoding(); + s->_elementType = type.innerType->visit(*this); + return unique_ptr(s); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitPointer(const ::Meta::PointerType& type) -{ - binary::PointerEncoding* s = new binary::PointerEncoding(); - s->_target = type.innerType->visit(*this); - return unique_ptr(s); -} +unique_ptr +binary::BinaryTypeEncodingSerializer::visitInterface( + const ::Meta::InterfaceType& type) { + auto* s = new binary::InterfaceDeclarationReferenceEncoding(); + s->_name = this->_heapWriter.push_string(type.interface->name); -unique_ptr binary::BinaryTypeEncodingSerializer::visitBlock(const ::Meta::BlockType& type) -{ - binary::BlockEncoding* s = new binary::BlockEncoding(); - s->_encodingsCount = (uint8_t)type.signature.size(); - for (::Meta::Type* signatureType : type.signature) { - s->_encodings.push_back(signatureType->visit(*this)); - } - return unique_ptr(s); -} + std::vector offsets; + for (auto protocol : type.protocols) { + offsets.push_back(this->_heapWriter.push_string(protocol->name)); + } + s->_protocols = this->_heapWriter.push_binaryArray(offsets); -unique_ptr binary::BinaryTypeEncodingSerializer::visitFunctionPointer(const ::Meta::FunctionPointerType& type) -{ - binary::FunctionEncoding* s = new binary::FunctionEncoding(); - s->_encodingsCount = (uint8_t)type.signature.size(); - for (::Meta::Type* signatureType : type.signature) { - s->_encodings.push_back(signatureType->visit(*this)); - } - return unique_ptr(s); + return unique_ptr(s); } -unique_ptr binary::BinaryTypeEncodingSerializer::visitStruct(const ::Meta::StructType& type) -{ - binary::DeclarationReferenceEncoding* s = new binary::DeclarationReferenceEncoding(BinaryTypeEncodingType::StructDeclarationReference); - s->_name = this->_heapWriter.push_string(type.structMeta->jsName); - return unique_ptr(s); -} - -unique_ptr binary::BinaryTypeEncodingSerializer::visitUnion(const ::Meta::UnionType& type) -{ - binary::DeclarationReferenceEncoding* s = new binary::DeclarationReferenceEncoding(BinaryTypeEncodingType::UnionDeclarationReference); - s->_name = this->_heapWriter.push_string(type.unionMeta->jsName); - return unique_ptr(s); -} - -unique_ptr binary::BinaryTypeEncodingSerializer::visitAnonymousStruct(const ::Meta::AnonymousStructType& type) -{ - return this->serializeRecordEncoding(binary::BinaryTypeEncodingType::AnonymousStruct, type.fields); -} - -unique_ptr binary::BinaryTypeEncodingSerializer::visitAnonymousUnion(const ::Meta::AnonymousUnionType& type) -{ - return this->serializeRecordEncoding(binary::BinaryTypeEncodingType::AnonymousUnion, type.fields); -} +unique_ptr +binary::BinaryTypeEncodingSerializer::visitBridgedInterface( + const ::Meta::BridgedInterfaceType& type) { + if (type.isId()) { + return this->visitId(::Meta::IdType()); + } + if (type.bridgedInterface == nullptr) { + throw logic_error(std::string("Unresolved bridged interface for " + "BridgedInterfaceType with name '") + + type.name + "'."); + } + auto s = new binary::InterfaceDeclarationReferenceEncoding(); + s->_name = this->_heapWriter.push_string(type.bridgedInterface->name); -unique_ptr binary::BinaryTypeEncodingSerializer::visitEnum(const ::Meta::EnumType& type) -{ - return type.underlyingType->visit(*this); -} + std::vector offsets; + s->_protocols = this->_heapWriter.push_binaryArray(offsets); -unique_ptr binary::BinaryTypeEncodingSerializer::visitTypeArgument(const ::Meta::TypeArgumentType& type) -{ - return type.underlyingType->visit(*this); + return unique_ptr(s); } -unique_ptr binary::BinaryTypeEncodingSerializer::serializeRecordEncoding(const binary::BinaryTypeEncodingType encodingType, const std::vector< ::Meta::RecordField>& fields) -{ - binary::AnonymousRecordEncoding* s = new binary::AnonymousRecordEncoding(encodingType); - s->_fieldsCount = (uint8_t)fields.size(); +unique_ptr +binary::BinaryTypeEncodingSerializer::visitPointer( + const ::Meta::PointerType& type) { + binary::PointerEncoding* s = new binary::PointerEncoding(); + s->_target = type.innerType->visit(*this); + return unique_ptr(s); +} - for (const ::Meta::RecordField& field : fields) { - s->_fieldNames.push_back(this->_heapWriter.push_string(field.name)); - } - - for (const ::Meta::RecordField& field : fields) { - s->_fieldEncodings.push_back(field.encoding->visit(*this)); - } - return unique_ptr(s); -} +unique_ptr +binary::BinaryTypeEncodingSerializer::visitBlock( + const ::Meta::BlockType& type) { + binary::BlockEncoding* s = new binary::BlockEncoding(); + s->_encodingsCount = (uint8_t)type.signature.size(); + for (::Meta::Type* signatureType : type.signature) { + s->_encodings.push_back(signatureType->visit(*this)); + } + return unique_ptr(s); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::visitFunctionPointer( + const ::Meta::FunctionPointerType& type) { + binary::FunctionEncoding* s = new binary::FunctionEncoding(); + s->_encodingsCount = (uint8_t)type.signature.size(); + for (::Meta::Type* signatureType : type.signature) { + s->_encodings.push_back(signatureType->visit(*this)); + } + return unique_ptr(s); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::visitStruct( + const ::Meta::StructType& type) { + binary::DeclarationReferenceEncoding* s = + new binary::DeclarationReferenceEncoding( + BinaryTypeEncodingType::StructDeclarationReference); + s->_name = this->_heapWriter.push_string(type.structMeta->jsName); + return unique_ptr(s); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::visitUnion( + const ::Meta::UnionType& type) { + binary::DeclarationReferenceEncoding* s = + new binary::DeclarationReferenceEncoding( + BinaryTypeEncodingType::UnionDeclarationReference); + s->_name = this->_heapWriter.push_string(type.unionMeta->jsName); + return unique_ptr(s); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::visitAnonymousStruct( + const ::Meta::AnonymousStructType& type) { + return this->serializeRecordEncoding( + binary::BinaryTypeEncodingType::AnonymousStruct, type.fields); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::visitAnonymousUnion( + const ::Meta::AnonymousUnionType& type) { + return this->serializeRecordEncoding( + binary::BinaryTypeEncodingType::AnonymousUnion, type.fields); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::visitEnum(const ::Meta::EnumType& type) { + return type.underlyingType->visit(*this); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::visitTypeArgument( + const ::Meta::TypeArgumentType& type) { + return type.underlyingType->visit(*this); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::visitNullable( + const ::Meta::NullableType& type) { + return type.innerType->visit(*this); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::serializeRecordEncoding( + const binary::BinaryTypeEncodingType encodingType, + const std::vector< ::Meta::RecordField>& fields) { + binary::AnonymousRecordEncoding* s = + new binary::AnonymousRecordEncoding(encodingType); + s->_fieldsCount = (uint8_t)fields.size(); + + for (const ::Meta::RecordField& field : fields) { + s->_fieldNames.push_back(this->_heapWriter.push_string(field.name)); + } -unique_ptr binary::BinaryTypeEncodingSerializer::visitExtVector(const ::Meta::ExtVectorType& type) -{ - binary::ExtVectorEncoding* s = new binary::ExtVectorEncoding(); - s->_size = type.size; - s->_elementType = type.innerType->visit(*this); - return unique_ptr(s); + for (const ::Meta::RecordField& field : fields) { + s->_fieldEncodings.push_back(field.encoding->visit(*this)); + } + return unique_ptr(s); +} + +unique_ptr +binary::BinaryTypeEncodingSerializer::visitExtVector( + const ::Meta::ExtVectorType& type) { + binary::ExtVectorEncoding* s = new binary::ExtVectorEncoding(); + s->_size = type.size; + s->_elementType = type.innerType->visit(*this); + return unique_ptr(s); } diff --git a/metadata-generator/src/Binary/binaryTypeEncodingSerializer.h b/metadata-generator/src/Binary/binaryTypeEncodingSerializer.h index afe002d1..9a53f307 100644 --- a/metadata-generator/src/Binary/binaryTypeEncodingSerializer.h +++ b/metadata-generator/src/Binary/binaryTypeEncodingSerializer.h @@ -1,101 +1,122 @@ #pragma once +#include + #include "Meta/TypeEntities.h" #include "binaryStructures.h" #include "binaryWriter.h" -#include using namespace std; namespace binary { /* - * \class BinaryTypeEncodingSerializer - * \brief Applies the Visitor pattern for serializing \c typeEncoding::TypeEncoding objects in binary format. - */ -class BinaryTypeEncodingSerializer : public ::Meta::TypeVisitor > { -private: - BinaryWriter _heapWriter; + * \class BinaryTypeEncodingSerializer + * \brief Applies the Visitor pattern for serializing \c + * typeEncoding::TypeEncoding objects in binary format. + */ +class BinaryTypeEncodingSerializer + : public ::Meta::TypeVisitor > { + private: + BinaryWriter _heapWriter; + + unique_ptr serializeRecordEncoding( + const binary::BinaryTypeEncodingType encodingType, + const std::vector< ::Meta::RecordField>& fields); + + public: + BinaryTypeEncodingSerializer(BinaryWriter& heapWriter) + : _heapWriter(heapWriter) {} - unique_ptr serializeRecordEncoding(const binary::BinaryTypeEncodingType encodingType, const std::vector< ::Meta::RecordField>& fields); + MetaFileOffset visit(std::vector< ::Meta::Type*>& types); -public: - BinaryTypeEncodingSerializer(BinaryWriter& heapWriter) - : _heapWriter(heapWriter) - { - } + virtual unique_ptr visitVoid() override; - MetaFileOffset visit(std::vector< ::Meta::Type*>& types); + virtual unique_ptr visitBool() override; - virtual unique_ptr visitVoid() override; + virtual unique_ptr visitShort() override; - virtual unique_ptr visitBool() override; + virtual unique_ptr visitUShort() override; - virtual unique_ptr visitShort() override; + virtual unique_ptr visitInt() override; - virtual unique_ptr visitUShort() override; + virtual unique_ptr visitUInt() override; - virtual unique_ptr visitInt() override; + virtual unique_ptr visitLong() override; - virtual unique_ptr visitUInt() override; + virtual unique_ptr visitUlong() override; - virtual unique_ptr visitLong() override; + virtual unique_ptr visitLongLong() override; - virtual unique_ptr visitUlong() override; + virtual unique_ptr visitULongLong() override; - virtual unique_ptr visitLongLong() override; + virtual unique_ptr visitSignedChar() override; - virtual unique_ptr visitULongLong() override; + virtual unique_ptr visitUnsignedChar() override; - virtual unique_ptr visitSignedChar() override; + virtual unique_ptr visitUnichar() override; - virtual unique_ptr visitUnsignedChar() override; + virtual unique_ptr visitCString() override; - virtual unique_ptr visitUnichar() override; + virtual unique_ptr visitFloat() override; - virtual unique_ptr visitCString() override; + virtual unique_ptr visitDouble() override; - virtual unique_ptr visitFloat() override; + virtual unique_ptr visitVaList() override; - virtual unique_ptr visitDouble() override; + virtual unique_ptr visitSelector() override; - virtual unique_ptr visitVaList() override; + virtual unique_ptr visitInstancetype() override; - virtual unique_ptr visitSelector() override; + virtual unique_ptr visitProtocol() override; - virtual unique_ptr visitInstancetype() override; + virtual unique_ptr visitClass( + const ::Meta::ClassType& type) override; - virtual unique_ptr visitProtocol() override; + virtual unique_ptr visitId(const ::Meta::IdType& type) override; - virtual unique_ptr visitClass(const ::Meta::ClassType& type) override; + virtual unique_ptr visitConstantArray( + const ::Meta::ConstantArrayType& type) override; - virtual unique_ptr visitId(const ::Meta::IdType& type) override; + virtual unique_ptr visitExtVector( + const ::Meta::ExtVectorType& type) override; - virtual unique_ptr visitConstantArray(const ::Meta::ConstantArrayType& type) override; - - virtual unique_ptr visitExtVector(const ::Meta::ExtVectorType& type) override; + virtual unique_ptr visitIncompleteArray( + const ::Meta::IncompleteArrayType& type) override; - virtual unique_ptr visitIncompleteArray(const ::Meta::IncompleteArrayType& type) override; + virtual unique_ptr visitInterface( + const ::Meta::InterfaceType& type) override; - virtual unique_ptr visitInterface(const ::Meta::InterfaceType& type) override; + virtual unique_ptr visitBridgedInterface( + const ::Meta::BridgedInterfaceType& type) override; - virtual unique_ptr visitBridgedInterface(const ::Meta::BridgedInterfaceType& type) override; + virtual unique_ptr visitPointer( + const ::Meta::PointerType& type) override; - virtual unique_ptr visitPointer(const ::Meta::PointerType& type) override; + virtual unique_ptr visitBlock( + const ::Meta::BlockType& type) override; - virtual unique_ptr visitBlock(const ::Meta::BlockType& type) override; + virtual unique_ptr visitFunctionPointer( + const ::Meta::FunctionPointerType& type) override; - virtual unique_ptr visitFunctionPointer(const ::Meta::FunctionPointerType& type) override; + virtual unique_ptr visitStruct( + const ::Meta::StructType& type) override; - virtual unique_ptr visitStruct(const ::Meta::StructType& type) override; + virtual unique_ptr visitUnion( + const ::Meta::UnionType& type) override; - virtual unique_ptr visitUnion(const ::Meta::UnionType& type) override; + virtual unique_ptr visitAnonymousStruct( + const ::Meta::AnonymousStructType& type) override; - virtual unique_ptr visitAnonymousStruct(const ::Meta::AnonymousStructType& type) override; + virtual unique_ptr visitAnonymousUnion( + const ::Meta::AnonymousUnionType& type) override; - virtual unique_ptr visitAnonymousUnion(const ::Meta::AnonymousUnionType& type) override; + virtual unique_ptr visitEnum( + const ::Meta::EnumType& type) override; - virtual unique_ptr visitEnum(const ::Meta::EnumType& type) override; + virtual unique_ptr visitTypeArgument( + const ::Meta::TypeArgumentType& type) override; - virtual unique_ptr visitTypeArgument(const ::Meta::TypeArgumentType& type) override; + virtual unique_ptr visitNullable( + const ::Meta::NullableType& type) override; }; -} +} // namespace binary diff --git a/metadata-generator/src/Meta/NameRetrieverVisitor.cpp b/metadata-generator/src/Meta/NameRetrieverVisitor.cpp index 5c70f742..a0257bc7 100644 --- a/metadata-generator/src/Meta/NameRetrieverVisitor.cpp +++ b/metadata-generator/src/Meta/NameRetrieverVisitor.cpp @@ -6,184 +6,206 @@ // #include "NameRetrieverVisitor.h" -#include "MetaEntities.h" #include +#include "MetaEntities.h" + NameRetrieverVisitor NameRetrieverVisitor::instanceObjC(false); NameRetrieverVisitor NameRetrieverVisitor::instanceTs(true); -std::string NameRetrieverVisitor::visitVoid() { - return "void"; -} - +std::string NameRetrieverVisitor::visitVoid() { return "void"; } + std::string NameRetrieverVisitor::visitBool() { - return this->tsNames ? "boolean" : "bool"; + return this->tsNames ? "boolean" : "bool"; } - + std::string NameRetrieverVisitor::visitShort() { - return this->tsNames ? "number" : "short"; + return this->tsNames ? "number" : "short"; } std::string NameRetrieverVisitor::visitUShort() { - return this->tsNames ? "number" : "unsigned short"; + return this->tsNames ? "number" : "unsigned short"; } - + std::string NameRetrieverVisitor::visitInt() { - return this->tsNames ? "number" : "int"; + return this->tsNames ? "number" : "int"; } - + std::string NameRetrieverVisitor::visitUInt() { - return this->tsNames ? "number" : "unsigned int"; + return this->tsNames ? "number" : "unsigned int"; } - + std::string NameRetrieverVisitor::visitLong() { - return this->tsNames ? "number" : "long"; + return this->tsNames ? "number" : "long"; } - + std::string NameRetrieverVisitor::visitUlong() { - return this->tsNames ? "number" : "unsigned long"; + return this->tsNames ? "number" : "unsigned long"; } - + std::string NameRetrieverVisitor::visitLongLong() { - return this->tsNames ? "number" : "long long"; + return this->tsNames ? "number" : "long long"; } - + std::string NameRetrieverVisitor::visitULongLong() { - return this->tsNames ? "number" : "unsigned long long"; + return this->tsNames ? "number" : "unsigned long long"; } - + std::string NameRetrieverVisitor::visitSignedChar() { - return this->tsNames ? "number" : "signed char"; + return this->tsNames ? "number" : "signed char"; } - + std::string NameRetrieverVisitor::visitUnsignedChar() { - return this->tsNames ? "number" : "unsigned char"; + return this->tsNames ? "number" : "unsigned char"; } - + std::string NameRetrieverVisitor::visitUnichar() { - return this->tsNames ? "number" : "wchar_t"; + return this->tsNames ? "number" : "wchar_t"; } - + std::string NameRetrieverVisitor::visitCString() { - return this->tsNames ? "string" : "char*"; + return this->tsNames ? "string" : "char*"; } - + std::string NameRetrieverVisitor::visitFloat() { - return this->tsNames ? "number" : "float"; + return this->tsNames ? "number" : "float"; } - + std::string NameRetrieverVisitor::visitDouble() { - return this->tsNames ? "number" : "double"; + return this->tsNames ? "number" : "double"; } - -std::string NameRetrieverVisitor::visitVaList() { - return ""; -} - + +std::string NameRetrieverVisitor::visitVaList() { return ""; } + std::string NameRetrieverVisitor::visitSelector() { - return this->tsNames ? "string" : "SEL"; + return this->tsNames ? "string" : "SEL"; } - + std::string NameRetrieverVisitor::visitInstancetype() { - return this->tsNames ? "any" : "instancetype"; + return this->tsNames ? "any" : "instancetype"; } - + std::string NameRetrieverVisitor::visitClass(const ClassType& typeDetails) { - return this->tsNames ? "any" : "Class"; + return this->tsNames ? "any" : "Class"; } - + std::string NameRetrieverVisitor::visitProtocol() { - return this->tsNames ? "any" : "Protocol"; + return this->tsNames ? "any" : "Protocol"; } - + std::string NameRetrieverVisitor::visitId(const IdType& typeDetails) { - return this->tsNames ? "any" : "id"; + return this->tsNames ? "any" : "id"; } - -std::string NameRetrieverVisitor::visitConstantArray(const ConstantArrayType& typeDetails) { - return this->generateFixedArray(typeDetails.innerType, typeDetails.size); + +std::string NameRetrieverVisitor::visitConstantArray( + const ConstantArrayType& typeDetails) { + return this->generateFixedArray(typeDetails.innerType, typeDetails.size); } - -std::string NameRetrieverVisitor::visitExtVector(const ExtVectorType& typeDetails) { - return this->generateFixedArray(typeDetails.innerType, typeDetails.size); + +std::string NameRetrieverVisitor::visitExtVector( + const ExtVectorType& typeDetails) { + return this->generateFixedArray(typeDetails.innerType, typeDetails.size); } -std::string NameRetrieverVisitor::visitIncompleteArray(const IncompleteArrayType& typeDetails) { - return typeDetails.innerType->visit(*this).append("[]"); +std::string NameRetrieverVisitor::visitIncompleteArray( + const IncompleteArrayType& typeDetails) { + return typeDetails.innerType->visit(*this).append("[]"); } - -std::string NameRetrieverVisitor::visitInterface(const InterfaceType& typeDetails) { - return this->tsNames ? typeDetails.interface->jsName : typeDetails.interface->name; + +std::string NameRetrieverVisitor::visitInterface( + const InterfaceType& typeDetails) { + return this->tsNames ? typeDetails.interface->jsName + : typeDetails.interface->name; } - -std::string NameRetrieverVisitor::visitBridgedInterface(const BridgedInterfaceType& typeDetails) { - return typeDetails.name; + +std::string NameRetrieverVisitor::visitBridgedInterface( + const BridgedInterfaceType& typeDetails) { + return typeDetails.name; } - + std::string NameRetrieverVisitor::visitPointer(const PointerType& typeDetails) { - return this->tsNames ? "any" : typeDetails.innerType->visit(*this).append("*"); + return this->tsNames ? "any" + : typeDetails.innerType->visit(*this).append("*"); } - + std::string NameRetrieverVisitor::visitBlock(const BlockType& typeDetails) { - return this->tsNames ? this->getFunctionTypeScriptName(typeDetails.signature) : "void*" /*TODO: construct objective-c full block definition*/; + return this->tsNames + ? this->getFunctionTypeScriptName(typeDetails.signature) + : "void*" /*TODO: construct objective-c full block definition*/; } -std::string NameRetrieverVisitor::visitFunctionPointer(const FunctionPointerType& typeDetails) { - return this->tsNames ? this->getFunctionTypeScriptName(typeDetails.signature) : "void*"/*TODO: construct objective-c full function pointer definition*/; +std::string NameRetrieverVisitor::visitFunctionPointer( + const FunctionPointerType& typeDetails) { + return this->tsNames ? this->getFunctionTypeScriptName(typeDetails.signature) + : "void*" /*TODO: construct objective-c full function + pointer definition*/ + ; } std::string NameRetrieverVisitor::visitStruct(const StructType& typeDetails) { - return this->tsNames ? typeDetails.structMeta->jsName : typeDetails.structMeta->name; + return this->tsNames ? typeDetails.structMeta->jsName + : typeDetails.structMeta->name; } - + std::string NameRetrieverVisitor::visitUnion(const UnionType& typeDetails) { - return this->tsNames ? typeDetails.unionMeta->jsName : typeDetails.unionMeta->name; + return this->tsNames ? typeDetails.unionMeta->jsName + : typeDetails.unionMeta->name; } - -std::string NameRetrieverVisitor::visitAnonymousStruct(const AnonymousStructType& typeDetails) { - return ""; + +std::string NameRetrieverVisitor::visitAnonymousStruct( + const AnonymousStructType& typeDetails) { + return ""; } - -std::string NameRetrieverVisitor::visitAnonymousUnion(const AnonymousUnionType& typeDetails) { - return ""; + +std::string NameRetrieverVisitor::visitAnonymousUnion( + const AnonymousUnionType& typeDetails) { + return ""; } - + std::string NameRetrieverVisitor::visitEnum(const EnumType& typeDetails) { - return this->tsNames ? typeDetails.enumMeta->jsName : typeDetails.enumMeta->name; + return this->tsNames ? typeDetails.enumMeta->jsName + : typeDetails.enumMeta->name; } - -std::string NameRetrieverVisitor::visitTypeArgument(const ::Meta::TypeArgumentType& type) { - return type.name; + +std::string NameRetrieverVisitor::visitTypeArgument( + const ::Meta::TypeArgumentType& type) { + return type.name; } -std::string NameRetrieverVisitor::generateFixedArray(const Type *el_type, size_t size) { - std::stringstream ss(el_type->visit(*this)); - ss << "["; - if (!this->tsNames) { - ss << size; - } - ss << "]"; - - return ss.str(); -} - -std::string NameRetrieverVisitor::getFunctionTypeScriptName(const std::vector &signature) { - // (p1: t1,...) => ret_type - assert(signature.size() > 0); - - std::stringstream ss; - ss << "("; - for (size_t i = 1; i < signature.size(); i++) { - if (i > 1) { - ss << ", "; - } - ss << "p" << i << ": " << signature[i]->visit(*this); - } - ss << ")"; - ss << " => "; - ss << signature[0]->visit(*this); - - return ss.str(); +std::string NameRetrieverVisitor::visitNullable( + const ::Meta::NullableType& type) { + return type.innerType->visit(*this); } +std::string NameRetrieverVisitor::generateFixedArray(const Type* el_type, + size_t size) { + std::stringstream ss(el_type->visit(*this)); + ss << "["; + if (!this->tsNames) { + ss << size; + } + ss << "]"; + + return ss.str(); +} + +std::string NameRetrieverVisitor::getFunctionTypeScriptName( + const std::vector& signature) { + // (p1: t1,...) => ret_type + assert(signature.size() > 0); + + std::stringstream ss; + ss << "("; + for (size_t i = 1; i < signature.size(); i++) { + if (i > 1) { + ss << ", "; + } + ss << "p" << i << ": " << signature[i]->visit(*this); + } + ss << ")"; + ss << " => "; + ss << signature[0]->visit(*this); + + return ss.str(); +} diff --git a/metadata-generator/src/Meta/NameRetrieverVisitor.h b/metadata-generator/src/Meta/NameRetrieverVisitor.h index f0a0df32..820427ee 100644 --- a/metadata-generator/src/Meta/NameRetrieverVisitor.h +++ b/metadata-generator/src/Meta/NameRetrieverVisitor.h @@ -8,98 +8,105 @@ #ifndef NameRetrieverVisitor_h #define NameRetrieverVisitor_h +#include + #include "TypeEntities.h" #include "TypeVisitor.h" -#include using namespace Meta; class NameRetrieverVisitor : public ::Meta::TypeVisitor { - -public: - static NameRetrieverVisitor instanceObjC; - static NameRetrieverVisitor instanceTs; - - virtual std::string visitVoid(); - - virtual std::string visitBool(); - - virtual std::string visitShort(); - - virtual std::string visitUShort(); - - virtual std::string visitInt(); - - virtual std::string visitUInt(); - - virtual std::string visitLong(); - - virtual std::string visitUlong(); - - virtual std::string visitLongLong(); - - virtual std::string visitULongLong(); - - virtual std::string visitSignedChar(); - - virtual std::string visitUnsignedChar(); - - virtual std::string visitUnichar(); - - virtual std::string visitCString(); - - virtual std::string visitFloat(); - - virtual std::string visitDouble(); - - virtual std::string visitVaList(); - - virtual std::string visitSelector(); - - virtual std::string visitInstancetype(); - - virtual std::string visitClass(const ClassType& typeDetails); - - virtual std::string visitProtocol(); - - virtual std::string visitId(const IdType& typeDetails); - - virtual std::string visitConstantArray(const ConstantArrayType& typeDetails); - - virtual std::string visitExtVector(const ExtVectorType& typeDetails); - - virtual std::string visitIncompleteArray(const IncompleteArrayType& typeDetails); - - virtual std::string visitInterface(const InterfaceType& typeDetails); - - virtual std::string visitBridgedInterface(const BridgedInterfaceType& typeDetails); - - virtual std::string visitPointer(const PointerType& typeDetails); - - virtual std::string visitBlock(const BlockType& typeDetails); - - virtual std::string visitFunctionPointer(const FunctionPointerType& typeDetails); - - virtual std::string visitStruct(const StructType& typeDetails); - - virtual std::string visitUnion(const UnionType& typeDetails); - - virtual std::string visitAnonymousStruct(const AnonymousStructType& typeDetails); - - virtual std::string visitAnonymousUnion(const AnonymousUnionType& typeDetails); - - virtual std::string visitEnum(const EnumType& typeDetails); - - virtual std::string visitTypeArgument(const ::Meta::TypeArgumentType& type); - -private: - NameRetrieverVisitor(bool tsNames): tsNames(tsNames) { } - - std::string getFunctionTypeScriptName(const std::vector &signature); - std::string generateFixedArray(const Type *el_type, size_t size); - -private: - bool tsNames; + public: + static NameRetrieverVisitor instanceObjC; + static NameRetrieverVisitor instanceTs; + + virtual std::string visitVoid(); + + virtual std::string visitBool(); + + virtual std::string visitShort(); + + virtual std::string visitUShort(); + + virtual std::string visitInt(); + + virtual std::string visitUInt(); + + virtual std::string visitLong(); + + virtual std::string visitUlong(); + + virtual std::string visitLongLong(); + + virtual std::string visitULongLong(); + + virtual std::string visitSignedChar(); + + virtual std::string visitUnsignedChar(); + + virtual std::string visitUnichar(); + + virtual std::string visitCString(); + + virtual std::string visitFloat(); + + virtual std::string visitDouble(); + + virtual std::string visitVaList(); + + virtual std::string visitSelector(); + + virtual std::string visitInstancetype(); + + virtual std::string visitClass(const ClassType& typeDetails); + + virtual std::string visitProtocol(); + + virtual std::string visitId(const IdType& typeDetails); + + virtual std::string visitConstantArray(const ConstantArrayType& typeDetails); + + virtual std::string visitExtVector(const ExtVectorType& typeDetails); + + virtual std::string visitIncompleteArray( + const IncompleteArrayType& typeDetails); + + virtual std::string visitInterface(const InterfaceType& typeDetails); + + virtual std::string visitBridgedInterface( + const BridgedInterfaceType& typeDetails); + + virtual std::string visitPointer(const PointerType& typeDetails); + + virtual std::string visitBlock(const BlockType& typeDetails); + + virtual std::string visitFunctionPointer( + const FunctionPointerType& typeDetails); + + virtual std::string visitStruct(const StructType& typeDetails); + + virtual std::string visitUnion(const UnionType& typeDetails); + + virtual std::string visitAnonymousStruct( + const AnonymousStructType& typeDetails); + + virtual std::string visitAnonymousUnion( + const AnonymousUnionType& typeDetails); + + virtual std::string visitEnum(const EnumType& typeDetails); + + virtual std::string visitTypeArgument(const ::Meta::TypeArgumentType& type); + + virtual std::string visitNullable(const ::Meta::NullableType& type); + + private: + NameRetrieverVisitor(bool tsNames) : tsNames(tsNames) {} + + std::string getFunctionTypeScriptName(const std::vector& signature); + std::string generateFixedArray(const Type* el_type, size_t size); + + private: + bool tsNames; }; #endif /* NameRetrieverVisitor_h */ diff --git a/metadata-generator/src/Meta/TypeEntities.h b/metadata-generator/src/Meta/TypeEntities.h index dfcc97a1..2a345012 100644 --- a/metadata-generator/src/Meta/TypeEntities.h +++ b/metadata-generator/src/Meta/TypeEntities.h @@ -1,10 +1,11 @@ #pragma once -#include "TypeVisitor.h" -#include "Utils/Noncopyable.h" #include #include +#include "TypeVisitor.h" +#include "Utils/Noncopyable.h" + namespace Meta { class ProtocolMeta; class InterfaceMeta; @@ -13,369 +14,314 @@ class UnionMeta; class EnumMeta; enum TypeType { - TypeVoid, - TypeBool, - TypeShort, - TypeUShort, - TypeInt, - TypeUInt, - TypeLong, - TypeULong, - TypeLongLong, - TypeULongLong, - TypeSignedChar, - TypeUnsignedChar, - TypeUnichar, - TypeCString, - TypeFloat, - TypeDouble, - TypeVaList, - TypeSelector, - TypeInstancetype, - TypeProtocol, - TypeClass, - TypeId, - TypeConstantArray, - TypeIncompleteArray, - TypePointer, - TypeBlock, - TypeFunctionPointer, - TypeInterface, - TypeBridgedInterface, - TypeStruct, - TypeUnion, - TypeAnonymousStruct, - TypeAnonymousUnion, - TypeEnum, - TypeTypeArgument, - TypeExtVector + TypeVoid, + TypeBool, + TypeShort, + TypeUShort, + TypeInt, + TypeUInt, + TypeLong, + TypeULong, + TypeLongLong, + TypeULongLong, + TypeSignedChar, + TypeUnsignedChar, + TypeUnichar, + TypeCString, + TypeFloat, + TypeDouble, + TypeVaList, + TypeSelector, + TypeInstancetype, + TypeProtocol, + TypeClass, + TypeId, + TypeConstantArray, + TypeIncompleteArray, + TypePointer, + TypeBlock, + TypeFunctionPointer, + TypeInterface, + TypeBridgedInterface, + TypeStruct, + TypeUnion, + TypeAnonymousStruct, + TypeAnonymousUnion, + TypeEnum, + TypeTypeArgument, + TypeExtVector, + TypeNullable }; class Type { - MAKE_NONCOPYABLE(Type); - -public: - Type(TypeType type) - : type(type) - { + MAKE_NONCOPYABLE(Type); + + public: + Type(TypeType type) : type(type) {} + + TypeType getType() const { return type; } + + template + const T& as() const { + return *static_cast(this); + } + + template + T& as() { + return *static_cast(this); + } + + bool is(TypeType type) const { return this->type == type; } + + template + T visit(TypeVisitor& visitor) const { + switch (this->type) { + case TypeVoid: + return visitor.visitVoid(); + case TypeBool: + return visitor.visitBool(); + case TypeShort: + return visitor.visitShort(); + case TypeUShort: + return visitor.visitUShort(); + case TypeInt: + return visitor.visitInt(); + case TypeUInt: + return visitor.visitUInt(); + case TypeLong: + return visitor.visitLong(); + case TypeULong: + return visitor.visitUlong(); + case TypeLongLong: + return visitor.visitLongLong(); + case TypeULongLong: + return visitor.visitULongLong(); + case TypeSignedChar: + return visitor.visitSignedChar(); + case TypeUnsignedChar: + return visitor.visitUnsignedChar(); + case TypeUnichar: + return visitor.visitUnichar(); + case TypeCString: + return visitor.visitCString(); + case TypeFloat: + return visitor.visitFloat(); + case TypeDouble: + return visitor.visitDouble(); + case TypeVaList: + return visitor.visitVaList(); + case TypeSelector: + return visitor.visitSelector(); + case TypeInstancetype: + return visitor.visitInstancetype(); + case TypeProtocol: + return visitor.visitProtocol(); + case TypeClass: + return visitor.visitClass(as()); + case TypeId: + return visitor.visitId(as()); + case TypeConstantArray: + return visitor.visitConstantArray(as()); + case TypeIncompleteArray: + return visitor.visitIncompleteArray(as()); + case TypePointer: + return visitor.visitPointer(as()); + case TypeBlock: + return visitor.visitBlock(as()); + case TypeFunctionPointer: + return visitor.visitFunctionPointer(as()); + case TypeInterface: + return visitor.visitInterface(as()); + case TypeBridgedInterface: + return visitor.visitBridgedInterface(as()); + case TypeStruct: + return visitor.visitStruct(as()); + case TypeUnion: + return visitor.visitUnion(as()); + case TypeAnonymousStruct: + return visitor.visitAnonymousStruct(as()); + case TypeAnonymousUnion: + return visitor.visitAnonymousUnion(as()); + case TypeEnum: + return visitor.visitEnum(as()); + case TypeTypeArgument: + return visitor.visitTypeArgument(as()); + case TypeExtVector: + return visitor.visitExtVector(as()); + case TypeNullable: + return visitor.visitNullable(as()); } + } - TypeType getType() const - { - return type; - } - - template - const T& as() const - { - return *static_cast(this); - } - - template - T& as() - { - return *static_cast(this); - } - - bool is(TypeType type) const - { - return this->type == type; - } - - template - T visit(TypeVisitor& visitor) const - { - switch (this->type) { - case TypeVoid: - return visitor.visitVoid(); - case TypeBool: - return visitor.visitBool(); - case TypeShort: - return visitor.visitShort(); - case TypeUShort: - return visitor.visitUShort(); - case TypeInt: - return visitor.visitInt(); - case TypeUInt: - return visitor.visitUInt(); - case TypeLong: - return visitor.visitLong(); - case TypeULong: - return visitor.visitUlong(); - case TypeLongLong: - return visitor.visitLongLong(); - case TypeULongLong: - return visitor.visitULongLong(); - case TypeSignedChar: - return visitor.visitSignedChar(); - case TypeUnsignedChar: - return visitor.visitUnsignedChar(); - case TypeUnichar: - return visitor.visitUnichar(); - case TypeCString: - return visitor.visitCString(); - case TypeFloat: - return visitor.visitFloat(); - case TypeDouble: - return visitor.visitDouble(); - case TypeVaList: - return visitor.visitVaList(); - case TypeSelector: - return visitor.visitSelector(); - case TypeInstancetype: - return visitor.visitInstancetype(); - case TypeProtocol: - return visitor.visitProtocol(); - case TypeClass: - return visitor.visitClass(as()); - case TypeId: - return visitor.visitId(as()); - case TypeConstantArray: - return visitor.visitConstantArray(as()); - case TypeIncompleteArray: - return visitor.visitIncompleteArray(as()); - case TypePointer: - return visitor.visitPointer(as()); - case TypeBlock: - return visitor.visitBlock(as()); - case TypeFunctionPointer: - return visitor.visitFunctionPointer(as()); - case TypeInterface: - return visitor.visitInterface(as()); - case TypeBridgedInterface: - return visitor.visitBridgedInterface(as()); - case TypeStruct: - return visitor.visitStruct(as()); - case TypeUnion: - return visitor.visitUnion(as()); - case TypeAnonymousStruct: - return visitor.visitAnonymousStruct(as()); - case TypeAnonymousUnion: - return visitor.visitAnonymousUnion(as()); - case TypeEnum: - return visitor.visitEnum(as()); - case TypeTypeArgument: - return visitor.visitTypeArgument(as()); - case TypeExtVector: - return visitor.visitExtVector(as()); - - } - } - -protected: - TypeType type; + protected: + TypeType type; }; struct RecordField { - RecordField() - : RecordField("", nullptr) - { - } + RecordField() : RecordField("", nullptr) {} - RecordField(std::string name, Type* encoding) - : name(name) - , encoding(encoding) - { - } + RecordField(std::string name, Type* encoding) + : name(name), encoding(encoding) {} - std::string name; - Type* encoding; + std::string name; + Type* encoding; }; class IdType : public Type { -public: - IdType(std::vector protocols = {}) - : Type(TypeType::TypeId) - , protocols(protocols) - { - } + public: + IdType(std::vector protocols = {}) + : Type(TypeType::TypeId), protocols(protocols) {} - std::vector protocols; + std::vector protocols; }; class ClassType : public Type { -public: - ClassType(std::vector protocols = {}) - : Type(TypeType::TypeClass) - , protocols(protocols) - { - } + public: + ClassType(std::vector protocols = {}) + : Type(TypeType::TypeClass), protocols(protocols) {} - std::vector protocols; + std::vector protocols; }; class TypeArgumentType : public Type { -public: - TypeArgumentType(Type* underlyingType, const std::string& name, std::vector protocols = {}) - : Type(TypeType::TypeTypeArgument) - , underlyingType(underlyingType) - , name(name) - , protocols(protocols) - { - } - - Type* underlyingType; - std::string name; - std::vector protocols; + public: + TypeArgumentType(Type* underlyingType, const std::string& name, + std::vector protocols = {}) + : Type(TypeType::TypeTypeArgument), + underlyingType(underlyingType), + name(name), + protocols(protocols) {} + + Type* underlyingType; + std::string name; + std::vector protocols; }; class InterfaceType : public Type { -public: - InterfaceType(InterfaceMeta* interface, std::vector protocols, std::vector typeArguments) - : Type(TypeType::TypeInterface) - , interface(interface) - , protocols(protocols) - , typeArguments(typeArguments) - { - } - - InterfaceMeta* interface; - std::vector protocols; - std::vector typeArguments; + public: + InterfaceType(InterfaceMeta* interface, std::vector protocols, + std::vector typeArguments) + : Type(TypeType::TypeInterface), + interface(interface), + protocols(protocols), + typeArguments(typeArguments) {} + + InterfaceMeta* interface; + std::vector protocols; + std::vector typeArguments; }; class BridgedInterfaceType : public Type { -public: - BridgedInterfaceType(std::string name, InterfaceMeta* bridgedInterface) - : Type(TypeType::TypeBridgedInterface) - , name(name) - , bridgedInterface(bridgedInterface) - { - } + public: + BridgedInterfaceType(std::string name, InterfaceMeta* bridgedInterface) + : Type(TypeType::TypeBridgedInterface), + name(name), + bridgedInterface(bridgedInterface) {} - bool isId() const - { - return name == "id"; - } + bool isId() const { return name == "id"; } - std::string name; - InterfaceMeta* bridgedInterface; + std::string name; + InterfaceMeta* bridgedInterface; }; class IncompleteArrayType : public Type { -public: - IncompleteArrayType(Type* innerType) - : Type(TypeType::TypeIncompleteArray) - , innerType(innerType) - { - } + public: + IncompleteArrayType(Type* innerType) + : Type(TypeType::TypeIncompleteArray), innerType(innerType) {} - Type* innerType; + Type* innerType; }; class ConstantArrayType : public Type { -public: - ConstantArrayType(Type* innerType, int size) - : Type(TypeType::TypeConstantArray) - , innerType(innerType) - , size(size) - { - } + public: + ConstantArrayType(Type* innerType, int size) + : Type(TypeType::TypeConstantArray), innerType(innerType), size(size) {} - Type* innerType; - int size; + Type* innerType; + int size; }; - + class ExtVectorType : public Type { -public: - ExtVectorType(Type* innerType, int size) - : Type(TypeType::TypeExtVector) - , innerType(innerType) - , size(size) - { - } - - Type* innerType; - int size; + public: + ExtVectorType(Type* innerType, int size) + : Type(TypeType::TypeExtVector), innerType(innerType), size(size) {} + + Type* innerType; + int size; }; class PointerType : public Type { -public: - PointerType(Type* innerType) - : Type(TypeType::TypePointer) - , innerType(innerType) - { - } + public: + PointerType(Type* innerType) + : Type(TypeType::TypePointer), innerType(innerType) {} - Type* innerType; + Type* innerType; }; class BlockType : public Type { -public: - BlockType(std::vector signature) - : Type(TypeType::TypeBlock) - , signature(signature) - { - } + public: + BlockType(std::vector signature) + : Type(TypeType::TypeBlock), signature(signature) {} - std::vector signature; + std::vector signature; }; class FunctionPointerType : public Type { -public: - FunctionPointerType(std::vector signature) - : Type(TypeType::TypeFunctionPointer) - , signature(signature) - { - } + public: + FunctionPointerType(std::vector signature) + : Type(TypeType::TypeFunctionPointer), signature(signature) {} - std::vector signature; + std::vector signature; }; class StructType : public Type { -public: - StructType(StructMeta* structMeta) - : Type(TypeType::TypeStruct) - , structMeta(structMeta) - { - } + public: + StructType(StructMeta* structMeta) + : Type(TypeType::TypeStruct), structMeta(structMeta) {} - StructMeta* structMeta; + StructMeta* structMeta; }; class UnionType : public Type { -public: - UnionType(UnionMeta* unionMeta) - : Type(TypeType::TypeUnion) - , unionMeta(unionMeta) - { - } + public: + UnionType(UnionMeta* unionMeta) + : Type(TypeType::TypeUnion), unionMeta(unionMeta) {} - UnionMeta* unionMeta; + UnionMeta* unionMeta; }; class AnonymousStructType : public Type { -public: - AnonymousStructType(std::vector fields) - : Type(TypeType::TypeAnonymousStruct) - , fields(fields) - { - } + public: + AnonymousStructType(std::vector fields) + : Type(TypeType::TypeAnonymousStruct), fields(fields) {} - std::vector fields; + std::vector fields; }; class AnonymousUnionType : public Type { -public: - AnonymousUnionType(std::vector fields) - : Type(TypeType::TypeAnonymousUnion) - , fields(fields) - { - } + public: + AnonymousUnionType(std::vector fields) + : Type(TypeType::TypeAnonymousUnion), fields(fields) {} - std::vector fields; + std::vector fields; }; class EnumType : public Type { -public: - EnumType(Type* underlyingType, EnumMeta* enumMeta) - : Type(TypeType::TypeEnum) - , underlyingType(underlyingType) - , enumMeta(enumMeta) - { - } + public: + EnumType(Type* underlyingType, EnumMeta* enumMeta) + : Type(TypeType::TypeEnum), + underlyingType(underlyingType), + enumMeta(enumMeta) {} + + Type* underlyingType; + EnumMeta* enumMeta; +}; + +class NullableType : public Type { + public: + NullableType(Type* innerType) + : Type(TypeType::TypeNullable), innerType(innerType) {} - Type* underlyingType; - EnumMeta* enumMeta; + Type* innerType; }; -} +} // namespace Meta diff --git a/metadata-generator/src/Meta/TypeFactory.cpp b/metadata-generator/src/Meta/TypeFactory.cpp index fb45d5e1..48aba440 100644 --- a/metadata-generator/src/Meta/TypeFactory.cpp +++ b/metadata-generator/src/Meta/TypeFactory.cpp @@ -1,8 +1,10 @@ #include "TypeFactory.h" + +#include + #include "CreationException.h" #include "MetaFactory.h" #include "Utils.h" -#include namespace Meta { using namespace std; @@ -15,537 +17,577 @@ static const std::vector KNOWN_BRIDGED_TYPES = { #undef NON_CF_TYPE }; -shared_ptr TypeFactory::getVoid() -{ - static shared_ptr type(new Type(TypeType::TypeVoid)); - return type; +shared_ptr TypeFactory::getVoid() { + static shared_ptr type(new Type(TypeType::TypeVoid)); + return type; } -shared_ptr TypeFactory::getBool() -{ - static shared_ptr type(new Type(TypeType::TypeBool)); - return type; +shared_ptr TypeFactory::getBool() { + static shared_ptr type(new Type(TypeType::TypeBool)); + return type; } -shared_ptr TypeFactory::getShort() -{ - static shared_ptr type(new Type(TypeType::TypeShort)); - return type; +shared_ptr TypeFactory::getShort() { + static shared_ptr type(new Type(TypeType::TypeShort)); + return type; } -shared_ptr TypeFactory::getUShort() -{ - static shared_ptr type(new Type(TypeType::TypeUShort)); - return type; +shared_ptr TypeFactory::getUShort() { + static shared_ptr type(new Type(TypeType::TypeUShort)); + return type; } -shared_ptr TypeFactory::getInt() -{ - static shared_ptr type(new Type(TypeType::TypeInt)); - return type; +shared_ptr TypeFactory::getInt() { + static shared_ptr type(new Type(TypeType::TypeInt)); + return type; } -shared_ptr TypeFactory::getUInt() -{ - static shared_ptr type(new Type(TypeType::TypeUInt)); - return type; +shared_ptr TypeFactory::getUInt() { + static shared_ptr type(new Type(TypeType::TypeUInt)); + return type; } -shared_ptr TypeFactory::getLong() -{ - static shared_ptr type(new Type(TypeType::TypeLong)); - return type; +shared_ptr TypeFactory::getLong() { + static shared_ptr type(new Type(TypeType::TypeLong)); + return type; } -shared_ptr TypeFactory::getULong() -{ - static shared_ptr type(new Type(TypeType::TypeULong)); - return type; +shared_ptr TypeFactory::getULong() { + static shared_ptr type(new Type(TypeType::TypeULong)); + return type; } -shared_ptr TypeFactory::getLongLong() -{ - static shared_ptr type(new Type(TypeType::TypeLongLong)); - return type; +shared_ptr TypeFactory::getLongLong() { + static shared_ptr type(new Type(TypeType::TypeLongLong)); + return type; } -shared_ptr TypeFactory::getULongLong() -{ - static shared_ptr type(new Type(TypeType::TypeULongLong)); - return type; +shared_ptr TypeFactory::getULongLong() { + static shared_ptr type(new Type(TypeType::TypeULongLong)); + return type; } -shared_ptr TypeFactory::getSignedChar() -{ - static shared_ptr type(new Type(TypeType::TypeSignedChar)); - return type; +shared_ptr TypeFactory::getSignedChar() { + static shared_ptr type(new Type(TypeType::TypeSignedChar)); + return type; } -shared_ptr TypeFactory::getUnsignedChar() -{ - static shared_ptr type(new Type(TypeType::TypeUnsignedChar)); - return type; +shared_ptr TypeFactory::getUnsignedChar() { + static shared_ptr type(new Type(TypeType::TypeUnsignedChar)); + return type; } -shared_ptr TypeFactory::getUnichar() -{ - static shared_ptr type(new Type(TypeType::TypeUnichar)); - return type; +shared_ptr TypeFactory::getUnichar() { + static shared_ptr type(new Type(TypeType::TypeUnichar)); + return type; } -shared_ptr TypeFactory::getCString() -{ - static shared_ptr type(new Type(TypeType::TypeCString)); - return type; +shared_ptr TypeFactory::getCString() { + static shared_ptr type(new Type(TypeType::TypeCString)); + return type; } -shared_ptr TypeFactory::getFloat() -{ - static shared_ptr type(new Type(TypeType::TypeFloat)); - return type; +shared_ptr TypeFactory::getFloat() { + static shared_ptr type(new Type(TypeType::TypeFloat)); + return type; } -shared_ptr TypeFactory::getDouble() -{ - static shared_ptr type(new Type(TypeType::TypeDouble)); - return type; +shared_ptr TypeFactory::getDouble() { + static shared_ptr type(new Type(TypeType::TypeDouble)); + return type; } -shared_ptr TypeFactory::getVaList() -{ - static shared_ptr type(new Type(TypeType::TypeVaList)); - return type; +shared_ptr TypeFactory::getVaList() { + static shared_ptr type(new Type(TypeType::TypeVaList)); + return type; } -shared_ptr TypeFactory::getSelector() -{ - static shared_ptr type(new Type(TypeType::TypeSelector)); - return type; +shared_ptr TypeFactory::getSelector() { + static shared_ptr type(new Type(TypeType::TypeSelector)); + return type; } -shared_ptr TypeFactory::getInstancetype() -{ - static shared_ptr type(new Type(TypeType::TypeInstancetype)); - return type; +shared_ptr TypeFactory::getInstancetype() { + static shared_ptr type(new Type(TypeType::TypeInstancetype)); + return type; } -shared_ptr TypeFactory::getProtocolType() -{ - static shared_ptr type(new Type(TypeType::TypeProtocol)); - return type; +shared_ptr TypeFactory::getProtocolType() { + static shared_ptr type(new Type(TypeType::TypeProtocol)); + return type; } -shared_ptr TypeFactory::create(const clang::Type* type) -{ - const clang::Type& typeRef = *type; - shared_ptr resultType(nullptr); +shared_ptr TypeFactory::create(const clang::Type* type) { + const clang::Type& typeRef = *type; + shared_ptr resultType(nullptr); - try { - // check for cached Type - Cache::const_iterator cachedTypeIt = _cache.find(type); - if (cachedTypeIt != _cache.end()) { - shared_ptr resultType = cachedTypeIt->second.first; - if (auto creationException = cachedTypeIt->second.second.get()) { - POLYMORPHIC_THROW(creationException); - } - - // revalidate in case the Type's metadata creation has failed after it was returned - // (e.g. from a forward declaration) - this->_metaFactory->validate(resultType.get()); - - return resultType; - } + try { + // check for cached Type + Cache::const_iterator cachedTypeIt = _cache.find(type); + if (cachedTypeIt != _cache.end()) { + shared_ptr resultType = cachedTypeIt->second.first; + if (auto creationException = cachedTypeIt->second.second.get()) { + POLYMORPHIC_THROW(creationException); + } - if (const clang::BuiltinType* concreteType = clang::dyn_cast(type)) - resultType = createFromBuiltinType(concreteType); - else if (const clang::TypedefType* concreteType = clang::dyn_cast(type)) - resultType = createFromTypedefType(concreteType); - else if (const clang::ObjCObjectPointerType* concreteType = clang::dyn_cast(type)) - resultType = createFromObjCObjectPointerType(concreteType); - else if (const clang::EnumType* concreteType = clang::dyn_cast(type)) - resultType = createFromEnumType(concreteType); - else if (const clang::PointerType* concreteType = clang::dyn_cast(type)) - resultType = createFromPointerType(concreteType); - else if (const clang::BlockPointerType* concreteType = clang::dyn_cast(type)) - resultType = createFromBlockPointerType(concreteType); - else if (const clang::RecordType* concreteType = clang::dyn_cast(type)) - resultType = createFromRecordType(concreteType); - else if (const clang::ExtVectorType* concreteType = clang::dyn_cast(type)) - resultType = createFromExtVectorType(concreteType); - else if (const clang::VectorType* concreteType = clang::dyn_cast(type)) - resultType = createFromVectorType(concreteType); - else if (const clang::ConstantArrayType* concreteType = clang::dyn_cast(type)) - resultType = createFromConstantArrayType(concreteType); - else if (const clang::IncompleteArrayType* concreteType = clang::dyn_cast(type)) - resultType = createFromIncompleteArrayType(concreteType); - else if (const clang::ElaboratedType* concreteType = clang::dyn_cast(type)) - resultType = createFromElaboratedType(concreteType); - else if (const clang::AdjustedType* concreteType = clang::dyn_cast(type)) - resultType = createFromAdjustedType(concreteType); - else if (const clang::FunctionProtoType* concreteType = clang::dyn_cast(type)) - resultType = createFromFunctionProtoType(concreteType); - else if (const clang::FunctionNoProtoType* concreteType = clang::dyn_cast(type)) - resultType = createFromFunctionNoProtoType(concreteType); - else if (const clang::ParenType* concreteType = clang::dyn_cast(type)) - resultType = createFromParenType(concreteType); - else if (const clang::AttributedType* concreteType = clang::dyn_cast(type)) - resultType = createFromAttributedType(concreteType); - else if (const clang::ObjCTypeParamType* concreteType = clang::dyn_cast(type)) - resultType = createFromObjCTypeParamType(concreteType); - else if (const clang::MacroQualifiedType* concreteType = clang::dyn_cast(type)) - resultType = createFromMacroQualifiedParamType(concreteType); - else - throw TypeCreationException(type, "Unable to create encoding for this type.", true); - } - catch (TypeCreationException& e) { - if (e.getType() == type) { - _cache.insert(make_pair(&typeRef, make_pair(nullptr, std::make_unique(e)))); - throw; - }; - pair insertionResult = _cache.insert(make_pair(&typeRef, make_pair(nullptr, nullptr))); - string message = CreationException::constructMessage("Can't create type dependency.", e.getDetailedMessage()); - insertionResult.first->second.second = std::make_unique(type, message, e.isError()); - POLYMORPHIC_THROW(insertionResult.first->second.second); - } - catch (MetaCreationException& e) { - pair insertionResult = _cache.insert(make_pair(&typeRef, make_pair(nullptr, nullptr))); - string message = CreationException::constructMessage("Can't create meta dependency.", e.getDetailedMessage()); - insertionResult.first->second.second = std::make_unique(type, message, e.isError()); - POLYMORPHIC_THROW(insertionResult.first->second.second); - } + // revalidate in case the Type's metadata creation has failed after it was + // returned (e.g. from a forward declaration) + this->_metaFactory->validate(resultType.get()); - assert(resultType != nullptr); - pair insertionResult = _cache.insert(make_pair(&typeRef, make_pair(nullptr, nullptr))); - if (insertionResult.second) { - assert(insertionResult.first->second.first.get() == nullptr); - insertionResult.first->second.first = resultType; - return resultType; - } - else { - return insertionResult.first->second.first; + return resultType; } -} - -shared_ptr TypeFactory::create(const clang::QualType& type) -{ - const clang::Type* typePtr = type.getTypePtrOrNull(); - if (typePtr) - return this->create(typePtr); - throw TypeCreationException(nullptr, "Unable to get the inner type of qualified type.", true); -} -shared_ptr TypeFactory::createFromConstantArrayType(const clang::ConstantArrayType* type) -{ - return make_shared(this->create(type->getElementType()).get(), (int)type->getSize().roundToDouble()); -} - -shared_ptr TypeFactory::createFromIncompleteArrayType(const clang::IncompleteArrayType* type) -{ - return make_shared(this->create(type->getElementType()).get()); -} - -shared_ptr TypeFactory::createFromBlockPointerType(const clang::BlockPointerType* type) -{ - const clang::Type* pointee = type->getPointeeType().getTypePtr(); - Type* pointeeType = this->create(pointee).get(); - assert(pointeeType->is(TypeType::TypeFunctionPointer)); - return make_shared(pointeeType->as().signature); -} - -shared_ptr TypeFactory::createFromBuiltinType(const clang::BuiltinType* type) -{ - switch (type->getKind()) { + if (const clang::BuiltinType* concreteType = + clang::dyn_cast(type)) + resultType = createFromBuiltinType(concreteType); + else if (const clang::TypedefType* concreteType = + clang::dyn_cast(type)) + resultType = createFromTypedefType(concreteType); + else if (const clang::ObjCObjectPointerType* concreteType = + clang::dyn_cast(type)) + resultType = createFromObjCObjectPointerType(concreteType); + else if (const clang::EnumType* concreteType = + clang::dyn_cast(type)) + resultType = createFromEnumType(concreteType); + else if (const clang::PointerType* concreteType = + clang::dyn_cast(type)) + resultType = createFromPointerType(concreteType); + else if (const clang::BlockPointerType* concreteType = + clang::dyn_cast(type)) + resultType = createFromBlockPointerType(concreteType); + else if (const clang::RecordType* concreteType = + clang::dyn_cast(type)) + resultType = createFromRecordType(concreteType); + else if (const clang::ExtVectorType* concreteType = + clang::dyn_cast(type)) + resultType = createFromExtVectorType(concreteType); + else if (const clang::VectorType* concreteType = + clang::dyn_cast(type)) + resultType = createFromVectorType(concreteType); + else if (const clang::ConstantArrayType* concreteType = + clang::dyn_cast(type)) + resultType = createFromConstantArrayType(concreteType); + else if (const clang::IncompleteArrayType* concreteType = + clang::dyn_cast(type)) + resultType = createFromIncompleteArrayType(concreteType); + else if (const clang::ElaboratedType* concreteType = + clang::dyn_cast(type)) + resultType = createFromElaboratedType(concreteType); + else if (const clang::AdjustedType* concreteType = + clang::dyn_cast(type)) + resultType = createFromAdjustedType(concreteType); + else if (const clang::FunctionProtoType* concreteType = + clang::dyn_cast(type)) + resultType = createFromFunctionProtoType(concreteType); + else if (const clang::FunctionNoProtoType* concreteType = + clang::dyn_cast(type)) + resultType = createFromFunctionNoProtoType(concreteType); + else if (const clang::ParenType* concreteType = + clang::dyn_cast(type)) + resultType = createFromParenType(concreteType); + else if (const clang::AttributedType* concreteType = + clang::dyn_cast(type)) + resultType = createFromAttributedType(concreteType); + else if (const clang::ObjCTypeParamType* concreteType = + clang::dyn_cast(type)) + resultType = createFromObjCTypeParamType(concreteType); + else if (const clang::MacroQualifiedType* concreteType = + clang::dyn_cast(type)) + resultType = createFromMacroQualifiedParamType(concreteType); + else + throw TypeCreationException( + type, "Unable to create encoding for this type.", true); + } catch (TypeCreationException& e) { + if (e.getType() == type) { + _cache.insert(make_pair( + &typeRef, + make_pair(nullptr, std::make_unique(e)))); + throw; + }; + pair insertionResult = + _cache.insert(make_pair(&typeRef, make_pair(nullptr, nullptr))); + string message = CreationException::constructMessage( + "Can't create type dependency.", e.getDetailedMessage()); + insertionResult.first->second.second = + std::make_unique(type, message, e.isError()); + POLYMORPHIC_THROW(insertionResult.first->second.second); + } catch (MetaCreationException& e) { + pair insertionResult = + _cache.insert(make_pair(&typeRef, make_pair(nullptr, nullptr))); + string message = CreationException::constructMessage( + "Can't create meta dependency.", e.getDetailedMessage()); + insertionResult.first->second.second = + std::make_unique(type, message, e.isError()); + POLYMORPHIC_THROW(insertionResult.first->second.second); + } + + assert(resultType != nullptr); + pair insertionResult = + _cache.insert(make_pair(&typeRef, make_pair(nullptr, nullptr))); + if (insertionResult.second) { + assert(insertionResult.first->second.first.get() == nullptr); + insertionResult.first->second.first = resultType; + return resultType; + } else { + return insertionResult.first->second.first; + } +} + +shared_ptr TypeFactory::create(const clang::QualType& type) { + const clang::Type* typePtr = type.getTypePtrOrNull(); + if (typePtr) return this->create(typePtr); + throw TypeCreationException( + nullptr, "Unable to get the inner type of qualified type.", true); +} + +shared_ptr TypeFactory::createFromConstantArrayType( + const clang::ConstantArrayType* type) { + return make_shared( + this->create(type->getElementType()).get(), + (int)type->getSize().roundToDouble()); +} + +shared_ptr TypeFactory::createFromIncompleteArrayType( + const clang::IncompleteArrayType* type) { + return make_shared( + this->create(type->getElementType()).get()); +} + +shared_ptr TypeFactory::createFromBlockPointerType( + const clang::BlockPointerType* type) { + const clang::Type* pointee = type->getPointeeType().getTypePtr(); + Type* pointeeType = this->create(pointee).get(); + assert(pointeeType->is(TypeType::TypeFunctionPointer)); + return make_shared( + pointeeType->as().signature); +} + +shared_ptr TypeFactory::createFromBuiltinType( + const clang::BuiltinType* type) { + switch (type->getKind()) { case clang::BuiltinType::Kind::Void: - return TypeFactory::getVoid(); + return TypeFactory::getVoid(); case clang::BuiltinType::Kind::Bool: - return TypeFactory::getBool(); + return TypeFactory::getBool(); case clang::BuiltinType::Kind::Char_S: case clang::BuiltinType::Kind::Char_U: case clang::BuiltinType::Kind::SChar: - return TypeFactory::getSignedChar(); + return TypeFactory::getSignedChar(); case clang::BuiltinType::Kind::Short: - return TypeFactory::getShort(); + return TypeFactory::getShort(); case clang::BuiltinType::Kind::Int: - return TypeFactory::getInt(); + return TypeFactory::getInt(); case clang::BuiltinType::Kind::Long: - return TypeFactory::getLong(); + return TypeFactory::getLong(); case clang::BuiltinType::Kind::LongLong: - return TypeFactory::getLongLong(); + return TypeFactory::getLongLong(); case clang::BuiltinType::Kind::UChar: - return TypeFactory::getUnsignedChar(); + return TypeFactory::getUnsignedChar(); case clang::BuiltinType::Kind::UShort: - return TypeFactory::getUShort(); + return TypeFactory::getUShort(); case clang::BuiltinType::Kind::UInt: - return TypeFactory::getUInt(); + return TypeFactory::getUInt(); case clang::BuiltinType::Kind::ULong: - return TypeFactory::getULong(); + return TypeFactory::getULong(); case clang::BuiltinType::Kind::ULongLong: - return TypeFactory::getULongLong(); + return TypeFactory::getULongLong(); case clang::BuiltinType::Kind::Float: - return TypeFactory::getFloat(); + return TypeFactory::getFloat(); case clang::BuiltinType::Kind::Double: - return TypeFactory::getDouble(); - // Objective-C does not support the long double type. @encode(long double) returns d, which is the same encoding as for double. + return TypeFactory::getDouble(); + // Objective-C does not support the long double type. @encode(long double) + // returns d, which is the same encoding as for double. case clang::BuiltinType::Kind::LongDouble: - return TypeFactory::getDouble(); + return TypeFactory::getDouble(); - // ObjCSel, ObjCId and ObjCClass builtin types should never enter in this method because these types should be handled on upper level. - // The 'SEL' type is represented as pointer to BuiltinType of kind ObjCSel. - // The 'id' type is actually represented by clang as TypedefType to ObjCObjectPointerType whose pointee is an ObjCObjectType with base BuiltinType::ObjCIdType. - // This is also valid for ObjCClass type. + // ObjCSel, ObjCId and ObjCClass builtin types should never enter in this + // method because these types should be handled on upper level. The 'SEL' + // type is represented as pointer to BuiltinType of kind ObjCSel. The 'id' + // type is actually represented by clang as TypedefType to + // ObjCObjectPointerType whose pointee is an ObjCObjectType with base + // BuiltinType::ObjCIdType. This is also valid for ObjCClass type. default: - throw TypeCreationException(type, string("Not supported builtin type(") + type->getTypeClassName() + ").", true); - } -} - -shared_ptr TypeFactory::createFromObjCObjectPointerType(const clang::ObjCObjectPointerType* type) -{ - vector protocols; - for (clang::ObjCProtocolDecl* qual : type->quals()) { - clang::ObjCProtocolDecl* protocolDef = qual->getDefinition(); - Meta* protocolMeta = nullptr; - if (protocolDef != nullptr && _metaFactory->tryCreate(*protocolDef, &protocolMeta)) { - assert(protocolMeta->is(MetaType::Protocol)); - protocols.push_back(&protocolMeta->as()); - } - } - if (type->isObjCIdType() || type->isObjCQualifiedIdType()) { - return make_shared(protocols); - } - if (type->isObjCClassType() || type->isObjCQualifiedClassType()) { - return make_shared(protocols); - } - - if (clang::ObjCInterfaceDecl* interface = type->getObjectType()->getInterface()) { - if (interface->getNameAsString() == "Protocol") { - return TypeFactory::getProtocolType(); - } - else if (clang::ObjCInterfaceDecl* interfaceDef = interface->getDefinition()) { - vector typeArguments; - for (const clang::QualType& typeArg : type->getTypeArgsAsWritten()) { - - typeArguments.push_back(this->create(typeArg).get()); - } - return make_shared(&_metaFactory->create(*interfaceDef)->as(), protocols, typeArguments); - } + throw TypeCreationException(type, + string("Not supported builtin type(") + + type->getTypeClassName() + ").", + true); + } +} + +shared_ptr TypeFactory::createFromObjCObjectPointerType( + const clang::ObjCObjectPointerType* type) { + vector protocols; + for (clang::ObjCProtocolDecl* qual : type->quals()) { + clang::ObjCProtocolDecl* protocolDef = qual->getDefinition(); + Meta* protocolMeta = nullptr; + if (protocolDef != nullptr && + _metaFactory->tryCreate(*protocolDef, &protocolMeta)) { + assert(protocolMeta->is(MetaType::Protocol)); + protocols.push_back(&protocolMeta->as()); } - - throw TypeCreationException(type, "Invalid interface pointer type.", true); -} - -shared_ptr TypeFactory::createFromPointerType(const clang::PointerType* type) -{ - clang::QualType qualPointee = type->getPointeeType(); - const clang::Type* pointee = qualPointee.getTypePtr(); - const clang::Type* canonicalPointee = pointee->getCanonicalTypeInternal().getTypePtr(); - - if (const clang::BuiltinType* builtinType = clang::dyn_cast(canonicalPointee)) { - if (builtinType->getKind() == clang::BuiltinType::Kind::ObjCSel) - return TypeFactory::getSelector(); - if (builtinType->getKind() == clang::BuiltinType::Kind::Char_S || builtinType->getKind() == clang::BuiltinType::Kind::UChar) - return TypeFactory::getCString(); + } + if (type->isObjCIdType() || type->isObjCQualifiedIdType()) { + return make_shared(protocols); + } + if (type->isObjCClassType() || type->isObjCQualifiedClassType()) { + return make_shared(protocols); + } + + if (clang::ObjCInterfaceDecl* interface = + type->getObjectType()->getInterface()) { + if (interface->getNameAsString() == "Protocol") { + return TypeFactory::getProtocolType(); + } else if (clang::ObjCInterfaceDecl* interfaceDef = + interface->getDefinition()) { + vector typeArguments; + for (const clang::QualType& typeArg : type->getTypeArgsAsWritten()) { + typeArguments.push_back(this->create(typeArg).get()); + } + return make_shared( + &_metaFactory->create(*interfaceDef)->as(), protocols, + typeArguments); } - - // if is a FunctionPointerType don't wrap the type in another pointer type - if (clang::isa(pointee)) { - return this->create(qualPointee); + } + + throw TypeCreationException(type, "Invalid interface pointer type.", true); +} + +shared_ptr TypeFactory::createFromPointerType( + const clang::PointerType* type) { + clang::QualType qualPointee = type->getPointeeType(); + const clang::Type* pointee = qualPointee.getTypePtr(); + const clang::Type* canonicalPointee = + pointee->getCanonicalTypeInternal().getTypePtr(); + + if (const clang::BuiltinType* builtinType = + clang::dyn_cast(canonicalPointee)) { + if (builtinType->getKind() == clang::BuiltinType::Kind::ObjCSel) + return TypeFactory::getSelector(); + if (builtinType->getKind() == clang::BuiltinType::Kind::Char_S || + builtinType->getKind() == clang::BuiltinType::Kind::UChar) + return TypeFactory::getCString(); + } + + // if is a FunctionPointerType don't wrap the type in another pointer type + if (clang::isa(pointee)) { + return this->create(qualPointee); + } + + return make_shared(this->create(qualPointee).get()); +} + +shared_ptr TypeFactory::createFromEnumType(const clang::EnumType* type) { + Type* innerType = this->create(type->getDecl()->getIntegerType()).get(); + auto& enumDecl = type->getDecl()->getDefinition() + ? *type->getDecl()->getDefinition() + : *type->getDecl(); + EnumMeta* enumMeta = &this->_metaFactory->create(enumDecl)->as(); + return make_shared(innerType, enumMeta); +} + +shared_ptr TypeFactory::createFromRecordType( + const clang::RecordType* type) { + clang::RecordDecl* recordDef = type->getDecl()->getDefinition(); + if (!recordDef) { + return TypeFactory::getVoid(); + } + if (recordDef->isUnion()) + throw TypeCreationException(type, "The record is an union.", true); + if (!recordDef->isStruct()) + throw TypeCreationException(type, "The record is not a struct.", true); + const clang::TagDecl* tagDecl = + clang::dyn_cast(type->getDecl()); + if (MetaFactory::getTypedefOrOwnName(tagDecl) == "") { + // The record is anonymous + vector fields; + for (clang::FieldDecl* field : recordDef->fields()) { + RecordField fieldMeta(field->getNameAsString(), + this->create(field->getType()).get()); + fields.push_back(fieldMeta); } + return make_shared(fields); + } - return make_shared(this->create(qualPointee).get()); + return make_shared( + &_metaFactory->create(*recordDef)->as()); } -shared_ptr TypeFactory::createFromEnumType(const clang::EnumType* type) -{ - Type* innerType = this->create(type->getDecl()->getIntegerType()).get(); - auto& enumDecl = type->getDecl()->getDefinition() ? *type->getDecl()->getDefinition() : *type->getDecl(); - EnumMeta* enumMeta = &this->_metaFactory->create(enumDecl)->as(); - return make_shared(innerType, enumMeta); -} +static shared_ptr tryCreateFromBridgedType(const clang::Type* type) { + if (const clang::PointerType* pointerType = + clang::dyn_cast(type)) { + const clang::Type* pointee = pointerType->getPointeeType().getTypePtr(); -shared_ptr TypeFactory::createFromRecordType(const clang::RecordType* type) -{ + // Check for pointer to toll-free bridged types + if (const clang::ElaboratedType* elaboratedType = + clang::dyn_cast(pointee)) { + if (const clang::TagType* tagType = clang::dyn_cast( + elaboratedType->desugar().getTypePtr())) { + const clang::TagDecl* tagDecl = tagType->getDecl(); - clang::RecordDecl* recordDef = type->getDecl()->getDefinition(); - if (!recordDef) { - return TypeFactory::getVoid(); - } - if (recordDef->isUnion()) - throw TypeCreationException(type, "The record is an union.", true); - if (!recordDef->isStruct()) - throw TypeCreationException(type, "The record is not a struct.", true); - const clang::TagDecl* tagDecl = clang::dyn_cast(type->getDecl()); - if (MetaFactory::getTypedefOrOwnName(tagDecl) == "") { - // The record is anonymous - vector fields; - for (clang::FieldDecl* field : recordDef->fields()) { - RecordField fieldMeta(field->getNameAsString(), this->create(field->getType()).get()); - fields.push_back(fieldMeta); + if (clang::ObjCBridgeMutableAttr* bridgeMutableAttr = + tagDecl->getAttr()) { + string name = bridgeMutableAttr->getBridgedType()->getName().str(); + return make_shared(name, nullptr); } - return make_shared(fields); - } - - return make_shared(&_metaFactory->create(*recordDef)->as()); -} - -static shared_ptr tryCreateFromBridgedType(const clang::Type* type) -{ - if (const clang::PointerType* pointerType = clang::dyn_cast(type)) { - const clang::Type* pointee = pointerType->getPointeeType().getTypePtr(); - // Check for pointer to toll-free bridged types - if (const clang::ElaboratedType* elaboratedType = clang::dyn_cast(pointee)) { - if (const clang::TagType* tagType = clang::dyn_cast(elaboratedType->desugar().getTypePtr())) { - const clang::TagDecl* tagDecl = tagType->getDecl(); - - if (clang::ObjCBridgeMutableAttr* bridgeMutableAttr = tagDecl->getAttr()) { - string name = bridgeMutableAttr->getBridgedType()->getName().str(); - return make_shared(name, nullptr); - } - - if (clang::ObjCBridgeAttr* bridgeAttr = tagDecl->getAttr()) { - string name = bridgeAttr->getBridgedType()->getName().str(); - return make_shared(name, nullptr); - } - } + if (clang::ObjCBridgeAttr* bridgeAttr = + tagDecl->getAttr()) { + string name = bridgeAttr->getBridgedType()->getName().str(); + return make_shared(name, nullptr); } + } } + } - return nullptr; + return nullptr; } -shared_ptr TypeFactory::createFromTypedefType(const clang::TypedefType* type) -{ - vector boolTypedefs{ "BOOL", "Boolean", "bool"}; - if (isSpecificTypedefType(type, boolTypedefs)) - return TypeFactory::getBool(); - if (isSpecificTypedefType(type, "unichar")) - return TypeFactory::getUnichar(); - if (isSpecificTypedefType(type, "__builtin_va_list")) - throw TypeCreationException(type, "VaList type is not supported.", true); - if (auto bridgedInterfaceType = tryCreateFromBridgedType(type->getDecl()->getUnderlyingType().getTypePtrOrNull())) { - return bridgedInterfaceType; - } - if (isSpecificTypedefType(type, KNOWN_BRIDGED_TYPES)) { - return make_shared("id", nullptr); - } - return this->create(type->getDecl()->getUnderlyingType()); +shared_ptr TypeFactory::createFromTypedefType( + const clang::TypedefType* type) { + vector boolTypedefs{"BOOL", "Boolean", "bool"}; + if (isSpecificTypedefType(type, boolTypedefs)) return TypeFactory::getBool(); + if (isSpecificTypedefType(type, "unichar")) return TypeFactory::getUnichar(); + if (isSpecificTypedefType(type, "__builtin_va_list")) + throw TypeCreationException(type, "VaList type is not supported.", true); + if (auto bridgedInterfaceType = tryCreateFromBridgedType( + type->getDecl()->getUnderlyingType().getTypePtrOrNull())) { + return bridgedInterfaceType; + } + if (isSpecificTypedefType(type, KNOWN_BRIDGED_TYPES)) { + return make_shared("id", nullptr); + } + return this->create(type->getDecl()->getUnderlyingType()); } -shared_ptr TypeFactory::createFromExtVectorType(const clang::ExtVectorType* type) -{ - return make_shared(this->create(type->getElementType()).get(), type->getNumElements()); +shared_ptr TypeFactory::createFromExtVectorType( + const clang::ExtVectorType* type) { + return make_shared(this->create(type->getElementType()).get(), + type->getNumElements()); } -shared_ptr TypeFactory::createFromVectorType(const clang::VectorType* type) -{ - throw TypeCreationException(type, "Vector type is not supported.", true); +shared_ptr TypeFactory::createFromVectorType( + const clang::VectorType* type) { + throw TypeCreationException(type, "Vector type is not supported.", true); } -shared_ptr TypeFactory::createFromElaboratedType(const clang::ElaboratedType* type) -{ - return this->create(type->getNamedType()); +shared_ptr TypeFactory::createFromElaboratedType( + const clang::ElaboratedType* type) { + return this->create(type->getNamedType()); } -shared_ptr TypeFactory::createFromAdjustedType(const clang::AdjustedType* type) -{ - return this->create(type->getOriginalType()); +shared_ptr TypeFactory::createFromAdjustedType( + const clang::AdjustedType* type) { + return this->create(type->getOriginalType()); } -shared_ptr TypeFactory::createFromFunctionProtoType(const clang::FunctionProtoType* type) -{ - vector signature; - signature.push_back(this->create(type->getReturnType()).get()); - for (const clang::QualType& parm : type->param_types()) - signature.push_back(this->create(parm).get()); - return make_shared(signature); +shared_ptr TypeFactory::createFromFunctionProtoType( + const clang::FunctionProtoType* type) { + vector signature; + signature.push_back(this->create(type->getReturnType()).get()); + for (const clang::QualType& parm : type->param_types()) + signature.push_back(this->create(parm).get()); + return make_shared(signature); } -shared_ptr TypeFactory::createFromFunctionNoProtoType(const clang::FunctionNoProtoType* type) -{ - vector signature; - signature.push_back(this->create(type->getReturnType()).get()); - return make_shared(signature); +shared_ptr TypeFactory::createFromFunctionNoProtoType( + const clang::FunctionNoProtoType* type) { + vector signature; + signature.push_back(this->create(type->getReturnType()).get()); + return make_shared(signature); } -shared_ptr TypeFactory::createFromParenType(const clang::ParenType* type) -{ - return this->create(type->desugar().getTypePtr()); +shared_ptr TypeFactory::createFromParenType( + const clang::ParenType* type) { + return this->create(type->desugar().getTypePtr()); } -shared_ptr TypeFactory::createFromAttributedType(const clang::AttributedType* type) -{ - return this->create(type->getModifiedType()); -} - -shared_ptr TypeFactory::createFromObjCTypeParamType(const clang::ObjCTypeParamType* type) -{ - clang::ObjCTypeParamDecl* typeParamDecl = type->getDecl(); - - vector protocols; - for (clang::ObjCProtocolDecl* decl : type->getProtocols()) { - clang::ObjCProtocolDecl* protocolDef = decl->getDefinition(); - Meta* protocolMeta = nullptr; - if (protocolDef != nullptr && _metaFactory->tryCreate(*protocolDef, &protocolMeta)) { - assert(protocolMeta->is(MetaType::Protocol)); - protocols.push_back(&protocolMeta->as()); - } +shared_ptr TypeFactory::createFromAttributedType( + const clang::AttributedType* type) { + auto innerType = this->create(type->getModifiedType()); + if (auto nullability = type->getImmediateNullability()) { + if (*nullability == clang::NullabilityKind::Nullable) { + return make_shared(innerType.get()); + } + } + return innerType; +} + +shared_ptr TypeFactory::createFromObjCTypeParamType( + const clang::ObjCTypeParamType* type) { + clang::ObjCTypeParamDecl* typeParamDecl = type->getDecl(); + + vector protocols; + for (clang::ObjCProtocolDecl* decl : type->getProtocols()) { + clang::ObjCProtocolDecl* protocolDef = decl->getDefinition(); + Meta* protocolMeta = nullptr; + if (protocolDef != nullptr && + _metaFactory->tryCreate(*protocolDef, &protocolMeta)) { + assert(protocolMeta->is(MetaType::Protocol)); + protocols.push_back(&protocolMeta->as()); } + } - return make_shared(this->create(typeParamDecl->getUnderlyingType()).get(), typeParamDecl->getNameAsString(), protocols); + return make_shared( + this->create(typeParamDecl->getUnderlyingType()).get(), + typeParamDecl->getNameAsString(), protocols); } -shared_ptr TypeFactory::createFromMacroQualifiedParamType(const clang::MacroQualifiedType* type) -{ - return create(type->desugar()); +shared_ptr TypeFactory::createFromMacroQualifiedParamType( + const clang::MacroQualifiedType* type) { + return create(type->desugar()); } -bool TypeFactory::isSpecificTypedefType(const clang::TypedefType* type, const string& typedefName) -{ - const vector typedefNames{ typedefName }; - return this->isSpecificTypedefType(type, typedefNames); +bool TypeFactory::isSpecificTypedefType(const clang::TypedefType* type, + const string& typedefName) { + const vector typedefNames{typedefName}; + return this->isSpecificTypedefType(type, typedefNames); } -bool TypeFactory::isSpecificTypedefType(const clang::TypedefType* type, const vector& typedefNames) -{ - clang::TypedefNameDecl* decl = type->getDecl(); - while (decl) { - if (find(typedefNames.begin(), typedefNames.end(), decl->getNameAsString()) != typedefNames.end()) { - return true; - } +bool TypeFactory::isSpecificTypedefType(const clang::TypedefType* type, + const vector& typedefNames) { + clang::TypedefNameDecl* decl = type->getDecl(); + while (decl) { + if (find(typedefNames.begin(), typedefNames.end(), + decl->getNameAsString()) != typedefNames.end()) { + return true; + } - clang::Type const* innerType = decl->getUnderlyingType().getTypePtr(); - if (const clang::TypedefType* innerTypedef = clang::dyn_cast(innerType)) { - decl = innerTypedef->getDecl(); - } - else { - return false; - } + clang::Type const* innerType = decl->getUnderlyingType().getTypePtr(); + if (const clang::TypedefType* innerTypedef = + clang::dyn_cast(innerType)) { + decl = innerTypedef->getDecl(); + } else { + return false; } - return false; -} - -void TypeFactory::resolveCachedBridgedInterfaceTypes(unordered_map& interfaceMap) -{ - unordered_map::const_iterator nsObjectIt = interfaceMap.find("NSObject"); - for (Cache::value_type& typeEntry : _cache) { - if (typeEntry.second.second.get() == nullptr) { - Type* type = typeEntry.second.first.get(); - if (type->is(TypeType::TypeBridgedInterface)) { - BridgedInterfaceType* bridgedType = &type->as(); - if (!bridgedType->isId()) { - unordered_map::const_iterator it = interfaceMap.find(bridgedType->name); - if (it != interfaceMap.end()) { - bridgedType->bridgedInterface = it->second; - } - else { - assert(nsObjectIt != interfaceMap.end()); - bridgedType->bridgedInterface = nsObjectIt->second; - cout << "Unable to resolve bridged interface type. Interface " << bridgedType->name << " not found. NSObject used instead." << endl; - } - } - } + } + return false; +} + +void TypeFactory::resolveCachedBridgedInterfaceTypes( + unordered_map& interfaceMap) { + unordered_map::const_iterator nsObjectIt = + interfaceMap.find("NSObject"); + for (Cache::value_type& typeEntry : _cache) { + if (typeEntry.second.second.get() == nullptr) { + Type* type = typeEntry.second.first.get(); + if (type->is(TypeType::TypeBridgedInterface)) { + BridgedInterfaceType* bridgedType = &type->as(); + if (!bridgedType->isId()) { + unordered_map::const_iterator it = + interfaceMap.find(bridgedType->name); + if (it != interfaceMap.end()) { + bridgedType->bridgedInterface = it->second; + } else { + assert(nsObjectIt != interfaceMap.end()); + bridgedType->bridgedInterface = nsObjectIt->second; + cout << "Unable to resolve bridged interface type. Interface " + << bridgedType->name << " not found. NSObject used instead." + << endl; + } } + } } + } } -} +} // namespace Meta diff --git a/metadata-generator/src/Meta/TypeVisitor.h b/metadata-generator/src/Meta/TypeVisitor.h index 230323e0..b2a77d3d 100644 --- a/metadata-generator/src/Meta/TypeVisitor.h +++ b/metadata-generator/src/Meta/TypeVisitor.h @@ -18,86 +18,94 @@ class AnonymousUnionType; class EnumType; class TypeArgumentType; class ExtVectorType; +class NullableType; /* - * \class TypeVisitor - * \brief Applies the Visitor pattern for \c Meta::Type objects. - * - * Returns a value of type \c T_RESULT - */ + * \class TypeVisitor + * \brief Applies the Visitor pattern for \c Meta::Type objects. + * + * Returns a value of type \c T_RESULT + */ template class TypeVisitor { -public: - virtual T_RESULT visitVoid() = 0; + public: + virtual T_RESULT visitVoid() = 0; - virtual T_RESULT visitBool() = 0; + virtual T_RESULT visitBool() = 0; - virtual T_RESULT visitShort() = 0; + virtual T_RESULT visitShort() = 0; - virtual T_RESULT visitUShort() = 0; + virtual T_RESULT visitUShort() = 0; - virtual T_RESULT visitInt() = 0; + virtual T_RESULT visitInt() = 0; - virtual T_RESULT visitUInt() = 0; + virtual T_RESULT visitUInt() = 0; - virtual T_RESULT visitLong() = 0; + virtual T_RESULT visitLong() = 0; - virtual T_RESULT visitUlong() = 0; + virtual T_RESULT visitUlong() = 0; - virtual T_RESULT visitLongLong() = 0; + virtual T_RESULT visitLongLong() = 0; - virtual T_RESULT visitULongLong() = 0; + virtual T_RESULT visitULongLong() = 0; - virtual T_RESULT visitSignedChar() = 0; + virtual T_RESULT visitSignedChar() = 0; - virtual T_RESULT visitUnsignedChar() = 0; + virtual T_RESULT visitUnsignedChar() = 0; - virtual T_RESULT visitUnichar() = 0; + virtual T_RESULT visitUnichar() = 0; - virtual T_RESULT visitCString() = 0; + virtual T_RESULT visitCString() = 0; - virtual T_RESULT visitFloat() = 0; + virtual T_RESULT visitFloat() = 0; - virtual T_RESULT visitDouble() = 0; + virtual T_RESULT visitDouble() = 0; - virtual T_RESULT visitVaList() = 0; + virtual T_RESULT visitVaList() = 0; - virtual T_RESULT visitSelector() = 0; + virtual T_RESULT visitSelector() = 0; - virtual T_RESULT visitInstancetype() = 0; + virtual T_RESULT visitInstancetype() = 0; - virtual T_RESULT visitClass(const ClassType& typeDetails) = 0; + virtual T_RESULT visitClass(const ClassType& typeDetails) = 0; - virtual T_RESULT visitProtocol() = 0; + virtual T_RESULT visitProtocol() = 0; - virtual T_RESULT visitId(const IdType& typeDetails) = 0; + virtual T_RESULT visitId(const IdType& typeDetails) = 0; - virtual T_RESULT visitConstantArray(const ConstantArrayType& typeDetails) = 0; - - virtual T_RESULT visitExtVector(const ExtVectorType& typeDetails) = 0; + virtual T_RESULT visitConstantArray(const ConstantArrayType& typeDetails) = 0; - virtual T_RESULT visitIncompleteArray(const IncompleteArrayType& typeDetails) = 0; + virtual T_RESULT visitExtVector(const ExtVectorType& typeDetails) = 0; - virtual T_RESULT visitInterface(const InterfaceType& typeDetails) = 0; + virtual T_RESULT visitIncompleteArray( + const IncompleteArrayType& typeDetails) = 0; - virtual T_RESULT visitBridgedInterface(const BridgedInterfaceType& typeDetails) = 0; + virtual T_RESULT visitInterface(const InterfaceType& typeDetails) = 0; - virtual T_RESULT visitPointer(const PointerType& typeDetails) = 0; + virtual T_RESULT visitBridgedInterface( + const BridgedInterfaceType& typeDetails) = 0; - virtual T_RESULT visitBlock(const BlockType& typeDetails) = 0; + virtual T_RESULT visitPointer(const PointerType& typeDetails) = 0; - virtual T_RESULT visitFunctionPointer(const FunctionPointerType& typeDetails) = 0; + virtual T_RESULT visitBlock(const BlockType& typeDetails) = 0; - virtual T_RESULT visitStruct(const StructType& typeDetails) = 0; + virtual T_RESULT visitFunctionPointer( + const FunctionPointerType& typeDetails) = 0; - virtual T_RESULT visitUnion(const UnionType& typeDetails) = 0; + virtual T_RESULT visitStruct(const StructType& typeDetails) = 0; - virtual T_RESULT visitAnonymousStruct(const AnonymousStructType& typeDetails) = 0; + virtual T_RESULT visitUnion(const UnionType& typeDetails) = 0; - virtual T_RESULT visitAnonymousUnion(const AnonymousUnionType& typeDetails) = 0; + virtual T_RESULT visitAnonymousStruct( + const AnonymousStructType& typeDetails) = 0; - virtual T_RESULT visitEnum(const EnumType& typeDetails) = 0; + virtual T_RESULT visitAnonymousUnion( + const AnonymousUnionType& typeDetails) = 0; - virtual T_RESULT visitTypeArgument(const ::Meta::TypeArgumentType& type) = 0; + virtual T_RESULT visitEnum(const EnumType& typeDetails) = 0; + + virtual T_RESULT visitTypeArgument(const ::Meta::TypeArgumentType& type) = 0; + + virtual T_RESULT visitNullable(const ::Meta::NullableType& type) = 0; }; -} +} // namespace Meta diff --git a/metadata-generator/src/Meta/ValidateMetaTypeVisitor.cpp b/metadata-generator/src/Meta/ValidateMetaTypeVisitor.cpp index a6910ff3..af47a7bd 100644 --- a/metadata-generator/src/Meta/ValidateMetaTypeVisitor.cpp +++ b/metadata-generator/src/Meta/ValidateMetaTypeVisitor.cpp @@ -7,197 +7,167 @@ #include "ValidateMetaTypeVisitor.h" +bool ValidateMetaTypeVisitor::visitVoid() { return true; } -bool ValidateMetaTypeVisitor::visitVoid() { - return true; -} +bool ValidateMetaTypeVisitor::visitBool() { return true; } -bool ValidateMetaTypeVisitor::visitBool() { - return true; -} +bool ValidateMetaTypeVisitor::visitShort() { return true; } -bool ValidateMetaTypeVisitor::visitShort() { - return true; -} +bool ValidateMetaTypeVisitor::visitUShort() { return true; } -bool ValidateMetaTypeVisitor::visitUShort() { - return true; -} +bool ValidateMetaTypeVisitor::visitInt() { return true; } -bool ValidateMetaTypeVisitor::visitInt() { - return true; -} +bool ValidateMetaTypeVisitor::visitUInt() { return true; } -bool ValidateMetaTypeVisitor::visitUInt() { - return true; -} +bool ValidateMetaTypeVisitor::visitLong() { return true; } -bool ValidateMetaTypeVisitor::visitLong() { - return true; -} +bool ValidateMetaTypeVisitor::visitUlong() { return true; } -bool ValidateMetaTypeVisitor::visitUlong() { - return true; -} +bool ValidateMetaTypeVisitor::visitLongLong() { return true; } -bool ValidateMetaTypeVisitor::visitLongLong() { - return true; -} +bool ValidateMetaTypeVisitor::visitULongLong() { return true; } -bool ValidateMetaTypeVisitor::visitULongLong() { - return true; -} +bool ValidateMetaTypeVisitor::visitSignedChar() { return true; } -bool ValidateMetaTypeVisitor::visitSignedChar() { - return true; -} +bool ValidateMetaTypeVisitor::visitUnsignedChar() { return true; } -bool ValidateMetaTypeVisitor::visitUnsignedChar() { - return true; -} +bool ValidateMetaTypeVisitor::visitUnichar() { return true; } -bool ValidateMetaTypeVisitor::visitUnichar() { - return true; -} +bool ValidateMetaTypeVisitor::visitCString() { return true; } -bool ValidateMetaTypeVisitor::visitCString() { - return true; -} +bool ValidateMetaTypeVisitor::visitFloat() { return true; } -bool ValidateMetaTypeVisitor::visitFloat() { - return true; -} +bool ValidateMetaTypeVisitor::visitDouble() { return true; } -bool ValidateMetaTypeVisitor::visitDouble() { - return true; -} +bool ValidateMetaTypeVisitor::visitVaList() { return true; } -bool ValidateMetaTypeVisitor::visitVaList() { - return true; -} - -bool ValidateMetaTypeVisitor::visitSelector() { - return true; -} +bool ValidateMetaTypeVisitor::visitSelector() { return true; } -bool ValidateMetaTypeVisitor::visitInstancetype() { - return true; -} +bool ValidateMetaTypeVisitor::visitInstancetype() { return true; } bool ValidateMetaTypeVisitor::visitClass(const ClassType& typeDetails) { - for (auto& p : typeDetails.protocols) { - this->_metaFactory.validate(p); - } + for (auto& p : typeDetails.protocols) { + this->_metaFactory.validate(p); + } - return true; + return true; } -bool ValidateMetaTypeVisitor::visitProtocol() { - return true; -} +bool ValidateMetaTypeVisitor::visitProtocol() { return true; } bool ValidateMetaTypeVisitor::visitId(const IdType& typeDetails) { - return true; + return true; } -bool ValidateMetaTypeVisitor::visitConstantArray(const ConstantArrayType& typeDetails) { - return true; +bool ValidateMetaTypeVisitor::visitConstantArray( + const ConstantArrayType& typeDetails) { + return true; } bool ValidateMetaTypeVisitor::visitExtVector(const ExtVectorType& typeDetails) { - return true; + return true; } -bool ValidateMetaTypeVisitor::visitIncompleteArray(const IncompleteArrayType& typeDetails) { - return true; +bool ValidateMetaTypeVisitor::visitIncompleteArray( + const IncompleteArrayType& typeDetails) { + return true; } bool ValidateMetaTypeVisitor::visitInterface(const InterfaceType& typeDetails) { - - this->_metaFactory.validate(typeDetails.interface); + this->_metaFactory.validate(typeDetails.interface); + + for (auto& p : typeDetails.protocols) { + this->_metaFactory.validate(p); + } - for (auto& p : typeDetails.protocols) { - this->_metaFactory.validate(p); - } - - for (auto typeArg : typeDetails.typeArguments) { - typeArg->visit(*this); - } - - return true; + for (auto typeArg : typeDetails.typeArguments) { + typeArg->visit(*this); + } + + return true; } -bool ValidateMetaTypeVisitor::visitBridgedInterface(const BridgedInterfaceType& typeDetails) { - if (typeDetails.bridgedInterface) { - this->_metaFactory.validate(typeDetails.bridgedInterface); - } - - return true; +bool ValidateMetaTypeVisitor::visitBridgedInterface( + const BridgedInterfaceType& typeDetails) { + if (typeDetails.bridgedInterface) { + this->_metaFactory.validate(typeDetails.bridgedInterface); + } + + return true; } bool ValidateMetaTypeVisitor::visitPointer(const PointerType& typeDetails) { - typeDetails.innerType->visit(*this); - - return true; + typeDetails.innerType->visit(*this); + + return true; } bool ValidateMetaTypeVisitor::visitBlock(const BlockType& typeDetails) { - for (auto type : typeDetails.signature) { - type->visit(*this); - } - - return true; + for (auto type : typeDetails.signature) { + type->visit(*this); + } + + return true; } -bool ValidateMetaTypeVisitor::visitFunctionPointer(const FunctionPointerType& typeDetails) { - for (auto type : typeDetails.signature) { - type->visit(*this); - } - - return true; +bool ValidateMetaTypeVisitor::visitFunctionPointer( + const FunctionPointerType& typeDetails) { + for (auto type : typeDetails.signature) { + type->visit(*this); + } + + return true; } bool ValidateMetaTypeVisitor::visitStruct(const StructType& typeDetails) { - this->_metaFactory.validate(typeDetails.structMeta); + this->_metaFactory.validate(typeDetails.structMeta); - return true; + return true; } bool ValidateMetaTypeVisitor::visitUnion(const UnionType& typeDetails) { - this->_metaFactory.validate(typeDetails.unionMeta); + this->_metaFactory.validate(typeDetails.unionMeta); - return true; + return true; } -bool ValidateMetaTypeVisitor::visitAnonymousStruct(const AnonymousStructType& typeDetails) { - for (auto field : typeDetails.fields) { - field.encoding->visit(*this); - } +bool ValidateMetaTypeVisitor::visitAnonymousStruct( + const AnonymousStructType& typeDetails) { + for (auto field : typeDetails.fields) { + field.encoding->visit(*this); + } - return true; + return true; } -bool ValidateMetaTypeVisitor::visitAnonymousUnion(const AnonymousUnionType& typeDetails) { - for (auto field : typeDetails.fields) { - field.encoding->visit(*this); - } - - return true; +bool ValidateMetaTypeVisitor::visitAnonymousUnion( + const AnonymousUnionType& typeDetails) { + for (auto field : typeDetails.fields) { + field.encoding->visit(*this); + } + + return true; } bool ValidateMetaTypeVisitor::visitEnum(const EnumType& typeDetails) { - this->_metaFactory.validate(typeDetails.enumMeta); + this->_metaFactory.validate(typeDetails.enumMeta); - return true; + return true; } -bool ValidateMetaTypeVisitor::visitTypeArgument(const TypeArgumentType& typeDetails) { - for (auto& p : typeDetails.protocols) { - this->_metaFactory.validate(p); - } - - typeDetails.underlyingType->visit(*this); +bool ValidateMetaTypeVisitor::visitTypeArgument( + const TypeArgumentType& typeDetails) { + for (auto& p : typeDetails.protocols) { + this->_metaFactory.validate(p); + } - return true; + typeDetails.underlyingType->visit(*this); + + return true; } +bool ValidateMetaTypeVisitor::visitNullable(const NullableType& typeDetails) { + typeDetails.innerType->visit(*this); + + return true; +} diff --git a/metadata-generator/src/Meta/ValidateMetaTypeVisitor.h b/metadata-generator/src/Meta/ValidateMetaTypeVisitor.h index a7b20293..83a26a66 100644 --- a/metadata-generator/src/Meta/ValidateMetaTypeVisitor.h +++ b/metadata-generator/src/Meta/ValidateMetaTypeVisitor.h @@ -15,85 +15,86 @@ using namespace Meta; class ValidateMetaTypeVisitor : public TypeVisitor { - -public: - explicit ValidateMetaTypeVisitor(MetaFactory& factory): _metaFactory(factory) { } - - virtual bool visitVoid(); - - virtual bool visitBool(); - - virtual bool visitShort(); - - virtual bool visitUShort(); - - virtual bool visitInt(); - - virtual bool visitUInt(); - - virtual bool visitLong(); - - virtual bool visitUlong(); - - virtual bool visitLongLong(); - - virtual bool visitULongLong(); - - virtual bool visitSignedChar(); - - virtual bool visitUnsignedChar(); - - virtual bool visitUnichar(); - - virtual bool visitCString(); - - virtual bool visitFloat(); - - virtual bool visitDouble(); - - virtual bool visitVaList(); - - virtual bool visitSelector(); - - virtual bool visitInstancetype(); - - virtual bool visitClass(const ClassType& typeDetails); - - virtual bool visitProtocol(); - - virtual bool visitId(const IdType& typeDetails); - - virtual bool visitConstantArray(const ConstantArrayType& typeDetails); - - virtual bool visitExtVector(const ExtVectorType& typeDetails); - - virtual bool visitIncompleteArray(const IncompleteArrayType& typeDetails); - - virtual bool visitInterface(const InterfaceType& typeDetails); - - virtual bool visitBridgedInterface(const BridgedInterfaceType& typeDetails); - - virtual bool visitPointer(const PointerType& typeDetails); - - virtual bool visitBlock(const BlockType& typeDetails); - - virtual bool visitFunctionPointer(const FunctionPointerType& typeDetails); - - virtual bool visitStruct(const StructType& typeDetails); - - virtual bool visitUnion(const UnionType& typeDetails); - - virtual bool visitAnonymousStruct(const AnonymousStructType& typeDetails); - - virtual bool visitAnonymousUnion(const AnonymousUnionType& typeDetails); - - virtual bool visitEnum(const EnumType& typeDetails); - - virtual bool visitTypeArgument(const ::Meta::TypeArgumentType& type); - - -private: - MetaFactory& _metaFactory; + public: + explicit ValidateMetaTypeVisitor(MetaFactory& factory) + : _metaFactory(factory) {} + + virtual bool visitVoid(); + + virtual bool visitBool(); + + virtual bool visitShort(); + + virtual bool visitUShort(); + + virtual bool visitInt(); + + virtual bool visitUInt(); + + virtual bool visitLong(); + + virtual bool visitUlong(); + + virtual bool visitLongLong(); + + virtual bool visitULongLong(); + + virtual bool visitSignedChar(); + + virtual bool visitUnsignedChar(); + + virtual bool visitUnichar(); + + virtual bool visitCString(); + + virtual bool visitFloat(); + + virtual bool visitDouble(); + + virtual bool visitVaList(); + + virtual bool visitSelector(); + + virtual bool visitInstancetype(); + + virtual bool visitClass(const ClassType& typeDetails); + + virtual bool visitProtocol(); + + virtual bool visitId(const IdType& typeDetails); + + virtual bool visitConstantArray(const ConstantArrayType& typeDetails); + + virtual bool visitExtVector(const ExtVectorType& typeDetails); + + virtual bool visitIncompleteArray(const IncompleteArrayType& typeDetails); + + virtual bool visitInterface(const InterfaceType& typeDetails); + + virtual bool visitBridgedInterface(const BridgedInterfaceType& typeDetails); + + virtual bool visitPointer(const PointerType& typeDetails); + + virtual bool visitBlock(const BlockType& typeDetails); + + virtual bool visitFunctionPointer(const FunctionPointerType& typeDetails); + + virtual bool visitStruct(const StructType& typeDetails); + + virtual bool visitUnion(const UnionType& typeDetails); + + virtual bool visitAnonymousStruct(const AnonymousStructType& typeDetails); + + virtual bool visitAnonymousUnion(const AnonymousUnionType& typeDetails); + + virtual bool visitEnum(const EnumType& typeDetails); + + virtual bool visitTypeArgument(const ::Meta::TypeArgumentType& type); + + virtual bool visitNullable(const ::Meta::NullableType& type); + + private: + MetaFactory& _metaFactory; }; #endif /* ValidateMetaTypeVisitor_h */ diff --git a/metadata-generator/src/TypeScript/DefinitionWriter.cpp b/metadata-generator/src/TypeScript/DefinitionWriter.cpp index d081c8fb..8976a031 100644 --- a/metadata-generator/src/TypeScript/DefinitionWriter.cpp +++ b/metadata-generator/src/TypeScript/DefinitionWriter.cpp @@ -1,882 +1,960 @@ #include "DefinitionWriter.h" -#include "Meta/Utils.h" -#include "Meta/NameRetrieverVisitor.h" -#include "Utils/StringUtils.h" -#include + #include + +#include #include +#include "Meta/NameRetrieverVisitor.h" +#include "Meta/Utils.h" +#include "Utils/StringUtils.h" + namespace TypeScript { using namespace Meta; -static std::unordered_set hiddenMethods = { "retain", "release", "autorelease", "allocWithZone", "zone", "countByEnumeratingWithStateObjectsCount" }; +static std::unordered_set hiddenMethods = { + "retain", "release", "autorelease", + "allocWithZone", "zone", "countByEnumeratingWithStateObjectsCount"}; -static std::unordered_set bannedIdentifiers = { "function", "arguments", "in" }; +static std::unordered_set bannedIdentifiers = {"function", + "arguments", "in"}; bool DefinitionWriter::applyManualChanges = false; -static std::string sanitizeParameterName(const std::string& parameterName) -{ - if (bannedIdentifiers.find(parameterName) != bannedIdentifiers.end()) { - return "_" + parameterName; - } - else { - return parameterName; - } +static std::string sanitizeParameterName(const std::string& parameterName) { + if (bannedIdentifiers.find(parameterName) != bannedIdentifiers.end()) { + return "_" + parameterName; + } else { + return parameterName; + } } -static std::string getTypeParametersStringOrEmpty(const clang::ObjCInterfaceDecl* interfaceDecl) -{ - std::ostringstream output; - if (clang::ObjCTypeParamList* typeParameters = interfaceDecl->getTypeParamListAsWritten()) { - if (typeParameters->size()) { - output << "<"; - for (unsigned i = 0; i < typeParameters->size(); i++) { - clang::ObjCTypeParamDecl* typeParam = *(typeParameters->begin() + i); - output << typeParam->getNameAsString(); - if (i < typeParameters->size() - 1) { - output << ", "; - } - } - output << ">"; +static std::string getTypeParametersStringOrEmpty( + const clang::ObjCInterfaceDecl* interfaceDecl) { + std::ostringstream output; + if (clang::ObjCTypeParamList* typeParameters = + interfaceDecl->getTypeParamListAsWritten()) { + if (typeParameters->size()) { + output << "<"; + for (unsigned i = 0; i < typeParameters->size(); i++) { + clang::ObjCTypeParamDecl* typeParam = *(typeParameters->begin() + i); + output << typeParam->getNameAsString(); + if (i < typeParameters->size() - 1) { + output << ", "; } + } + output << ">"; } + } - return output.str(); + return output.str(); } - -static std::vector getTypeParameterNames(const clang::ObjCInterfaceDecl* interfaceDecl) -{ - std::vector params; - if (clang::ObjCTypeParamList* typeParameters = interfaceDecl->getTypeParamListAsWritten()) { - if (typeParameters->size()) { - for (unsigned i = 0; i < typeParameters->size(); i++) { - clang::ObjCTypeParamDecl* typeParam = *(typeParameters->begin() + i); - params.push_back(typeParam->getNameAsString()); - } - } - } - return params; + +static std::vector getTypeParameterNames( + const clang::ObjCInterfaceDecl* interfaceDecl) { + std::vector params; + if (clang::ObjCTypeParamList* typeParameters = + interfaceDecl->getTypeParamListAsWritten()) { + if (typeParameters->size()) { + for (unsigned i = 0; i < typeParameters->size(); i++) { + clang::ObjCTypeParamDecl* typeParam = *(typeParameters->begin() + i); + params.push_back(typeParam->getNameAsString()); + } + } + } + return params; } - -std::string DefinitionWriter::getTypeArgumentsStringOrEmpty(const clang::ObjCObjectType* objectType) -{ - std::ostringstream output; - llvm::ArrayRef typeArgs = objectType->getTypeArgsAsWritten(); - if (!typeArgs.empty()) { + +std::string DefinitionWriter::getTypeArgumentsStringOrEmpty( + const clang::ObjCObjectType* objectType) { + std::ostringstream output; + llvm::ArrayRef typeArgs = objectType->getTypeArgsAsWritten(); + if (!typeArgs.empty()) { + output << "<"; + for (unsigned i = 0; i < typeArgs.size(); i++) { + output << tsifyType(*_typeFactory.create(typeArgs[i])); + if (i < typeArgs.size() - 1) { + output << ", "; + } + } + output << ">"; + } else { + /* Fill implicit id parameters in similar cases: + * @interface MyInterface + * @interface MyDerivedInterface : MyInterface + */ + if (clang::ObjCTypeParamList* typeParameters = + objectType->getInterface()->getTypeParamListAsWritten()) { + if (typeParameters->size()) { output << "<"; - for (unsigned i = 0; i < typeArgs.size(); i++) { - output << tsifyType(*_typeFactory.create(typeArgs[i])); - if (i < typeArgs.size() - 1) { - output << ", "; - } + for (unsigned i = 0; i < typeParameters->size(); i++) { + output << "NSObject"; + if (i < typeParameters->size() - 1) { + output << ", "; + } } output << ">"; + } } - else { - /* Fill implicit id parameters in similar cases: - * @interface MyInterface - * @interface MyDerivedInterface : MyInterface - */ - if (clang::ObjCTypeParamList* typeParameters = objectType->getInterface()->getTypeParamListAsWritten()) { - if (typeParameters->size()) { - output << "<"; - for (unsigned i = 0; i < typeParameters->size(); i++) { - output << "NSObject"; - if (i < typeParameters->size() - 1) { - output << ", "; - } - } - output << ">"; - } - } - } + } - return output.str(); + return output.str(); } -void DefinitionWriter::visit(InterfaceMeta* meta) -{ - CompoundMemberMap compoundStaticMethods; - for (MethodMeta* method : meta->staticMethods) { - compoundStaticMethods.emplace(method->jsName, std::make_pair(meta, method)); - } - - CompoundMemberMap compoundInstanceMethods; - for (MethodMeta* method : meta->instanceMethods) { - compoundInstanceMethods.emplace(method->jsName, std::make_pair(meta, method)); - } - - CompoundMemberMap baseClassInstanceProperties; - CompoundMemberMap ownInstanceProperties; - for (PropertyMeta* property : meta->instanceProperties) { - if (ownInstanceProperties.find(property->jsName) == ownInstanceProperties.end()) { - ownInstanceProperties.emplace(property->jsName, std::make_pair(meta, property)); - } - } - - CompoundMemberMap baseClassStaticProperties; - CompoundMemberMap ownStaticProperties; - for (PropertyMeta* property : meta->staticProperties) { - if (ownStaticProperties.find(property->jsName) == ownStaticProperties.end()) { - ownStaticProperties.emplace(property->jsName, std::make_pair(meta, property)); - } - } - - std::unordered_set inheritedProtocols; - - CompoundMemberMap inheritedStaticMethods; - getInheritedMembersRecursive(meta, &inheritedStaticMethods, nullptr, nullptr, nullptr); - for (auto& methodPair : inheritedStaticMethods) { - MethodMeta* method = methodPair.second.second; - if (!method->signature[0]->is(TypeInstancetype)) { - continue; - } - if (compoundStaticMethods.find(method->jsName) != compoundStaticMethods.end()) { - continue; - } - compoundStaticMethods.emplace(methodPair); - } - - std::string metaJsName = meta->jsName; - std::string parametersString = getTypeParametersStringOrEmpty(clang::cast(meta->declaration)); - - if (DefinitionWriter::applyManualChanges) { - if (metaJsName == "UIEvent") { - metaJsName = "_UIEvent"; - } else if (metaJsName == "HMMutableCharacteristicEvent") { - // We need to add 'extends NSObject in order to inherit NSObject properties. By default it is exported as - // @interface HMMutableCharacteristicEvent> : HMCharacteristicEvent - parametersString = ""; - } - } - - _buffer << std::endl - << _docSet.getCommentFor(meta).toString("") << "declare class " << metaJsName << parametersString; - if (meta->base != nullptr) { - _buffer << " extends " << localizeReference(*meta->base) << getTypeArgumentsStringOrEmpty(clang::cast(meta->declaration)->getSuperClassType()); - } - - CompoundMemberMap protocolInheritedStaticProperties; - CompoundMemberMap protocolInheritedInstanceProperties; - std::unordered_set protocols; - if (meta->protocols.size()) { - _buffer << " implements "; - for (size_t i = 0; i < meta->protocols.size(); i++) { - getProtocolMembersRecursive(meta->protocols[i], &compoundStaticMethods, &compoundInstanceMethods, &protocolInheritedStaticProperties, &protocolInheritedInstanceProperties, protocols); - _buffer << localizeReference(*meta->protocols[i]); - if (i < meta->protocols.size() - 1) { - _buffer << ", "; - } - } - } - _buffer << " {" << std::endl; - - std::unordered_set immediateProtocols; - for (auto protocol : protocols) { - if (inheritedProtocols.find(protocol) == inheritedProtocols.end()) { - immediateProtocols.insert(protocol); - } - } - - for (auto& methodPair : compoundStaticMethods) { - if (ownStaticProperties.find(methodPair.first) != ownStaticProperties.end()) { - continue; - } - - std::string output = writeMethod(methodPair, meta, immediateProtocols); - if (output.size()) { - MethodMeta* method = methodPair.second.second; - BaseClassMeta* owner = methodPair.second.first; - _buffer << std::endl - << _docSet.getCommentFor(method, owner).toString("\t"); - _buffer << "\tstatic " << output << std::endl; - } - } - - for (auto& propertyPair : ownInstanceProperties) { - BaseClassMeta* owner = propertyPair.second.first; - PropertyMeta* propertyMeta = propertyPair.second.second; - - if (owner == meta) { - this->writeProperty(propertyMeta, owner, meta, baseClassInstanceProperties); - } - } - - for (auto& propertyPair : ownStaticProperties) { - BaseClassMeta* owner = propertyPair.second.first; - PropertyMeta* propertyMeta = propertyPair.second.second; - - if (owner == meta) { - this->writeProperty(propertyMeta, owner, meta, baseClassInstanceProperties); - } - } - - for (auto& propertyPair : protocolInheritedInstanceProperties) { - BaseClassMeta* owner = propertyPair.second.first; - PropertyMeta* propertyMeta = propertyPair.second.second; - - bool isDuplicated = ownInstanceProperties.find(propertyMeta->jsName) != ownInstanceProperties.end(); - if (immediateProtocols.find(reinterpret_cast(owner)) != immediateProtocols.end() && !isDuplicated) { - this->writeProperty(propertyMeta, owner, meta, baseClassInstanceProperties); - } - } - - for (auto& propertyPair : protocolInheritedStaticProperties) { - BaseClassMeta* owner = propertyPair.second.first; - PropertyMeta* propertyMeta = propertyPair.second.second; - this->writeProperty(propertyMeta, owner, meta, baseClassStaticProperties); - } - - auto objectAtIndexedSubscript = compoundInstanceMethods.find("objectAtIndexedSubscript"); - if (objectAtIndexedSubscript != compoundInstanceMethods.end()) { - const Type* retType = objectAtIndexedSubscript->second.second->signature[0]; - std::string indexerReturnType = computeMethodReturnType(retType, meta, true); - _buffer << "\t[index: number]: " << indexerReturnType << ";" << std::endl; - } - - if (compoundInstanceMethods.find("countByEnumeratingWithStateObjectsCount") != compoundInstanceMethods.end()) { - _buffer << "\t[Symbol.iterator](): Iterator;" << std::endl; - } - - for (auto& methodPair : compoundInstanceMethods) { - if (methodPair.second.second->getFlags(MethodIsInitializer)) { - _buffer << std::endl - << _docSet.getCommentFor(methodPair.second.second, methodPair.second.first).toString("\t"); - _buffer << "\t" << writeConstructor(methodPair, meta) << std::endl; - } - } - - for (auto& methodPair : compoundInstanceMethods) { - if (ownInstanceProperties.find(methodPair.first) != ownInstanceProperties.end()) { - continue; - } - - // if (methodPair.second.second->getFlags(MethodIsInitializer)) { - // continue; - // } - - std::string output = writeMethod(methodPair, meta, immediateProtocols, true); - if (output.size()) { - _buffer << std::endl - << _docSet.getCommentFor(methodPair.second.second, methodPair.second.first).toString("\t"); - _buffer << "\t" << output << std::endl; - } - } - - _buffer << "}" << std::endl; +void DefinitionWriter::visit(InterfaceMeta* meta) { + CompoundMemberMap compoundStaticMethods; + for (MethodMeta* method : meta->staticMethods) { + compoundStaticMethods.emplace(method->jsName, std::make_pair(meta, method)); + } + + CompoundMemberMap compoundInstanceMethods; + for (MethodMeta* method : meta->instanceMethods) { + compoundInstanceMethods.emplace(method->jsName, + std::make_pair(meta, method)); + } + + CompoundMemberMap baseClassInstanceProperties; + CompoundMemberMap ownInstanceProperties; + for (PropertyMeta* property : meta->instanceProperties) { + if (ownInstanceProperties.find(property->jsName) == + ownInstanceProperties.end()) { + ownInstanceProperties.emplace(property->jsName, + std::make_pair(meta, property)); + } + } + + CompoundMemberMap baseClassStaticProperties; + CompoundMemberMap ownStaticProperties; + for (PropertyMeta* property : meta->staticProperties) { + if (ownStaticProperties.find(property->jsName) == + ownStaticProperties.end()) { + ownStaticProperties.emplace(property->jsName, + std::make_pair(meta, property)); + } + } + + std::unordered_set inheritedProtocols; + + CompoundMemberMap inheritedStaticMethods; + getInheritedMembersRecursive(meta, &inheritedStaticMethods, nullptr, nullptr, + nullptr); + for (auto& methodPair : inheritedStaticMethods) { + MethodMeta* method = methodPair.second.second; + if (!method->signature[0]->is(TypeInstancetype)) { + continue; + } + if (compoundStaticMethods.find(method->jsName) != + compoundStaticMethods.end()) { + continue; + } + compoundStaticMethods.emplace(methodPair); + } + + std::string metaJsName = meta->jsName; + std::string parametersString = getTypeParametersStringOrEmpty( + clang::cast(meta->declaration)); + + if (DefinitionWriter::applyManualChanges) { + if (metaJsName == "UIEvent") { + metaJsName = "_UIEvent"; + } else if (metaJsName == "HMMutableCharacteristicEvent") { + // We need to add 'extends NSObject in order to inherit NSObject + // properties. By default it is exported as + // @interface HMMutableCharacteristicEvent> : HMCharacteristicEvent + parametersString = ""; + } + } + + _buffer << std::endl + << _docSet.getCommentFor(meta).toString("") << "declare class " + << metaJsName << parametersString; + if (meta->base != nullptr) { + _buffer << " extends " << localizeReference(*meta->base) + << getTypeArgumentsStringOrEmpty( + clang::cast(meta->declaration) + ->getSuperClassType()); + } + + CompoundMemberMap protocolInheritedStaticProperties; + CompoundMemberMap protocolInheritedInstanceProperties; + std::unordered_set protocols; + if (meta->protocols.size()) { + _buffer << " implements "; + for (size_t i = 0; i < meta->protocols.size(); i++) { + getProtocolMembersRecursive( + meta->protocols[i], &compoundStaticMethods, &compoundInstanceMethods, + &protocolInheritedStaticProperties, + &protocolInheritedInstanceProperties, protocols); + _buffer << localizeReference(*meta->protocols[i]); + if (i < meta->protocols.size() - 1) { + _buffer << ", "; + } + } + } + _buffer << " {" << std::endl; + + std::unordered_set immediateProtocols; + for (auto protocol : protocols) { + if (inheritedProtocols.find(protocol) == inheritedProtocols.end()) { + immediateProtocols.insert(protocol); + } + } + + for (auto& methodPair : compoundStaticMethods) { + if (ownStaticProperties.find(methodPair.first) != + ownStaticProperties.end()) { + continue; + } + + std::string output = writeMethod(methodPair, meta, immediateProtocols); + if (output.size()) { + MethodMeta* method = methodPair.second.second; + BaseClassMeta* owner = methodPair.second.first; + _buffer << std::endl + << _docSet.getCommentFor(method, owner).toString("\t"); + _buffer << "\tstatic " << output << std::endl; + } + } + + for (auto& propertyPair : ownInstanceProperties) { + BaseClassMeta* owner = propertyPair.second.first; + PropertyMeta* propertyMeta = propertyPair.second.second; + + if (owner == meta) { + this->writeProperty(propertyMeta, owner, meta, + baseClassInstanceProperties); + } + } + + for (auto& propertyPair : ownStaticProperties) { + BaseClassMeta* owner = propertyPair.second.first; + PropertyMeta* propertyMeta = propertyPair.second.second; + + if (owner == meta) { + this->writeProperty(propertyMeta, owner, meta, + baseClassInstanceProperties); + } + } + + for (auto& propertyPair : protocolInheritedInstanceProperties) { + BaseClassMeta* owner = propertyPair.second.first; + PropertyMeta* propertyMeta = propertyPair.second.second; + + bool isDuplicated = ownInstanceProperties.find(propertyMeta->jsName) != + ownInstanceProperties.end(); + if (immediateProtocols.find(reinterpret_cast(owner)) != + immediateProtocols.end() && + !isDuplicated) { + this->writeProperty(propertyMeta, owner, meta, + baseClassInstanceProperties); + } + } + + for (auto& propertyPair : protocolInheritedStaticProperties) { + BaseClassMeta* owner = propertyPair.second.first; + PropertyMeta* propertyMeta = propertyPair.second.second; + this->writeProperty(propertyMeta, owner, meta, baseClassStaticProperties); + } + + auto objectAtIndexedSubscript = + compoundInstanceMethods.find("objectAtIndexedSubscript"); + if (objectAtIndexedSubscript != compoundInstanceMethods.end()) { + const Type* retType = objectAtIndexedSubscript->second.second->signature[0]; + std::string indexerReturnType = + computeMethodReturnType(retType, meta, true); + _buffer << "\t[index: number]: " << indexerReturnType << ";" << std::endl; + } + + if (compoundInstanceMethods.find("countByEnumeratingWithStateObjectsCount") != + compoundInstanceMethods.end()) { + _buffer << "\t[Symbol.iterator](): Iterator;" << std::endl; + } + + for (auto& methodPair : compoundInstanceMethods) { + if (methodPair.second.second->getFlags(MethodIsInitializer)) { + _buffer << std::endl + << _docSet + .getCommentFor(methodPair.second.second, + methodPair.second.first) + .toString("\t"); + _buffer << "\t" << writeConstructor(methodPair, meta) << std::endl; + } + } + + for (auto& methodPair : compoundInstanceMethods) { + if (ownInstanceProperties.find(methodPair.first) != + ownInstanceProperties.end()) { + continue; + } + + // if (methodPair.second.second->getFlags(MethodIsInitializer)) { + // continue; + // } + + std::string output = + writeMethod(methodPair, meta, immediateProtocols, true); + if (output.size()) { + _buffer << std::endl + << _docSet + .getCommentFor(methodPair.second.second, + methodPair.second.first) + .toString("\t"); + _buffer << "\t" << output << std::endl; + } + } + + _buffer << "}" << std::endl; } -void DefinitionWriter::writeProperty(PropertyMeta* propertyMeta, BaseClassMeta* owner, InterfaceMeta* target, CompoundMemberMap baseClassProperties) -{ - _buffer << std::endl - << _docSet.getCommentFor(propertyMeta, owner).toString("\t"); - _buffer << "\t"; - - if (clang::cast(propertyMeta->declaration)->isClassProperty()) { - _buffer << "static "; - } - - if (!propertyMeta->setter) { - _buffer << "readonly "; - } - - bool optOutTypeChecking = false; - auto result = baseClassProperties.find(propertyMeta->jsName); - if (result != baseClassProperties.end()) { - optOutTypeChecking = result->second.second->getter->signature[0] != propertyMeta->getter->signature[0]; - } - _buffer << writeProperty(propertyMeta, target, optOutTypeChecking); - - if (owner != target) { - _buffer << " // inherited from " << localizeReference(*owner); - } - - _buffer << std::endl; +void DefinitionWriter::writeProperty( + PropertyMeta* propertyMeta, BaseClassMeta* owner, InterfaceMeta* target, + CompoundMemberMap baseClassProperties) { + _buffer << std::endl + << _docSet.getCommentFor(propertyMeta, owner).toString("\t"); + _buffer << "\t"; + + if (clang::cast(propertyMeta->declaration) + ->isClassProperty()) { + _buffer << "static "; + } + + if (!propertyMeta->setter) { + _buffer << "readonly "; + } + + bool optOutTypeChecking = false; + auto result = baseClassProperties.find(propertyMeta->jsName); + if (result != baseClassProperties.end()) { + optOutTypeChecking = result->second.second->getter->signature[0] != + propertyMeta->getter->signature[0]; + } + _buffer << writeProperty(propertyMeta, target, optOutTypeChecking); + + if (owner != target) { + _buffer << " // inherited from " << localizeReference(*owner); + } + + _buffer << std::endl; } -void DefinitionWriter::getInheritedMembersRecursive(InterfaceMeta* interface, - CompoundMemberMap* staticMethods, +void DefinitionWriter::getInheritedMembersRecursive( + InterfaceMeta* interface, CompoundMemberMap* staticMethods, CompoundMemberMap* instanceMethods, CompoundMemberMap* staticProperties, - CompoundMemberMap* instanceProperties) -{ - auto base = interface->base; - if (!base) { - return; - } - - if (staticMethods) { - for (MethodMeta* method : base->staticMethods) { - if (staticMethods->find(method->jsName) == staticMethods->end()) { - staticMethods->emplace(method->jsName, std::make_pair(base, method)); - } - } - } - - if (instanceMethods) { - for (MethodMeta* method : base->instanceMethods) { - if (instanceMethods->find(method->jsName) == instanceMethods->end()) { - instanceMethods->emplace(method->jsName, std::make_pair(base, method)); - } - } - } - - if (staticProperties) { - for (PropertyMeta* property : base->staticProperties) { - if (staticProperties->find(property->jsName) == staticProperties->end()) { - staticProperties->emplace(property->jsName, std::make_pair(base, property)); - } - } - } - - if (instanceProperties) { - for (PropertyMeta* property : base->instanceProperties) { - if (instanceProperties->find(property->jsName) == instanceProperties->end()) { - instanceProperties->emplace(property->jsName, std::make_pair(base, property)); - } - } - } - - // accumulate... - std::unordered_set protocols; - for (auto protocol : base->protocols) { - getProtocolMembersRecursive(protocol, staticMethods, instanceMethods, staticProperties, instanceProperties, protocols); - } - - getInheritedMembersRecursive(base, staticMethods, instanceMethods, staticProperties, instanceProperties); + CompoundMemberMap* instanceProperties) { + auto base = interface->base; + if (!base) { + return; + } + + if (staticMethods) { + for (MethodMeta* method : base->staticMethods) { + if (staticMethods->find(method->jsName) == staticMethods->end()) { + staticMethods->emplace(method->jsName, std::make_pair(base, method)); + } + } + } + + if (instanceMethods) { + for (MethodMeta* method : base->instanceMethods) { + if (instanceMethods->find(method->jsName) == instanceMethods->end()) { + instanceMethods->emplace(method->jsName, std::make_pair(base, method)); + } + } + } + + if (staticProperties) { + for (PropertyMeta* property : base->staticProperties) { + if (staticProperties->find(property->jsName) == staticProperties->end()) { + staticProperties->emplace(property->jsName, + std::make_pair(base, property)); + } + } + } + + if (instanceProperties) { + for (PropertyMeta* property : base->instanceProperties) { + if (instanceProperties->find(property->jsName) == + instanceProperties->end()) { + instanceProperties->emplace(property->jsName, + std::make_pair(base, property)); + } + } + } + + // accumulate... + std::unordered_set protocols; + for (auto protocol : base->protocols) { + getProtocolMembersRecursive(protocol, staticMethods, instanceMethods, + staticProperties, instanceProperties, + protocols); + } + + getInheritedMembersRecursive(base, staticMethods, instanceMethods, + staticProperties, instanceProperties); } -void DefinitionWriter::getProtocolMembersRecursive(ProtocolMeta* protocolMeta, - CompoundMemberMap* staticMethods, +void DefinitionWriter::getProtocolMembersRecursive( + ProtocolMeta* protocolMeta, CompoundMemberMap* staticMethods, CompoundMemberMap* instanceMethods, CompoundMemberMap* staticProperties, CompoundMemberMap* instanceProperties, - std::unordered_set& visitedProtocols) -{ - visitedProtocols.insert(protocolMeta); - - if (staticMethods) { - for (MethodMeta* method : protocolMeta->staticMethods) { - if (staticMethods->find(method->jsName) == staticMethods->end()) { - staticMethods->emplace(method->jsName, std::make_pair(protocolMeta, method)); - } - } - } - - if (instanceMethods) { - for (MethodMeta* method : protocolMeta->instanceMethods) { - if (instanceMethods->find(method->jsName) == instanceMethods->end()) { - instanceMethods->emplace(method->jsName, std::make_pair(protocolMeta, method)); - } - } - } - - if (staticProperties) { - for (PropertyMeta* property : protocolMeta->staticProperties) { - if (staticProperties->find(property->jsName) == staticProperties->end()) { - staticProperties->emplace(property->jsName, std::make_pair(protocolMeta, property)); - } - } - } - - if (instanceProperties) { - for (PropertyMeta* property : protocolMeta->instanceProperties) { - if (instanceProperties->find(property->jsName) == instanceProperties->end()) { - instanceProperties->emplace(property->jsName, std::make_pair(protocolMeta, property)); - } - } - } - - for (ProtocolMeta* protocol : protocolMeta->protocols) { - getProtocolMembersRecursive(protocol, staticMethods, instanceMethods, staticProperties, instanceProperties, visitedProtocols); - } + std::unordered_set& visitedProtocols) { + visitedProtocols.insert(protocolMeta); + + if (staticMethods) { + for (MethodMeta* method : protocolMeta->staticMethods) { + if (staticMethods->find(method->jsName) == staticMethods->end()) { + staticMethods->emplace(method->jsName, + std::make_pair(protocolMeta, method)); + } + } + } + + if (instanceMethods) { + for (MethodMeta* method : protocolMeta->instanceMethods) { + if (instanceMethods->find(method->jsName) == instanceMethods->end()) { + instanceMethods->emplace(method->jsName, + std::make_pair(protocolMeta, method)); + } + } + } + + if (staticProperties) { + for (PropertyMeta* property : protocolMeta->staticProperties) { + if (staticProperties->find(property->jsName) == staticProperties->end()) { + staticProperties->emplace(property->jsName, + std::make_pair(protocolMeta, property)); + } + } + } + + if (instanceProperties) { + for (PropertyMeta* property : protocolMeta->instanceProperties) { + if (instanceProperties->find(property->jsName) == + instanceProperties->end()) { + instanceProperties->emplace(property->jsName, + std::make_pair(protocolMeta, property)); + } + } + } + + for (ProtocolMeta* protocol : protocolMeta->protocols) { + getProtocolMembersRecursive(protocol, staticMethods, instanceMethods, + staticProperties, instanceProperties, + visitedProtocols); + } } -void DefinitionWriter::visit(ProtocolMeta* meta) -{ +void DefinitionWriter::visit(ProtocolMeta* meta) { + _buffer << std::endl << _docSet.getCommentFor(meta).toString(""); + + std::string metaName = meta->jsName; + + if (DefinitionWriter::applyManualChanges) { + if (metaName == "AudioBuffer") { + metaName = "_AudioBuffer"; + } + } + + _buffer << "interface " << metaName; + std::map conformedProtocolsProperties; + if (meta->protocols.size()) { + _buffer << " extends "; + for (size_t i = 0; i < meta->protocols.size(); i++) { + std::transform(meta->protocols[i]->instanceProperties.begin(), + meta->protocols[i]->instanceProperties.end(), + std::inserter(conformedProtocolsProperties, + conformedProtocolsProperties.end()), + [](PropertyMeta* propertyMeta) { + return std::make_pair(propertyMeta->jsName, + propertyMeta); + }); + + _buffer << localizeReference(*meta->protocols[i]); + if (i < meta->protocols.size() - 1) { + _buffer << ", "; + } + } + } + _buffer << " {" << std::endl; + + for (PropertyMeta* property : meta->instanceProperties) { + bool optOutTypeChecking = + conformedProtocolsProperties.find(property->jsName) != + conformedProtocolsProperties.end(); _buffer << std::endl - << _docSet.getCommentFor(meta).toString(""); - - std::string metaName = meta->jsName; - - if (DefinitionWriter::applyManualChanges) { - - if (metaName == "AudioBuffer") { - metaName = "_AudioBuffer"; - } - } + << _docSet.getCommentFor(property, meta).toString("\t") << "\t" + << writeProperty(property, meta, optOutTypeChecking) << std::endl; + } - _buffer << "interface " << metaName; - std::map conformedProtocolsProperties; - if (meta->protocols.size()) { - _buffer << " extends "; - for (size_t i = 0; i < meta->protocols.size(); i++) { - std::transform(meta->protocols[i]->instanceProperties.begin(), meta->protocols[i]->instanceProperties.end(), std::inserter(conformedProtocolsProperties, conformedProtocolsProperties.end()), [](PropertyMeta* propertyMeta) { - return std::make_pair(propertyMeta->jsName, propertyMeta); - }); - - _buffer << localizeReference(*meta->protocols[i]); - if (i < meta->protocols.size() - 1) { - _buffer << ", "; - } - } + for (MethodMeta* method : meta->instanceMethods) { + if (hiddenMethods.find(method->jsName) == hiddenMethods.end()) { + _buffer << std::endl + << _docSet.getCommentFor(method, meta).toString("\t") << "\t" + << writeMethod(method, meta) << std::endl; } - _buffer << " {" << std::endl; + } - for (PropertyMeta* property : meta->instanceProperties) { - bool optOutTypeChecking = conformedProtocolsProperties.find(property->jsName) != conformedProtocolsProperties.end(); - _buffer << std::endl - << _docSet.getCommentFor(property, meta).toString("\t") << "\t" << writeProperty(property, meta, optOutTypeChecking) << std::endl; - } + _buffer << "}" << std::endl; - for (MethodMeta* method : meta->instanceMethods) { - if (hiddenMethods.find(method->jsName) == hiddenMethods.end()) { - _buffer << std::endl - << _docSet.getCommentFor(method, meta).toString("\t") << "\t" << writeMethod(method, meta) << std::endl; - } - } + _buffer << "declare var " << metaName << ": {" << std::endl; - _buffer << "}" << std::endl; + _buffer << std::endl << "\tprototype: " << metaName << ";" << std::endl; - _buffer << "declare var " << metaName << ": {" << std::endl; + CompoundMemberMap compoundStaticMethods; + for (MethodMeta* method : meta->staticMethods) { + compoundStaticMethods.emplace(method->jsName, std::make_pair(meta, method)); + } - _buffer << std::endl - << "\tprototype: " << metaName << ";" << std::endl; + std::unordered_set protocols; + for (ProtocolMeta* protocol : meta->protocols) { + getProtocolMembersRecursive(protocol, &compoundStaticMethods, nullptr, + nullptr, nullptr, protocols); + } - CompoundMemberMap compoundStaticMethods; - for (MethodMeta* method : meta->staticMethods) { - compoundStaticMethods.emplace(method->jsName, std::make_pair(meta, method)); + for (auto& methodPair : compoundStaticMethods) { + std::string output = writeMethod(methodPair, meta, protocols); + if (output.size()) { + MethodMeta* method = methodPair.second.second; + BaseClassMeta* owner = methodPair.second.first; + _buffer << std::endl + << _docSet.getCommentFor(method, owner).toString("\t"); + _buffer << "\t" << output << std::endl; } + } - std::unordered_set protocols; - for (ProtocolMeta* protocol : meta->protocols) { - getProtocolMembersRecursive(protocol, &compoundStaticMethods, nullptr, nullptr, nullptr, protocols); - } - - for (auto& methodPair : compoundStaticMethods) { - std::string output = writeMethod(methodPair, meta, protocols); - if (output.size()) { - MethodMeta* method = methodPair.second.second; - BaseClassMeta* owner = methodPair.second.first; - _buffer << std::endl - << _docSet.getCommentFor(method, owner).toString("\t"); - _buffer << "\t" << output << std::endl; - } - } - - _buffer << "};" << std::endl; + _buffer << "};" << std::endl; } -std::string DefinitionWriter::writeConstructor(const CompoundMemberMap::value_type& initializer, - const BaseClassMeta* owner) -{ - MethodMeta* method = initializer.second.second; - assert(method->getFlags(MethodIsInitializer)); - - std::ostringstream output; +std::string DefinitionWriter::writeConstructor( + const CompoundMemberMap::value_type& initializer, + const BaseClassMeta* owner) { + MethodMeta* method = initializer.second.second; + assert(method->getFlags(MethodIsInitializer)); + + std::ostringstream output; + + if (method->constructorTokens == "") { + output << "constructor();"; + } else { + std::vector ctorTokens; + StringUtils::split(method->constructorTokens, ':', + std::back_inserter(ctorTokens)); + output << "constructor(o: { "; + for (size_t i = 0; i < ctorTokens.size(); i++) { + output << ctorTokens[i] << ": "; + output << (i + 1 < method->signature.size() + ? tsifyType(*method->signature[i + 1], true) + : "void") + << "; "; + } + output << "});"; + } + + BaseClassMeta* initializerOwner = initializer.second.first; + if (initializerOwner != owner) { + output << " // inherited from " << initializerOwner->jsName; + } + + return output.str(); +} - if (method->constructorTokens == "") { - output << "constructor();"; - } - else { - std::vector ctorTokens; - StringUtils::split(method->constructorTokens, ':', std::back_inserter(ctorTokens)); - output << "constructor(o: { "; - for (size_t i = 0; i < ctorTokens.size(); i++) { - output << ctorTokens[i] << ": "; - output << (i + 1 < method->signature.size() ? tsifyType(*method->signature[i + 1], true) : "void") << "; "; - } - output << "});"; +void getClosedGenericsIfAny(Type& type, std::vector& params) { + if (type.is(TypeInterface)) { + const InterfaceType& interfaceType = type.as(); + for (size_t i = 0; i < interfaceType.typeArguments.size(); i++) { + getClosedGenericsIfAny(*interfaceType.typeArguments[i], params); } - - BaseClassMeta* initializerOwner = initializer.second.first; - if (initializerOwner != owner) { - output << " // inherited from " << initializerOwner->jsName; + } else if (type.is(TypeTypeArgument)) { + TypeArgumentType* typeArg = &type.as(); + if (typeArg->visit(NameRetrieverVisitor::instanceTs) != "") { + if (std::find(params.begin(), params.end(), typeArg) == params.end()) { + params.push_back(typeArg); + } } - - return output.str(); + } } - -void getClosedGenericsIfAny(Type& type, std::vector& params) -{ - if (type.is(TypeInterface)) { - const InterfaceType& interfaceType = type.as(); - for (size_t i = 0; i < interfaceType.typeArguments.size(); i++) { - getClosedGenericsIfAny(*interfaceType.typeArguments[i], params); - } - } else if (type.is(TypeTypeArgument)) { - TypeArgumentType* typeArg = &type.as(); - if (typeArg->visit(NameRetrieverVisitor::instanceTs) != "") { - if (std::find(params.begin(), params.end(), typeArg) == params.end()) { - params.push_back(typeArg); - } + +std::string DefinitionWriter::writeMethod(MethodMeta* meta, + BaseClassMeta* owner, + bool canUseThisType) { + const clang::ObjCMethodDecl& methodDecl = + *clang::dyn_cast(meta->declaration); + auto parameters = methodDecl.parameters(); + + std::vector parameterNames; + std::vector paramsGenerics; + std::vector ownerGenerics; + if (owner->is(Interface)) { + ownerGenerics = getTypeParameterNames(clang::cast( + static_cast(owner)->declaration)); + } + + std::transform( + parameters.begin(), parameters.end(), std::back_inserter(parameterNames), + [](clang::ParmVarDecl* param) { return param->getNameAsString(); }); + + for (size_t i = 0; i < parameterNames.size(); i++) { + getClosedGenericsIfAny(*meta->signature[i + 1], paramsGenerics); + for (size_t n = 0; n < parameterNames.size(); n++) { + if (parameterNames[i] == parameterNames[n] && i != n) { + parameterNames[n] += std::to_string(n); + } + } + } + if (!paramsGenerics.empty()) { + for (size_t i = 0; i < paramsGenerics.size(); i++) { + std::string name = + paramsGenerics[i]->visit(NameRetrieverVisitor::instanceTs); + if (std::find(ownerGenerics.begin(), ownerGenerics.end(), name) == + ownerGenerics.end()) { + paramsGenerics.erase(paramsGenerics.begin() + i); + i--; + } + } + } + + std::ostringstream output; + + output << meta->jsName; + bool skipGenerics = false; + + if (DefinitionWriter::applyManualChanges) { + // HMMutableCharacteristicEvent constructors should not have generics. + // Default export: static alloc(): + // HMMutableCharacteristicEvent; + if (owner->jsName == "HMMutableCharacteristicEvent" && + (meta->jsName == "alloc" || meta->jsName == "new")) { + skipGenerics = true; + } + } + + const Type* retType = meta->signature[0]; + + if (!methodDecl.isInstanceMethod() && owner->is(MetaType::Interface)) { + if ((retType->is(TypeInstancetype) || + DefinitionWriter::hasClosedGenerics(*retType)) && + !skipGenerics) { + output << getTypeParametersStringOrEmpty( + clang::cast( + static_cast(owner)->declaration)); + } else if (!paramsGenerics.empty()) { + output << "<"; + for (size_t i = 0; i < paramsGenerics.size(); i++) { + auto name = paramsGenerics[i]->visit(NameRetrieverVisitor::instanceTs); + output << name; + if (i < paramsGenerics.size() - 1) { + output << ", "; } - } + } + output << ">"; + } + } + + if ((owner->type == MetaType::Protocol && + methodDecl.getImplementationControl() == + clang::ObjCMethodDecl::ImplementationControl::Optional) || + (owner->is(MetaType::Protocol) && meta->getFlags(MethodIsInitializer))) { + output << "?"; + } + + output << "("; + + size_t lastParamIndex = + meta->getFlags(::Meta::MetaFlags::MethodHasErrorOutParameter) + ? (meta->signature.size() - 1) + : meta->signature.size(); + + if (DefinitionWriter::applyManualChanges) { + // Default export: + // copy(sender: any): void; + // ObjC interface: + // - (IBAction)copy:(nullable id)sender; -> overrides parent class' (UIView) + // `copy` method + if (owner->jsName == "PDFView" && meta->jsName == "copy") { + lastParamIndex = 0; + } + } + + for (size_t i = 1; i < lastParamIndex; i++) { + output << sanitizeParameterName(parameterNames[i - 1]) << ": " + << tsifyType(*meta->signature[i], true); + + if (i < lastParamIndex - 1) { + output << ", "; + } + } + + // If the method has an NSError** last parameter, emit an optional error + // parameter + if (meta->getFlags(::Meta::MetaFlags::MethodHasErrorOutParameter)) { + // If there were already parameters emitted, ensure we add a comma + if (lastParamIndex > 1) { + output << ", "; + } + // Emit a typed optional parameter for the NSError** out parameter. + // We use the conventional name 'error' and the interop.Reference wrapper + // expected by NativeScript. + output << "error?: interop.Reference"; + } + + output << "): "; + if (skipGenerics) { + output << "any;"; + } else { + output << computeMethodReturnType(retType, owner, canUseThisType) << ";"; + } + + return output.str(); } -std::string DefinitionWriter::writeMethod(MethodMeta* meta, BaseClassMeta* owner, bool canUseThisType) -{ - const clang::ObjCMethodDecl& methodDecl = *clang::dyn_cast(meta->declaration); - auto parameters = methodDecl.parameters(); +std::string DefinitionWriter::writeMethod( + CompoundMemberMap::value_type& methodPair, BaseClassMeta* owner, + const std::unordered_set& protocols, bool canUseThisType) { + std::ostringstream output; - std::vector parameterNames; - std::vector paramsGenerics; - std::vector ownerGenerics; - if (owner->is(Interface)) { - ownerGenerics = getTypeParameterNames(clang::cast(static_cast(owner)->declaration)); - } - - std::transform(parameters.begin(), parameters.end(), std::back_inserter(parameterNames), [](clang::ParmVarDecl* param) { - - return param->getNameAsString(); - }); - - for (size_t i = 0; i < parameterNames.size(); i++) { - getClosedGenericsIfAny(*meta->signature[i+1], paramsGenerics); - for (size_t n = 0; n < parameterNames.size(); n++) { - if (parameterNames[i] == parameterNames[n] && i != n) { - parameterNames[n] += std::to_string(n); - } - } - } - if (!paramsGenerics.empty()) { - for (size_t i = 0; i < paramsGenerics.size(); i++) { - std::string name = paramsGenerics[i]->visit(NameRetrieverVisitor::instanceTs); - if (std::find(ownerGenerics.begin(), ownerGenerics.end(), name) == ownerGenerics.end()) - { - paramsGenerics.erase(paramsGenerics.begin() + i); - i--; - } - } - } - - std::ostringstream output; + BaseClassMeta* memberOwner = methodPair.second.first; + MethodMeta* method = methodPair.second.second; - output << meta->jsName; - bool skipGenerics = false; + if (hiddenMethods.find(method->jsName) != hiddenMethods.end()) { + return std::string(); + } - if (DefinitionWriter::applyManualChanges) { - // HMMutableCharacteristicEvent constructors should not have generics. Default export: - // static alloc(): HMMutableCharacteristicEvent; - if (owner->jsName == "HMMutableCharacteristicEvent" && (meta->jsName == "alloc" || meta->jsName == "new")) { - skipGenerics = true; - } - } + bool isOwnMethod = memberOwner == owner; + bool implementsProtocol = + protocols.find(static_cast(memberOwner)) != + protocols.end(); + bool returnsInstanceType = method->signature[0]->is(TypeInstancetype); - const Type* retType = meta->signature[0]; - - if (!methodDecl.isInstanceMethod() && owner->is(MetaType::Interface)) { - if ((retType->is(TypeInstancetype) || DefinitionWriter::hasClosedGenerics(*retType)) && !skipGenerics) { - output << getTypeParametersStringOrEmpty( - clang::cast(static_cast(owner)->declaration)); - } else if (!paramsGenerics.empty()) { - output << "<"; - for (size_t i = 0; i < paramsGenerics.size(); i++) { - auto name = paramsGenerics[i]->visit(NameRetrieverVisitor::instanceTs); - output << name; - if (i < paramsGenerics.size() - 1) { - output << ", "; - } - } - output << ">"; - } + if (isOwnMethod || implementsProtocol || returnsInstanceType) { + output << writeMethod(method, owner, canUseThisType); + if (!isOwnMethod && !implementsProtocol) { + output << " // inherited from " + << localizeReference(memberOwner->jsName, + memberOwner->module->getFullModuleName()); } + } - if ((owner->type == MetaType::Protocol && methodDecl.getImplementationControl() == clang::ObjCMethodDecl::ImplementationControl::Optional) || (owner->is(MetaType::Protocol) && meta->getFlags(MethodIsInitializer))) { - output << "?"; - } - - output << "("; - - size_t lastParamIndex = meta->getFlags(::Meta::MetaFlags::MethodHasErrorOutParameter) ? (meta->signature.size() - 1) : meta->signature.size(); - - if (DefinitionWriter::applyManualChanges) { - // Default export: - // copy(sender: any): void; - // ObjC interface: - // - (IBAction)copy:(nullable id)sender; -> overrides parent class' (UIView) `copy` method - if (owner->jsName == "PDFView" && meta->jsName == "copy") { - lastParamIndex = 0; - } - } - - for (size_t i = 1; i < lastParamIndex; i++) { - - output << sanitizeParameterName(parameterNames[i - 1]) << ": " << tsifyType(*meta->signature[i], true); - - if (i < lastParamIndex - 1) { - output << ", "; - } - - } - - // If the method has an NSError** last parameter, emit an optional error parameter - if (meta->getFlags(::Meta::MetaFlags::MethodHasErrorOutParameter)) { - // If there were already parameters emitted, ensure we add a comma - if (lastParamIndex > 1) { - output << ", "; - } - // Emit a typed optional parameter for the NSError** out parameter. - // We use the conventional name 'error' and the interop.Reference wrapper expected by NativeScript. - output << "error?: interop.Reference"; - } - - output << "): "; - if (skipGenerics) { - output << "any;"; - } else { - output << computeMethodReturnType(retType, owner, canUseThisType) << ";"; - } - - return output.str(); + return output.str(); } -std::string DefinitionWriter::writeMethod(CompoundMemberMap::value_type& methodPair, BaseClassMeta* owner, const std::unordered_set& protocols, bool canUseThisType) -{ - std::ostringstream output; - - BaseClassMeta* memberOwner = methodPair.second.first; - MethodMeta* method = methodPair.second.second; - - if (hiddenMethods.find(method->jsName) != hiddenMethods.end()) { - return std::string(); - } - - bool isOwnMethod = memberOwner == owner; - bool implementsProtocol = protocols.find(static_cast(memberOwner)) != protocols.end(); - bool returnsInstanceType = method->signature[0]->is(TypeInstancetype); - - if (isOwnMethod || implementsProtocol || returnsInstanceType) { - output << writeMethod(method, owner, canUseThisType); - if (!isOwnMethod && !implementsProtocol) { - output << " // inherited from " << localizeReference(memberOwner->jsName, memberOwner->module->getFullModuleName()); - } - } - - return output.str(); +std::string DefinitionWriter::writeProperty(PropertyMeta* meta, + BaseClassMeta* owner, + bool optOutTypeChecking) { + std::ostringstream output; + + if (hiddenMethods.find(meta->jsName) != hiddenMethods.end()) { + return std::string(); + } + + // prevent writing out empty property names + if (meta->jsName.length() == 0) { + return std::string(); + } + + output << meta->jsName; + if (owner->is(MetaType::Protocol) && + clang::dyn_cast(meta->declaration) + ->getPropertyImplementation() == + clang::ObjCPropertyDecl::PropertyControl::Optional) { + output << "?"; + } + + std::string returnType = tsifyType(*meta->getter->signature[0]); + if (optOutTypeChecking) { + output << ": any; /*" << returnType << " */"; + } else { + output << ": " << returnType << ";"; + } + + return output.str(); } -std::string DefinitionWriter::writeProperty(PropertyMeta* meta, BaseClassMeta* owner, bool optOutTypeChecking) -{ - std::ostringstream output; +void DefinitionWriter::visit(CategoryMeta* meta) {} - if (hiddenMethods.find(meta->jsName) != hiddenMethods.end()) { - return std::string(); - } +void DefinitionWriter::visit(FunctionMeta* meta) { + const clang::FunctionDecl& functionDecl = + *clang::dyn_cast(meta->declaration); - // prevent writing out empty property names - if (meta->jsName.length() == 0) { - return std::string(); + std::ostringstream params; + for (size_t i = 1; i < meta->signature.size(); i++) { + std::string name = sanitizeParameterName( + functionDecl.getParamDecl(i - 1)->getNameAsString()); + params << (name.size() ? name : "p" + std::to_string(i)) << ": " + << tsifyType(*meta->signature[i], true); + if (i < meta->signature.size() - 1) { + params << ", "; } + } - output << meta->jsName; - if (owner->is(MetaType::Protocol) && clang::dyn_cast(meta->declaration)->getPropertyImplementation() == clang::ObjCPropertyDecl::PropertyControl::Optional) { - output << "?"; - } + _buffer << std::endl << _docSet.getCommentFor(meta).toString(""); + _buffer << "declare function " << meta->jsName << "(" << params.str() + << "): "; - std::string returnType = tsifyType(*meta->getter->signature[0]); - if (optOutTypeChecking) { - output << ": any; /*" << returnType << " */"; - } - else { - output << ": " << returnType << ";"; + std::string returnName; + if (meta->name == "UIApplicationMain" || meta->name == "NSApplicationMain" || + meta->name == "dispatch_main") { + returnName = "never"; + } else { + returnName = tsifyType(*meta->signature[0]); + if (meta->getFlags(MetaFlags::FunctionReturnsUnmanaged)) { + returnName = "interop.Unmanaged<" + returnName + ">"; } + } - return output.str(); -} + _buffer << returnName << ";"; -void DefinitionWriter::visit(CategoryMeta* meta) -{ + _buffer << std::endl; } -void DefinitionWriter::visit(FunctionMeta* meta) -{ - const clang::FunctionDecl& functionDecl = *clang::dyn_cast(meta->declaration); +void DefinitionWriter::visit(StructMeta* meta) { + std::string metaName = meta->jsName; - std::ostringstream params; - for (size_t i = 1; i < meta->signature.size(); i++) { - std::string name = sanitizeParameterName(functionDecl.getParamDecl(i - 1)->getNameAsString()); - params << (name.size() ? name : "p" + std::to_string(i)) << ": " << tsifyType(*meta->signature[i], true); - if (i < meta->signature.size() - 1) { - params << ", "; - } + if (DefinitionWriter::applyManualChanges) { + if (metaName == "AudioBuffer") { + metaName = "_AudioBuffer"; } + } - _buffer << std::endl - << _docSet.getCommentFor(meta).toString(""); - _buffer << "declare function " << meta->jsName - << "(" << params.str() << "): "; + TSComment comment = _docSet.getCommentFor(meta); + _buffer << std::endl << comment.toString(""); - std::string returnName; - if (meta->name == "UIApplicationMain" || meta->name == "NSApplicationMain" || meta->name == "dispatch_main") { - returnName = "never"; - } - else { - returnName = tsifyType(*meta->signature[0]); - if (meta->getFlags(MetaFlags::FunctionReturnsUnmanaged)) { - returnName = "interop.Unmanaged<" + returnName + ">"; - } - } + _buffer << "interface " << metaName << " {" << std::endl; + writeMembers(meta->fields, comment.fields); + _buffer << "}" << std::endl; - _buffer << returnName << ";"; + _buffer << "declare var " << metaName << ": interop.StructType<" << metaName + << ">;"; - _buffer << std::endl; + _buffer << std::endl; } -void DefinitionWriter::visit(StructMeta* meta) -{ - - std::string metaName = meta->jsName; +void DefinitionWriter::visit(UnionMeta* meta) { + TSComment comment = _docSet.getCommentFor(meta); + _buffer << std::endl << comment.toString(""); - if (DefinitionWriter::applyManualChanges) { - if (metaName == "AudioBuffer") { - metaName = "_AudioBuffer"; - } - } - - TSComment comment = _docSet.getCommentFor(meta); - _buffer << std::endl - << comment.toString(""); - - _buffer << "interface " << metaName << " {" << std::endl; - writeMembers(meta->fields, comment.fields); - _buffer << "}" << std::endl; + _buffer << "interface " << meta->jsName << " {" << std::endl; + writeMembers(meta->fields, comment.fields); + _buffer << "}" << std::endl; - _buffer << "declare var " << metaName << ": interop.StructType<" << metaName << ">;"; - - _buffer << std::endl; + _buffer << std::endl; } -void DefinitionWriter::visit(UnionMeta* meta) -{ - TSComment comment = _docSet.getCommentFor(meta); - _buffer << std::endl - << comment.toString(""); +void DefinitionWriter::writeMembers(const std::vector& fields, + std::vector fieldsComments) { + for (size_t i = 0; i < fields.size(); i++) { + if (i < fieldsComments.size()) { + _buffer << fieldsComments[i].toString("\t"); + } - _buffer << "interface " << meta->jsName << " {" << std::endl; - writeMembers(meta->fields, comment.fields); - _buffer << "}" << std::endl; + // prevent writing empty field names, + // fixes issue with structs containing emtpy bitfields (ie. + // __darwin_fp_control) + if (fields[i].name.length() == 0) { + continue; + } - _buffer << std::endl; + _buffer << "\t" << fields[i].name << ": " << tsifyType(*fields[i].encoding) + << ";" << std::endl; + } } -void DefinitionWriter::writeMembers(const std::vector& fields, std::vector fieldsComments) -{ - for (size_t i = 0; i < fields.size(); i++) { - if (i < fieldsComments.size()) { - _buffer << fieldsComments[i].toString("\t"); - } - - // prevent writing empty field names, - // fixes issue with structs containing emtpy bitfields (ie. __darwin_fp_control) - if(fields[i].name.length() == 0) { - continue; - } +void DefinitionWriter::visit(EnumMeta* meta) { + _buffer << std::endl << _docSet.getCommentFor(meta).toString(""); + _buffer << "declare const enum " << meta->jsName << " {" << std::endl; - _buffer << "\t" << fields[i].name << ": " << tsifyType(*fields[i].encoding) << ";" << std::endl; - } -} + std::vector& fields = meta->swiftNameFields.size() != 0 + ? meta->swiftNameFields + : meta->fullNameFields; -void DefinitionWriter::visit(EnumMeta* meta) -{ + for (size_t i = 0; i < fields.size(); i++) { _buffer << std::endl - << _docSet.getCommentFor(meta).toString(""); - _buffer << "declare const enum " << meta->jsName << " {" << std::endl; - - std::vector& fields = meta->swiftNameFields.size() != 0 ? meta->swiftNameFields : meta->fullNameFields; - - for (size_t i = 0; i < fields.size(); i++) { - _buffer << std::endl - << _docSet.getCommentFor(meta->fullNameFields[i].name, MetaType::EnumConstant).toString("\t"); - _buffer << "\t" << fields[i].name << " = " << fields[i].value; - if (i < fields.size() - 1) { - _buffer << ","; - } - _buffer << std::endl; + << _docSet + .getCommentFor(meta->fullNameFields[i].name, + MetaType::EnumConstant) + .toString("\t"); + _buffer << "\t" << fields[i].name << " = " << fields[i].value; + if (i < fields.size() - 1) { + _buffer << ","; } - - _buffer << "}"; _buffer << std::endl; + } + + _buffer << "}"; + _buffer << std::endl; } -void DefinitionWriter::visit(VarMeta* meta) -{ - _buffer << std::endl - << _docSet.getCommentFor(meta).toString(""); - _buffer << "declare var " << meta->jsName << ": " << tsifyType(*meta->signature) << ";" << std::endl; +void DefinitionWriter::visit(VarMeta* meta) { + _buffer << std::endl << _docSet.getCommentFor(meta).toString(""); + _buffer << "declare var " << meta->jsName << ": " + << tsifyType(*meta->signature) << ";" << std::endl; } -std::string DefinitionWriter::writeFunctionProto(const std::vector& signature) -{ - std::ostringstream output; - output << "("; +std::string DefinitionWriter::writeFunctionProto( + const std::vector& signature) { + std::ostringstream output; + output << "("; - for (size_t i = 1; i < signature.size(); i++) { - output << "p" << i << ": " << tsifyType(*signature[i]); - if (i < signature.size() - 1) { - output << ", "; - } + for (size_t i = 1; i < signature.size(); i++) { + output << "p" << i << ": " << tsifyType(*signature[i]); + if (i < signature.size() - 1) { + output << ", "; } + } - output << ") => " << tsifyType(*signature[0]); - return output.str(); + output << ") => " << tsifyType(*signature[0]); + return output.str(); } -void DefinitionWriter::visit(MethodMeta* meta) -{ -} +void DefinitionWriter::visit(MethodMeta* meta) {} -void DefinitionWriter::visit(PropertyMeta* meta) -{ -} +void DefinitionWriter::visit(PropertyMeta* meta) {} -void DefinitionWriter::visit(EnumConstantMeta* meta) -{ - // The member will be printed by its parent EnumMeta as a TS Enum - if (meta->isScoped) { - return; - } +void DefinitionWriter::visit(EnumConstantMeta* meta) { + // The member will be printed by its parent EnumMeta as a TS Enum + if (meta->isScoped) { + return; + } - _buffer << std::endl; - _buffer << "declare const " << meta->jsName << ": number;"; - _buffer << std::endl; + _buffer << std::endl; + _buffer << "declare const " << meta->jsName << ": number;"; + _buffer << std::endl; } -std::string DefinitionWriter::localizeReference(const std::string& jsName, std::string moduleName) -{ - if (DefinitionWriter::applyManualChanges) { - if (jsName == "AudioBuffer") { - return "_AudioBuffer"; - } else if (jsName == "UIEvent") { - return "_UIEvent"; - } +std::string DefinitionWriter::localizeReference(const std::string& jsName, + std::string moduleName) { + if (DefinitionWriter::applyManualChanges) { + if (jsName == "AudioBuffer") { + return "_AudioBuffer"; + } else if (jsName == "UIEvent") { + return "_UIEvent"; } - return jsName; + } + return jsName; } -std::string DefinitionWriter::localizeReference(const ::Meta::Meta& meta) -{ - return localizeReference(meta.jsName, meta.module->getFullModuleName()); +std::string DefinitionWriter::localizeReference(const ::Meta::Meta& meta) { + return localizeReference(meta.jsName, meta.module->getFullModuleName()); } -bool DefinitionWriter::hasClosedGenerics(const Type& type) -{ - if (type.is(TypeInterface)) { - const InterfaceType& interfaceType = type.as(); - return interfaceType.typeArguments.size(); - } +bool DefinitionWriter::hasClosedGenerics(const Type& type) { + if (type.is(TypeInterface)) { + const InterfaceType& interfaceType = type.as(); + return interfaceType.typeArguments.size(); + } - return false; + return false; } -std::string DefinitionWriter::tsifyType(const Type& type, const bool isFuncParam) -{ - switch (type.getType()) { +std::string DefinitionWriter::tsifyType(const Type& type, + const bool isFuncParam) { + switch (type.getType()) { case TypeVoid: - return "void"; + return "void"; case TypeBool: - return "boolean"; + return "boolean"; case TypeSignedChar: case TypeUnsignedChar: case TypeShort: @@ -889,205 +967,221 @@ std::string DefinitionWriter::tsifyType(const Type& type, const bool isFuncParam case TypeULongLong: case TypeFloat: case TypeDouble: - return "number"; + return "number"; case TypeUnichar: case TypeSelector: - return "string"; + return "string"; case TypeCString: { - std::string res = isFuncParam ? "string | " : ""; - Type typeVoid(TypeVoid); - res += tsifyType(::Meta::PointerType(&typeVoid), isFuncParam); - return res; + std::string res = isFuncParam ? "string | " : ""; + Type typeVoid(TypeVoid); + res += tsifyType(::Meta::PointerType(&typeVoid), isFuncParam); + return res; } case TypeProtocol: - return "any /* Protocol */"; + return "any /* Protocol */"; case TypeClass: - return "typeof " + localizeReference("NSObject", "ObjectiveC"); + return "typeof " + localizeReference("NSObject", "ObjectiveC"); case TypeId: { - const IdType& idType = type.as(); - if (idType.protocols.size() == 1) { - std::string protocol = localizeReference(*idType.protocols[0]); - // We pass string to be marshalled to NSString which conforms to NSCopying. NSCopying is tricky. - if (protocol != "NSCopying") { - return protocol; - } + const IdType& idType = type.as(); + if (idType.protocols.size() == 1) { + std::string protocol = localizeReference(*idType.protocols[0]); + // We pass string to be marshalled to NSString which conforms to + // NSCopying. NSCopying is tricky. + if (protocol != "NSCopying") { + return protocol; } - return "any"; + } + return "any"; } case TypeConstantArray: + return "interop.Reference<" + + tsifyType(*type.as().innerType) + ">"; case TypeExtVector: - return "interop.Reference<" + tsifyType(*type.as().innerType) + ">"; + return "interop.Reference<" + + tsifyType(*type.as().innerType) + ">"; case TypeIncompleteArray: - return "interop.Reference<" + tsifyType(*type.as().innerType) + ">"; + return "interop.Reference<" + + tsifyType(*type.as().innerType) + ">"; case TypePointer: { - const PointerType& pointerType = type.as(); - return (pointerType.innerType->is(TypeVoid)) ? "interop.Pointer | interop.Reference" : "interop.Pointer | interop.Reference<" + tsifyType(*pointerType.innerType) + ">"; + const PointerType& pointerType = type.as(); + std::string result = (pointerType.innerType->is(TypeVoid)) + ? "interop.Pointer | interop.Reference" + : "interop.Pointer | interop.Reference<" + + tsifyType(*pointerType.innerType) + ">"; + if (isFuncParam) { + result += " | ArrayBufferLike | ArrayBufferView"; + } + return result; } case TypeBlock: - return writeFunctionProto(type.as().signature); + return writeFunctionProto(type.as().signature); case TypeFunctionPointer: - return "interop.FunctionReference<" + writeFunctionProto(type.as().signature) - + ">"; + return "interop.FunctionReference<" + + writeFunctionProto(type.as().signature) + ">"; case TypeInterface: case TypeBridgedInterface: { - if (type.is(TypeType::TypeBridgedInterface) && type.as().isId()) { - return tsifyType(IdType()); - } + if (type.is(TypeType::TypeBridgedInterface) && + type.as().isId()) { + return tsifyType(IdType()); + } - const InterfaceMeta& interface = type.is(TypeType::TypeInterface) ? *type.as().interface : *type.as().bridgedInterface; - if (interface.name == "NSNumber") { - return "number"; - } - else if (interface.name == "NSString") { - return "string"; - } - else if (interface.name == "NSDate") { - return "Date"; + const InterfaceMeta& interface = type.is(TypeType::TypeInterface) ? *type.as().interface : *type.as().bridgedInterface; + if (interface.name == "NSNumber") { + return "number"; + } else if (interface.name == "NSString") { + return "string"; + } else if (interface.name == "NSDate") { + return "Date"; + } + + if (DefinitionWriter::applyManualChanges) { + if (interface.name == "UIEvent") { + return "_UIEvent"; } - - if (DefinitionWriter::applyManualChanges) { - if (interface.name == "UIEvent") { - return "_UIEvent"; - } - } + } - std::ostringstream output; - output << localizeReference(interface); + std::ostringstream output; + output << localizeReference(interface); - bool hasClosedGenerics = DefinitionWriter::hasClosedGenerics(type); - std::string firstElementType; - if (hasClosedGenerics) { - const InterfaceType& interfaceType = type.as(); - output << "<"; - for (size_t i = 0; i < interfaceType.typeArguments.size(); i++) { - std::string argType = tsifyType(*interfaceType.typeArguments[i]); - output << argType; - if (i == 0) { - firstElementType = argType;//we only need this for NSArray - } - if (i < interfaceType.typeArguments.size() - 1) { - output << ", "; - } - } - output << ">"; + bool hasClosedGenerics = DefinitionWriter::hasClosedGenerics(type); + std::string firstElementType; + if (hasClosedGenerics) { + const InterfaceType& interfaceType = type.as(); + output << "<"; + for (size_t i = 0; i < interfaceType.typeArguments.size(); i++) { + std::string argType = tsifyType(*interfaceType.typeArguments[i]); + output << argType; + if (i == 0) { + firstElementType = argType; // we only need this for NSArray + } + if (i < interfaceType.typeArguments.size() - 1) { + output << ", "; + } } - else { - // This also translates CFArray to NSArray - if (auto typeParamList = clang::dyn_cast(interface.declaration)->getTypeParamListAsWritten()) { - output << "<"; - for (size_t i = 0; i < typeParamList->size(); i++) { - output << "any"; - if (i < typeParamList->size() - 1) { - output << ", "; - } - } - output << ">"; + output << ">"; + } else { + // This also translates CFArray to NSArray + if (auto typeParamList = + clang::dyn_cast(interface.declaration) + ->getTypeParamListAsWritten()) { + output << "<"; + for (size_t i = 0; i < typeParamList->size(); i++) { + output << "any"; + if (i < typeParamList->size() - 1) { + output << ", "; } + } + output << ">"; } - - std::vector protocols; - if (type.is(TypeType::TypeInterface) && type.as().protocols.size() > 0) { - for (auto & protocol : type.as().protocols) { - if (protocol->jsName != "NSCopying") { - protocols.push_back(protocol->jsName); - } - } + } + + std::vector protocols; + if (type.is(TypeType::TypeInterface) && + type.as().protocols.size() > 0) { + for (auto& protocol : type.as().protocols) { + if (protocol->jsName != "NSCopying") { + protocols.push_back(protocol->jsName); + } } - - if (protocols.size() > 0) { - // Example: -(NSObject