/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_cli_ure.hxx" #include "climaker_share.h" #include "rtl/string.hxx" #include "rtl/ustrbuf.hxx" #include "com/sun/star/reflection/XIndirectTypeDescription.hpp" #include "com/sun/star/reflection/XStructTypeDescription.hpp" #include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" #include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription.hpp" #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp" #include <vector> using namespace ::System::Reflection; using namespace ::rtl; using namespace ::com::sun::star; using namespace ::com::sun::star::uno; namespace climaker { System::String* mapUnoPolymorphicName(System::String* unoName); //------------------------------------------------------------------------------ static inline ::System::String * to_cts_name( OUString const & uno_name ) { OUStringBuffer buf( 7 + uno_name.getLength() ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("unoidl.") ); buf.append( uno_name ); return ustring_to_String( buf.makeStringAndClear() ); } //------------------------------------------------------------------------------ static inline ::System::Object * to_cli_constant( Any const & value ) { switch (value.getValueTypeClass()) { case TypeClass_CHAR: return __box ((::System::Char) *reinterpret_cast< sal_Unicode const * >( value.getValue() )); case TypeClass_BOOLEAN: return __box ((::System::Boolean) sal_False != *reinterpret_cast< sal_Bool const * >( value.getValue() )); case TypeClass_BYTE: return __box ((::System::Byte) *reinterpret_cast< sal_Int8 const * >( value.getValue() )); case TypeClass_SHORT: return __box ((::System::Int16) *reinterpret_cast< sal_Int16 const * >( value.getValue() )); case TypeClass_UNSIGNED_SHORT: return __box ((::System::UInt16) *reinterpret_cast< sal_uInt16 const * >( value.getValue() )); case TypeClass_LONG: return __box ((::System::Int32) *reinterpret_cast< sal_Int32 const * >( value.getValue() )); case TypeClass_UNSIGNED_LONG: return __box ((::System::UInt32) *reinterpret_cast< sal_uInt32 const * >( value.getValue() )); case TypeClass_HYPER: return __box ((::System::Int64) *reinterpret_cast< sal_Int64 const * >( value.getValue() )); case TypeClass_UNSIGNED_HYPER: return __box ((::System::UInt64) *reinterpret_cast< sal_uInt64 const * >( value.getValue() )); case TypeClass_FLOAT: return __box ((::System::Single) *reinterpret_cast< float const * >( value.getValue() )); case TypeClass_DOUBLE: return __box ((::System::Double) *reinterpret_cast< double const * >( value.getValue() )); default: throw RuntimeException( OUSTR("unexpected constant type ") + value.getValueType().getTypeName(), Reference< XInterface >() ); } } //------------------------------------------------------------------------------ static inline void emit_ldarg( Emit::ILGenerator * code, ::System::Int32 index ) { switch (index) { case 0: code->Emit( Emit::OpCodes::Ldarg_0 ); break; case 1: code->Emit( Emit::OpCodes::Ldarg_1 ); break; case 2: code->Emit( Emit::OpCodes::Ldarg_2 ); break; case 3: code->Emit( Emit::OpCodes::Ldarg_3 ); break; default: if (index < 0x100) code->Emit( Emit::OpCodes::Ldarg_S, (::System::Byte) index ); else if (index < 0x8000) code->Emit( Emit::OpCodes::Ldarg_S, (::System::Int16) index ); else code->Emit( Emit::OpCodes::Ldarg, index ); break; } } void polymorphicStructNameToStructName(::System::String ** sPolyName) { if ((*sPolyName)->EndsWith(S">") == false) return; int index = (*sPolyName)->IndexOf('<'); OSL_ASSERT(index != -1); *sPolyName = (*sPolyName)->Substring(0, index); } System::String* mapUnoTypeName(System::String * typeName) { ::System::Text::StringBuilder* buf= new System::Text::StringBuilder(); ::System::String * sUnoName = ::System::String::Copy(typeName); //determine if the type is a sequence and its dimensions int dims= 0; if (typeName->StartsWith(S"["))//if (usUnoName[0] == '[') { int index= 1; while (true) { if (typeName->get_Chars(index++) == ']')//if (usUnoName[index++] == ']') dims++; if (typeName->get_Chars(index++) != '[')//usUnoName[index++] != '[') break; } sUnoName = sUnoName->Substring(index - 1);//usUnoName = usUnoName.copy(index - 1); } if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoBool))) buf->Append(const_cast<System::String*>(Constants::sBoolean)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoChar))) buf->Append(const_cast<System::String*>(Constants::sChar)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoByte))) buf->Append(const_cast<System::String*>(Constants::sByte)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoShort))) buf->Append(const_cast<System::String*>(Constants::sInt16)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoUShort))) buf->Append(const_cast<System::String*>(Constants::sUInt16)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoLong))) buf->Append(const_cast<System::String*>(Constants::sInt32)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoULong))) buf->Append(const_cast<System::String*>(Constants::sUInt32)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoHyper))) buf->Append(const_cast<System::String*>(Constants::sInt64)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoUHyper))) buf->Append(const_cast<System::String*>(Constants::sUInt64)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoFloat))) buf->Append(const_cast<System::String*>(Constants::sSingle)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoDouble))) buf->Append(const_cast<System::String*>(Constants::sDouble)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoString))) buf->Append(const_cast<System::String*>(Constants::sString)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoVoid))) buf->Append(const_cast<System::String*>(Constants::sVoid)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoType))) buf->Append(const_cast<System::String*>(Constants::sType)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoXInterface))) buf->Append(const_cast<System::String*>(Constants::sObject)); else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoAny))) { buf->Append(const_cast<System::String*>(Constants::sAny)); } else { //put "unoidl." at the beginning buf->Append(const_cast<System::String*>(Constants::sUnoidl)); buf->Append(mapUnoPolymorphicName(sUnoName)); } // append [] for (;dims--;) buf->Append(const_cast<System::String*>(Constants::sBrackets)); return buf->ToString(); } /** For example, there is an uno type com.sun.star.Foo<char, long>. The values in the type list are uno types and are replaced by cli types, such as System.Char, System.Int32, etc. Strings can be as complicated as this test.MyStruct<char,test.MyStruct<long, []string>> */ System::String* mapUnoPolymorphicName(System::String* unoName) { int index = unoName->IndexOf('<'); if (index == -1) return unoName; System::Text::StringBuilder * builder = new System::Text::StringBuilder(unoName->Substring(0, index +1 )); //Find the first occurrence of ',' //If the parameter is a polymorphic struct then we need to ignore everything //between the brackets because it can also contain commas //get the type list within < and > int endIndex = unoName->Length - 1; index++; int cur = index; int countParams = 0; while (cur <= endIndex) { System::Char c = unoName->Chars[cur]; if (c == ',' || c == '>') { //insert a comma if needed if (countParams != 0) builder->Append(S","); countParams++; System::String * sParam = unoName->Substring(index, cur - index); //skip the comma cur++; //the the index to the beginning of the next param index = cur; builder->Append(mapUnoTypeName(sParam)); } else if (c == '<') { cur++; //continue until the matching '>' int numNested = 0; for (;;cur++) { System::Char curChar = unoName->Chars[cur]; if (curChar == '<') { numNested ++; } else if (curChar == '>') { if (numNested > 0) numNested--; else break; } } } cur++; } builder->Append((System::Char) '>'); return builder->ToString(); } //______________________________________________________________________________ Assembly * TypeEmitter::type_resolve( ::System::Object *, ::System::ResolveEventArgs * args ) { ::System::String * cts_name = args->get_Name(); ::System::Type * ret_type = m_module_builder->GetType( cts_name, false /* no exc */ ); if (0 == ret_type) { iface_entry * entry = dynamic_cast< iface_entry * >( m_incomplete_ifaces->get_Item( cts_name ) ); if (0 != entry) ret_type = entry->m_type_builder; } if (0 == ret_type) { sal_Int32 len = m_extra_assemblies->get_Length(); for ( sal_Int32 pos = 0; pos < len; ++pos ) { ret_type = m_extra_assemblies[ pos ]->GetType( cts_name, false /* no exc */ ); if (0 != ret_type) { if (g_verbose) { ::System::Console::WriteLine( "> resolving type {0} from {1}.", cts_name, ret_type->get_Assembly()->get_FullName() ); } break; } } } if (0 != ret_type) return ret_type->get_Assembly(); return 0; } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type( ::System::String * cts_name, bool throw_exc ) { ::System::Type * ret_type = m_module_builder->GetType( cts_name, false ); //We get the type from the ModuleBuilder even if the type is not complete //but have been defined. //if (ret_type == 0) //{ // iface_entry * entry = dynamic_cast< iface_entry * >( // m_incomplete_ifaces->get_Item( cts_name ) ); // if (0 != entry) // ret_type = entry->m_type_builder; //} //try the cli_basetypes assembly if (ret_type == 0) { ::System::Text::StringBuilder * builder = new ::System::Text::StringBuilder(cts_name); builder->Append(S",cli_basetypes"); ret_type = ::System::Type::GetType(builder->ToString()); } if (ret_type == 0) { try { // may call on type_resolve() return ::System::Type::GetType( cts_name, throw_exc ); } catch (::System::Exception* exc) { //If the type is not found one may have forgotten to specify assemblies with //additional types ::System::Text::StringBuilder * sb = new ::System::Text::StringBuilder(); sb->Append(new ::System::String(S"\nThe type ")); sb->Append(cts_name); sb->Append(new ::System::String(S" \n could not be found. Did you forget to " \ S"specify an additional assembly with the --reference option?\n")); if (throw_exc) throw new ::System::Exception(sb->ToString(), exc); } } else { return ret_type; } } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type_Exception() { if (0 == m_type_Exception) { m_type_Exception = get_type( S"unoidl.com.sun.star.uno.Exception", false /* no exc */ ); if (0 == m_type_Exception) { // define hardcoded type unoidl.com.sun.star.uno.Exception Emit::TypeBuilder * type_builder = m_module_builder->DefineType( S"unoidl.com.sun.star.uno.Exception", (TypeAttributes) (TypeAttributes::Public | TypeAttributes::BeforeFieldInit | TypeAttributes::AnsiClass), __typeof (::System::Exception) ); Emit::FieldBuilder * field_Context = type_builder->DefineField( S"Context", __typeof (::System::Object), FieldAttributes::Public ); // default .ctor type_builder->DefineDefaultConstructor( c_ctor_method_attr ); // .ctor ::System::Type * param_types[] = new ::System::Type *[ 2 ]; param_types[ 0 ] = __typeof (::System::String); param_types[ 1 ] = __typeof (::System::Object); Emit::ConstructorBuilder * ctor_builder = type_builder->DefineConstructor( c_ctor_method_attr, CallingConventions::Standard, param_types ); ctor_builder->DefineParameter( 1, ParameterAttributes::In, S"Message" ); ctor_builder->DefineParameter( 2, ParameterAttributes::In, S"Context" ); Emit::ILGenerator * code = ctor_builder->GetILGenerator(); code->Emit( Emit::OpCodes::Ldarg_0 ); code->Emit( Emit::OpCodes::Ldarg_1 ); param_types = new ::System::Type * [ 1 ]; param_types[ 0 ] = __typeof (::System::String); code->Emit( Emit::OpCodes::Call, __typeof (::System::Exception) ->GetConstructor( param_types ) ); code->Emit( Emit::OpCodes::Ldarg_0 ); code->Emit( Emit::OpCodes::Ldarg_2 ); code->Emit( Emit::OpCodes::Stfld, field_Context ); code->Emit( Emit::OpCodes::Ret ); if (g_verbose) { ::System::Console::WriteLine( "> emitting exception type " "unoidl.com.sun.star.uno.Exception" ); } m_type_Exception = type_builder->CreateType(); } } return m_type_Exception; } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type_RuntimeException() { if (0 == m_type_RuntimeException) { m_type_RuntimeException = get_type( S"unoidl.com.sun.star.uno.RuntimeException", false /* no exc */ ); if (0 == m_type_RuntimeException) { // define hardcoded type unoidl.com.sun.star.uno.RuntimeException ::System::Type * type_Exception = get_type_Exception(); Emit::TypeBuilder * type_builder = m_module_builder->DefineType( S"unoidl.com.sun.star.uno.RuntimeException", (TypeAttributes) (TypeAttributes::Public | TypeAttributes::BeforeFieldInit | TypeAttributes::AnsiClass), type_Exception ); // default .ctor type_builder->DefineDefaultConstructor( c_ctor_method_attr ); // .ctor ::System::Type * param_types [] = new ::System::Type * [ 2 ]; param_types[ 0 ] = __typeof (::System::String); param_types[ 1 ] = __typeof (::System::Object); Emit::ConstructorBuilder * ctor_builder = type_builder->DefineConstructor( c_ctor_method_attr, CallingConventions::Standard, param_types ); ctor_builder->DefineParameter( 1, ParameterAttributes::In, S"Message" ); ctor_builder->DefineParameter( 2, ParameterAttributes::In, S"Context" ); Emit::ILGenerator * code = ctor_builder->GetILGenerator(); code->Emit( Emit::OpCodes::Ldarg_0 ); code->Emit( Emit::OpCodes::Ldarg_1 ); code->Emit( Emit::OpCodes::Ldarg_2 ); code->Emit( Emit::OpCodes::Call, type_Exception->GetConstructor( param_types ) ); code->Emit( Emit::OpCodes::Ret ); if (g_verbose) { ::System::Console::WriteLine( "> emitting exception type " "unoidl.com.sun.star.uno.RuntimeException" ); } m_type_RuntimeException = type_builder->CreateType(); } } return m_type_RuntimeException; } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type( Reference< reflection::XConstantTypeDescription > const & xType ) { ::System::String * cts_name = to_cts_name( xType->getName() ); ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); if (0 == ret_type) { Reference< reflection::XConstantTypeDescription > xConstant( xType, UNO_QUERY_THROW ); ::System::Object * constant = to_cli_constant( xConstant->getConstantValue() ); Emit::TypeBuilder * type_builder = m_module_builder->DefineType( cts_name, (TypeAttributes) (TypeAttributes::Public | TypeAttributes::Sealed | TypeAttributes::BeforeFieldInit | TypeAttributes::AnsiClass) ); Emit::FieldBuilder * field_builder = type_builder->DefineField( cts_name->Substring( cts_name->LastIndexOf( '.' ) +1 ), constant->GetType(), (FieldAttributes) (FieldAttributes::Public | FieldAttributes::Static | FieldAttributes::Literal) ); field_builder->SetConstant( constant ); if (g_verbose) { ::System::Console::WriteLine( "> emitting constant type {0}", cts_name ); } ret_type = type_builder->CreateType(); } return ret_type; } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type( Reference< reflection::XConstantsTypeDescription > const & xType ) { ::System::String * cts_name = to_cts_name( xType->getName() ); ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); if (0 == ret_type) { Emit::TypeBuilder * type_builder = m_module_builder->DefineType( cts_name, (TypeAttributes) (TypeAttributes::Public | TypeAttributes::Sealed | TypeAttributes::BeforeFieldInit | TypeAttributes::AnsiClass) ); Sequence< Reference< reflection::XConstantTypeDescription > > seq_constants( xType->getConstants() ); Reference< reflection::XConstantTypeDescription > const * constants = seq_constants.getConstArray(); sal_Int32 constants_length = seq_constants.getLength(); for ( sal_Int32 constants_pos = 0; constants_pos < constants_length; ++constants_pos ) { Reference< reflection::XConstantTypeDescription > const & xConstant = constants[ constants_pos ]; ::System::Object * constant = to_cli_constant( xConstant->getConstantValue() ); ::System::String * uno_name = ustring_to_String( xConstant->getName() ); Emit::FieldBuilder * field_builder = type_builder->DefineField( uno_name->Substring( uno_name->LastIndexOf( '.' ) +1 ), constant->GetType(), (FieldAttributes) (FieldAttributes::Public | FieldAttributes::Static | FieldAttributes::Literal) ); field_builder->SetConstant( constant ); } if (g_verbose) { ::System::Console::WriteLine( "> emitting constants group type {0}", cts_name ); } ret_type = type_builder->CreateType(); } return ret_type; } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type( Reference< reflection::XEnumTypeDescription > const & xType ) { ::System::String * cts_name = to_cts_name( xType->getName() ); ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); if (0 == ret_type) { // Emit::EnumBuilder * enum_builder = // m_module_builder->DefineEnum( // cts_name, // (TypeAttributes) (TypeAttributes::Public | // // TypeAttributes::Sealed | // TypeAttributes::AnsiClass), // __typeof (::System::Int32) ); // workaround enum builder bug Emit::TypeBuilder * enum_builder = m_module_builder->DefineType( cts_name, (TypeAttributes) (TypeAttributes::Public | TypeAttributes::Sealed), __typeof (::System::Enum) ); enum_builder->DefineField( S"value__", __typeof (::System::Int32), (FieldAttributes) (FieldAttributes::Private | FieldAttributes::SpecialName | FieldAttributes::RTSpecialName) ); Sequence< OUString > seq_enum_names( xType->getEnumNames() ); Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() ); sal_Int32 enum_length = seq_enum_names.getLength(); OSL_ASSERT( enum_length == seq_enum_values.getLength() ); OUString const * enum_names = seq_enum_names.getConstArray(); sal_Int32 const * enum_values = seq_enum_values.getConstArray(); for ( sal_Int32 enum_pos = 0; enum_pos < enum_length; ++enum_pos ) { // enum_builder->DefineLiteral( // ustring_to_String( enum_names[ enum_pos ] ), // __box ((::System::Int32) enum_values[ enum_pos ]) ); Emit::FieldBuilder * field_builder = enum_builder->DefineField( ustring_to_String( enum_names[ enum_pos ] ), enum_builder, (FieldAttributes) (FieldAttributes::Public | FieldAttributes::Static | FieldAttributes::Literal) ); field_builder->SetConstant( __box ((::System::Int32) enum_values[ enum_pos ]) ); } if (g_verbose) { ::System::Console::WriteLine( "> emitting enum type {0}", cts_name ); } ret_type = enum_builder->CreateType(); } return ret_type; } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type( Reference< reflection::XCompoundTypeDescription > const & xType ) { OUString uno_name( xType->getName() ); if (TypeClass_EXCEPTION == xType->getTypeClass()) { if (uno_name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.uno.Exception") )) { return get_type_Exception(); } if (uno_name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.uno.RuntimeException") )) { return get_type_RuntimeException(); } } ::System::String * cts_name = to_cts_name( uno_name ); // if the struct is an instantiated polymorpic struct then we create the simple struct name // For example: // void func ([in] PolyStruct<boolean> arg); //PolyStruct<boolean> will be converted to PolyStruct polymorphicStructNameToStructName( & cts_name); ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); if (0 == ret_type) { Reference< reflection::XCompoundTypeDescription > xBaseType( xType->getBaseType(), UNO_QUERY ); ::System::Type * base_type = (xBaseType.is() ? get_type( xBaseType ) : __typeof (::System::Object)); Emit::TypeBuilder * type_builder = m_module_builder->DefineType( cts_name, (TypeAttributes) (TypeAttributes::Public | TypeAttributes::BeforeFieldInit | TypeAttributes::AnsiClass), base_type ); // insert to be completed struct_entry * entry = new struct_entry(); xType->acquire(); entry->m_xType = xType.get(); entry->m_type_builder = type_builder; entry->m_base_type = base_type; m_incomplete_structs->Add( cts_name, entry ); // type is incomplete ret_type = type_builder; } //In case of an instantiated polymorphic struct we want to return a //uno.PolymorphicType (inherits Type) rather then Type. This is needed for constructing //the service code. We can only do that if the struct is completed. if (m_generated_structs->get_Item(cts_name)) { Reference< reflection::XStructTypeDescription> xStructTypeDesc( xType, UNO_QUERY); if (xStructTypeDesc.is()) { Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments(); sal_Int32 numTypes = seqTypeArgs.getLength(); if (numTypes > 0) { //it is an instantiated polymorphic struct ::System::String * sCliName = mapUnoTypeName(ustring_to_String(xType->getName())); ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName); } } } return ret_type; } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type( Reference< reflection::XInterfaceTypeDescription2 > const & xType ) { OUString uno_name( xType->getName() ); if (uno_name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") )) { return __typeof (::System::Object); } ::System::String * cts_name = to_cts_name( xType->getName() ); ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); if (0 == ret_type) { Emit::TypeBuilder * type_builder; TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public | TypeAttributes::Interface | TypeAttributes::Abstract | TypeAttributes::AnsiClass); std::vector<Reference<reflection::XInterfaceTypeDescription2> > vecBaseTypes; Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes = xType->getBaseTypes(); if (seqBaseTypes.getLength() > 0) { for (int i = 0; i < seqBaseTypes.getLength(); i++) { Reference<reflection::XInterfaceTypeDescription2> xIfaceTd = resolveInterfaceTypedef(seqBaseTypes[i]); if (xIfaceTd->getName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ) == sal_False) { vecBaseTypes.push_back(xIfaceTd); } } ::System::Type * base_interfaces [] = new ::System::Type * [ vecBaseTypes.size() ]; typedef std::vector<Reference<reflection::XInterfaceTypeDescription2> >::const_iterator it; int index = 0; for (it i = vecBaseTypes.begin(); i != vecBaseTypes.end(); i++, index++) base_interfaces[ index ] = get_type( *i ); type_builder = m_module_builder->DefineType( cts_name, attr, 0, base_interfaces ); } else { ::System::Console::WriteLine( "warning: IDL interface {0} is not derived from " "com.sun.star.uno.XInterface!", ustring_to_String( uno_name ) ); type_builder = m_module_builder->DefineType( cts_name, attr ); } // insert to be completed iface_entry * entry = new iface_entry(); xType->acquire(); entry->m_xType = xType.get(); entry->m_type_builder = type_builder; m_incomplete_ifaces->Add( cts_name, entry ); // type is incomplete ret_type = type_builder; } return ret_type; } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type( Reference< reflection::XServiceTypeDescription2 > const & xType ) { if (xType->isSingleInterfaceBased() == sal_False) return NULL; System::String * cts_name = to_cts_name( xType->getName() ); System::Type * ret_type = get_type( cts_name, false /* no exc */ ); if (ret_type != NULL) return ret_type; TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public | TypeAttributes::Sealed | TypeAttributes::BeforeFieldInit | TypeAttributes::AnsiClass); Emit::TypeBuilder * type_builder = m_module_builder->DefineType( cts_name, attr); // insert to be completed service_entry * entry = new service_entry(); xType->acquire(); entry->m_xType = xType.get(); entry->m_type_builder = type_builder; m_incomplete_services->Add(cts_name,entry ); return type_builder; } ::System::Type * TypeEmitter::get_type( Reference<reflection::XSingletonTypeDescription2 > const & xType ) { if (xType->isInterfaceBased() == sal_False) return NULL; ::System::String* cts_name = to_cts_name( xType->getName() ); ::System::Type * ret_type = get_type( cts_name, false /* no exc */ ); if (ret_type != NULL) return ret_type; TypeAttributes attr = static_cast<TypeAttributes>( TypeAttributes::Public | TypeAttributes::Sealed | TypeAttributes::BeforeFieldInit | TypeAttributes::AnsiClass); Emit::TypeBuilder * type_builder = m_module_builder->DefineType( cts_name, attr); // insert to be completed singleton_entry * entry = new singleton_entry(); xType->acquire(); entry->m_xType = xType.get(); entry->m_type_builder = type_builder; m_incomplete_singletons->Add(cts_name,entry ); return type_builder; } //______________________________________________________________________________ ::System::Type * TypeEmitter::complete_iface_type( iface_entry * entry ) { Emit::TypeBuilder * type_builder = entry->m_type_builder; reflection::XInterfaceTypeDescription2 * xType = entry->m_xType; Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes( xType->getBaseTypes() ); if (seqBaseTypes.getLength() > 0) { for (int i = 0; i < seqBaseTypes.getLength(); i++) { //make sure we get the interface rather then a typedef Reference<reflection::XInterfaceTypeDescription2> aBaseType = resolveInterfaceTypedef( seqBaseTypes[i]); if (aBaseType->getName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ) == sal_False) { ::System::String * basetype_name = to_cts_name( aBaseType->getName() ); iface_entry * base_entry = dynamic_cast< iface_entry * >( m_incomplete_ifaces->get_Item( basetype_name ) ); if (0 != base_entry) { // complete uncompleted base type first complete_iface_type( base_entry ); } } } } Sequence< Reference< reflection::XInterfaceMemberTypeDescription > > seq_members( xType->getMembers() ); Reference< reflection::XInterfaceMemberTypeDescription > const * members = seq_members.getConstArray(); sal_Int32 members_length = seq_members.getLength(); for ( sal_Int32 members_pos = 0; members_pos < members_length; ++members_pos ) { Reference< reflection::XInterfaceMemberTypeDescription > const & xMember = members[ members_pos ]; Sequence< Reference< reflection::XTypeDescription > > seq_exceptions; Emit::MethodBuilder * method_builder; const MethodAttributes c_method_attr = (MethodAttributes) (MethodAttributes::Public | MethodAttributes::Abstract | MethodAttributes::Virtual | MethodAttributes::NewSlot | MethodAttributes::HideBySig); //#if defined(_MSC_VER) && (_MSC_VER < 1400) // MethodAttributes::Instance); //#else // Instance); //#endif if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass()) { Reference< reflection::XInterfaceMethodTypeDescription > xMethod( xMember, UNO_QUERY_THROW ); Sequence< Reference< reflection::XMethodParameter > > seq_parameters( xMethod->getParameters() ); sal_Int32 params_length = seq_parameters.getLength(); ::System::Type * param_types [] = new ::System::Type * [ params_length ]; Reference< reflection::XMethodParameter > const * parameters = seq_parameters.getConstArray(); // first determine all types //Make the first param type as return type sal_Int32 params_pos = 0; for ( ; params_pos < params_length; ++params_pos ) { Reference< reflection::XMethodParameter > const & xParam = parameters[ params_pos ]; ::System::Type * param_type = get_type( xParam->getType() ); ::System::String * param_type_name = param_type->get_FullName(); if (xParam->isOut()) { param_type = get_type( ::System::String::Concat( param_type_name, S"&" ), true ); } param_types[ xParam->getPosition() ] = param_type; } // create method // if (tb) // method_builder = type_builder->DefineMethod( // ustring_to_String( xMethod->getMemberName() ), // c_method_attr, tb, // param_types ); // else method_builder = type_builder->DefineMethod( ustring_to_String( xMethod->getMemberName() ), c_method_attr, get_type( xMethod->getReturnType() ), param_types ); // then define parameter infos params_pos = 0; for ( ; params_pos < params_length; ++params_pos ) { Reference< reflection::XMethodParameter > const & xParam = parameters[ params_pos ]; long param_flags = 0; if (xParam->isIn()) param_flags |= ParameterAttributes::In; if (xParam->isOut()) param_flags |= ParameterAttributes::Out; OSL_ASSERT( 0 != param_flags ); method_builder->DefineParameter( xParam->getPosition() +1 /* starts with 1 */, (ParameterAttributes) param_flags, ustring_to_String( xParam->getName() ) ); } //Apply attribute TypeParametersAttribute to return value if it //is a parameterized Type. Currently only structs can have parameters. Reference<reflection::XStructTypeDescription> xReturnStruct( xMethod->getReturnType(), UNO_QUERY); if (xReturnStruct.is()) { Sequence<Reference<reflection::XTypeDescription> > seq_type_args = xReturnStruct->getTypeArguments(); if (seq_type_args.getLength() != 0) { //get th ctor of the attribute ::System::Type * arCtor[] = {::System::Type::GetType(S"System.Type[]")}; //Get the arguments for the attribute's ctor Reference<reflection::XTypeDescription> const * arXTypeArgs = seq_type_args.getConstArray(); int numTypes = seq_type_args.getLength(); ::System::Type * arCtsTypes[] = new ::System::Type*[numTypes]; for (int i = 0; i < numTypes; i++) arCtsTypes[i] = get_type(arXTypeArgs[i]); ::System::Object * arArgs[] = {arCtsTypes}; Emit::CustomAttributeBuilder * attrBuilder = new Emit::CustomAttributeBuilder( __typeof(::uno::TypeArgumentsAttribute) ->GetConstructor( arCtor), arArgs); method_builder->SetCustomAttribute(attrBuilder); } } //define UNO exception attribute (exceptions)-------------------------------------- Emit::CustomAttributeBuilder* attrBuilder = get_iface_method_exception_attribute(xMethod); if (attrBuilder != NULL) method_builder->SetCustomAttribute(attrBuilder); // oneway attribute if (xMethod->isOneway()) { ::System::Type * arCtorOneway[] = new ::System::Type*[0]; ::System::Object * arArgs[] = new ::System::Object*[0]; Emit::CustomAttributeBuilder * attrBuilder = new Emit::CustomAttributeBuilder( __typeof(::uno::OnewayAttribute)->GetConstructor( arCtorOneway), arArgs); method_builder->SetCustomAttribute(attrBuilder); } } else // attribute { OSL_ASSERT( TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() ); Reference< reflection::XInterfaceAttributeTypeDescription2 > xAttribute( xMember, UNO_QUERY_THROW ); const MethodAttributes c_property_method_attr = (MethodAttributes) (c_method_attr | MethodAttributes::SpecialName); ::System::Type * attribute_type = get_type( xAttribute->getType() ); ::System::Type * parameters [] = new ::System::Type * [ 0 ]; Emit::PropertyBuilder * property_builder = type_builder->DefineProperty( ustring_to_String( xAttribute->getMemberName() ), PropertyAttributes::None, attribute_type, parameters ); //set BoundAttribute, if necessary if (xAttribute->isBound()) { ConstructorInfo * ctorBoundAttr = __typeof(::uno::BoundAttribute)->GetConstructor( new System::Type*[0]); Emit::CustomAttributeBuilder * attrBuilderBound = new Emit::CustomAttributeBuilder( ctorBoundAttr, new ::System::Object*[0]); property_builder->SetCustomAttribute(attrBuilderBound); } // getter Emit::MethodBuilder * method_builder = type_builder->DefineMethod( ustring_to_String( OUSTR("get_") + xAttribute->getMemberName() ), c_property_method_attr, attribute_type, parameters ); //define UNO exception attribute (exceptions)-------------------------------------- Emit::CustomAttributeBuilder* attrBuilder = get_exception_attribute(xAttribute->getGetExceptions()); if (attrBuilder != NULL) method_builder->SetCustomAttribute(attrBuilder); property_builder->SetGetMethod( method_builder ); if (! xAttribute->isReadOnly()) { // setter parameters = new ::System::Type * [ 1 ]; parameters[ 0 ] = attribute_type; method_builder = type_builder->DefineMethod( ustring_to_String( OUSTR("set_") + xAttribute->getMemberName() ), c_property_method_attr, 0, parameters ); // define parameter info method_builder->DefineParameter( 1 /* starts with 1 */, ParameterAttributes::In, S"value" ); //define UNO exception attribute (exceptions)-------------------------------------- Emit::CustomAttributeBuilder* attrBuilder = get_exception_attribute(xAttribute->getSetExceptions()); if (attrBuilder != NULL) method_builder->SetCustomAttribute(attrBuilder); property_builder->SetSetMethod( method_builder ); } } } // remove from incomplete types map ::System::String * cts_name = type_builder->get_FullName(); m_incomplete_ifaces->Remove( cts_name ); xType->release(); if (g_verbose) { ::System::Console::WriteLine( "> emitting interface type {0}", cts_name ); } return type_builder->CreateType(); } ::System::Type * TypeEmitter::complete_struct_type( struct_entry * entry ) { OSL_ASSERT(entry); ::System::String * cts_name = entry->m_type_builder->get_FullName(); //Polymorphic struct, define uno.TypeParametersAttribute //A polymorphic struct cannot have a basetype. //When we create the template of the struct then we have no exact types //and the name does not contain a parameter list Sequence< OUString > seq_type_parameters; Reference< reflection::XStructTypeDescription> xStructTypeDesc( entry->m_xType, UNO_QUERY); if (xStructTypeDesc.is()) { seq_type_parameters = xStructTypeDesc->getTypeParameters(); int numTypes = 0; if ((numTypes = seq_type_parameters.getLength()) > 0) { ::System::Object * aArg[] = new ::System::Object*[numTypes]; for (int i = 0; i < numTypes; i++) aArg[i] = ustring_to_String(seq_type_parameters.getConstArray()[i]); ::System::Object * args[] = {aArg}; ::System::Type * arTypesCtor[] = {::System::Type::GetType(S"System.String[]")}; Emit::CustomAttributeBuilder * attrBuilder = new Emit::CustomAttributeBuilder( __typeof(::uno::TypeParametersAttribute)->GetConstructor(arTypesCtor), args); entry->m_type_builder->SetCustomAttribute(attrBuilder); } } // optional: lookup base type whether generated entry of this session struct_entry * base_type_entry = 0; if (0 != entry->m_base_type) { //ToDo maybe get from incomplete structs base_type_entry = dynamic_cast< struct_entry * >( m_generated_structs->get_Item( entry->m_base_type->get_FullName() ) ); } // members Sequence< Reference< reflection::XTypeDescription > > seq_members( entry->m_xType->getMemberTypes() ); Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() ); sal_Int32 members_length = seq_members.getLength(); OSL_ASSERT( seq_member_names.getLength() == members_length ); //check if we have a XTypeDescription for every member. If not then the user may //have forgotten to specify additional rdbs with the --extra option. Reference< reflection::XTypeDescription > const * pseq_members = seq_members.getConstArray(); OUString const * pseq_member_names = seq_member_names.getConstArray(); for (int i = 0; i < members_length; i++) { const OUString sType(entry->m_xType->getName()); const OUString sMemberName(pseq_member_names[i]); if ( ! pseq_members[i].is()) throw RuntimeException(OUSTR("Missing type description . Check if you need to " \ "specify additional RDBs with the --extra option. Type missing for: ") + sType + OUSTR("::") + sMemberName,0); } sal_Int32 all_members_length = 0; sal_Int32 member_pos; sal_Int32 type_param_pos = 0; // collect base types; wrong order ::System::Collections::ArrayList * base_types_list = new ::System::Collections::ArrayList( 3 /* initial capacity */ ); for (::System::Type * base_type_pos = entry->m_base_type; ! base_type_pos->Equals( __typeof (::System::Object) ); base_type_pos = base_type_pos->get_BaseType() ) { base_types_list->Add( base_type_pos ); if (base_type_pos->Equals( __typeof (::System::Exception) )) { // special Message member all_members_length += 1; break; // don't include System.Exception base classes } else { //ensure the base type is complete. Otherwise GetFields won't work get_complete_struct(base_type_pos->get_FullName()); all_members_length += base_type_pos->GetFields( (BindingFlags) (BindingFlags::Instance | BindingFlags::Public | BindingFlags::DeclaredOnly) ) ->get_Length(); } } // create all_members arrays; right order ::System::String * all_member_names[] = new ::System::String * [all_members_length + members_length ]; ::System::Type * all_param_types[] = new ::System::Type * [all_members_length + members_length ]; member_pos = 0; for ( sal_Int32 pos = base_types_list->get_Count(); pos--; ) { ::System::Type * base_type = __try_cast< ::System::Type * >( base_types_list->get_Item( pos ) ); if (base_type->Equals( __typeof (::System::Exception) )) { all_member_names[ member_pos ] = S"Message"; all_param_types[ member_pos ] = __typeof (::System::String); ++member_pos; } else { ::System::String * base_type_name = base_type->get_FullName(); //ToDo m_generated_structs? struct_entry * entry = dynamic_cast< struct_entry * >( m_generated_structs->get_Item( base_type_name ) ); if (0 == entry) { // complete type FieldInfo * fields [] = base_type->GetFields( (BindingFlags) (BindingFlags::Instance | BindingFlags::Public | BindingFlags::DeclaredOnly) ); sal_Int32 len = fields->get_Length(); for ( sal_Int32 pos = 0; pos < len; ++pos ) { FieldInfo * field = fields[ pos ]; all_member_names[ member_pos ] = field->get_Name(); all_param_types[ member_pos ] = field->get_FieldType(); ++member_pos; } } else // generated during this session: // members may be incomplete ifaces { sal_Int32 len = entry->m_member_names->get_Length(); for ( sal_Int32 pos = 0; pos < len; ++pos ) { all_member_names[ member_pos ] = entry->m_member_names[ pos ]; all_param_types[ member_pos ] = entry->m_param_types[ pos ]; ++member_pos; } } } } OSL_ASSERT( all_members_length == member_pos ); // build up entry // struct_entry * entry = new struct_entry(); entry->m_member_names = new ::System::String * [ members_length ]; entry->m_param_types = new ::System::Type * [ members_length ]; // add members Emit::FieldBuilder * members[] = new Emit::FieldBuilder * [ members_length ]; //Reference< reflection::XTypeDescription > const * pseq_members = // seq_members.getConstArray(); //OUString const * pseq_member_names = // seq_member_names.getConstArray(); int curParamIndex = 0; //count the fields which have parameterized types for ( member_pos = 0; member_pos < members_length; ++member_pos ) { ::System::String * field_name = ustring_to_String( pseq_member_names[ member_pos ] ); ::System::Type * field_type; //Special handling of struct parameter types bool bParameterizedType = false; if (pseq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN) { bParameterizedType = true; if (type_param_pos < seq_type_parameters.getLength()) { field_type = __typeof(::System::Object); type_param_pos++; } else { throw RuntimeException( OUSTR("unexpected member type in ") + entry->m_xType->getName(), Reference< XInterface >() ); } } else { field_type = get_type( pseq_members[ member_pos ] ); } members[ member_pos ] = entry->m_type_builder->DefineField( field_name, field_type, FieldAttributes::Public ); //parameterized type (polymorphic struct) ? if (bParameterizedType && xStructTypeDesc.is()) { //get the name OSL_ASSERT(seq_type_parameters.getLength() > curParamIndex); ::System::String* sTypeName = ustring_to_String( seq_type_parameters.getConstArray()[curParamIndex++]); ::System::Object * args[] = {sTypeName}; //set ParameterizedTypeAttribute ::System::Type * arCtorTypes[] = {__typeof(::System::String)}; Emit::CustomAttributeBuilder * attrBuilder = new Emit::CustomAttributeBuilder( __typeof(::uno::ParameterizedTypeAttribute) ->GetConstructor(arCtorTypes), args); members[member_pos]->SetCustomAttribute(attrBuilder); } // add to all_members all_member_names[ all_members_length + member_pos ] = field_name; all_param_types[ all_members_length + member_pos ] = field_type; // add to entry entry->m_member_names[ member_pos ] = field_name; entry->m_param_types[ member_pos ] = field_type; } all_members_length += members_length; // default .ctor Emit::ConstructorBuilder * ctor_builder = entry->m_type_builder->DefineConstructor( c_ctor_method_attr, CallingConventions::Standard, new ::System::Type * [ 0 ] ); Emit::ILGenerator * code = ctor_builder->GetILGenerator(); code->Emit( Emit::OpCodes::Ldarg_0 ); code->Emit( Emit::OpCodes::Call, 0 == base_type_entry ? entry->m_base_type->GetConstructor( new ::System::Type * [ 0 ] ) : base_type_entry->m_default_ctor ); // default initialize members for ( member_pos = 0; member_pos < members_length; ++member_pos ) { FieldInfo * field = members[ member_pos ]; ::System::Type * field_type = field->get_FieldType(); // ::System::Type * new_field_type = m_module_builder->GetType(field_type->FullName, false); // default initialize: // string, type, enum, sequence, struct, exception, any if (field_type->Equals( __typeof (::System::String) )) { code->Emit( Emit::OpCodes::Ldarg_0 ); code->Emit( Emit::OpCodes::Ldstr, S"" ); code->Emit( Emit::OpCodes::Stfld, field ); } else if (field_type->Equals( __typeof (::System::Type) )) { code->Emit( Emit::OpCodes::Ldarg_0 ); code->Emit( Emit::OpCodes::Ldtoken, __typeof (::System::Void) ); code->Emit( Emit::OpCodes::Call, m_method_info_Type_GetTypeFromHandle ); code->Emit( Emit::OpCodes::Stfld, field ); } else if (field_type->get_IsArray()) { //Find the value type. In case of sequence<sequence< ... > > find the actual value type ::System::Type * value = field_type; while ((value = value->GetElementType())->get_IsArray()); //If the value type is a struct then make sure it is fully created. get_complete_struct(value->get_FullName()); code->Emit( Emit::OpCodes::Ldarg_0 ); code->Emit( Emit::OpCodes::Ldc_I4_0 ); code->Emit( Emit::OpCodes::Newarr, field_type->GetElementType() ); code->Emit( Emit::OpCodes::Stfld, field ); } else if (field_type->get_IsValueType()) { if (field_type->get_FullName()->Equals( S"uno.Any" )) { code->Emit( Emit::OpCodes::Ldarg_0 ); code->Emit( Emit::OpCodes::Ldsfld, __typeof(::uno::Any)->GetField(S"VOID")); code->Emit( Emit::OpCodes::Stfld, field ); } } else if (field_type->get_IsClass()) { /* may be XInterface */ if (! field_type->Equals( __typeof (::System::Object) )) { // struct, exception //make sure the struct is already complete. get_complete_struct(field_type->get_FullName()); code->Emit( Emit::OpCodes::Ldarg_0 ); code->Emit( Emit::OpCodes::Newobj, //GetConstructor requires that the member types of the object which is to be constructed are already known. field_type->GetConstructor( new ::System::Type * [ 0 ] ) ); code->Emit( Emit::OpCodes::Stfld, field ); } } } code->Emit( Emit::OpCodes::Ret ); entry->m_default_ctor = ctor_builder; // parameterized .ctor including all base members ctor_builder = entry->m_type_builder->DefineConstructor( c_ctor_method_attr, CallingConventions::Standard, all_param_types ); for ( member_pos = 0; member_pos < all_members_length; ++member_pos ) { ctor_builder->DefineParameter( member_pos +1 /* starts with 1 */, ParameterAttributes::In, all_member_names[ member_pos ] ); } code = ctor_builder->GetILGenerator(); // call base .ctor code->Emit( Emit::OpCodes::Ldarg_0 ); // push this sal_Int32 base_members_length = all_members_length - members_length; ::System::Type * param_types [] = new ::System::Type * [ base_members_length ]; for ( member_pos = 0; member_pos < base_members_length; ++member_pos ) { emit_ldarg( code, member_pos +1 ); param_types[ member_pos ] = all_param_types[ member_pos ]; } code->Emit( Emit::OpCodes::Call, 0 == base_type_entry ? entry->m_base_type->GetConstructor( param_types ) : base_type_entry->m_ctor ); // initialize members for ( member_pos = 0; member_pos < members_length; ++member_pos ) { code->Emit( Emit::OpCodes::Ldarg_0 ); // push this emit_ldarg( code, member_pos + base_members_length +1 ); code->Emit( Emit::OpCodes::Stfld, members[ member_pos ] ); } code->Emit( Emit::OpCodes::Ret ); entry->m_ctor = ctor_builder; if (g_verbose) { ::System::Console::WriteLine( "> emitting {0} type {1}", TypeClass_STRUCT == entry->m_xType->getTypeClass() ? S"struct" : S"exception", cts_name); } // new entry m_generated_structs->Add(cts_name, entry ); ::System::Type * ret_type = entry->m_type_builder->CreateType(); // remove from incomplete types map m_incomplete_structs->Remove( cts_name ); entry->m_xType->release(); if (g_verbose) { ::System::Console::WriteLine( "> emitting struct type {0}", cts_name); } return ret_type; } //Examples of generated code // public static XWeak constructor1(XComponentContext ctx) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // return (XWeak) factory.createInstanceWithContext("service_specifier", ctx); // } // public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // Any[] arAny = new Any[3]; // arAny[0] = new Any(typeof(int), a); // arAny[1] = new Any(typeof(int), b); // arAny[2] = new Any(c.Type, c.Value); // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx); // } // Notice that a any parameter is NOT wrapped by another any. Instead the new any is created with the type and value // of the parameter. // public static XWeak constructor3(XComponentContext ctx, params Any[] c) // { // XMultiComponentFactory factory = ctx.getServiceManager(); // if (factory == null) // throw new com.sun.star.uno.DeploymentException("bla", null); // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx); // } ::System::Type * TypeEmitter::complete_service_type(service_entry * entry) { Emit::TypeBuilder * type_builder = entry->m_type_builder; reflection::XServiceTypeDescription2 * xServiceType = entry->m_xType; //Create the private default constructor Emit::ConstructorBuilder* ctor_builder = type_builder->DefineConstructor( (MethodAttributes) (MethodAttributes::Private | MethodAttributes::HideBySig | MethodAttributes::SpecialName | MethodAttributes::RTSpecialName), CallingConventions::Standard, NULL); Emit::ILGenerator* ilGen = ctor_builder->GetILGenerator(); ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this ilGen->Emit( Emit::OpCodes::Call, type_builder->BaseType->GetConstructor(new ::System::Type*[0])); ilGen->Emit( Emit::OpCodes::Ret ); //Create the service constructors. //obtain the interface which makes up this service, it is the return //type of the constructor functions Reference<reflection::XInterfaceTypeDescription2> xIfaceType( xServiceType->getInterface(), UNO_QUERY); if (xIfaceType.is () == sal_False) xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface()); System::Type * retType = get_type(xIfaceType); //Create the ConstructorInfo for a DeploymentException ::System::Type * typeDeploymentExc = get_type(S"unoidl.com.sun.star.uno.DeploymentException", true); ::System::Type * arTypeCtor[] = {__typeof(::System::String), __typeof(::System::Object)}; ::System::Reflection::ConstructorInfo * ctorDeploymentException = typeDeploymentExc->GetConstructor(arTypeCtor); Sequence<Reference<reflection::XServiceConstructorDescription> > seqCtors = xServiceType->getConstructors(); ::System::Type * type_uno_exception = get_type(S"unoidl.com.sun.star.uno.Exception", true); for (int i = seqCtors.getLength() - 1; i >= 0; i--) { bool bParameterArray = false; ::System::Type * typeAny = __typeof(::uno::Any); const Reference<reflection::XServiceConstructorDescription> & ctorDes = seqCtors[i]; //obtain the parameter types Sequence<Reference<reflection::XParameter> > seqParams = ctorDes->getParameters(); Reference<reflection::XParameter> const * arXParams = seqParams.getConstArray(); sal_Int32 cParams = seqParams.getLength(); ::System::Type * arTypeParameters[] = new ::System::Type* [cParams + 1]; arTypeParameters[0] = get_type(S"unoidl.com.sun.star.uno.XComponentContext", true); for (int iparam = 0; iparam != cParams; iparam++) { if (arXParams[iparam]->isRestParameter()) arTypeParameters[iparam + 1] = __typeof(::uno::Any[]); else arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType()); } //The array arTypeParameters can contain: //System.Type and uno.PolymorphicType. //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem. //The exception will read something like no on information for parameter # d //Maybe we need no override another Type method in PolymorphicType ... //Until we have figured this out, we will create another array of System.Type which //we pass on to DefineMethod. ::System::Type * arParamTypes[] = new ::System::Type * [cParams + 1]; // arParamTypes[0] = get_type(S"unoidl.com.sun.star.uno.XComponentContext", true); for (int i = 0; i < cParams + 1; i++) { ::uno::PolymorphicType * pT = dynamic_cast< ::uno::PolymorphicType * >(arTypeParameters[i]); if (pT) arParamTypes[i] = pT->OriginalType; else arParamTypes[i] = arTypeParameters[i]; } //define method System::String * ctorName; if (ctorDes->isDefaultConstructor()) ctorName = new ::System::String(S"create"); else ctorName = ustring_to_String(ctorDes->getName()); Emit::MethodBuilder* method_builder = type_builder->DefineMethod( ctorName, static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig | MethodAttributes::Static), retType, // arTypeParameters); arParamTypes); //define UNO exception attribute (exceptions)-------------------------------------- Emit::CustomAttributeBuilder* attrBuilder = get_service_exception_attribute(ctorDes); if (attrBuilder != NULL) method_builder->SetCustomAttribute(attrBuilder); //------------------------------------------------------------- //define parameter attributes (paramarray), names etc. //The first parameter is the XComponentContext, which cannot be obtained //from reflection. //The context is not part of the idl description method_builder->DefineParameter( 1, ParameterAttributes::In, S"the_context"); Emit::ParameterBuilder * arParameterBuilder[] = new Emit::ParameterBuilder * [cParams]; for (int iparam = 0; iparam != cParams; iparam++) { Reference<reflection::XParameter> const & aParam = arXParams[iparam]; ::System::String * sParamName = ustring_to_String(aParam->getName()); arParameterBuilder[iparam] = method_builder->DefineParameter( iparam + 2, ParameterAttributes::In, sParamName); if (aParam->isRestParameter()) { bParameterArray = true; //set the ParameterArrayAttribute ::System::Reflection::ConstructorInfo* ctor_info = __typeof(System::ParamArrayAttribute)->GetConstructor( new ::System::Type*[0]); Emit::CustomAttributeBuilder * attr_builder = new Emit::CustomAttributeBuilder(ctor_info, new ::System::Object*[0]); arParameterBuilder[iparam]->SetCustomAttribute(attr_builder); break; } } Emit::ILGenerator * ilGen = method_builder->GetILGenerator(); //Define locals --------------------------------- //XMultiComponentFactory Emit::LocalBuilder* local_factory = ilGen->DeclareLocal( get_type(S"unoidl.com.sun.star.lang.XMultiComponentFactory", true)); //The return type Emit::LocalBuilder* local_return_val = ilGen->DeclareLocal(retType); //Obtain the XMultiComponentFactory and throw an exception if we do not get one ilGen->Emit(Emit::OpCodes::Ldarg_0); ::System::Reflection::MethodInfo * methodGetServiceManager = get_type( S"unoidl.com.sun.star.uno.XComponentContext", true) ->GetMethod(S"getServiceManager"); ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager); ilGen->Emit(Emit::OpCodes::Stloc, local_factory); ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); Emit::Label label1 = ilGen->DefineLabel(); ilGen->Emit(Emit::OpCodes::Brtrue, label1); //The string for the exception ::System::Text::StringBuilder * strbuilder = new ::System::Text::StringBuilder(256); strbuilder->Append(S"The service "); strbuilder->Append(to_cts_name(xServiceType->getName())); strbuilder->Append(S" could not be created. The context failed to supply the service manager."); ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString()); ilGen->Emit(Emit::OpCodes::Ldarg_0); ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException); ilGen->Emit(Emit::OpCodes::Throw); ilGen->MarkLabel(label1); //We create a try/ catch around the createInstanceWithContext, etc. functions //There are 3 cases //1. function do not specify exceptions. Then RuntimeExceptions are retrhown and other // exceptions produce a DeploymentException. //2. function specify Exception. Then all exceptions fly through //3. function specifies exceptions but no Exception. Then these are rethrown // and other exceptions, except RuntimeException, produce a deployment exception. //In case there are no parameters we call //XMultiComponentFactory.createInstanceWithContext ::System::Collections::ArrayList * arExceptionTypes = get_service_ctor_method_exceptions_reduced(ctorDes->getExceptions()); if (arExceptionTypes->Contains( type_uno_exception) == false) { ilGen->BeginExceptionBlock(); } if (cParams == 0) { ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName())); ilGen->Emit(Emit::OpCodes::Ldarg_0); ::System::Reflection::MethodInfo * methodCreate = local_factory->get_LocalType()->GetMethod(S"createInstanceWithContext"); ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate); } else if(bParameterArray) { //Service constructor with parameter array ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName())); ilGen->Emit(Emit::OpCodes::Ldarg_1); ilGen->Emit(Emit::OpCodes::Ldarg_0); ::System::Reflection::MethodInfo * methodCreate = local_factory->get_LocalType()->GetMethod(S"createInstanceWithArgumentsAndContext"); ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate); } else { // Any param1, Any param2, etc. // For each parameter,except the component context, and parameter array // and Any is created. Emit::LocalBuilder * arLocalAny[] = new Emit::LocalBuilder* [cParams]; for (int iParam = 0; iParam < cParams; iParam ++) { arLocalAny[iParam] = ilGen->DeclareLocal(typeAny); } //Any[]. This array is filled with the created Anys which contain the parameters //and the values contained in the parameter array Emit::LocalBuilder * local_anyParams = ilGen->DeclareLocal(__typeof(::uno::Any[])); //Create the Any for every argument, except for the parameter array //arLocalAny contains the LocalBuilder for all these parameters. //we call the ctor Any(Type, Object) //If the parameter is an Any then the Any is created with Any(param.Type, param.Value); ::System::Type * arTypesCtorAny[] = {__typeof(::System::Type), __typeof(::System::Object)}; ::System::Reflection::ConstructorInfo * ctorAny = typeAny->GetConstructor( arTypesCtorAny); ::System::Reflection::MethodInfo * methodAnyGetType = typeAny->GetProperty(S"Type")->GetGetMethod(); ::System::Reflection::MethodInfo * methodAnyGetValue = typeAny->GetProperty(S"Value")->GetGetMethod(); for (int i = 0; i < arLocalAny->Length; i ++) { //check if the parameter is a polymorphic struct ::uno::PolymorphicType *polyType = dynamic_cast< ::uno::PolymorphicType* >(arTypeParameters[i+1]); //arTypeParameters[i+1] = polyType->OriginalType; if (polyType) { //It is a polymorphic struct //Load the uninitialized local Any on which we will call the ctor ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]); // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName) // Prepare the first parameter ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->get_OriginalType()); ::System::Type * arTypeParams[] = {__typeof(::System::RuntimeTypeHandle)}; ilGen->Emit(Emit::OpCodes::Call, __typeof(::System::Type)->GetMethod( S"GetTypeFromHandle", arTypeParams)); // Prepare the second parameter ilGen->Emit(Emit::OpCodes::Ldstr, polyType->get_PolymorphicName()); // Make the actual call ::System::Type * arTypeParam_GetType[] = { __typeof(::System::Type), __typeof(::System::String) }; ilGen->Emit(Emit::OpCodes::Call, __typeof(::uno::PolymorphicType)->GetMethod(new System::String(S"GetType"), arTypeParam_GetType)); //Stack is: localAny, PolymorphicType //Call Any::Any(Type, Object) //Prepare the second parameter for the any ctor ilGen->Emit(Emit::OpCodes::Ldarg, i + 1); // if the parameter is a value type then we need to box it, because // the Any ctor takes an Object if (arTypeParameters[i+1]->IsValueType) ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]); ilGen->Emit(Emit::OpCodes::Call, ctorAny); } else if (arTypeParameters[i+1] == typeAny) { //Create the call new Any(param.Type,param,Value) //Stack must be Any,Type,Value //First load the Any which is to be constructed ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]); //Load the Type, which is obtained by calling param.Type ilGen->Emit(Emit::OpCodes::Ldarga, i + 1); ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType); //Load the Value, which is obtained by calling param.Value ilGen->Emit(Emit::OpCodes::Ldarga, i + 1); ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue); //Call the Any ctor. ilGen->Emit(Emit::OpCodes::Call, ctorAny); } else { ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]); ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]); ::System::Type * arTypeParams[] = {__typeof(::System::RuntimeTypeHandle)}; ilGen->Emit(Emit::OpCodes::Call, __typeof(::System::Type)->GetMethod( S"GetTypeFromHandle", arTypeParams)); ilGen->Emit(Emit::OpCodes::Ldarg, i + 1); // if the parameter is a value type then we need to box it, because // the Any ctor takes an Object if (arTypeParameters[i+1]->IsValueType) ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]); ilGen->Emit(Emit::OpCodes::Call, ctorAny); } } //Create the Any[] that is passed to the //createInstanceWithContext[AndArguments] function ilGen->Emit(Emit::OpCodes::Ldc_I4, arLocalAny->Length); ilGen->Emit(Emit::OpCodes::Newarr, typeAny); ilGen->Emit(Emit::OpCodes::Stloc, local_anyParams); //Assign all Anys created from the parameters //array to the Any[] for (int i = 0; i < arLocalAny->Length; i++) { ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams); ilGen->Emit(Emit::OpCodes::Ldc_I4, i); ilGen->Emit(Emit::OpCodes::Ldelema, typeAny); ilGen->Emit(Emit::OpCodes::Ldloc, arLocalAny[i]); ilGen->Emit(Emit::OpCodes::Stobj, typeAny); } // call createInstanceWithContextAndArguments ilGen->Emit(Emit::OpCodes::Ldloc, local_factory); ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName())); ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams); ilGen->Emit(Emit::OpCodes::Ldarg_0); ::System::Reflection::MethodInfo * methodCreate = local_factory->get_LocalType()->GetMethod(S"createInstanceWithArgumentsAndContext"); ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate); } //cast the object returned by the functions createInstanceWithContext or //createInstanceWithArgumentsAndContext to the interface type ilGen->Emit(Emit::OpCodes::Castclass, retType); ilGen->Emit(Emit::OpCodes::Stloc, local_return_val); //catch exceptions thrown by createInstanceWithArgumentsAndContext and createInstanceWithContext if (arExceptionTypes->Contains(type_uno_exception) == false) { // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;} ilGen->BeginCatchBlock(get_type(S"unoidl.com.sun.star.uno.RuntimeException", true)); ilGen->Emit(Emit::OpCodes::Pop); ilGen->Emit(Emit::OpCodes::Rethrow); //catch and rethrow all other defined Exceptions for (int i = 0; i < arExceptionTypes->Count; i++) { ::System::Type * excType = __try_cast< ::System::Type* >( arExceptionTypes->get_Item(i)); if (excType->IsInstanceOfType( get_type(S"unoidl.com.sun.star.uno.RuntimeException", true))) {// we have a catch for RuntimeException already defined continue; } //catch Exception and rethrow ilGen->BeginCatchBlock(excType); ilGen->Emit(Emit::OpCodes::Pop); ilGen->Emit(Emit::OpCodes::Rethrow); } //catch (unoidl.com.sun.star.uno.Exception) {throw DeploymentException...} ilGen->BeginCatchBlock(type_uno_exception); //Define the local variable that keeps the exception Emit::LocalBuilder * local_exception = ilGen->DeclareLocal( type_uno_exception); //Store the exception ilGen->Emit(Emit::OpCodes::Stloc, local_exception); //prepare the construction of the exception strbuilder = new ::System::Text::StringBuilder(256); strbuilder->Append(S"The context (com.sun.star.uno.XComponentContext) failed to supply the service "); strbuilder->Append(to_cts_name(xServiceType->getName())); strbuilder->Append(S": "); ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString()); //add to the string the Exception.Message ilGen->Emit(Emit::OpCodes::Ldloc, local_exception); ilGen->Emit(Emit::OpCodes::Callvirt, type_uno_exception->GetProperty(S"Message")->GetGetMethod()); ::System::Type * arConcatParams [] = {__typeof(System::String), __typeof(System::String)}; ilGen->Emit(Emit::OpCodes::Call, __typeof(System::String)->GetMethod(S"Concat", arConcatParams)); //load contex argument ilGen->Emit(Emit::OpCodes::Ldarg_0); ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException); ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc); ilGen->EndExceptionBlock(); } //Check if the service instance was created and throw a exception if not. Emit::Label label_service_created = ilGen->DefineLabel(); ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val); ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created); strbuilder = new ::System::Text::StringBuilder(256); strbuilder->Append(S"The context (com.sun.star.uno.XComponentContext) failed to supply the service "); strbuilder->Append(to_cts_name(xServiceType->getName())); strbuilder->Append(S"."); ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString()); ilGen->Emit(Emit::OpCodes::Ldarg_0); ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException); ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc); ilGen->MarkLabel(label_service_created); ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val); ilGen->Emit(Emit::OpCodes::Ret); } // remove from incomplete types map ::System::String * cts_name = type_builder->get_FullName(); m_incomplete_services->Remove( cts_name ); xServiceType->release(); if (g_verbose) { ::System::Console::WriteLine( "> emitting service type {0}", cts_name ); } return type_builder->CreateType(); } Emit::CustomAttributeBuilder* TypeEmitter::get_service_exception_attribute( const Reference<reflection::XServiceConstructorDescription> & ctorDes ) { return get_exception_attribute(ctorDes->getExceptions()); } Emit::CustomAttributeBuilder* TypeEmitter::get_iface_method_exception_attribute( const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod ) { const Sequence<Reference<reflection::XTypeDescription> > seqTD = xMethod->getExceptions(); int len = seqTD.getLength(); Sequence<Reference<reflection::XCompoundTypeDescription> > seqCTD(len); Reference<reflection::XCompoundTypeDescription> * arCTD = seqCTD.getArray(); for (int i = 0; i < len; i++) arCTD[i] = Reference<reflection::XCompoundTypeDescription>(seqTD[i], UNO_QUERY_THROW); return get_exception_attribute(seqCTD); } Emit::CustomAttributeBuilder* TypeEmitter::get_exception_attribute( const Sequence<Reference< reflection::XCompoundTypeDescription > >& seq_exceptionsTd ) { Emit::CustomAttributeBuilder * attr_builder = NULL; Reference< reflection::XCompoundTypeDescription > const * exceptions = seq_exceptionsTd.getConstArray(); ::System::Type * arTypesCtor[] = {::System::Type::GetType(S"System.Type[]")}; ConstructorInfo * ctor_ExceptionAttribute = __typeof(::uno::ExceptionAttribute)->GetConstructor(arTypesCtor); sal_Int32 exc_length = seq_exceptionsTd.getLength(); if (exc_length != 0) // opt { ::System::Type * exception_types [] = new ::System::Type * [ exc_length ]; for ( sal_Int32 exc_pos = 0; exc_pos < exc_length; ++exc_pos ) { Reference< reflection::XCompoundTypeDescription > const & xExc = exceptions[ exc_pos ]; exception_types[ exc_pos ] = get_type( xExc ); } ::System::Object * args [] = {exception_types}; attr_builder = new Emit::CustomAttributeBuilder( ctor_ExceptionAttribute, args ); } return attr_builder; } ::System::Type * TypeEmitter::complete_singleton_type(singleton_entry * entry) { Emit::TypeBuilder * type_builder = entry->m_type_builder; reflection::XSingletonTypeDescription2 * xSingletonType = entry->m_xType; ::System::String* sSingletonName = to_cts_name(xSingletonType->getName()); //Create the private default constructor Emit::ConstructorBuilder* ctor_builder = type_builder->DefineConstructor( static_cast<MethodAttributes>(MethodAttributes::Private | MethodAttributes::HideBySig | MethodAttributes::SpecialName | MethodAttributes::RTSpecialName), CallingConventions::Standard, NULL); Emit::ILGenerator* ilGen = ctor_builder->GetILGenerator(); ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this ilGen->Emit( Emit::OpCodes::Call, type_builder->BaseType->GetConstructor(new ::System::Type*[0])); ilGen->Emit( Emit::OpCodes::Ret ); //obtain the interface which makes up this service, it is the return //type of the constructor functions Reference<reflection::XInterfaceTypeDescription2> xIfaceType( xSingletonType->getInterface(), UNO_QUERY); if (xIfaceType.is () == sal_False) xIfaceType = resolveInterfaceTypedef(xSingletonType->getInterface()); System::Type * retType = get_type(xIfaceType); //define method ::System::Type * arTypeParameters[] = {get_type(S"unoidl.com.sun.star.uno.XComponentContext", true)}; Emit::MethodBuilder* method_builder = type_builder->DefineMethod( new System::String(S"get"), static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig | MethodAttributes::Static), retType, arTypeParameters); // method_builder->SetCustomAttribute(get_service_ctor_method_attribute(ctorDes)); //The first parameter is the XComponentContext, which cannot be obtained //from reflection. //The context is not part of the idl description method_builder->DefineParameter(1, ParameterAttributes::In, S"the_context"); ilGen = method_builder->GetILGenerator(); //Define locals --------------------------------- // Any, returned by XComponentContext.getValueByName Emit::LocalBuilder* local_any = ilGen->DeclareLocal(__typeof(::uno::Any)); //Call XContext::getValueByName ilGen->Emit(Emit::OpCodes::Ldarg_0); // build the singleton name : /singleton/unoidl.com.sun.star.XXX ::System::Text::StringBuilder* sBuilder = new ::System::Text::StringBuilder(S"/singletons/"); sBuilder->Append(sSingletonName); ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString()); ::System::Reflection::MethodInfo * methodGetValueByName = get_type(S"unoidl.com.sun.star.uno.XComponentContext", true)->GetMethod(S"getValueByName"); ilGen->Emit(Emit::OpCodes::Callvirt, methodGetValueByName); ilGen->Emit(Emit::OpCodes::Stloc_0); //Contains the returned Any a value? ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any); ::System::Reflection::MethodInfo * methodHasValue = __typeof(::uno::Any)->GetMethod(S"hasValue"); ilGen->Emit(Emit::OpCodes::Call, methodHasValue); //If not, then throw an DeploymentException Emit::Label label_singleton_exists = ilGen->DefineLabel(); ilGen->Emit(Emit::OpCodes::Brtrue_S, label_singleton_exists); sBuilder = new ::System::Text::StringBuilder( S"Component context fails to supply singleton "); sBuilder->Append(sSingletonName); sBuilder->Append(S" of type "); sBuilder->Append(retType->FullName); sBuilder->Append(S"."); ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString()); ilGen->Emit(Emit::OpCodes::Ldarg_0); ::System::Type * arTypesCtorDeploymentException[] = { __typeof(::System::String), __typeof(::System::Object)}; ilGen->Emit(Emit::OpCodes::Newobj, get_type(S"unoidl.com.sun.star.uno.DeploymentException",true) ->GetConstructor(arTypesCtorDeploymentException)); ilGen->Emit(Emit::OpCodes::Throw); ilGen->MarkLabel(label_singleton_exists); //Cast the singleton contained in the Any to the expected interface and return it. ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any); ilGen->Emit(Emit::OpCodes::Call, __typeof(::uno::Any)->GetProperty(S"Value")->GetGetMethod()); ilGen->Emit(Emit::OpCodes::Castclass, retType); ilGen->Emit(Emit::OpCodes::Ret); // remove from incomplete types map ::System::String * cts_name = type_builder->get_FullName(); m_incomplete_singletons->Remove( cts_name ); xSingletonType->release(); if (g_verbose) { ::System::Console::WriteLine( "> emitting singleton type {0}", cts_name ); } return type_builder->CreateType(); } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_type( Reference< reflection::XTypeDescription > const & xType ) { switch (xType->getTypeClass()) { case TypeClass_VOID: return __typeof (::System::Void); case TypeClass_CHAR: return __typeof (::System::Char); case TypeClass_BOOLEAN: return __typeof (::System::Boolean); case TypeClass_BYTE: return __typeof (::System::Byte); case TypeClass_SHORT: return __typeof (::System::Int16); case TypeClass_UNSIGNED_SHORT: return __typeof (::System::UInt16); case TypeClass_LONG: return __typeof (::System::Int32); case TypeClass_UNSIGNED_LONG: return __typeof (::System::UInt32); case TypeClass_HYPER: return __typeof (::System::Int64); case TypeClass_UNSIGNED_HYPER: return __typeof (::System::UInt64); case TypeClass_FLOAT: return __typeof (::System::Single); case TypeClass_DOUBLE: return __typeof (::System::Double); case TypeClass_STRING: return __typeof (::System::String); case TypeClass_TYPE: return __typeof (::System::Type); case TypeClass_ANY: return __typeof(::uno::Any); case TypeClass_ENUM: return get_type( Reference< reflection::XEnumTypeDescription >( xType, UNO_QUERY_THROW ) ); case TypeClass_TYPEDEF: // unwind typedefs return get_type( Reference< reflection::XIndirectTypeDescription >( xType, UNO_QUERY_THROW )->getReferencedType() ); case TypeClass_STRUCT: case TypeClass_EXCEPTION: return get_type( Reference< reflection::XCompoundTypeDescription >( xType, UNO_QUERY_THROW ) ); case TypeClass_SEQUENCE: { ::System::Type * element_type = get_type( Reference< reflection::XIndirectTypeDescription >( xType, UNO_QUERY_THROW )->getReferencedType() ); ::System::Type * retType = get_type( ::System::String::Concat( element_type->get_FullName(), S"[]" ), true ); ::uno::PolymorphicType * pt = dynamic_cast< ::uno::PolymorphicType * >(element_type); if (pt) { ::System::String * sName = ::System::String::Concat(pt->PolymorphicName, S"[]"); retType = ::uno::PolymorphicType::GetType(retType, sName); } return retType; } case TypeClass_INTERFACE: return get_type( Reference< reflection::XInterfaceTypeDescription2 >( xType, UNO_QUERY_THROW ) ); case TypeClass_CONSTANT: return get_type( Reference< reflection::XConstantTypeDescription >( xType, UNO_QUERY_THROW ) ); case TypeClass_CONSTANTS: return get_type( Reference< reflection::XConstantsTypeDescription >( xType, UNO_QUERY_THROW ) ); case TypeClass_SERVICE: return get_type( Reference< reflection::XServiceTypeDescription2 >( xType, UNO_QUERY_THROW) ); case TypeClass_SINGLETON: return get_type( Reference< reflection::XSingletonTypeDescription2 >( xType, UNO_QUERY_THROW) ); case TypeClass_MODULE: // ignore these return 0; default: throw RuntimeException( OUSTR("unexpected type ") + xType->getName(), Reference< XInterface >() ); } } //______________________________________________________________________________ ::System::Type * TypeEmitter::get_complete_struct( ::System::String * sName) { struct_entry * pStruct = __try_cast< struct_entry *>( m_incomplete_structs->get_Item(sName)); if (pStruct) { complete_struct_type(pStruct); } //get_type will ask the module builder for the type or otherwise all known assemblies. return get_type(sName, true); } void TypeEmitter::Dispose() { while (true) { ::System::Collections::IDictionaryEnumerator * enumerator = m_incomplete_ifaces->GetEnumerator(); if (! enumerator->MoveNext()) break; complete_iface_type( __try_cast< iface_entry * >( enumerator->get_Value() ) ); } while (true) { ::System::Collections::IDictionaryEnumerator * enumerator = m_incomplete_structs->GetEnumerator(); if (! enumerator->MoveNext()) break; complete_struct_type( __try_cast< struct_entry * >( enumerator->get_Value() ) ); } while (true) { ::System::Collections::IDictionaryEnumerator * enumerator = m_incomplete_services->GetEnumerator(); if (! enumerator->MoveNext()) break; complete_service_type( __try_cast< service_entry * >( enumerator->get_Value() ) ); } while (true) { ::System::Collections::IDictionaryEnumerator * enumerator = m_incomplete_singletons->GetEnumerator(); if (! enumerator->MoveNext()) break; complete_singleton_type( __try_cast< singleton_entry * >( enumerator->get_Value() ) ); } } //______________________________________________________________________________ TypeEmitter::TypeEmitter( ::System::Reflection::Emit::ModuleBuilder * module_builder, ::System::Reflection::Assembly * extra_assemblies [] ) : m_module_builder( module_builder ), m_extra_assemblies( extra_assemblies ), m_method_info_Type_GetTypeFromHandle( 0 ), m_type_Exception( 0 ), m_type_RuntimeException( 0 ), m_incomplete_ifaces( new ::System::Collections::Hashtable() ), m_incomplete_structs( new ::System::Collections::Hashtable() ), m_incomplete_services(new ::System::Collections::Hashtable() ), m_incomplete_singletons(new ::System::Collections::Hashtable() ), m_generated_structs( new ::System::Collections::Hashtable() ) { ::System::Type * param_types[] = new ::System::Type * [ 1 ]; param_types[ 0 ] = __typeof (::System::RuntimeTypeHandle); m_method_info_Type_GetTypeFromHandle = __typeof (::System::Type) ->GetMethod( "GetTypeFromHandle", param_types ); } ::System::Collections::ArrayList * TypeEmitter::get_service_ctor_method_exceptions_reduced( const Sequence<Reference<reflection::XCompoundTypeDescription> > & seqExceptionsTd) { if (seqExceptionsTd.getLength() == 0) return new ::System::Collections::ArrayList(); ::System::Collections::ArrayList * arTypes = new ::System::Collections::ArrayList(); for (int i = 0; i < seqExceptionsTd.getLength(); i++) arTypes->Add(get_type(to_cts_name(seqExceptionsTd[i]->getName()), true)); int start = 0; while (true) { bool bRemove = false; for (int i = start; i < arTypes->Count; i++) { ::System::Type * t = __try_cast< ::System::Type* >(arTypes->get_Item(i)); for (int j = 0; j < arTypes->Count; j++) { if (t->IsSubclassOf(__try_cast< ::System::Type* >(arTypes->get_Item(j)))) { arTypes->RemoveAt(i); bRemove = true; break; } } if (bRemove) break; start++; } if (bRemove == false) break; } return arTypes; } css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > resolveInterfaceTypedef( const css::uno::Reference<css::reflection::XTypeDescription>& type) { Reference<reflection::XInterfaceTypeDescription2> xIfaceTd(type, UNO_QUERY); if (xIfaceTd.is()) return xIfaceTd; Reference<reflection::XIndirectTypeDescription> xIndTd( type, UNO_QUERY); if (xIndTd.is() == sal_False) throw css::uno::Exception( OUSTR("resolveInterfaceTypedef was called with an invalid argument"), 0); return resolveInterfaceTypedef(xIndTd->getReferencedType()); } }