Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/cli_ure/source/climaker/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 91 kB image not shown  

Quelle  climaker_emit.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   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 .
 */


#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 ::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 )
{
    return ustring_to_String("unoidl." + uno_name);
}


static inline ::System::Object ^ to_cli_constant( Any const & value )
{
    switch (value.getValueTypeClass())
    {
    case TypeClass_CHAR:
        return ((::System::Char) *reinterpret_cast< sal_Unicode const * >(
                value.getValue() ));
    case TypeClass_BOOLEAN:
        return ((::System::Boolean)
             sal_False != *reinterpret_cast< sal_Bool const * >(
                 value.getValue() ));
    case TypeClass_BYTE:
        return ((::System::Byte) *reinterpret_cast< sal_Int8 const * >(
                value.getValue() ));
    case TypeClass_SHORT:
        return ((::System::Int16) *reinterpret_cast< sal_Int16 const * >(
                value.getValue() ));
    case TypeClass_UNSIGNED_SHORT:
        return ((::System::UInt16) *reinterpret_cast< sal_uInt16 const * >(
                value.getValue() ));
    case TypeClass_LONG:
        return ((::System::Int32) *reinterpret_cast< sal_Int32 const * >(
                value.getValue() ));
    case TypeClass_UNSIGNED_LONG:
        return ((::System::UInt32) *reinterpret_cast< sal_uInt32 const * >(
                value.getValue() ));
    case TypeClass_HYPER:
        return ((::System::Int64) *reinterpret_cast< sal_Int64 const * >(
                value.getValue() ));
    case TypeClass_UNSIGNED_HYPER:
        return ((::System::UInt64) *reinterpret_cast< sal_uInt64 const * >(
                value.getValue() ));
    case TypeClass_FLOAT:
        return ((::System::Single) *reinterpret_castfloat const * >(
                value.getValue() ));
    case TypeClass_DOUBLE:
        return ((::System::Double) *reinterpret_castdouble const * >(
                value.getValue() ));
    default:
        throw RuntimeException(
            "unexpected constant type " +
            value.getValueTypeName() );
    }
}


static inline void emit_ldarg( Emit::ILGenerator ^ code, ::System::Int32 index )
{
    switch (index)
    {
    case 0:
#pragma warning (push)
#pragma warning (disable: 4538) // const/volatile qualifiers on this type are not supported
        code->Emit( Emit::OpCodes::Ldarg_0 );
#pragma warning (pop)
        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(">") == 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= gcnew 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("["))//if (usUnoName[0] == '[')
    {
        int index= 1;
        while (true)
        {
            if (typeName[index++] == ']')//if (usUnoName[index++] == ']')
                dims++;
            if (typeName[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 a 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 =
        gcnew 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[cur];
        if (c == ',' || c == '>')
        {
            //insert a comma if needed
            if (countParams != 0)
                builder->Append(",");
            countParams++;
            System::String ^ sParam = unoName->Substring(index, cur - index);
            //skip the comma
            cur++;
            //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[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->Name;
    ::System::Type ^ ret_type = nullptr;

    iface_entry ^ entry = dynamic_cast< iface_entry ^ >(m_incomplete_ifaces[cts_name] );
    if (nullptr != entry)
        ret_type = entry->m_type_builder;

    if (nullptr == ret_type)
    {
        sal_Int32 len = m_extra_assemblies->Length;
        for ( sal_Int32 pos = 0; pos < len; ++pos )
        {
            ret_type = m_extra_assemblies[ pos ]->GetType(
                cts_name, false /* no exc */ );
            if (nullptr != ret_type)
            {
                if (g_bVerbose)
                {
                    ::System::Console::WriteLine(
                        "> resolving type {0} from {1}.",
                        cts_name, ret_type->Assembly->FullName );
                }
                break;
            }
        }
    }
    if (nullptr != ret_type)
        return ret_type->Assembly;
    return nullptr;
}


::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 == nullptr)
    {
        ::System::Text::StringBuilder ^ builder = gcnew ::System::Text::StringBuilder(cts_name);
        builder->Append(",cli_basetypes");
        ret_type = ::System::Type::GetType(builder->ToString());
    }

    if (ret_type == nullptr)
    {
        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 = gcnew ::System::Text::StringBuilder();
            sb->Append(gcnew ::System::String("\nThe type "));
            sb->Append(cts_name);
            sb->Append(gcnew ::System::String(" \n could not be found. Did you forget to "
                "specify an additional assembly with the --reference option?\n"));
            if (throw_exc)
                throw gcnew ::System::Exception(sb->ToString(), exc);
        }
    }
    else
    {
        return ret_type;
    }
}


::System::Type ^ TypeEmitter::get_type_Exception()
{
    if (nullptr == m_type_Exception)
    {
        m_type_Exception = get_type(
            "unoidl.com.sun.star.uno.Exception"false /* no exc */ );
        if (nullptr == m_type_Exception)
        {
            // define hardcoded type unoidl.com.sun.star.uno.Exception
            Emit::TypeBuilder ^ type_builder =
                m_module_builder->DefineType(
                      "unoidl.com.sun.star.uno.Exception",
                      (TypeAttributes) (TypeAttributes::Public |
                                        TypeAttributes::BeforeFieldInit |
                                        TypeAttributes::AnsiClass),
                      (::System::Exception::typeid) );
            Emit::FieldBuilder ^ field_Context = type_builder->DefineField(
                "Context", (::System::Object::typeid),
                FieldAttributes::Public );
            // default .ctor
            type_builder->DefineDefaultConstructor( c_ctor_method_attr );
            // .ctor
            array< ::System::Type^>^ param_types =
                  gcnew array< ::System::Type^>(2);
            param_types[ 0 ] = ::System::String::typeid;
            param_types[ 1 ] = ::System::Object::typeid;
            Emit::ConstructorBuilder ^ ctor_builder =
                type_builder->DefineConstructor(
                    c_ctor_method_attr, CallingConventions::Standard,
                    param_types );
            ctor_builder->DefineParameter(
                1, ParameterAttributes::In, "Message" );
            ctor_builder->DefineParameter(
                2, ParameterAttributes::In, "Context" );
            Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
            code->Emit( Emit::OpCodes::Ldarg_0 );
            code->Emit( Emit::OpCodes::Ldarg_1 );
            param_types = gcnew array< ::System::Type^>(1);
            param_types[ 0 ] = ::System::String::typeid;
            code->Emit(
                Emit::OpCodes::Call,
                (::System::Exception::typeid)
                  ->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_bVerbose)
            {
                ::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 (nullptr == m_type_RuntimeException)
    {
        m_type_RuntimeException = get_type(
            "unoidl.com.sun.star.uno.RuntimeException"false /* no exc */ );
        if (nullptr == 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(
                      "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
            array< ::System::Type^>^ param_types =
                  gcnew array< ::System::Type^>(2);
            param_types[ 0 ] = ::System::String::typeid;
            param_types[ 1 ] = ::System::Object::typeid;
            Emit::ConstructorBuilder ^ ctor_builder =
                type_builder->DefineConstructor(
                    c_ctor_method_attr, CallingConventions::Standard,
                    param_types );
            ctor_builder->DefineParameter(
                1, ParameterAttributes::In, "Message" );
            ctor_builder->DefineParameter(
                2, ParameterAttributes::In, "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_bVerbose)
            {
                ::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 (nullptr == ret_type)
    {
        Reference< reflection::XConstantTypeDescription > xConstant(
            xType, UNO_SET_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_bVerbose)
        {
            ::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 (nullptr == ret_type)
    {
        Emit::TypeBuilder ^ type_builder =
            m_module_builder->DefineType(
                cts_name,
                (TypeAttributes) (TypeAttributes::Public |
                                  TypeAttributes::Sealed |
                                  TypeAttributes::BeforeFieldInit |
                                  TypeAttributes::AnsiClass) );

        const Sequence< Reference<
            reflection::XConstantTypeDescription > > seq_constants(
                xType->getConstants() );
        sal_Int32 constants_length = seq_constants.getLength();
        for ( sal_Int32 constants_pos = 0;
              constants_pos < constants_length; ++constants_pos )
        {
            Reference<
                reflection::XConstantTypeDescription > const & xConstant =
                seq_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_bVerbose)
        {
            ::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 (nullptr == ret_type)
    {
        // workaround enum builder bug
        Emit::TypeBuilder ^ enum_builder =
            m_module_builder->DefineType(
                cts_name,
                (TypeAttributes) (TypeAttributes::Public |
                                  TypeAttributes::Sealed),
                ::System::Enum::typeid );
        enum_builder->DefineField(
            "value__", ::System::Int32::typeid,
            (FieldAttributes) (FieldAttributes::Private |
                               FieldAttributes::SpecialName |
                               FieldAttributes::RTSpecialName) );
        const Sequence< OUString > seq_enum_names( xType->getEnumNames() );
        const Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() );
        sal_Int32 enum_length = seq_enum_names.getLength();
        OSL_ASSERT( enum_length == seq_enum_values.getLength() );
        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( seq_enum_names[ enum_pos ] ),
                    enum_builder,
                    (FieldAttributes) (FieldAttributes::Public |
                                       FieldAttributes::Static |
                                       FieldAttributes::Literal) );
            field_builder->SetConstant(
                ((::System::Int32) seq_enum_values[ enum_pos ]) );
        }

        if (g_bVerbose)
        {
            ::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 == "com.sun.star.uno.Exception" )
        {
            return get_type_Exception();
        }
        if ( uno_name == "com.sun.star.uno.RuntimeException" )
        {
            return get_type_RuntimeException();
        }
    }
    ::System::String ^ cts_name = to_cts_name( uno_name );
    // if the struct is an instantiated polymorphic 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 (nullptr == ret_type)
    {
        Reference< reflection::XCompoundTypeDescription > xBaseType(
            xType->getBaseType(), UNO_QUERY );
        ::System::Type ^ base_type = (xBaseType.is()
                                      ? get_type( xBaseType )
                                      : ::System::Object::typeid);
        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 = gcnew 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 than Type. This is needed for constructing
    //the service code. We can only do that if the struct is completed.
    if (m_generated_structs[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 == "com.sun.star.uno.XInterface" )
    {
        return ::System::Object::typeid;
    }

    ::System::String ^ cts_name = to_cts_name( xType->getName() );
    ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
    if (nullptr == 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() != "com.sun.star.uno.XInterface" )
                {
                    vecBaseTypes.push_back(xIfaceTd);
                }
            }

            array< ::System::Type^>^ base_interfaces =
                  gcnew array< ::System::Type^>( vecBaseTypes.size() );

            int index = 0;
            for (auto const & vecBaseType : vecBaseTypes)
            {
                base_interfaces[ index ] = get_type( vecBaseType );
                ++index;
            }
            type_builder = m_module_builder->DefineType(
                cts_name, attr, nullptr, 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 = gcnew 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 nullptr;

    System::String ^ cts_name = to_cts_name( xType->getName() );
    System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
    if (ret_type != nullptr)
        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 = gcnew 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 nullptr;

    ::System::String^ cts_name = to_cts_name( xType->getName() );
    ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
    if (ret_type != nullptr)
        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 = gcnew 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 than a typedef
            Reference<reflection::XInterfaceTypeDescription2> aBaseType =
                resolveInterfaceTypedef( seqBaseTypes[i]);

            if ( aBaseType->getName() != "com.sun.star.uno.XInterface" )
            {
                ::System::String ^ basetype_name = to_cts_name( aBaseType->getName() );
                iface_entry ^ base_entry = dynamic_cast< iface_entry ^ >(
                    m_incomplete_ifaces[basetype_name] );
                if (nullptr != base_entry)
                {
                // complete uncompleted base type first
                    complete_iface_type( base_entry );
                }
            }
        }
    }

    const Sequence<
        Reference< reflection::XInterfaceMemberTypeDescription > > seq_members(
            xType->getMembers() );
    sal_Int32 members_length = seq_members.getLength();
    for ( sal_Int32 members_pos = 0;
          members_pos < members_length; ++members_pos )
    {
        Reference<
            reflection::XInterfaceMemberTypeDescription > const & xMember =
            seq_members[ members_pos ];
        Sequence< Reference< reflection::XTypeDescription > > seq_exceptions;

        MethodAttributes c_method_attr = (MethodAttributes)
            (MethodAttributes::Public |
             MethodAttributes::Abstract |
             MethodAttributes::Virtual |
             MethodAttributes::NewSlot |
             MethodAttributes::HideBySig);

        if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass())
        {
            Reference< reflection::XInterfaceMethodTypeDescription > xMethod(
                xMember, UNO_QUERY_THROW );

            const Sequence<
                Reference< reflection::XMethodParameter > > seq_parameters(
                    xMethod->getParameters() );
            sal_Int32 params_length = seq_parameters.getLength();
            array< ::System::Type^>^ param_types =
                  gcnew array< ::System::Type^>( params_length );
            // 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 =
                    seq_parameters[ params_pos ];
                ::System::Type ^ param_type = get_type( xParam->getType() );
                ::System::String ^ param_type_name = param_type->FullName;
                if (xParam->isOut())
                {
                    param_type = get_type(
                        ::System::String::Concat(
                            param_type_name, "&" ), 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
            Emit::MethodBuilder ^ 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 =
                    seq_parameters[ params_pos ];
                long param_flags = 0;
                if (xParam->isIn())
                    param_flags |= (long)ParameterAttributes::In;
                if (xParam->isOut())
                    param_flags |= (long)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())
            {
                const Sequence<Reference<reflection::XTypeDescription> > seq_type_args =
                    xReturnStruct->getTypeArguments();
                if (seq_type_args.getLength() != 0)
                {
                    //get the ctor of the attribute
                    array< ::System::Type^>^ arCtor = {::System::Type::GetType("System.Type[]")};
                    //Get the arguments for the attribute's ctor
                    int numTypes = seq_type_args.getLength();
                    array< ::System::Type^>^ arCtsTypes = gcnew array< ::System::Type^>(numTypes);
                    for (int i = 0; i < numTypes; i++)
                        arCtsTypes[i] = get_type(seq_type_args[i]);
                    array< ::System::Object^>^ arArgs = {arCtsTypes};

                    Emit::CustomAttributeBuilder ^ attrBuilder =
                        gcnew Emit::CustomAttributeBuilder(
                            ::uno::TypeArgumentsAttribute::typeid
                            ->GetConstructor( arCtor),
                            arArgs);

                    method_builder->SetCustomAttribute(attrBuilder);
                }
            }

            //define UNO exception attribute (exceptions)--------------------------------------
            Emit::CustomAttributeBuilder^ attrBuilder =
                get_iface_method_exception_attribute(xMethod);
            if (attrBuilder != nullptr)
                method_builder->SetCustomAttribute(attrBuilder);

            // oneway attribute
            if (xMethod->isOneway())
            {
                array< ::System::Type^>^ arCtorOneway = gcnew array< ::System::Type^>(0);
                array< ::System::Object^>^ arArgs = gcnew array< ::System::Object^>(0);
                Emit::CustomAttributeBuilder ^ attrBuilder2 =
                    gcnew Emit::CustomAttributeBuilder(
                        ::uno::OnewayAttribute::typeid->GetConstructor( arCtorOneway),
                        arArgs);
                method_builder->SetCustomAttribute(attrBuilder2);
            }
        }
        else // attribute
        {
            OSL_ASSERT(
                TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() );
            Reference<
                reflection::XInterfaceAttributeTypeDescription2 > xAttribute(
                    xMember, UNO_QUERY_THROW );

            MethodAttributes c_property_method_attr = (MethodAttributes)
                (c_method_attr | MethodAttributes::SpecialName);

            ::System::Type ^ attribute_type = get_type( xAttribute->getType() );
            array< ::System::Type^>^ parameters  =
                  gcnew array< ::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 =
                    ::uno::BoundAttribute::typeid->GetConstructor(
                        gcnew array<System::Type^>(0));
                Emit::CustomAttributeBuilder ^ attrBuilderBound =
                    gcnew Emit::CustomAttributeBuilder(
                        ctorBoundAttr, gcnew array< ::System::Object^>(0));
                property_builder->SetCustomAttribute(attrBuilderBound);
            }

            // getter
            Emit::MethodBuilder ^ method_builder =
                type_builder->DefineMethod(
                    ustring_to_String( "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 != nullptr)
                method_builder->SetCustomAttribute(attrBuilder);

            property_builder->SetGetMethod( method_builder );

            if (! xAttribute->isReadOnly())
            {
                // setter
                parameters = gcnew array< ::System::Type^> ( 1 );
                parameters[ 0 ] = attribute_type;
                method_builder =
                    type_builder->DefineMethod(
                        ustring_to_String( "set_" +
                                           xAttribute->getMemberName() ),
                        c_property_method_attr, nullptr, parameters );
                // define parameter info
                method_builder->DefineParameter(
                    1 /* starts with 1 */, ParameterAttributes::In, "value" );
                //define UNO exception attribute (exceptions)--------------------------------------
                Emit::CustomAttributeBuilder^ attrBuilder2 =
                    get_exception_attribute(xAttribute->getSetExceptions());
                if (attrBuilder2 != nullptr)
                    method_builder->SetCustomAttribute(attrBuilder2);

                property_builder->SetSetMethod( method_builder );
            }
        }
    }

    // remove from incomplete types map
    ::System::String ^ cts_name = type_builder->FullName;
    m_incomplete_ifaces->Remove( cts_name );
    xType->release();

    if (g_bVerbose)
    {
        ::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->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)
        {
            array< ::System::Object^>^ aArg = gcnew array< ::System::Object^>(numTypes);
            for (int i = 0; i < numTypes; i++)
                aArg[i] = ustring_to_String(seq_type_parameters[i]);
            array< ::System::Object^>^ args = {aArg};

            array< ::System::Type^>^ arTypesCtor =
            {::System::Type::GetType("System.String[]")};
            Emit::CustomAttributeBuilder ^ attrBuilder =
                gcnew Emit::CustomAttributeBuilder(
                ::uno::TypeParametersAttribute::typeid->GetConstructor(arTypesCtor),
                args);
            entry->m_type_builder->SetCustomAttribute(attrBuilder);
        }
    }

    // optional: lookup base type whether generated entry of this session
    struct_entry ^ base_type_entry = nullptr;
    if (nullptr != entry->m_base_type)
    {
        //ToDo maybe get from incomplete structs
        base_type_entry =
            dynamic_cast< struct_entry ^ >(
                m_generated_structs[
                    entry->m_base_type->FullName ] );
    }

        // members
    const Sequence< Reference< reflection::XTypeDescription > > seq_members(
        entry->m_xType->getMemberTypes() );
    const 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.
    for (int i = 0; i < members_length; i++)
    {
        const OUString sType(entry->m_xType->getName());
        const OUString sMemberName(seq_member_names[i]);
        if ( ! seq_members[i].is())
            throw RuntimeException("Missing type description . Check if you need to "
            "specify additional RDBs with the --extra option. Type missing for: " +  sType +
            "::" + 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 =
            gcnew ::System::Collections::ArrayList( 3 /* initial capacity */ );
    for (::System::Type ^ base_type_pos = entry->m_base_type;
        ! base_type_pos->Equals( ::System::Object::typeid );
        base_type_pos = base_type_pos->BaseType )
    {
        base_types_list->Add( base_type_pos );
        if (base_type_pos->Equals( ::System::Exception::typeid ))
        {
            // 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->FullName);
            all_members_length +=
                base_type_pos->GetFields(
                (BindingFlags) (BindingFlags::Instance |
                BindingFlags::Public |
                BindingFlags::DeclaredOnly) )
                ->Length;
        }
    }

    // create all_members arrays; right order
    array< ::System::String^>^ all_member_names =
        gcnew array< ::System::String^> (all_members_length + members_length );
    array< ::System::Type^>^ all_param_types =
        gcnew array< ::System::Type^> (all_members_length + members_length );
    member_pos = 0;
    for ( sal_Int32 pos = base_types_list->Count; pos--; )
    {
        ::System::Type ^ base_type = safe_cast< ::System::Type ^ >(
            base_types_list[pos] );
        if (base_type->Equals( ::System::Exception::typeid ))
        {
            all_member_names[ member_pos ] = "Message";
            all_param_types[ member_pos ] = ::System::String::typeid;
            ++member_pos;
        }
        else
        {
            ::System::String ^ base_type_name = base_type->FullName;

            //ToDo m_generated_structs?
            struct_entry ^ entry2 =
                dynamic_cast< struct_entry ^ >(
                m_generated_structs[base_type_name] );
            if (nullptr == entry2)
            {
                // complete type
                array<FieldInfo^>^ fields =
                    base_type->GetFields(
                    (BindingFlags) (BindingFlags::Instance |
                    BindingFlags::Public |
                    BindingFlags::DeclaredOnly) );
                sal_Int32 len = fields->Length;
                for ( sal_Int32 pos2 = 0; pos2 < len; ++pos2 )
                {
                    FieldInfo ^ field = fields[ pos2 ];
                    all_member_names[ member_pos ] = field->Name;
                    all_param_types[ member_pos ] = field->FieldType;
                    ++member_pos;
                }
            }
            else // generated during this session:
                // members may be incomplete ifaces
            {
                sal_Int32 len = entry2->m_member_names->Length;
                for ( sal_Int32 pos2 = 0; pos2 < len; ++pos2 )
                {
                    all_member_names[ member_pos ] =
                        entry2->m_member_names[ pos2 ];
                    all_param_types[ member_pos ] =
                        entry2->m_param_types[ pos2 ];
                    ++member_pos;
                }
            }
        }
    }
    OSL_ASSERT( all_members_length == member_pos );

    // build up entry
//    struct_entry * entry = new struct_entry();
    entry->m_member_names = gcnew array< ::System::String^> ( members_length );
    entry->m_param_types = gcnew array< ::System::Type^> ( members_length );

    // add members
    array<Emit::FieldBuilder^>^ members = gcnew array<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( seq_member_names[ member_pos ] );
        ::System::Type ^ field_type;
        //Special handling of struct parameter types
        bool bParameterizedType = false;
        if (seq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN)
        {
            bParameterizedType = true;
            if (type_param_pos < seq_type_parameters.getLength())
            {
                field_type = ::System::Object::typeid;
                type_param_pos++;
            }
            else
            {
                throw RuntimeException(
                    "unexpected member type in " + entry->m_xType->getName() );
            }
        }
        else
        {
            field_type = get_type( seq_members[ member_pos ] );

            if (field_type->IsArray
                && m_incomplete_structs[cts_name]
                && !field_type->Namespace->Equals("System"))
            {
                //Find the value type. In case of sequence<sequence< ... > > find the actual value type
                ::System::Type ^ value = field_type;
                while ((value = value->GetElementType())->IsArray);
                //If the value type is a struct then make sure it is fully created.
                get_complete_struct(value->FullName);
                field_type = get_type(seq_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[curParamIndex++]);
            array< ::System::Object^>^ args = {sTypeName};
            //set ParameterizedTypeAttribute
            array< ::System::Type^>^ arCtorTypes = {::System::String::typeid};

            Emit::CustomAttributeBuilder ^ attrBuilder =
                gcnew Emit::CustomAttributeBuilder(
                ::uno::ParameterizedTypeAttribute::typeid
                ->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,
        gcnew array< ::System::Type^> ( 0 ) );
    Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
    code->Emit( Emit::OpCodes::Ldarg_0 );
    code->Emit(
        Emit::OpCodes::Call,
        nullptr == base_type_entry
        ? entry->m_base_type->GetConstructor( gcnew array< ::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->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( ::System::String::typeid ))
        {
            code->Emit( Emit::OpCodes::Ldarg_0 );
            code->Emit( Emit::OpCodes::Ldstr, "" );
            code->Emit( Emit::OpCodes::Stfld, field );
        }
        else if (field_type->Equals( ::System::Type::typeid ))
        {
            code->Emit( Emit::OpCodes::Ldarg_0 );
            code->Emit(
                Emit::OpCodes::Ldtoken, ::System::Void::typeid );
            code->Emit(
                Emit::OpCodes::Call, m_method_info_Type_GetTypeFromHandle );
            code->Emit( Emit::OpCodes::Stfld, field );
        }
        else if (field_type->IsArray)
        {
            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->IsValueType)
        {
            if (field_type->FullName->Equals( "uno.Any" ))
            {
                code->Emit( Emit::OpCodes::Ldarg_0 );
                code->Emit( Emit::OpCodes::Ldsfld, ::uno::Any::typeid->GetField("VOID"));
                code->Emit( Emit::OpCodes::Stfld, field );
            }
        }
        else if (field_type->IsClass)
        {
            /* may be XInterface */
            if (! field_type->Equals( ::System::Object::typeid ))
            {
                // struct, exception
                //make sure the struct is already complete.
                get_complete_struct(field_type->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(
                    gcnew array< ::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;
    array< ::System::Type^>^ param_types  =
        gcnew array< ::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,
        nullptr == 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_bVerbose)
    {
        ::System::Console::WriteLine(
            "> emitting {0} type {1}",
            TypeClass_STRUCT == entry->m_xType->getTypeClass()
            ? "struct"
            : "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_bVerbose)
    {
        ::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 an 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, nullptr);

    Emit::ILGenerator^ ilGen1 = ctor_builder->GetILGenerator();
    ilGen1->Emit( Emit::OpCodes::Ldarg_0 ); // push this
    ilGen1->Emit(
            Emit::OpCodes::Call,
            type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
    ilGen1->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("unoidl.com.sun.star.uno.DeploymentException"true);

    array< ::System::Type^>^ arTypeCtor = {::System::String::typeid,
                                         ::System::Object::typeid};
    ::System::Reflection::ConstructorInfo ^ ctorDeploymentException  =
          typeDeploymentExc->GetConstructor(arTypeCtor);

    Sequence<Reference<reflection::XServiceConstructorDescription> >  seqCtors =
        xServiceType->getConstructors();

    ::System::Type ^ type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception"true);

    for (int j = seqCtors.getLength() - 1; j >= 0; j--)
    {
        bool bParameterArray = false;
        ::System::Type ^ typeAny = ::uno::Any::typeid;
        const Reference<reflection::XServiceConstructorDescription> & ctorDes =
            seqCtors[j];
        //obtain the parameter types
        const Sequence<Reference<reflection::XParameter> > seqParams =
            ctorDes->getParameters();
        sal_Int32 cParams = seqParams.getLength();
        array< ::System::Type^>^ arTypeParameters = gcnew array< ::System::Type^> (cParams + 1);
        arTypeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext"true);
        for (int iparam = 0; iparam != cParams; iparam++)
        {
            if (seqParams[iparam]->isRestParameter())
                arTypeParameters[iparam + 1] = array< ::uno::Any>::typeid;
            else
                arTypeParameters[iparam + 1] = get_type(seqParams[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.
        array< ::System::Type^>^ arParamTypes = gcnew array< ::System::Type^> (cParams + 1);
//        arParamTypes[0] = get_type("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 = gcnew ::System::String("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 != nullptr)
            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, "the_context");

        array<Emit::ParameterBuilder^>^ arParameterBuilder =
            gcnew array<Emit::ParameterBuilder^> (cParams);
        for (int iparam = 0; iparam != cParams; iparam++)
        {
            Reference<reflection::XParameter> const & aParam = seqParams[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 =
                    System::ParamArrayAttribute::typeid->GetConstructor(
                        gcnew array< ::System::Type^>(0));
                Emit::CustomAttributeBuilder ^ attr_builder =
                    gcnew Emit::CustomAttributeBuilder(ctor_info, gcnew array< ::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("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(
            "unoidl.com.sun.star.uno.XComponentContext"true)
                ->GetMethod("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 = gcnew ::System::Text::StringBuilder(256);
        strbuilder->Append("The service ");
        strbuilder->Append(to_cts_name(xServiceType->getName()));
        strbuilder->Append(" could not be created. The context failed to supply the service manager.");

--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=88 H=89 G=88

¤ Dauer der Verarbeitung: 0.9 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.