xref: /trunk/main/cli_ure/source/climaker/climaker_emit.cxx (revision 9c15e1abd703a7953928d7a80655ae1a76a41f6d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_cli_ure.hxx"
26 
27 #include "climaker_share.h"
28 
29 #include "rtl/string.hxx"
30 #include "rtl/ustrbuf.hxx"
31 #include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
32 #include "com/sun/star/reflection/XStructTypeDescription.hpp"
33 #include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp"
34 #include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp"
35 #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription.hpp"
36 #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp"
37 #include <vector>
38 
39 using namespace ::System::Reflection;
40 
41 using namespace ::rtl;
42 using namespace ::com::sun::star;
43 using namespace ::com::sun::star::uno;
44 
45 namespace climaker
46 {
47 System::String ^ mapUnoPolymorphicName(System::String ^ unoName);
48 //------------------------------------------------------------------------------
49 static inline ::System::String ^ to_cts_name(
50     OUString const & uno_name )
51 {
52     OUStringBuffer buf( 7 + uno_name.getLength() );
53     buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("unoidl.") );
54     buf.append( uno_name );
55     return ustring_to_String( buf.makeStringAndClear() );
56 }
57 
58 //------------------------------------------------------------------------------
59 static inline ::System::Object ^ to_cli_constant( Any const & value )
60 {
61     switch (value.getValueTypeClass())
62     {
63     case TypeClass_CHAR:
64         return (::System::Object ^)((::System::Char) *reinterpret_cast< sal_Unicode const * >(
65                 value.getValue() ));
66     case TypeClass_BOOLEAN:
67         return (::System::Object ^)((::System::Boolean)
68              sal_False != *reinterpret_cast< sal_Bool const * >(
69                  value.getValue() ));
70     case TypeClass_BYTE:
71         return (::System::Object ^)((::System::Byte) *reinterpret_cast< sal_Int8 const * >(
72                 value.getValue() ));
73     case TypeClass_SHORT:
74         return (::System::Object ^)((::System::Int16) *reinterpret_cast< sal_Int16 const * >(
75                 value.getValue() ));
76     case TypeClass_UNSIGNED_SHORT:
77         return (::System::Object ^)((::System::UInt16) *reinterpret_cast< sal_uInt16 const * >(
78                 value.getValue() ));
79     case TypeClass_LONG:
80         return (::System::Object ^)((::System::Int32) *reinterpret_cast< sal_Int32 const * >(
81                 value.getValue() ));
82     case TypeClass_UNSIGNED_LONG:
83         return (::System::Object ^)((::System::UInt32) *reinterpret_cast< sal_uInt32 const * >(
84                 value.getValue() ));
85     case TypeClass_HYPER:
86         return (::System::Object ^)((::System::Int64) *reinterpret_cast< sal_Int64 const * >(
87                 value.getValue() ));
88     case TypeClass_UNSIGNED_HYPER:
89         return (::System::Object ^)((::System::UInt64) *reinterpret_cast< sal_uInt64 const * >(
90                 value.getValue() ));
91     case TypeClass_FLOAT:
92         return (::System::Object ^)((::System::Single) *reinterpret_cast< float const * >(
93                 value.getValue() ));
94     case TypeClass_DOUBLE:
95         return (::System::Object ^)((::System::Double) *reinterpret_cast< double const * >(
96                 value.getValue() ));
97     default:
98         throw RuntimeException(
99             OUSTR("unexpected constant type ") +
100             value.getValueType().getTypeName(),
101             Reference< XInterface >() );
102     }
103 }
104 
105 //------------------------------------------------------------------------------
106 static inline void emit_ldarg( Emit::ILGenerator ^ code, ::System::Int32 index )
107 {
108     switch (index)
109     {
110     case 0:
111         code->Emit( Emit::OpCodes::Ldarg_0 );
112         break;
113     case 1:
114         code->Emit( Emit::OpCodes::Ldarg_1 );
115         break;
116     case 2:
117         code->Emit( Emit::OpCodes::Ldarg_2 );
118         break;
119     case 3:
120         code->Emit( Emit::OpCodes::Ldarg_3 );
121         break;
122     default:
123         if (index < 0x100)
124             code->Emit( Emit::OpCodes::Ldarg_S, (::System::Byte) index );
125         else if (index < 0x8000)
126             code->Emit( Emit::OpCodes::Ldarg_S, (::System::Int16) index );
127         else
128             code->Emit( Emit::OpCodes::Ldarg, index );
129         break;
130     }
131 }
132 
133 void polymorphicStructNameToStructName(::System::String ^* sPolyName)
134 {
135     if ((*sPolyName)->EndsWith(">") == false)
136         return;
137 
138     int index = (*sPolyName)->IndexOf('<');
139     OSL_ASSERT(index != -1);
140     *sPolyName = (*sPolyName)->Substring(0, index);
141 }
142 
143 
144 System::String ^ mapUnoTypeName(System::String ^ typeName)
145 {
146     ::System::Text::StringBuilder ^ buf= gcnew System::Text::StringBuilder();
147     ::System::String ^ sUnoName = ::System::String::Copy(typeName);
148     //determine if the type is a sequence and its dimensions
149     int dims= 0;
150     if (typeName->StartsWith("["))//if (usUnoName[0] == '[')
151     {
152         int index= 1;
153         while (true)
154         {
155             if (typeName[ index++ ] == ']')//if (usUnoName[index++] == ']')
156                 dims++;
157             if (typeName[ index++ ] != '[')//usUnoName[index++] != '[')
158                 break;
159         }
160         sUnoName = sUnoName->Substring(index - 1);//usUnoName = usUnoName.copy(index - 1);
161     }
162     if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoBool)))
163         buf->Append(const_cast<System::String ^>(Constants::sBoolean));
164     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoChar)))
165         buf->Append(const_cast<System::String ^>(Constants::sChar));
166     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoByte)))
167         buf->Append(const_cast<System::String ^>(Constants::sByte));
168     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoShort)))
169         buf->Append(const_cast<System::String ^>(Constants::sInt16));
170     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoUShort)))
171         buf->Append(const_cast<System::String ^>(Constants::sUInt16));
172     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoLong)))
173         buf->Append(const_cast<System::String ^>(Constants::sInt32));
174     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoULong)))
175         buf->Append(const_cast<System::String ^>(Constants::sUInt32));
176     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoHyper)))
177         buf->Append(const_cast<System::String ^>(Constants::sInt64));
178     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoUHyper)))
179         buf->Append(const_cast<System::String ^>(Constants::sUInt64));
180     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoFloat)))
181         buf->Append(const_cast<System::String ^>(Constants::sSingle));
182     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoDouble)))
183         buf->Append(const_cast<System::String ^>(Constants::sDouble));
184     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoString)))
185         buf->Append(const_cast<System::String ^>(Constants::sString));
186     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoVoid)))
187         buf->Append(const_cast<System::String ^>(Constants::sVoid));
188     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoType)))
189         buf->Append(const_cast<System::String ^>(Constants::sType));
190     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoXInterface)))
191         buf->Append(const_cast<System::String ^>(Constants::sObject));
192     else if (sUnoName->Equals(const_cast<System::String ^>(Constants::sUnoAny)))
193     {
194         buf->Append(const_cast<System::String ^>(Constants::sAny));
195     }
196     else
197     {
198         //put "unoidl." at the beginning
199         buf->Append(const_cast<System::String ^>(Constants::sUnoidl));
200         buf->Append(mapUnoPolymorphicName(sUnoName));
201     }
202     // append []
203     for (;dims--;)
204         buf->Append(const_cast<System::String ^>(Constants::sBrackets));
205 
206     return buf->ToString();
207 }
208 
209 
210 /** For example, there is an uno type
211     com.sun.star.Foo<char, long>.
212     The values in the type list
213     are uno types and are replaced by cli types, such as System.Char,
214     System.Int32, etc.
215 
216     Strings can be as complicated as this
217     test.MyStruct<char,test.MyStruct<long, []string>>
218  */
219 System::String ^ mapUnoPolymorphicName(System::String ^ unoName)
220 {
221     int index = unoName->IndexOf('<');
222     if (index == -1)
223         return unoName;
224 
225     System::Text::StringBuilder ^ builder =
226         gcnew System::Text::StringBuilder(unoName->Substring(0, index +1 ));
227 
228     //Find the first occurrence of ','
229     //If the parameter is a polymorphic struct then we need to ignore everything
230     //between the brackets because it can also contain commas
231     //get the type list within < and >
232     int endIndex = unoName->Length - 1;
233     index++;
234     int cur = index;
235     int countParams = 0;
236     while (cur <= endIndex)
237     {
238         System::Char c = unoName[cur];
239         if (c == ',' || c == '>')
240         {
241             //insert a comma if needed
242             if (countParams != 0)
243                 builder->Append(",");
244             countParams++;
245             System::String ^ sParam = unoName->Substring(index, cur - index);
246             //skip the comma
247             cur++;
248             //the index to the beginning of the next param
249             index = cur;
250             builder->Append(mapUnoTypeName(sParam));
251         }
252         else if (c == '<')
253         {
254             cur++;
255             //continue until the matching '>'
256             int numNested = 0;
257             for (;;cur++)
258             {
259                 System::Char curChar = unoName[cur];
260                 if (curChar == '<')
261                 {
262                     numNested ++;
263                 }
264                 else if (curChar == '>')
265                 {
266                     if (numNested > 0)
267                         numNested--;
268                     else
269                         break;
270                 }
271             }
272         }
273         cur++;
274     }
275 
276     builder->Append((System::Char) '>');
277     return builder->ToString();
278 }
279 
280 
281 
282 //______________________________________________________________________________
283 Assembly ^ TypeEmitter::type_resolve(
284     ::System::Object ^, ::System::ResolveEventArgs ^ args )
285 {
286     ::System::String ^ cts_name = args->Name;
287 
288     // Two things have to happen before anything else, and both exist because
289     // AppDomain::TypeResolve is not re-entrancy-guarded: asking the
290     // ModuleBuilder for a name it cannot resolve raises TypeResolve again, for
291     // the same name, and lands straight back here.
292     //
293     // First: refuse to answer a name we are already answering.  Returning
294     // nullptr tells the runtime we cannot help, which is true, and ends the
295     // chain instead of extending it.
296     if (m_resolving->ContainsKey( cts_name ))
297         return nullptr;
298 
299     // Second: consult the incomplete-interface table BEFORE the ModuleBuilder.
300     // A type that has been DefineType'd but not yet CreateType'd is in that
301     // table, and on .NET 4 ModuleBuilder::GetType does not return it -- so
302     // asking the ModuleBuilder first is both slower and the thing that
303     // recurses.
304     ::System::Type ^ ret_type = nullptr;
305     {
306         iface_entry ^ entry = dynamic_cast< iface_entry ^ >(
307             m_incomplete_ifaces[ cts_name ] );
308         if (nullptr != entry)
309             ret_type = entry->m_type_builder;
310     }
311 
312     if (nullptr == ret_type)
313     {
314         m_resolving->Add( cts_name, cts_name );
315         try
316         {
317             ret_type = m_module_builder->GetType( cts_name, false /* no exc */ );
318         }
319         finally
320         {
321             m_resolving->Remove( cts_name );
322         }
323     }
324     if (nullptr == ret_type)
325     {
326         sal_Int32 len = m_extra_assemblies->Length;
327         for ( sal_Int32 pos = 0; pos < len; ++pos )
328         {
329             ret_type = m_extra_assemblies[ pos ]->GetType(
330                 cts_name, false /* no exc */ );
331             if (nullptr != ret_type)
332             {
333                 if (g_verbose)
334                 {
335                     ::System::Console::WriteLine(
336                         "> resolving type {0} from {1}.",
337                         cts_name, ret_type->Assembly->FullName );
338                 }
339                 break;
340             }
341         }
342     }
343     if (nullptr != ret_type)
344         return ret_type->Assembly;
345     return nullptr;
346 }
347 
348 //______________________________________________________________________________
349 ::System::Type ^ TypeEmitter::get_type(
350     ::System::String ^ cts_name, bool throw_exc )
351 {
352     ::System::Type ^ ret_type = m_module_builder->GetType( cts_name, false );
353 
354     // The lines below were commented out with the note "We get the type from
355     // the ModuleBuilder even if the type is not complete but have been
356     // defined."  That was true of the .NET this was written against; it is not
357     // true of .NET 4, where ModuleBuilder::GetType returns null for a type that
358     // has been DefineType'd but not yet CreateType'd.
359     //
360     // Leaving them commented out is not merely a missed lookup -- it does not
361     // terminate.  The caller falls through to Type::GetType, which raises
362     // AppDomain::TypeResolve, whose handler is type_resolve, which asks
363     // ModuleBuilder::GetType for the same name, which raises TypeResolve
364     // again.  AppDomain::TypeResolve has no re-entrancy guard, so climaker
365     // dies with a StackOverflowException the second time any interface is
366     // looked up -- the first time defines it, the second recurses:
367     //
368     //     Process is terminated due to StackOverflowException.
369     //
370     // The incomplete-interface table is exactly the right answer here, which
371     // is presumably why it was written in the first place.
372     if (ret_type == nullptr)
373     {
374         iface_entry ^ entry = dynamic_cast< iface_entry ^ >(
375             m_incomplete_ifaces[ cts_name ] );
376         if (nullptr != entry)
377             ret_type = entry->m_type_builder;
378     }
379         //try the cli_basetypes assembly
380     if (ret_type == nullptr)
381     {
382         ::System::Text::StringBuilder ^ builder = gcnew ::System::Text::StringBuilder(cts_name);
383         builder->Append(",cli_basetypes");
384         ret_type = ::System::Type::GetType(builder->ToString());
385     }
386 
387     if (ret_type == nullptr)
388     {
389         try
390         {
391             // may call on type_resolve()
392             return ::System::Type::GetType( cts_name, throw_exc );
393         }
394         catch (::System::Exception ^ exc)
395         {
396             //If the type is not found one may have forgotten to specify assemblies with
397             //additional types
398             ::System::Text::StringBuilder ^ sb = gcnew ::System::Text::StringBuilder();
399             sb->Append(gcnew ::System::String("\nThe type "));
400             sb->Append(cts_name);
401             sb->Append(gcnew ::System::String(" \n could not be found. Did you forget to " \
402                 "specify an additional assembly with the --reference option?\n"));
403             if (throw_exc)
404                 throw gcnew ::System::Exception(sb->ToString(), exc);
405         }
406     }
407     else
408     {
409         return ret_type;
410     }
411 }
412 
413 //______________________________________________________________________________
414 ::System::Type ^ TypeEmitter::get_type_Exception()
415 {
416     if (nullptr == m_type_Exception)
417     {
418         m_type_Exception = get_type(
419             "unoidl.com.sun.star.uno.Exception", false /* no exc */ );
420         if (nullptr == m_type_Exception)
421         {
422             // define hardcoded type unoidl.com.sun.star.uno.Exception
423             Emit::TypeBuilder ^ type_builder =
424                 m_module_builder->DefineType(
425                       "unoidl.com.sun.star.uno.Exception",
426                       (TypeAttributes) (TypeAttributes::Public |
427                                         TypeAttributes::BeforeFieldInit |
428                                         TypeAttributes::AnsiClass),
429                       ::System::Exception::typeid );
430             Emit::FieldBuilder ^ field_Context = type_builder->DefineField(
431                 "Context", ::System::Object::typeid,
432                 FieldAttributes::Public );
433             // default .ctor
434             type_builder->DefineDefaultConstructor( c_ctor_method_attr );
435             // .ctor
436             cli::array< ::System::Type ^ > ^ param_types =
437                   gcnew cli::array< ::System::Type ^ >( 2 );
438             param_types[ 0 ] = ::System::String::typeid;
439             param_types[ 1 ] = ::System::Object::typeid;
440             Emit::ConstructorBuilder ^ ctor_builder =
441                 type_builder->DefineConstructor(
442                     c_ctor_method_attr, CallingConventions::Standard,
443                     param_types );
444             ctor_builder->DefineParameter(
445                 1, ParameterAttributes::In, "Message" );
446             ctor_builder->DefineParameter(
447                 2, ParameterAttributes::In, "Context" );
448             Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
449             code->Emit( Emit::OpCodes::Ldarg_0 );
450             code->Emit( Emit::OpCodes::Ldarg_1 );
451             param_types = gcnew cli::array< ::System::Type ^ >( 1 );
452             param_types[ 0 ] = ::System::String::typeid;
453             code->Emit(
454                 Emit::OpCodes::Call,
455                 ::System::Exception::typeid
456                   ->GetConstructor( param_types ) );
457             code->Emit( Emit::OpCodes::Ldarg_0 );
458             code->Emit( Emit::OpCodes::Ldarg_2 );
459             code->Emit( Emit::OpCodes::Stfld, field_Context );
460             code->Emit( Emit::OpCodes::Ret );
461 
462             if (g_verbose)
463             {
464                 ::System::Console::WriteLine(
465                     "> emitting exception type "
466                     "unoidl.com.sun.star.uno.Exception" );
467             }
468             m_type_Exception = type_builder->CreateType();
469         }
470     }
471     return m_type_Exception;
472 }
473 
474 //______________________________________________________________________________
475 ::System::Type ^ TypeEmitter::get_type_RuntimeException()
476 {
477     if (nullptr == m_type_RuntimeException)
478     {
479         m_type_RuntimeException = get_type(
480             "unoidl.com.sun.star.uno.RuntimeException", false /* no exc */ );
481         if (nullptr == m_type_RuntimeException)
482         {
483             // define hardcoded type unoidl.com.sun.star.uno.RuntimeException
484             ::System::Type ^ type_Exception = get_type_Exception();
485             Emit::TypeBuilder ^ type_builder =
486                   m_module_builder->DefineType(
487                       "unoidl.com.sun.star.uno.RuntimeException",
488                       (TypeAttributes) (TypeAttributes::Public |
489                                         TypeAttributes::BeforeFieldInit |
490                                         TypeAttributes::AnsiClass),
491                       type_Exception );
492             // default .ctor
493             type_builder->DefineDefaultConstructor( c_ctor_method_attr );
494             // .ctor
495             cli::array< ::System::Type ^ > ^ param_types =
496                   gcnew cli::array< ::System::Type ^ >( 2 );
497             param_types[ 0 ] = ::System::String::typeid;
498             param_types[ 1 ] = ::System::Object::typeid;
499             Emit::ConstructorBuilder ^ ctor_builder =
500                 type_builder->DefineConstructor(
501                     c_ctor_method_attr, CallingConventions::Standard,
502                     param_types );
503             ctor_builder->DefineParameter(
504                 1, ParameterAttributes::In, "Message" );
505             ctor_builder->DefineParameter(
506                 2, ParameterAttributes::In, "Context" );
507             Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
508             code->Emit( Emit::OpCodes::Ldarg_0 );
509             code->Emit( Emit::OpCodes::Ldarg_1 );
510             code->Emit( Emit::OpCodes::Ldarg_2 );
511             code->Emit(
512                 Emit::OpCodes::Call,
513                 type_Exception->GetConstructor( param_types ) );
514             code->Emit( Emit::OpCodes::Ret );
515 
516             if (g_verbose)
517             {
518                 ::System::Console::WriteLine(
519                     "> emitting exception type "
520                     "unoidl.com.sun.star.uno.RuntimeException" );
521             }
522             m_type_RuntimeException = type_builder->CreateType();
523         }
524     }
525     return m_type_RuntimeException;
526 }
527 
528 //______________________________________________________________________________
529 ::System::Type ^ TypeEmitter::get_type(
530     Reference< reflection::XConstantTypeDescription > const & xType )
531 {
532     ::System::String ^ cts_name = to_cts_name( xType->getName() );
533     ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
534     if (nullptr == ret_type)
535     {
536         Reference< reflection::XConstantTypeDescription > xConstant(
537             xType, UNO_QUERY_THROW );
538         ::System::Object ^ constant =
539               to_cli_constant( xConstant->getConstantValue() );
540         Emit::TypeBuilder ^ type_builder =
541             m_module_builder->DefineType(
542                 cts_name,
543                 (TypeAttributes) (TypeAttributes::Public |
544                                   TypeAttributes::Sealed |
545                                   TypeAttributes::BeforeFieldInit |
546                                   TypeAttributes::AnsiClass) );
547 
548         Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
549             cts_name->Substring( cts_name->LastIndexOf( '.' ) +1 ),
550             constant->GetType(),
551             (FieldAttributes) (FieldAttributes::Public |
552                                FieldAttributes::Static |
553                                FieldAttributes::Literal) );
554         field_builder->SetConstant( constant );
555 
556         if (g_verbose)
557         {
558             ::System::Console::WriteLine(
559                 "> emitting constant type {0}", cts_name );
560         }
561         ret_type = type_builder->CreateType();
562     }
563     return ret_type;
564 }
565 
566 //______________________________________________________________________________
567 ::System::Type ^ TypeEmitter::get_type(
568     Reference< reflection::XConstantsTypeDescription > const & xType )
569 {
570     ::System::String ^ cts_name = to_cts_name( xType->getName() );
571     ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
572     if (nullptr == ret_type)
573     {
574         Emit::TypeBuilder ^ type_builder =
575             m_module_builder->DefineType(
576                 cts_name,
577                 (TypeAttributes) (TypeAttributes::Public |
578                                   TypeAttributes::Sealed |
579                                   TypeAttributes::BeforeFieldInit |
580                                   TypeAttributes::AnsiClass) );
581 
582         Sequence< Reference<
583             reflection::XConstantTypeDescription > > seq_constants(
584                 xType->getConstants() );
585         Reference< reflection::XConstantTypeDescription > const * constants =
586             seq_constants.getConstArray();
587         sal_Int32 constants_length = seq_constants.getLength();
588         for ( sal_Int32 constants_pos = 0;
589               constants_pos < constants_length; ++constants_pos )
590         {
591             Reference<
592                 reflection::XConstantTypeDescription > const & xConstant =
593                 constants[ constants_pos ];
594             ::System::Object ^ constant =
595                   to_cli_constant( xConstant->getConstantValue() );
596             ::System::String ^ uno_name =
597                   ustring_to_String( xConstant->getName() );
598             Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
599                 uno_name->Substring( uno_name->LastIndexOf( '.' ) +1 ),
600                 constant->GetType(),
601                 (FieldAttributes) (FieldAttributes::Public |
602                                    FieldAttributes::Static |
603                                    FieldAttributes::Literal) );
604             field_builder->SetConstant( constant );
605         }
606 
607         if (g_verbose)
608         {
609             ::System::Console::WriteLine(
610                 "> emitting constants group type {0}", cts_name );
611         }
612         ret_type = type_builder->CreateType();
613     }
614     return ret_type;
615 }
616 
617 //______________________________________________________________________________
618 ::System::Type ^ TypeEmitter::get_type(
619     Reference< reflection::XEnumTypeDescription > const & xType )
620 {
621     ::System::String ^ cts_name = to_cts_name( xType->getName() );
622     ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
623     if (nullptr == ret_type)
624     {
625 //       Emit::EnumBuilder ^ enum_builder =
626 //           m_module_builder->DefineEnum(
627 //               cts_name,
628 //               (TypeAttributes) (TypeAttributes::Public |
629 // //                                  TypeAttributes::Sealed |
630 //                                 TypeAttributes::AnsiClass),
631 //               ::System::Int32::typeid );
632         // workaround enum builder bug
633         Emit::TypeBuilder ^ enum_builder =
634             m_module_builder->DefineType(
635                 cts_name,
636                 (TypeAttributes) (TypeAttributes::Public |
637                                   TypeAttributes::Sealed),
638                 ::System::Enum::typeid );
639         enum_builder->DefineField(
640             "value__", ::System::Int32::typeid,
641             (FieldAttributes) (FieldAttributes::Private |
642                                FieldAttributes::SpecialName |
643                                FieldAttributes::RTSpecialName) );
644         Sequence< OUString > seq_enum_names( xType->getEnumNames() );
645         Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() );
646         sal_Int32 enum_length = seq_enum_names.getLength();
647         OSL_ASSERT( enum_length == seq_enum_values.getLength() );
648         OUString const * enum_names = seq_enum_names.getConstArray();
649         sal_Int32 const * enum_values = seq_enum_values.getConstArray();
650         for ( sal_Int32 enum_pos = 0; enum_pos < enum_length; ++enum_pos )
651         {
652 //           enum_builder->DefineLiteral(
653 //               ustring_to_String( enum_names[ enum_pos ] ),
654 //               (::System::Object ^)((::System::Int32) enum_values[ enum_pos ]) );
655             Emit::FieldBuilder ^ field_builder =
656                 enum_builder->DefineField(
657                     ustring_to_String( enum_names[ enum_pos ] ),
658                     enum_builder,
659                     (FieldAttributes) (FieldAttributes::Public |
660                                        FieldAttributes::Static |
661                                        FieldAttributes::Literal) );
662             field_builder->SetConstant(
663                 (::System::Object ^)((::System::Int32) enum_values[ enum_pos ]) );
664         }
665 
666         if (g_verbose)
667         {
668             ::System::Console::WriteLine(
669                 "> emitting enum type {0}", cts_name );
670         }
671         ret_type = enum_builder->CreateType();
672     }
673     return ret_type;
674 }
675 
676 //______________________________________________________________________________
677 ::System::Type ^ TypeEmitter::get_type(
678     Reference< reflection::XCompoundTypeDescription > const & xType )
679 {
680     OUString uno_name( xType->getName() );
681     if (TypeClass_EXCEPTION == xType->getTypeClass())
682     {
683         if (uno_name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
684                                        "com.sun.star.uno.Exception") ))
685         {
686             return get_type_Exception();
687         }
688         if (uno_name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(
689                                        "com.sun.star.uno.RuntimeException") ))
690         {
691             return get_type_RuntimeException();
692         }
693     }
694     ::System::String ^ cts_name = to_cts_name( uno_name );
695     // if the struct is an instantiated polymorphic struct then we create the simple struct name
696     // For example:
697     // void func ([in] PolyStruct<boolean> arg);
698     //PolyStruct<boolean> will be converted to PolyStruct
699     polymorphicStructNameToStructName( & cts_name);
700 
701     ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
702     if (nullptr == ret_type)
703     {
704         Reference< reflection::XCompoundTypeDescription > xBaseType(
705             xType->getBaseType(), UNO_QUERY );
706         ::System::Type ^ base_type = (xBaseType.is()
707                                       ? get_type( xBaseType )
708                                       : ::System::Object::typeid);
709         Emit::TypeBuilder ^ type_builder =
710             m_module_builder->DefineType(
711                 cts_name,
712                 (TypeAttributes) (TypeAttributes::Public |
713                                   TypeAttributes::BeforeFieldInit |
714                                   TypeAttributes::AnsiClass),
715                 base_type );
716 
717 
718         // insert to be completed
719         struct_entry ^ entry = gcnew struct_entry();
720         xType->acquire();
721         entry->m_xType = xType.get();
722         entry->m_type_builder = type_builder;
723         entry->m_base_type = base_type;
724         m_incomplete_structs->Add( cts_name, entry );
725 
726         // type is incomplete
727         ret_type = type_builder;
728     }
729 
730     //In case of an instantiated polymorphic struct we want to return a
731     //uno.PolymorphicType (inherits Type) rather then Type. This is needed for constructing
732     //the service code. We can only do that if the struct is completed.
733     if (m_generated_structs[ cts_name ])
734     {
735         Reference< reflection::XStructTypeDescription> xStructTypeDesc(
736             xType, UNO_QUERY);
737 
738         if (xStructTypeDesc.is())
739         {
740             Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments();
741             sal_Int32 numTypes = seqTypeArgs.getLength();
742             if (numTypes > 0)
743             {
744                 //it is an instantiated polymorphic struct
745                 ::System::String ^ sCliName = mapUnoTypeName(ustring_to_String(xType->getName()));
746                 ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName);
747             }
748         }
749     }
750     return ret_type;
751 }
752 
753 //______________________________________________________________________________
754 ::System::Type ^ TypeEmitter::get_type(
755     Reference< reflection::XInterfaceTypeDescription2 > const & xType )
756 {
757     OUString uno_name( xType->getName() );
758     if (uno_name.equalsAsciiL(
759             RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ))
760     {
761         return ::System::Object::typeid;
762     }
763 
764     ::System::String ^ cts_name = to_cts_name( xType->getName() );
765     ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
766     if (nullptr == ret_type)
767     {
768         Emit::TypeBuilder ^ type_builder;
769 
770         TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
771                                                 TypeAttributes::Interface |
772                                                 TypeAttributes::Abstract |
773                                                 TypeAttributes::AnsiClass);
774 
775         std::vector<Reference<reflection::XInterfaceTypeDescription2> > vecBaseTypes;
776         Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes =
777             xType->getBaseTypes();
778         if (seqBaseTypes.getLength() > 0)
779         {
780             for (int i = 0; i < seqBaseTypes.getLength(); i++)
781             {
782                 Reference<reflection::XInterfaceTypeDescription2> xIfaceTd =
783                     resolveInterfaceTypedef(seqBaseTypes[i]);
784 
785                 if (xIfaceTd->getName().equalsAsciiL(
786                         RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ) == sal_False)
787                 {
788                     vecBaseTypes.push_back(xIfaceTd);
789                 }
790             }
791 
792             cli::array< ::System::Type ^ > ^ base_interfaces =
793                   gcnew cli::array< ::System::Type ^ >( vecBaseTypes.size() );
794 
795             typedef std::vector<Reference<reflection::XInterfaceTypeDescription2> >::const_iterator it;
796             int index = 0;
797             for (it i = vecBaseTypes.begin(); i != vecBaseTypes.end(); i++, index++)
798                 base_interfaces[ index ] = get_type( *i );
799             type_builder = m_module_builder->DefineType(
800                 cts_name, attr, nullptr, base_interfaces );
801         }
802         else
803         {
804             ::System::Console::WriteLine(
805                 "warning: IDL interface {0} is not derived from "
806                 "com.sun.star.uno.XInterface!",
807                 ustring_to_String( uno_name ) );
808 
809             type_builder = m_module_builder->DefineType( cts_name, attr );
810         }
811 
812         // insert to be completed
813         iface_entry ^ entry = gcnew iface_entry();
814         xType->acquire();
815         entry->m_xType = xType.get();
816         entry->m_type_builder = type_builder;
817         m_incomplete_ifaces->Add( cts_name, entry );
818 
819         // type is incomplete
820         ret_type = type_builder;
821     }
822     return ret_type;
823 }
824 
825 
826 //______________________________________________________________________________
827 ::System::Type ^ TypeEmitter::get_type(
828     Reference< reflection::XServiceTypeDescription2 > const & xType )
829 {
830     if (xType->isSingleInterfaceBased() == sal_False)
831         return nullptr;
832 
833     System::String ^ cts_name = to_cts_name( xType->getName() );
834     System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
835     if (ret_type != nullptr)
836         return ret_type;
837 
838     TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
839                                             TypeAttributes::Sealed |
840                                             TypeAttributes::BeforeFieldInit |
841                                             TypeAttributes::AnsiClass);
842 
843     Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
844         cts_name, attr);
845 
846     // insert to be completed
847     service_entry ^ entry = gcnew service_entry();
848     xType->acquire();
849     entry->m_xType = xType.get();
850     entry->m_type_builder = type_builder;
851     m_incomplete_services->Add(cts_name,entry );
852 
853     return type_builder;
854 }
855 
856 ::System::Type ^ TypeEmitter::get_type(
857     Reference<reflection::XSingletonTypeDescription2 > const & xType )
858 {
859     if (xType->isInterfaceBased() == sal_False)
860         return nullptr;
861 
862     ::System::String ^ cts_name = to_cts_name( xType->getName() );
863     ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
864     if (ret_type != nullptr)
865         return ret_type;
866 
867     TypeAttributes attr = static_cast<TypeAttributes>(
868         TypeAttributes::Public |
869         TypeAttributes::Sealed |
870         TypeAttributes::BeforeFieldInit |
871         TypeAttributes::AnsiClass);
872 
873     Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
874         cts_name, attr);
875 
876     // insert to be completed
877     singleton_entry ^ entry = gcnew singleton_entry();
878     xType->acquire();
879     entry->m_xType = xType.get();
880     entry->m_type_builder = type_builder;
881     m_incomplete_singletons->Add(cts_name,entry );
882 
883     return type_builder;
884 
885 }
886 
887 //______________________________________________________________________________
888 ::System::Type ^ TypeEmitter::complete_iface_type( iface_entry ^ entry )
889 {
890     Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
891     reflection::XInterfaceTypeDescription2 * xType = entry->m_xType;
892 
893     Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes( xType->getBaseTypes() );
894     if (seqBaseTypes.getLength() > 0)
895     {
896         for (int i = 0; i < seqBaseTypes.getLength(); i++)
897         {
898             //make sure we get the interface rather then a typedef
899             Reference<reflection::XInterfaceTypeDescription2> aBaseType =
900                 resolveInterfaceTypedef( seqBaseTypes[i]);
901 
902             if (aBaseType->getName().equalsAsciiL(
903                     RTL_CONSTASCII_STRINGPARAM("com.sun.star.uno.XInterface") ) == sal_False)
904             {
905                 ::System::String ^ basetype_name = to_cts_name( aBaseType->getName() );
906                 iface_entry ^ base_entry = dynamic_cast< iface_entry ^ >(
907                     m_incomplete_ifaces[ basetype_name ] );
908                 if (nullptr != base_entry)
909                 {
910                 // complete uncompleted base type first
911                     complete_iface_type( base_entry );
912                 }
913             }
914         }
915     }
916 
917     Sequence<
918         Reference< reflection::XInterfaceMemberTypeDescription > > seq_members(
919             xType->getMembers() );
920     Reference< reflection::XInterfaceMemberTypeDescription > const * members =
921         seq_members.getConstArray();
922     sal_Int32 members_length = seq_members.getLength();
923     for ( sal_Int32 members_pos = 0;
924           members_pos < members_length; ++members_pos )
925     {
926         Reference<
927             reflection::XInterfaceMemberTypeDescription > const & xMember =
928             members[ members_pos ];
929         Sequence< Reference< reflection::XTypeDescription > > seq_exceptions;
930         Emit::MethodBuilder ^ method_builder;
931 
932         const MethodAttributes c_method_attr = (MethodAttributes)
933             (MethodAttributes::Public |
934              MethodAttributes::Abstract |
935              MethodAttributes::Virtual |
936              MethodAttributes::NewSlot |
937              MethodAttributes::HideBySig);
938 //#if defined(_MSC_VER) && (_MSC_VER < 1400)
939 //           MethodAttributes::Instance);
940 //#else
941 //       Instance);
942 //#endif
943 
944         if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass())
945         {
946             Reference< reflection::XInterfaceMethodTypeDescription > xMethod(
947                 xMember, UNO_QUERY_THROW );
948 
949             Sequence<
950                 Reference< reflection::XMethodParameter > > seq_parameters(
951                     xMethod->getParameters() );
952             sal_Int32 params_length = seq_parameters.getLength();
953             cli::array< ::System::Type ^ > ^ param_types =
954                   gcnew cli::array< ::System::Type ^ >( params_length );
955             Reference< reflection::XMethodParameter > const * parameters =
956                 seq_parameters.getConstArray();
957             // first determine all types
958             //Make the first param type as return type
959             sal_Int32 params_pos = 0;
960             for ( ; params_pos < params_length; ++params_pos )
961             {
962                 Reference< reflection::XMethodParameter > const & xParam =
963                     parameters[ params_pos ];
964                 ::System::Type ^ param_type = get_type( xParam->getType() );
965                 ::System::String ^ param_type_name = param_type->FullName;
966                 if (xParam->isOut())
967                 {
968                     param_type = get_type(
969                         ::System::String::Concat(
970                             param_type_name, "&" ), true );
971                 }
972                 param_types[ xParam->getPosition() ] = param_type;
973             }
974 
975 
976             // create method
977 //           if (tb)
978 //               method_builder = type_builder->DefineMethod(
979 //               ustring_to_String( xMethod->getMemberName() ),
980 //               c_method_attr, tb,
981 //               param_types );
982 //           else
983                 method_builder = type_builder->DefineMethod(
984                     ustring_to_String( xMethod->getMemberName() ),
985                     c_method_attr, get_type( xMethod->getReturnType() ),
986                     param_types );
987             // then define parameter infos
988             params_pos = 0;
989             for ( ; params_pos < params_length; ++params_pos )
990             {
991                 Reference< reflection::XMethodParameter > const & xParam =
992                     parameters[ params_pos ];
993                 long param_flags = 0;
994                 if (xParam->isIn())
995                     param_flags |= (long)ParameterAttributes::In;
996                 if (xParam->isOut())
997                     param_flags |= (long)ParameterAttributes::Out;
998                 OSL_ASSERT( 0 != param_flags );
999                 method_builder->DefineParameter(
1000                     xParam->getPosition() +1 /* starts with 1 */,
1001                     (ParameterAttributes) param_flags,
1002                     ustring_to_String( xParam->getName() ) );
1003             }
1004             //Apply attribute TypeParametersAttribute to return value if it
1005             //is a parameterized Type. Currently only structs can have parameters.
1006             Reference<reflection::XStructTypeDescription> xReturnStruct(
1007                 xMethod->getReturnType(), UNO_QUERY);
1008 
1009             if (xReturnStruct.is())
1010             {
1011                 Sequence<Reference<reflection::XTypeDescription> > seq_type_args =
1012                     xReturnStruct->getTypeArguments();
1013                 if (seq_type_args.getLength() != 0)
1014                 {
1015                     //get th ctor of the attribute
1016                     cli::array< ::System::Type ^ > ^ arCtor = {::System::Type::GetType("System.Type[]")};
1017                     //Get the arguments for the attribute's ctor
1018                     Reference<reflection::XTypeDescription> const * arXTypeArgs =
1019                         seq_type_args.getConstArray();
1020                     int numTypes = seq_type_args.getLength();
1021                     cli::array< ::System::Type ^ > ^ arCtsTypes = gcnew cli::array< ::System::Type ^ >( numTypes );
1022                     for (int i = 0; i < numTypes; i++)
1023                         arCtsTypes[i] = get_type(arXTypeArgs[i]);
1024                     cli::array< ::System::Object ^ > ^ arArgs = {arCtsTypes};
1025 
1026                     Emit::CustomAttributeBuilder ^ attrBuilder =
1027                         gcnew Emit::CustomAttributeBuilder(
1028                             ::uno::TypeArgumentsAttribute::typeid
1029                             ->GetConstructor( arCtor),
1030                             arArgs);
1031 
1032                     method_builder->SetCustomAttribute(attrBuilder);
1033                 }
1034             }
1035 
1036             //define UNO exception attribute (exceptions)--------------------------------------
1037             Emit::CustomAttributeBuilder ^ attrBuilder =
1038                 get_iface_method_exception_attribute(xMethod);
1039             if (attrBuilder != nullptr)
1040                 method_builder->SetCustomAttribute(attrBuilder);
1041 
1042             // oneway attribute
1043             if (xMethod->isOneway())
1044             {
1045                 cli::array< ::System::Type ^ > ^ arCtorOneway = gcnew cli::array< ::System::Type ^ >( 0 );
1046                 cli::array< ::System::Object ^ > ^ arArgs = gcnew cli::array< ::System::Object ^ >( 0 );
1047                 Emit::CustomAttributeBuilder ^ attrBuilder =
1048                     gcnew Emit::CustomAttributeBuilder(
1049                         ::uno::OnewayAttribute::typeid->GetConstructor( arCtorOneway),
1050                         arArgs);
1051                 method_builder->SetCustomAttribute(attrBuilder);
1052             }
1053         }
1054         else // attribute
1055         {
1056             OSL_ASSERT(
1057                 TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() );
1058             Reference<
1059                 reflection::XInterfaceAttributeTypeDescription2 > xAttribute(
1060                     xMember, UNO_QUERY_THROW );
1061 
1062             const MethodAttributes c_property_method_attr = (MethodAttributes)
1063                 ((int)c_method_attr | (int)MethodAttributes::SpecialName);
1064 
1065             ::System::Type ^ attribute_type = get_type( xAttribute->getType() );
1066             cli::array< ::System::Type ^ > ^ parameters =
1067                   gcnew cli::array< ::System::Type ^ >( 0 );
1068 
1069             Emit::PropertyBuilder ^ property_builder =
1070                 type_builder->DefineProperty(
1071                     ustring_to_String( xAttribute->getMemberName() ),
1072                     PropertyAttributes::None,
1073                     attribute_type, parameters );
1074 
1075             //set BoundAttribute, if necessary
1076             if (xAttribute->isBound())
1077             {
1078                 ConstructorInfo ^ ctorBoundAttr =
1079                     ::uno::BoundAttribute::typeid->GetConstructor(
1080                         gcnew cli::array< System::Type ^ >( 0 ));
1081                 Emit::CustomAttributeBuilder ^ attrBuilderBound =
1082                     gcnew Emit::CustomAttributeBuilder(
1083                         ctorBoundAttr, gcnew cli::array< ::System::Object ^ >( 0 ));
1084                 property_builder->SetCustomAttribute(attrBuilderBound);
1085             }
1086 
1087             // getter
1088             Emit::MethodBuilder ^ method_builder =
1089                 type_builder->DefineMethod(
1090                     ustring_to_String( OUSTR("get_") +
1091                                        xAttribute->getMemberName() ),
1092                     c_property_method_attr, attribute_type, parameters );
1093 
1094             //define UNO exception attribute (exceptions)--------------------------------------
1095             Emit::CustomAttributeBuilder ^ attrBuilder =
1096                 get_exception_attribute(xAttribute->getGetExceptions());
1097             if (attrBuilder != nullptr)
1098                 method_builder->SetCustomAttribute(attrBuilder);
1099 
1100             property_builder->SetGetMethod( method_builder );
1101 
1102             if (! xAttribute->isReadOnly())
1103             {
1104                 // setter
1105                 parameters = gcnew cli::array< ::System::Type ^ >( 1 );
1106                 parameters[ 0 ] = attribute_type;
1107                 method_builder =
1108                     type_builder->DefineMethod(
1109                         ustring_to_String( OUSTR("set_") +
1110                                            xAttribute->getMemberName() ),
1111                         c_property_method_attr, nullptr, parameters );
1112                 // define parameter info
1113                 method_builder->DefineParameter(
1114                     1 /* starts with 1 */, ParameterAttributes::In, "value" );
1115                 //define UNO exception attribute (exceptions)--------------------------------------
1116                 Emit::CustomAttributeBuilder ^ attrBuilder =
1117                     get_exception_attribute(xAttribute->getSetExceptions());
1118                 if (attrBuilder != nullptr)
1119                     method_builder->SetCustomAttribute(attrBuilder);
1120 
1121                 property_builder->SetSetMethod( method_builder );
1122             }
1123         }
1124     }
1125 
1126     // remove from incomplete types map
1127     ::System::String ^ cts_name = type_builder->FullName;
1128     m_incomplete_ifaces->Remove( cts_name );
1129     xType->release();
1130 
1131     if (g_verbose)
1132     {
1133         ::System::Console::WriteLine(
1134             "> emitting interface type {0}", cts_name );
1135     }
1136     return type_builder->CreateType();
1137 }
1138 
1139 ::System::Type ^ TypeEmitter::complete_struct_type( struct_entry ^ entry )
1140 {
1141      OSL_ASSERT(entry);
1142     ::System::String ^ cts_name = entry->m_type_builder->FullName;
1143 
1144     //Polymorphic struct, define uno.TypeParametersAttribute
1145     //A polymorphic struct cannot have a basetype.
1146     //When we create the template of the struct then we have no exact types
1147     //and the name does not contain a parameter list
1148     Sequence< OUString > seq_type_parameters;
1149     Reference< reflection::XStructTypeDescription> xStructTypeDesc(
1150         entry->m_xType, UNO_QUERY);
1151     if (xStructTypeDesc.is())
1152     {
1153         seq_type_parameters = xStructTypeDesc->getTypeParameters();
1154         int numTypes = 0;
1155         if ((numTypes = seq_type_parameters.getLength()) > 0)
1156         {
1157             cli::array< ::System::Object ^ > ^ aArg = gcnew cli::array< ::System::Object ^ >( numTypes );
1158             for (int i = 0; i < numTypes; i++)
1159                 aArg[i] = ustring_to_String(seq_type_parameters.getConstArray()[i]);
1160             cli::array< ::System::Object ^ > ^ args = {aArg};
1161 
1162             cli::array< ::System::Type ^ > ^ arTypesCtor =
1163             {::System::Type::GetType("System.String[]")};
1164             Emit::CustomAttributeBuilder ^ attrBuilder =
1165                 gcnew Emit::CustomAttributeBuilder(
1166                 ::uno::TypeParametersAttribute::typeid->GetConstructor(arTypesCtor),
1167                 args);
1168             entry->m_type_builder->SetCustomAttribute(attrBuilder);
1169         }
1170     }
1171 
1172     // optional: lookup base type whether generated entry of this session
1173     struct_entry ^ base_type_entry = nullptr;
1174     if (nullptr != entry->m_base_type)
1175     {
1176         //ToDo maybe get from incomplete structs
1177         base_type_entry =
1178             dynamic_cast< struct_entry ^ >(
1179                 m_generated_structs[ entry->m_base_type->FullName ] );
1180     }
1181 
1182         // members
1183     Sequence< Reference< reflection::XTypeDescription > > seq_members(
1184         entry->m_xType->getMemberTypes() );
1185     Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() );
1186     sal_Int32 members_length = seq_members.getLength();
1187     OSL_ASSERT( seq_member_names.getLength() == members_length );
1188     //check if we have a XTypeDescription for every member. If not then the user may
1189     //have forgotten to specify additional rdbs with the --extra option.
1190     Reference< reflection::XTypeDescription > const * pseq_members =
1191             seq_members.getConstArray();
1192     OUString const * pseq_member_names =
1193         seq_member_names.getConstArray();
1194     for (int i = 0; i < members_length; i++)
1195     {
1196         const OUString sType(entry->m_xType->getName());
1197         const OUString sMemberName(pseq_member_names[i]);
1198         if ( ! pseq_members[i].is())
1199             throw RuntimeException(OUSTR("Missing type description . Check if you need to " \
1200             "specify additional RDBs with the --extra option. Type missing for: ") + sType +
1201             OUSTR("::") + sMemberName,0);
1202     }
1203 
1204     sal_Int32 all_members_length = 0;
1205     sal_Int32 member_pos;
1206     sal_Int32 type_param_pos = 0;
1207 
1208     // collect base types; wrong order
1209     ::System::Collections::ArrayList ^ base_types_list =
1210             gcnew ::System::Collections::ArrayList( 3 /* initial capacity */ );
1211     for (::System::Type ^ base_type_pos = entry->m_base_type;
1212         ! base_type_pos->Equals( ::System::Object::typeid );
1213         base_type_pos = base_type_pos->BaseType )
1214     {
1215         base_types_list->Add( base_type_pos );
1216         if (base_type_pos->Equals( ::System::Exception::typeid ))
1217         {
1218             // special Message member
1219             all_members_length += 1;
1220             break; // don't include System.Exception base classes
1221         }
1222         else
1223         {
1224             //ensure the base type is complete. Otherwise GetFields won't work
1225             get_complete_struct(base_type_pos->FullName);
1226             all_members_length +=
1227                 base_type_pos->GetFields(
1228                 (BindingFlags) (BindingFlags::Instance |
1229                 BindingFlags::Public |
1230                 BindingFlags::DeclaredOnly) )
1231                 ->Length;
1232         }
1233     }
1234 
1235     // create all_members arrays; right order
1236     cli::array< ::System::String ^ > ^ all_member_names =
1237         gcnew cli::array< ::System::String ^ >( all_members_length + members_length );
1238     cli::array< ::System::Type ^ > ^ all_param_types =
1239         gcnew cli::array< ::System::Type ^ >( all_members_length + members_length );
1240     member_pos = 0;
1241     for ( sal_Int32 pos = base_types_list->Count; pos--; )
1242     {
1243         ::System::Type ^ base_type = safe_cast< ::System::Type ^ >(
1244             base_types_list[ pos ] );
1245         if (base_type->Equals( ::System::Exception::typeid ))
1246         {
1247             all_member_names[ member_pos ] = "Message";
1248             all_param_types[ member_pos ] = ::System::String::typeid;
1249             ++member_pos;
1250         }
1251         else
1252         {
1253             ::System::String ^ base_type_name = base_type->FullName;
1254 
1255             //ToDo m_generated_structs?
1256             struct_entry ^ entry =
1257                 dynamic_cast< struct_entry ^ >(
1258                 m_generated_structs[ base_type_name ] );
1259             if (nullptr == entry)
1260             {
1261                 // complete type
1262                 cli::array< FieldInfo ^ > ^ fields =
1263                     base_type->GetFields(
1264                     (BindingFlags) (BindingFlags::Instance |
1265                     BindingFlags::Public |
1266                     BindingFlags::DeclaredOnly) );
1267                 sal_Int32 len = fields->Length;
1268                 for ( sal_Int32 pos = 0; pos < len; ++pos )
1269                 {
1270                     FieldInfo ^ field = fields[ pos ];
1271                     all_member_names[ member_pos ] = field->Name;
1272                     all_param_types[ member_pos ] = field->FieldType;
1273                     ++member_pos;
1274                 }
1275             }
1276             else // generated during this session:
1277                 // members may be incomplete ifaces
1278             {
1279                 sal_Int32 len = entry->m_member_names->Length;
1280                 for ( sal_Int32 pos = 0; pos < len; ++pos )
1281                 {
1282                     all_member_names[ member_pos ] =
1283                         entry->m_member_names[ pos ];
1284                     all_param_types[ member_pos ] =
1285                         entry->m_param_types[ pos ];
1286                     ++member_pos;
1287                 }
1288             }
1289         }
1290     }
1291     OSL_ASSERT( all_members_length == member_pos );
1292 
1293     // build up entry
1294 //  struct_entry ^ entry = gcnew struct_entry();
1295     entry->m_member_names = gcnew cli::array< ::System::String ^ >( members_length );
1296     entry->m_param_types = gcnew cli::array< ::System::Type ^ >( members_length );
1297 
1298     // add members
1299     cli::array< Emit::FieldBuilder ^ > ^ members = gcnew cli::array< Emit::FieldBuilder ^ >( members_length );
1300     //Reference< reflection::XTypeDescription > const * pseq_members =
1301     //  seq_members.getConstArray();
1302     //OUString const * pseq_member_names =
1303     //  seq_member_names.getConstArray();
1304 
1305     int curParamIndex = 0; //count the fields which have parameterized types
1306     for ( member_pos = 0; member_pos < members_length; ++member_pos )
1307     {
1308         ::System::String ^ field_name =
1309             ustring_to_String( pseq_member_names[ member_pos ] );
1310         ::System::Type ^ field_type;
1311         //Special handling of struct parameter types
1312         bool bParameterizedType = false;
1313         if (pseq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN)
1314         {
1315             bParameterizedType = true;
1316             if (type_param_pos < seq_type_parameters.getLength())
1317             {
1318                 field_type = ::System::Object::typeid;
1319                 type_param_pos++;
1320             }
1321             else
1322             {
1323                 throw RuntimeException(
1324                     OUSTR("unexpected member type in ") + entry->m_xType->getName(),
1325                     Reference< XInterface >() );
1326             }
1327         }
1328         else
1329         {
1330             field_type =
1331                 get_type( pseq_members[ member_pos ] );
1332         }
1333         members[ member_pos ] =
1334             entry->m_type_builder->DefineField(
1335             field_name, field_type, FieldAttributes::Public );
1336 
1337         //parameterized type (polymorphic struct) ?
1338         if (bParameterizedType && xStructTypeDesc.is())
1339         {
1340             //get the name
1341             OSL_ASSERT(seq_type_parameters.getLength() > curParamIndex);
1342             ::System::String ^ sTypeName = ustring_to_String(
1343                 seq_type_parameters.getConstArray()[curParamIndex++]);
1344             cli::array< ::System::Object ^ > ^ args = {sTypeName};
1345             //set ParameterizedTypeAttribute
1346             cli::array< ::System::Type ^ > ^ arCtorTypes = {::System::String::typeid};
1347 
1348             Emit::CustomAttributeBuilder ^ attrBuilder =
1349                 gcnew Emit::CustomAttributeBuilder(
1350                 ::uno::ParameterizedTypeAttribute::typeid
1351                 ->GetConstructor(arCtorTypes),
1352                 args);
1353 
1354             members[member_pos]->SetCustomAttribute(attrBuilder);
1355         }
1356         // add to all_members
1357         all_member_names[ all_members_length + member_pos ] = field_name;
1358         all_param_types[ all_members_length + member_pos ] = field_type;
1359         // add to entry
1360         entry->m_member_names[ member_pos ] = field_name;
1361         entry->m_param_types[ member_pos ] = field_type;
1362     }
1363     all_members_length += members_length;
1364 
1365     // default .ctor
1366     Emit::ConstructorBuilder ^ ctor_builder =
1367         entry->m_type_builder->DefineConstructor(
1368         c_ctor_method_attr, CallingConventions::Standard,
1369         gcnew cli::array< ::System::Type ^ >( 0 ) );
1370     Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
1371     code->Emit( Emit::OpCodes::Ldarg_0 );
1372     code->Emit(
1373         Emit::OpCodes::Call,
1374         nullptr == base_type_entry
1375         ? entry->m_base_type->GetConstructor( gcnew cli::array< ::System::Type ^ >( 0 ) )
1376         : base_type_entry->m_default_ctor );
1377     // default initialize members
1378     for ( member_pos = 0; member_pos < members_length; ++member_pos )
1379     {
1380         FieldInfo ^ field = members[ member_pos ];
1381         ::System::Type ^ field_type = field->FieldType;
1382         //          ::System::Type ^ new_field_type = m_module_builder->GetType(field_type->FullName, false);
1383         // default initialize:
1384         // string, type, enum, sequence, struct, exception, any
1385         if (field_type->Equals( ::System::String::typeid ))
1386         {
1387             code->Emit( Emit::OpCodes::Ldarg_0 );
1388             code->Emit( Emit::OpCodes::Ldstr, "" );
1389             code->Emit( Emit::OpCodes::Stfld, field );
1390         }
1391         else if (field_type->Equals( ::System::Type::typeid ))
1392         {
1393             code->Emit( Emit::OpCodes::Ldarg_0 );
1394             code->Emit(
1395                 Emit::OpCodes::Ldtoken, ::System::Void::typeid );
1396             code->Emit(
1397                 Emit::OpCodes::Call, m_method_info_Type_GetTypeFromHandle );
1398             code->Emit( Emit::OpCodes::Stfld, field );
1399         }
1400         else if (field_type->IsArray)
1401         {
1402             //Find the value type. In case of sequence<sequence< ... > > find the actual value type
1403             ::System::Type ^ value = field_type;
1404             while ((value = value->GetElementType())->IsArray);
1405             //If the value type is a struct then make sure it is fully created.
1406             get_complete_struct(value->FullName);
1407 
1408             code->Emit( Emit::OpCodes::Ldarg_0 );
1409             code->Emit( Emit::OpCodes::Ldc_I4_0 );
1410             code->Emit(
1411                 Emit::OpCodes::Newarr, field_type->GetElementType() );
1412             code->Emit( Emit::OpCodes::Stfld, field );
1413         }
1414         else if (field_type->IsValueType)
1415         {
1416             if (field_type->FullName->Equals( "uno.Any" ))
1417             {
1418                 code->Emit( Emit::OpCodes::Ldarg_0 );
1419                 code->Emit( Emit::OpCodes::Ldsfld, ::uno::Any::typeid->GetField("VOID"));
1420                 code->Emit( Emit::OpCodes::Stfld, field );
1421             }
1422         }
1423         else if (field_type->IsClass)
1424         {
1425             /* may be XInterface */
1426             if (! field_type->Equals( ::System::Object::typeid ))
1427             {
1428                 // struct, exception
1429                 //make sure the struct is already complete.
1430                 get_complete_struct(field_type->FullName);
1431                 code->Emit( Emit::OpCodes::Ldarg_0 );
1432                 code->Emit(
1433                     Emit::OpCodes::Newobj,
1434                     //GetConstructor requires that the member types of the object which is to be constructed are already known.
1435                     field_type->GetConstructor(
1436                     gcnew cli::array< ::System::Type ^ >( 0 ) ) );
1437                 code->Emit( Emit::OpCodes::Stfld, field );
1438             }
1439         }
1440     }
1441     code->Emit( Emit::OpCodes::Ret );
1442     entry->m_default_ctor = ctor_builder;
1443 
1444     // parameterized .ctor including all base members
1445     ctor_builder = entry->m_type_builder->DefineConstructor(
1446         c_ctor_method_attr, CallingConventions::Standard, all_param_types );
1447     for ( member_pos = 0; member_pos < all_members_length; ++member_pos )
1448     {
1449         ctor_builder->DefineParameter(
1450             member_pos +1 /* starts with 1 */, ParameterAttributes::In,
1451             all_member_names[ member_pos ] );
1452     }
1453     code = ctor_builder->GetILGenerator();
1454     // call base .ctor
1455     code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1456     sal_Int32 base_members_length = all_members_length - members_length;
1457     cli::array< ::System::Type ^ > ^ param_types =
1458         gcnew cli::array< ::System::Type ^ >( base_members_length );
1459     for ( member_pos = 0; member_pos < base_members_length; ++member_pos )
1460     {
1461         emit_ldarg( code, member_pos +1 );
1462         param_types[ member_pos ] = all_param_types[ member_pos ];
1463     }
1464     code->Emit(
1465         Emit::OpCodes::Call,
1466         nullptr == base_type_entry
1467         ? entry->m_base_type->GetConstructor( param_types )
1468         : base_type_entry->m_ctor );
1469     // initialize members
1470     for ( member_pos = 0; member_pos < members_length; ++member_pos )
1471     {
1472         code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1473         emit_ldarg( code, member_pos + base_members_length +1 );
1474         code->Emit( Emit::OpCodes::Stfld, members[ member_pos ] );
1475     }
1476     code->Emit( Emit::OpCodes::Ret );
1477     entry->m_ctor = ctor_builder;
1478 
1479     if (g_verbose)
1480     {
1481         ::System::Console::WriteLine(
1482             "> emitting {0} type {1}",
1483             TypeClass_STRUCT == entry->m_xType->getTypeClass()
1484             ? "struct"
1485             : "exception",
1486             cts_name);
1487     }
1488     // new entry
1489     m_generated_structs->Add(cts_name, entry );
1490     ::System::Type ^ ret_type = entry->m_type_builder->CreateType();
1491 
1492     // remove from incomplete types map
1493     m_incomplete_structs->Remove( cts_name );
1494     entry->m_xType->release();
1495 
1496     if (g_verbose)
1497     {
1498         ::System::Console::WriteLine(
1499             "> emitting struct type {0}", cts_name);
1500     }
1501     return ret_type;
1502 }
1503 
1504 //Examples of generated code
1505 //      public static XWeak constructor1(XComponentContext ctx)
1506 //      {
1507 //          XMultiComponentFactory factory = ctx.getServiceManager();
1508 //          if (factory == null)
1509 //              throw new com.sun.star.uno.DeploymentException("bla", null);
1510 //          return (XWeak) factory.createInstanceWithContext("service_specifier", ctx);
1511 //      }
1512 //      public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c)
1513 //      {
1514 //          XMultiComponentFactory factory = ctx.getServiceManager();
1515 //          if (factory == null)
1516 //              throw new com.sun.star.uno.DeploymentException("bla", null);
1517 //          Any[] arAny = new Any[3];
1518 //          arAny[0] = new Any(typeof(int), a);
1519 //          arAny[1] = new Any(typeof(int), b);
1520 //          arAny[2] = new Any(c.Type, c.Value);
1521 //          return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx);
1522 //      }
1523 // Notice that a any parameter is NOT wrapped by another any. Instead the new any is created with the type and value
1524 // of the parameter.
1525 
1526 //      public static XWeak constructor3(XComponentContext ctx, params Any[] c)
1527 //      {
1528 //          XMultiComponentFactory factory = ctx.getServiceManager();
1529 //          if (factory == null)
1530 //              throw new com.sun.star.uno.DeploymentException("bla", null);
1531 //          return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx);
1532 //      }
1533 ::System::Type ^ TypeEmitter::complete_service_type(service_entry ^ entry)
1534 {
1535     Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
1536     reflection::XServiceTypeDescription2 * xServiceType = entry->m_xType;
1537 
1538     //Create the private default constructor
1539     Emit::ConstructorBuilder ^ ctor_builder =
1540         type_builder->DefineConstructor(
1541             (MethodAttributes) (MethodAttributes::Private |
1542                                 MethodAttributes::HideBySig |
1543                                 MethodAttributes::SpecialName |
1544                                 MethodAttributes::RTSpecialName),
1545             CallingConventions::Standard, nullptr);
1546 
1547     Emit::ILGenerator ^ ilGen = ctor_builder->GetILGenerator();
1548     ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1549     ilGen->Emit(
1550             Emit::OpCodes::Call,
1551             type_builder->BaseType->GetConstructor(gcnew cli::array< ::System::Type ^ >( 0 )));
1552     ilGen->Emit( Emit::OpCodes::Ret );
1553 
1554 
1555     //Create the service constructors.
1556     //obtain the interface which makes up this service, it is the return
1557     //type of the constructor functions
1558     Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
1559         xServiceType->getInterface(), UNO_QUERY);
1560     if (xIfaceType.is () == sal_False)
1561         xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface());
1562     System::Type ^ retType = get_type(xIfaceType);
1563 
1564     //Create the ConstructorInfo for a DeploymentException
1565     ::System::Type ^ typeDeploymentExc =
1566           get_type("unoidl.com.sun.star.uno.DeploymentException", true);
1567 
1568     cli::array< ::System::Type ^ > ^ arTypeCtor = {::System::String::typeid,
1569                                          ::System::Object::typeid};
1570     ::System::Reflection::ConstructorInfo ^ ctorDeploymentException  =
1571           typeDeploymentExc->GetConstructor(arTypeCtor);
1572 
1573     Sequence<Reference<reflection::XServiceConstructorDescription> >  seqCtors =
1574         xServiceType->getConstructors();
1575 
1576     ::System::Type ^ type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception", true);
1577 
1578     for (int i = seqCtors.getLength() - 1; i >= 0; i--)
1579     {
1580         bool bParameterArray = false;
1581         ::System::Type ^ typeAny = ::uno::Any::typeid;
1582         const Reference<reflection::XServiceConstructorDescription> & ctorDes =
1583             seqCtors[i];
1584         //obtain the parameter types
1585         Sequence<Reference<reflection::XParameter> > seqParams =
1586             ctorDes->getParameters();
1587         Reference<reflection::XParameter> const * arXParams = seqParams.getConstArray();
1588         sal_Int32 cParams = seqParams.getLength();
1589         cli::array< ::System::Type ^ > ^ arTypeParameters = gcnew cli::array< ::System::Type ^ >( cParams + 1 );
1590         arTypeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1591         for (int iparam = 0; iparam != cParams; iparam++)
1592         {
1593             if (arXParams[iparam]->isRestParameter())
1594                 arTypeParameters[iparam + 1] = cli::array< ::uno::Any >::typeid;
1595             else
1596                 arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType());
1597         }
1598         //The array arTypeParameters can contain:
1599         //System.Type and uno.PolymorphicType.
1600         //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem.
1601         //The exception will read something like no on information for parameter # d
1602         //Maybe we need no override another Type method in PolymorphicType ...
1603         //Until we have figured this out, we will create another array of System.Type which
1604         //we pass on to DefineMethod.
1605         cli::array< ::System::Type ^ > ^ arParamTypes = gcnew cli::array< ::System::Type ^ >( cParams + 1 );
1606 //      arParamTypes[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1607         for (int i = 0; i < cParams + 1; i++)
1608         {
1609             ::uno::PolymorphicType ^ pT = dynamic_cast< ::uno::PolymorphicType ^ >(arTypeParameters[i]);
1610             if (pT)
1611                 arParamTypes[i] = pT->OriginalType;
1612             else
1613                 arParamTypes[i] = arTypeParameters[i];
1614         }
1615         //define method
1616         System::String ^ ctorName;
1617         if (ctorDes->isDefaultConstructor())
1618             ctorName = gcnew ::System::String("create");
1619         else
1620             ctorName = ustring_to_String(ctorDes->getName());
1621         Emit::MethodBuilder ^ method_builder = type_builder->DefineMethod(
1622             ctorName,
1623             static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
1624                                           MethodAttributes::Static),
1625             retType,
1626 //          arTypeParameters);
1627             arParamTypes);
1628 
1629         //define UNO exception attribute (exceptions)--------------------------------------
1630         Emit::CustomAttributeBuilder ^ attrBuilder = get_service_exception_attribute(ctorDes);
1631         if (attrBuilder != nullptr)
1632             method_builder->SetCustomAttribute(attrBuilder);
1633 
1634         //-------------------------------------------------------------
1635         //define parameter attributes (paramarray), names etc.
1636         //The first parameter is the XComponentContext, which cannot be obtained
1637         //from reflection.
1638         //The context is not part of the idl description
1639         method_builder->DefineParameter(
1640             1, ParameterAttributes::In, "the_context");
1641 
1642         cli::array< Emit::ParameterBuilder ^ > ^ arParameterBuilder =
1643             gcnew cli::array< Emit::ParameterBuilder ^ >( cParams );
1644         for (int iparam = 0; iparam != cParams; iparam++)
1645         {
1646             Reference<reflection::XParameter> const & aParam = arXParams[iparam];
1647             ::System::String ^ sParamName = ustring_to_String(aParam->getName());
1648 
1649             arParameterBuilder[iparam] = method_builder->DefineParameter(
1650                 iparam + 2, ParameterAttributes::In, sParamName);
1651 
1652             if (aParam->isRestParameter())
1653             {
1654                 bParameterArray = true;
1655                 //set the ParameterArrayAttribute
1656                 ::System::Reflection::ConstructorInfo ^ ctor_info =
1657                     System::ParamArrayAttribute::typeid->GetConstructor(
1658                         gcnew cli::array< ::System::Type ^ >( 0 ));
1659                 Emit::CustomAttributeBuilder ^ attr_builder =
1660                     gcnew Emit::CustomAttributeBuilder(ctor_info, gcnew cli::array< ::System::Object ^ >( 0 ));
1661                 arParameterBuilder[iparam]->SetCustomAttribute(attr_builder);
1662                 break;
1663             }
1664         }
1665 
1666         Emit::ILGenerator ^ ilGen = method_builder->GetILGenerator();
1667 
1668         //Define locals ---------------------------------
1669         //XMultiComponentFactory
1670         Emit::LocalBuilder ^ local_factory =
1671             ilGen->DeclareLocal(
1672                 get_type("unoidl.com.sun.star.lang.XMultiComponentFactory", true));
1673 
1674         //The return type
1675         Emit::LocalBuilder ^ local_return_val =
1676             ilGen->DeclareLocal(retType);
1677 
1678         //Obtain the XMultiComponentFactory and throw an exception if we do not get one
1679         ilGen->Emit(Emit::OpCodes::Ldarg_0);
1680 
1681         ::System::Reflection::MethodInfo ^ methodGetServiceManager = get_type(
1682             "unoidl.com.sun.star.uno.XComponentContext", true)
1683                 ->GetMethod("getServiceManager");
1684         ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager);
1685         ilGen->Emit(Emit::OpCodes::Stloc, local_factory);
1686         ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1687         Emit::Label label1 = ilGen->DefineLabel();
1688         ilGen->Emit(Emit::OpCodes::Brtrue, label1);
1689         //The string for the exception
1690         ::System::Text::StringBuilder ^ strbuilder = gcnew ::System::Text::StringBuilder(256);
1691         strbuilder->Append("The service ");
1692         strbuilder->Append(to_cts_name(xServiceType->getName()));
1693         strbuilder->Append(" could not be created. The context failed to supply the service manager.");
1694 
1695         ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1696         ilGen->Emit(Emit::OpCodes::Ldarg_0);
1697         ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1698         ilGen->Emit(Emit::OpCodes::Throw);
1699         ilGen->MarkLabel(label1);
1700 
1701         //We create a try/ catch around the createInstanceWithContext, etc. functions
1702         //There are 3 cases
1703         //1. function do not specify exceptions. Then RuntimeExceptions are retrhown and other
1704         //   exceptions produce a DeploymentException.
1705         //2. function specify Exception. Then all exceptions fly through
1706         //3. function specifies exceptions but no Exception. Then these are rethrown
1707         //   and other exceptions, except RuntimeException, produce a deployment exception.
1708         //In case there are no parameters we call
1709         //XMultiComponentFactory.createInstanceWithContext
1710 
1711         ::System::Collections::ArrayList ^ arExceptionTypes =
1712               get_service_ctor_method_exceptions_reduced(ctorDes->getExceptions());
1713         if (arExceptionTypes->Contains(
1714                 type_uno_exception) == false)
1715         {
1716             ilGen->BeginExceptionBlock();
1717         }
1718         if (cParams == 0)
1719         {
1720             ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1721             ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1722             ilGen->Emit(Emit::OpCodes::Ldarg_0);
1723 
1724             ::System::Reflection::MethodInfo ^ methodCreate =
1725                     local_factory->LocalType->GetMethod("createInstanceWithContext");
1726             ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1727         }
1728         else if(bParameterArray)
1729         {
1730             //Service constructor with parameter array
1731             ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1732             ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1733             ilGen->Emit(Emit::OpCodes::Ldarg_1);
1734             ilGen->Emit(Emit::OpCodes::Ldarg_0);
1735             ::System::Reflection::MethodInfo ^ methodCreate =
1736                     local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1737             ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1738         }
1739         else
1740         {
1741             // Any param1, Any param2, etc.
1742             // For each parameter,except the component context, and parameter array
1743             // and Any is created.
1744             cli::array< Emit::LocalBuilder ^ > ^ arLocalAny = gcnew cli::array< Emit::LocalBuilder ^ >( cParams );
1745 
1746             for (int iParam = 0; iParam < cParams; iParam ++)
1747             {
1748                 arLocalAny[iParam] = ilGen->DeclareLocal(typeAny);
1749             }
1750 
1751             //Any[]. This array is filled with the created Anys which contain the parameters
1752             //and the values contained in the parameter array
1753             Emit::LocalBuilder ^ local_anyParams =
1754                 ilGen->DeclareLocal(cli::array< ::uno::Any >::typeid);
1755 
1756             //Create the Any for every argument, except for the parameter array
1757             //arLocalAny contains the LocalBuilder for all these parameters.
1758             //we call the ctor Any(Type, Object)
1759             //If the parameter is an Any then the Any is created with Any(param.Type, param.Value);
1760             cli::array< ::System::Type ^ > ^ arTypesCtorAny = {::System::Type::typeid,
1761                                                     ::System::Object::typeid};
1762             ::System::Reflection::ConstructorInfo ^ ctorAny =
1763                 typeAny->GetConstructor( arTypesCtorAny);
1764             ::System::Reflection::MethodInfo ^ methodAnyGetType =
1765                 typeAny->GetProperty("Type")->GetGetMethod();
1766             ::System::Reflection::MethodInfo ^ methodAnyGetValue =
1767                 typeAny->GetProperty("Value")->GetGetMethod();
1768             for (int i = 0; i < arLocalAny->Length; i ++)
1769             {
1770                 //check if the parameter is a polymorphic struct
1771                 ::uno::PolymorphicType ^polyType = dynamic_cast< ::uno::PolymorphicType ^ >(arTypeParameters[i+1]);
1772                 //arTypeParameters[i+1] = polyType->OriginalType;
1773                 if (polyType)
1774                 {
1775                     //It is a polymorphic struct
1776                     //Load the uninitialized local Any on which we will call the ctor
1777                     ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1778                     // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName)
1779                     // Prepare the first parameter
1780                     ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->OriginalType);
1781                     cli::array< ::System::Type ^ > ^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1782                     ilGen->Emit(Emit::OpCodes::Call,
1783                                 ::System::Type::typeid->GetMethod(
1784                                     "GetTypeFromHandle", arTypeParams));
1785                     // Prepare the second parameter
1786                     ilGen->Emit(Emit::OpCodes::Ldstr, polyType->PolymorphicName);
1787                     // Make the actual call
1788                     cli::array< ::System::Type ^ > ^ arTypeParam_GetType = {
1789                         ::System::Type::typeid, ::System::String::typeid };
1790                     ilGen->Emit(Emit::OpCodes::Call,
1791                     ::uno::PolymorphicType::typeid->GetMethod(gcnew System::String("GetType"),
1792                         arTypeParam_GetType));
1793 
1794                     //Stack is: localAny, PolymorphicType
1795                     //Call Any::Any(Type, Object)
1796                     //Prepare the second parameter for the any ctor
1797                     ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1798                     // if the parameter is a value type then we need to box it, because
1799                     // the Any ctor takes an Object
1800                     if (arTypeParameters[i+1]->IsValueType)
1801                         ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1802                     ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1803                 }
1804                 else if (arTypeParameters[i+1] == typeAny)
1805                 {
1806                     //Create the call new Any(param.Type,param,Value)
1807                     //Stack must be Any,Type,Value
1808                     //First load the Any which is to be constructed
1809                     ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1810                     //Load the Type, which is obtained by calling param.Type
1811                     ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1812                     ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType);
1813                     //Load the Value, which is obtained by calling param.Value
1814                     ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1815                     ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue);
1816                     //Call the Any ctor.
1817                     ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1818                 }
1819                 else
1820                 {
1821                     ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1822                     ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]);
1823 
1824                     cli::array< ::System::Type ^ > ^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1825                     ilGen->Emit(Emit::OpCodes::Call,
1826                                 ::System::Type::typeid->GetMethod(
1827                                     "GetTypeFromHandle", arTypeParams));
1828                     ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1829                     // if the parameter is a value type then we need to box it, because
1830                     // the Any ctor takes an Object
1831                     if (arTypeParameters[i+1]->IsValueType)
1832                         ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1833                     ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1834                 }
1835             }
1836 
1837             //Create the Any[] that is passed to the
1838             //createInstanceWithContext[AndArguments] function
1839             ilGen->Emit(Emit::OpCodes::Ldc_I4, arLocalAny->Length);
1840             ilGen->Emit(Emit::OpCodes::Newarr, typeAny);
1841             ilGen->Emit(Emit::OpCodes::Stloc, local_anyParams);
1842 
1843             //Assign all Anys created from the parameters
1844             //array to the Any[]
1845             for (int i = 0; i < arLocalAny->Length; i++)
1846             {
1847                 ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1848                 ilGen->Emit(Emit::OpCodes::Ldc_I4, i);
1849                 ilGen->Emit(Emit::OpCodes::Ldelema, typeAny);
1850                 ilGen->Emit(Emit::OpCodes::Ldloc, arLocalAny[i]);
1851                 ilGen->Emit(Emit::OpCodes::Stobj, typeAny);
1852             }
1853             // call createInstanceWithContextAndArguments
1854             ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1855             ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1856             ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1857             ilGen->Emit(Emit::OpCodes::Ldarg_0);
1858             ::System::Reflection::MethodInfo ^ methodCreate =
1859                     local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1860             ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1861         }
1862         //cast the object returned by the functions createInstanceWithContext or
1863         //createInstanceWithArgumentsAndContext to the interface type
1864         ilGen->Emit(Emit::OpCodes::Castclass, retType);
1865         ilGen->Emit(Emit::OpCodes::Stloc, local_return_val);
1866 
1867         //catch exceptions thrown by createInstanceWithArgumentsAndContext and createInstanceWithContext
1868         if (arExceptionTypes->Contains(type_uno_exception) == false)
1869         {
1870             // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;}
1871             ilGen->BeginCatchBlock(get_type("unoidl.com.sun.star.uno.RuntimeException", true));
1872             ilGen->Emit(Emit::OpCodes::Pop);
1873             ilGen->Emit(Emit::OpCodes::Rethrow);
1874 
1875             //catch and rethrow all other defined Exceptions
1876             for (int i = 0; i < arExceptionTypes->Count; i++)
1877             {
1878                 ::System::Type ^ excType = safe_cast< ::System::Type ^ >(
1879                     arExceptionTypes[ i ]);
1880                 if (excType->IsInstanceOfType(
1881                         get_type("unoidl.com.sun.star.uno.RuntimeException", true)))
1882                 {// we have a catch for RuntimeException already defined
1883                     continue;
1884                 }
1885 
1886                 //catch Exception and rethrow
1887                 ilGen->BeginCatchBlock(excType);
1888                 ilGen->Emit(Emit::OpCodes::Pop);
1889                 ilGen->Emit(Emit::OpCodes::Rethrow);
1890             }
1891             //catch (unoidl.com.sun.star.uno.Exception) {throw DeploymentException...}
1892             ilGen->BeginCatchBlock(type_uno_exception);
1893 
1894             //Define the local variable that keeps the exception
1895              Emit::LocalBuilder ^ local_exception = ilGen->DeclareLocal(
1896                  type_uno_exception);
1897 
1898              //Store the exception
1899              ilGen->Emit(Emit::OpCodes::Stloc, local_exception);
1900 
1901             //prepare the construction of the exception
1902              strbuilder = gcnew ::System::Text::StringBuilder(256);
1903              strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1904              strbuilder->Append(to_cts_name(xServiceType->getName()));
1905              strbuilder->Append(": ");
1906 
1907              ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1908 
1909             //add to the string the Exception.Message
1910             ilGen->Emit(Emit::OpCodes::Ldloc, local_exception);
1911             ilGen->Emit(Emit::OpCodes::Callvirt,
1912                         type_uno_exception->GetProperty("Message")->GetGetMethod());
1913             cli::array< ::System::Type ^ > ^ arConcatParams = {System::String::typeid,
1914                                                   System::String::typeid};
1915             ilGen->Emit(Emit::OpCodes::Call,
1916                         System::String::typeid->GetMethod("Concat", arConcatParams));
1917             //load context argument
1918             ilGen->Emit(Emit::OpCodes::Ldarg_0);
1919             ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1920             ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1921 
1922             ilGen->EndExceptionBlock();
1923         }
1924 
1925 
1926         //Check if the service instance was created and throw a exception if not.
1927         Emit::Label label_service_created = ilGen->DefineLabel();
1928         ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1929         ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created);
1930 
1931         strbuilder = gcnew ::System::Text::StringBuilder(256);
1932         strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1933         strbuilder->Append(to_cts_name(xServiceType->getName()));
1934         strbuilder->Append(".");
1935         ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1936         ilGen->Emit(Emit::OpCodes::Ldarg_0);
1937         ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1938         ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1939 
1940         ilGen->MarkLabel(label_service_created);
1941         ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1942         ilGen->Emit(Emit::OpCodes::Ret);
1943 
1944     }
1945     // remove from incomplete types map
1946     ::System::String ^ cts_name = type_builder->FullName;
1947     m_incomplete_services->Remove( cts_name );
1948     xServiceType->release();
1949     if (g_verbose)
1950     {
1951         ::System::Console::WriteLine(
1952             "> emitting service type {0}", cts_name );
1953     }
1954     return type_builder->CreateType();
1955 }
1956 
1957 
1958 Emit::CustomAttributeBuilder ^ TypeEmitter::get_service_exception_attribute(
1959     const Reference<reflection::XServiceConstructorDescription> & ctorDes )
1960 {
1961     return get_exception_attribute(ctorDes->getExceptions());
1962 }
1963 
1964 Emit::CustomAttributeBuilder ^ TypeEmitter::get_iface_method_exception_attribute(
1965     const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod )
1966 {
1967 
1968     const Sequence<Reference<reflection::XTypeDescription> > seqTD = xMethod->getExceptions();
1969     int len = seqTD.getLength();
1970     Sequence<Reference<reflection::XCompoundTypeDescription> > seqCTD(len);
1971     Reference<reflection::XCompoundTypeDescription> * arCTD = seqCTD.getArray();
1972     for (int i = 0; i < len; i++)
1973         arCTD[i] = Reference<reflection::XCompoundTypeDescription>(seqTD[i], UNO_QUERY_THROW);
1974     return get_exception_attribute(seqCTD);
1975 }
1976 
1977 Emit::CustomAttributeBuilder ^ TypeEmitter::get_exception_attribute(
1978 
1979     const Sequence<Reference< reflection::XCompoundTypeDescription > >& seq_exceptionsTd )
1980 {
1981     Emit::CustomAttributeBuilder ^ attr_builder = nullptr;
1982 
1983     Reference< reflection::XCompoundTypeDescription > const * exceptions =
1984         seq_exceptionsTd.getConstArray();
1985 
1986     cli::array< ::System::Type ^ > ^ arTypesCtor = {::System::Type::GetType("System.Type[]")};
1987     ConstructorInfo ^ ctor_ExceptionAttribute =
1988         ::uno::ExceptionAttribute::typeid->GetConstructor(arTypesCtor);
1989 
1990     sal_Int32 exc_length = seq_exceptionsTd.getLength();
1991     if (exc_length != 0) // opt
1992     {
1993         cli::array< ::System::Type ^ > ^ exception_types =
1994               gcnew cli::array< ::System::Type ^ >( exc_length );
1995         for ( sal_Int32 exc_pos = 0; exc_pos < exc_length; ++exc_pos )
1996         {
1997             Reference< reflection::XCompoundTypeDescription > const & xExc =
1998                 exceptions[ exc_pos ];
1999             exception_types[ exc_pos ] = get_type( xExc );
2000         }
2001         cli::array< ::System::Object ^ > ^ args = {exception_types};
2002         attr_builder = gcnew Emit::CustomAttributeBuilder(
2003             ctor_ExceptionAttribute, args );
2004     }
2005     return attr_builder;
2006 }
2007 
2008 
2009 ::System::Type ^ TypeEmitter::complete_singleton_type(singleton_entry ^ entry)
2010 {
2011     Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
2012     reflection::XSingletonTypeDescription2 * xSingletonType = entry->m_xType;
2013     ::System::String ^ sSingletonName = to_cts_name(xSingletonType->getName());
2014 
2015     //Create the private default constructor
2016     Emit::ConstructorBuilder ^ ctor_builder =
2017         type_builder->DefineConstructor(
2018             static_cast<MethodAttributes>(MethodAttributes::Private |
2019                                           MethodAttributes::HideBySig |
2020                                           MethodAttributes::SpecialName |
2021                                           MethodAttributes::RTSpecialName),
2022             CallingConventions::Standard, nullptr);
2023 
2024     Emit::ILGenerator ^ ilGen = ctor_builder->GetILGenerator();
2025     ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
2026     ilGen->Emit(
2027             Emit::OpCodes::Call,
2028             type_builder->BaseType->GetConstructor(gcnew cli::array< ::System::Type ^ >( 0 )));
2029     ilGen->Emit( Emit::OpCodes::Ret );
2030 
2031 
2032     //obtain the interface which makes up this service, it is the return
2033     //type of the constructor functions
2034     Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
2035         xSingletonType->getInterface(), UNO_QUERY);
2036     if (xIfaceType.is () == sal_False)
2037         xIfaceType = resolveInterfaceTypedef(xSingletonType->getInterface());
2038     System::Type ^ retType = get_type(xIfaceType);
2039 
2040     //define method
2041     cli::array< ::System::Type ^ > ^ arTypeParameters = {get_type("unoidl.com.sun.star.uno.XComponentContext", true)};
2042     Emit::MethodBuilder ^ method_builder = type_builder->DefineMethod(
2043         gcnew System::String("get"),
2044         static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
2045                                       MethodAttributes::Static),
2046         retType,
2047         arTypeParameters);
2048 
2049 
2050 //       method_builder->SetCustomAttribute(get_service_ctor_method_attribute(ctorDes));
2051 
2052     //The first parameter is the XComponentContext, which cannot be obtained
2053     //from reflection.
2054     //The context is not part of the idl description
2055     method_builder->DefineParameter(1, ParameterAttributes::In, "the_context");
2056 
2057 
2058     ilGen = method_builder->GetILGenerator();
2059     //Define locals ---------------------------------
2060     // Any, returned by XComponentContext.getValueByName
2061     Emit::LocalBuilder ^ local_any =
2062         ilGen->DeclareLocal(::uno::Any::typeid);
2063 
2064     //Call XContext::getValueByName
2065     ilGen->Emit(Emit::OpCodes::Ldarg_0);
2066     // build the singleton name : /singleton/unoidl.com.sun.star.XXX
2067     ::System::Text::StringBuilder ^ sBuilder =
2068           gcnew ::System::Text::StringBuilder("/singletons/");
2069     sBuilder->Append(sSingletonName);
2070     ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
2071 
2072     ::System::Reflection::MethodInfo ^ methodGetValueByName =
2073           get_type("unoidl.com.sun.star.uno.XComponentContext", true)->GetMethod("getValueByName");
2074     ilGen->Emit(Emit::OpCodes::Callvirt, methodGetValueByName);
2075     ilGen->Emit(Emit::OpCodes::Stloc_0);
2076 
2077     //Contains the returned Any a value?
2078     ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
2079     ::System::Reflection::MethodInfo ^ methodHasValue =
2080           ::uno::Any::typeid->GetMethod("hasValue");
2081     ilGen->Emit(Emit::OpCodes::Call, methodHasValue);
2082 
2083     //If not, then throw an DeploymentException
2084     Emit::Label label_singleton_exists = ilGen->DefineLabel();
2085     ilGen->Emit(Emit::OpCodes::Brtrue_S, label_singleton_exists);
2086     sBuilder = gcnew ::System::Text::StringBuilder(
2087         "Component context fails to supply singleton ");
2088     sBuilder->Append(sSingletonName);
2089     sBuilder->Append(" of type ");
2090     sBuilder->Append(retType->FullName);
2091     sBuilder->Append(".");
2092     ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
2093     ilGen->Emit(Emit::OpCodes::Ldarg_0);
2094     cli::array< ::System::Type ^ > ^ arTypesCtorDeploymentException = {
2095         ::System::String::typeid, ::System::Object::typeid};
2096     ilGen->Emit(Emit::OpCodes::Newobj,
2097                 get_type("unoidl.com.sun.star.uno.DeploymentException",true)
2098                 ->GetConstructor(arTypesCtorDeploymentException));
2099     ilGen->Emit(Emit::OpCodes::Throw);
2100     ilGen->MarkLabel(label_singleton_exists);
2101 
2102     //Cast the singleton contained in the Any to the expected interface and return it.
2103     ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
2104     ilGen->Emit(Emit::OpCodes::Call, ::uno::Any::typeid->GetProperty("Value")->GetGetMethod());
2105     ilGen->Emit(Emit::OpCodes::Castclass, retType);
2106     ilGen->Emit(Emit::OpCodes::Ret);
2107 
2108     // remove from incomplete types map
2109     ::System::String ^ cts_name = type_builder->FullName;
2110     m_incomplete_singletons->Remove( cts_name );
2111     xSingletonType->release();
2112     if (g_verbose)
2113     {
2114         ::System::Console::WriteLine(
2115             "> emitting singleton type {0}", cts_name );
2116     }
2117     return type_builder->CreateType();
2118 }
2119 
2120 
2121 //______________________________________________________________________________
2122 ::System::Type ^ TypeEmitter::get_type(
2123     Reference< reflection::XTypeDescription > const & xType )
2124 {
2125     switch (xType->getTypeClass())
2126     {
2127     case TypeClass_VOID:
2128         return ::System::Void::typeid;
2129     case TypeClass_CHAR:
2130         return ::System::Char::typeid;
2131     case TypeClass_BOOLEAN:
2132         return ::System::Boolean::typeid;
2133     case TypeClass_BYTE:
2134         return ::System::Byte::typeid;
2135     case TypeClass_SHORT:
2136         return ::System::Int16::typeid;
2137     case TypeClass_UNSIGNED_SHORT:
2138         return ::System::UInt16::typeid;
2139     case TypeClass_LONG:
2140         return ::System::Int32::typeid;
2141     case TypeClass_UNSIGNED_LONG:
2142         return ::System::UInt32::typeid;
2143     case TypeClass_HYPER:
2144         return ::System::Int64::typeid;
2145     case TypeClass_UNSIGNED_HYPER:
2146         return ::System::UInt64::typeid;
2147     case TypeClass_FLOAT:
2148         return ::System::Single::typeid;
2149     case TypeClass_DOUBLE:
2150         return ::System::Double::typeid;
2151     case TypeClass_STRING:
2152         return ::System::String::typeid;
2153     case TypeClass_TYPE:
2154         return ::System::Type::typeid;
2155     case TypeClass_ANY:
2156         return ::uno::Any::typeid;
2157     case TypeClass_ENUM:
2158         return get_type( Reference< reflection::XEnumTypeDescription >(
2159                              xType, UNO_QUERY_THROW ) );
2160     case TypeClass_TYPEDEF:
2161         // unwind typedefs
2162         return get_type(
2163             Reference< reflection::XIndirectTypeDescription >(
2164                 xType, UNO_QUERY_THROW )->getReferencedType() );
2165     case TypeClass_STRUCT:
2166     case TypeClass_EXCEPTION:
2167         return get_type(
2168             Reference< reflection::XCompoundTypeDescription >(
2169                 xType, UNO_QUERY_THROW ) );
2170     case TypeClass_SEQUENCE:
2171     {
2172         ::System::Type ^ element_type = get_type(
2173             Reference< reflection::XIndirectTypeDescription >(
2174                 xType, UNO_QUERY_THROW )->getReferencedType() );
2175         ::System::Type ^ retType = get_type(
2176             ::System::String::Concat(
2177                 element_type->FullName, "[]" ), true );
2178 
2179         ::uno::PolymorphicType ^ pt = dynamic_cast< ::uno::PolymorphicType ^ >(element_type);
2180         if (pt)
2181         {
2182             ::System::String ^ sName = ::System::String::Concat(pt->PolymorphicName, "[]");
2183             retType = ::uno::PolymorphicType::GetType(retType, sName);
2184         }
2185         return retType;
2186     }
2187     case TypeClass_INTERFACE:
2188         return get_type(
2189             Reference< reflection::XInterfaceTypeDescription2 >(
2190                 xType, UNO_QUERY_THROW ) );
2191     case TypeClass_CONSTANT:
2192         return get_type(
2193             Reference< reflection::XConstantTypeDescription >(
2194                 xType, UNO_QUERY_THROW ) );
2195     case TypeClass_CONSTANTS:
2196         return get_type(
2197             Reference< reflection::XConstantsTypeDescription >(
2198                 xType, UNO_QUERY_THROW ) );
2199     case TypeClass_SERVICE:
2200         return get_type(
2201             Reference< reflection::XServiceTypeDescription2 >(
2202                 xType, UNO_QUERY_THROW) );
2203     case TypeClass_SINGLETON:
2204         return get_type(
2205             Reference< reflection::XSingletonTypeDescription2 >(
2206                 xType, UNO_QUERY_THROW) );
2207     case TypeClass_MODULE:
2208         // ignore these
2209         return nullptr;
2210     default:
2211         throw RuntimeException(
2212             OUSTR("unexpected type ") + xType->getName(),
2213             Reference< XInterface >() );
2214     }
2215 }
2216 
2217 //______________________________________________________________________________
2218 ::System::Type ^ TypeEmitter::get_complete_struct( ::System::String ^ sName)
2219 {
2220     struct_entry ^ pStruct = safe_cast< struct_entry ^ >(
2221         m_incomplete_structs[ sName ]);
2222     if (pStruct)
2223     {
2224         complete_struct_type(pStruct);
2225     }
2226     //get_type will ask the module builder for the type or otherwise all known assemblies.
2227     return get_type(sName, true);
2228 }
2229 TypeEmitter::~TypeEmitter()
2230 {
2231     while (true)
2232     {
2233         ::System::Collections::IDictionaryEnumerator ^ enumerator =
2234               m_incomplete_ifaces->GetEnumerator();
2235         if (! enumerator->MoveNext())
2236             break;
2237         complete_iface_type(
2238             safe_cast< iface_entry ^ >( enumerator->Value ) );
2239     }
2240 
2241     while (true)
2242     {
2243         ::System::Collections::IDictionaryEnumerator ^ enumerator =
2244               m_incomplete_structs->GetEnumerator();
2245         if (! enumerator->MoveNext())
2246             break;
2247         complete_struct_type(
2248             safe_cast< struct_entry ^ >( enumerator->Value ) );
2249     }
2250 
2251 
2252     while (true)
2253     {
2254         ::System::Collections::IDictionaryEnumerator ^ enumerator =
2255               m_incomplete_services->GetEnumerator();
2256         if (! enumerator->MoveNext())
2257             break;
2258         complete_service_type(
2259             safe_cast< service_entry ^ >( enumerator->Value ) );
2260     }
2261 
2262     while (true)
2263     {
2264         ::System::Collections::IDictionaryEnumerator ^ enumerator =
2265               m_incomplete_singletons->GetEnumerator();
2266         if (! enumerator->MoveNext())
2267             break;
2268         complete_singleton_type(
2269             safe_cast< singleton_entry ^ >( enumerator->Value ) );
2270     }
2271 }
2272 //______________________________________________________________________________
2273 TypeEmitter::TypeEmitter(
2274     ::System::Reflection::Emit::ModuleBuilder ^ module_builder,
2275     cli::array< ::System::Reflection::Assembly ^ > ^ extra_assemblies )
2276     : m_module_builder( module_builder ),
2277       m_extra_assemblies( extra_assemblies ),
2278       m_method_info_Type_GetTypeFromHandle( nullptr ),
2279       m_type_Exception( nullptr ),
2280       m_type_RuntimeException( nullptr ),
2281       m_incomplete_ifaces( gcnew ::System::Collections::Hashtable() ),
2282       m_resolving( gcnew ::System::Collections::Hashtable() ),
2283       m_incomplete_structs( gcnew ::System::Collections::Hashtable() ),
2284       m_incomplete_services(gcnew ::System::Collections::Hashtable() ),
2285       m_incomplete_singletons(gcnew ::System::Collections::Hashtable() ),
2286       m_generated_structs( gcnew ::System::Collections::Hashtable() )
2287 {
2288     cli::array< ::System::Type ^ > ^ param_types = gcnew cli::array< ::System::Type ^ >( 1 );
2289     param_types[ 0 ] = ::System::RuntimeTypeHandle::typeid;
2290     m_method_info_Type_GetTypeFromHandle =
2291         ::System::Type::typeid
2292           ->GetMethod( "GetTypeFromHandle", param_types );
2293 }
2294 
2295 ::System::Collections::ArrayList ^ TypeEmitter::get_service_ctor_method_exceptions_reduced(
2296     const Sequence<Reference<reflection::XCompoundTypeDescription> > & seqExceptionsTd)
2297 {
2298     if (seqExceptionsTd.getLength() == 0)
2299         return gcnew ::System::Collections::ArrayList();
2300 
2301     ::System::Collections::ArrayList ^ arTypes = gcnew ::System::Collections::ArrayList();
2302     for (int i = 0; i < seqExceptionsTd.getLength(); i++)
2303         arTypes->Add(get_type(to_cts_name(seqExceptionsTd[i]->getName()), true));
2304 
2305     int start = 0;
2306     while (true)
2307     {
2308         bool bRemove = false;
2309         for (int i = start; i < arTypes->Count; i++)
2310         {
2311             ::System::Type ^ t = safe_cast< ::System::Type ^ >(arTypes[ i ]);
2312             for (int j = 0; j < arTypes->Count; j++)
2313             {
2314                 if (t->IsSubclassOf(safe_cast< ::System::Type ^ >(arTypes[ j ])))
2315                 {
2316                     arTypes->RemoveAt(i);
2317                     bRemove = true;
2318                     break;
2319                 }
2320             }
2321             if (bRemove)
2322                 break;
2323             start++;
2324         }
2325 
2326         if (bRemove == false)
2327             break;
2328     }
2329     return arTypes;
2330 }
2331 
2332 
2333 css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
2334 resolveInterfaceTypedef(
2335     const css::uno::Reference<css::reflection::XTypeDescription>& type)
2336 {
2337     Reference<reflection::XInterfaceTypeDescription2>
2338         xIfaceTd(type, UNO_QUERY);
2339 
2340     if (xIfaceTd.is())
2341         return xIfaceTd;
2342 
2343     Reference<reflection::XIndirectTypeDescription> xIndTd(
2344         type, UNO_QUERY);
2345     if (xIndTd.is() == sal_False)
2346         throw css::uno::Exception(
2347             OUSTR("resolveInterfaceTypedef was called with an invalid argument"), 0);
2348 
2349     return resolveInterfaceTypedef(xIndTd->getReferencedType());
2350 }
2351 
2352 
2353 }
2354