Bump version to 6.4-15
[LibreOffice.git] / cli_ure / source / climaker / climaker_emit.cxx
blob0f3c3b73a0b98261367be0342af5d96a83eef101
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "climaker_share.h"
22 #include "rtl/string.hxx"
23 #include "rtl/ustrbuf.hxx"
24 #include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
25 #include "com/sun/star/reflection/XStructTypeDescription.hpp"
26 #include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp"
27 #include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp"
28 #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription.hpp"
29 #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp"
30 #include <vector>
32 using namespace ::System::Reflection;
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno;
37 namespace climaker
39 System::String^ mapUnoPolymorphicName(System::String^ unoName);
41 static inline ::System::String ^ to_cts_name(
42 OUString const & uno_name )
44 return ustring_to_String("unoidl." + uno_name);
48 static inline ::System::Object ^ to_cli_constant( Any const & value )
50 switch (value.getValueTypeClass())
52 case TypeClass_CHAR:
53 return ((::System::Char) *reinterpret_cast< sal_Unicode const * >(
54 value.getValue() ));
55 case TypeClass_BOOLEAN:
56 return ((::System::Boolean)
57 sal_False != *reinterpret_cast< sal_Bool const * >(
58 value.getValue() ));
59 case TypeClass_BYTE:
60 return ((::System::Byte) *reinterpret_cast< sal_Int8 const * >(
61 value.getValue() ));
62 case TypeClass_SHORT:
63 return ((::System::Int16) *reinterpret_cast< sal_Int16 const * >(
64 value.getValue() ));
65 case TypeClass_UNSIGNED_SHORT:
66 return ((::System::UInt16) *reinterpret_cast< sal_uInt16 const * >(
67 value.getValue() ));
68 case TypeClass_LONG:
69 return ((::System::Int32) *reinterpret_cast< sal_Int32 const * >(
70 value.getValue() ));
71 case TypeClass_UNSIGNED_LONG:
72 return ((::System::UInt32) *reinterpret_cast< sal_uInt32 const * >(
73 value.getValue() ));
74 case TypeClass_HYPER:
75 return ((::System::Int64) *reinterpret_cast< sal_Int64 const * >(
76 value.getValue() ));
77 case TypeClass_UNSIGNED_HYPER:
78 return ((::System::UInt64) *reinterpret_cast< sal_uInt64 const * >(
79 value.getValue() ));
80 case TypeClass_FLOAT:
81 return ((::System::Single) *reinterpret_cast< float const * >(
82 value.getValue() ));
83 case TypeClass_DOUBLE:
84 return ((::System::Double) *reinterpret_cast< double const * >(
85 value.getValue() ));
86 default:
87 throw RuntimeException(
88 "unexpected constant type " +
89 value.getValueType().getTypeName() );
94 static inline void emit_ldarg( Emit::ILGenerator ^ code, ::System::Int32 index )
96 switch (index)
98 case 0:
99 #pragma warning (push)
100 #pragma warning (disable: 4538) // const/volatile qualifiers on this type are not supported
101 code->Emit( Emit::OpCodes::Ldarg_0 );
102 #pragma warning (pop)
103 break;
104 case 1:
105 code->Emit( Emit::OpCodes::Ldarg_1 );
106 break;
107 case 2:
108 code->Emit( Emit::OpCodes::Ldarg_2 );
109 break;
110 case 3:
111 code->Emit( Emit::OpCodes::Ldarg_3 );
112 break;
113 default:
114 if (index < 0x100)
115 code->Emit( Emit::OpCodes::Ldarg_S, (::System::Byte) index );
116 else if (index < 0x8000)
117 code->Emit( Emit::OpCodes::Ldarg_S, (::System::Int16) index );
118 else
119 code->Emit( Emit::OpCodes::Ldarg, index );
120 break;
124 void polymorphicStructNameToStructName(::System::String ^* sPolyName)
126 if ((*sPolyName)->EndsWith(">") == false)
127 return;
129 int index = (*sPolyName)->IndexOf('<');
130 OSL_ASSERT(index != -1);
131 *sPolyName = (*sPolyName)->Substring(0, index);
135 System::String^ mapUnoTypeName(System::String ^ typeName)
137 ::System::Text::StringBuilder^ buf= gcnew System::Text::StringBuilder();
138 ::System::String ^ sUnoName = ::System::String::Copy(typeName);
139 //determine if the type is a sequence and its dimensions
140 int dims= 0;
141 if (typeName->StartsWith("["))//if (usUnoName[0] == '[')
143 int index= 1;
144 while (true)
146 if (typeName[index++] == ']')//if (usUnoName[index++] == ']')
147 dims++;
148 if (typeName[index++] != '[')//usUnoName[index++] != '[')
149 break;
151 sUnoName = sUnoName->Substring(index - 1);//usUnoName = usUnoName.copy(index - 1);
153 if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoBool)))
154 buf->Append(const_cast<System::String^>(Constants::sBoolean));
155 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoChar)))
156 buf->Append(const_cast<System::String^>(Constants::sChar));
157 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoByte)))
158 buf->Append(const_cast<System::String^>(Constants::sByte));
159 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoShort)))
160 buf->Append(const_cast<System::String^>(Constants::sInt16));
161 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoUShort)))
162 buf->Append(const_cast<System::String^>(Constants::sUInt16));
163 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoLong)))
164 buf->Append(const_cast<System::String^>(Constants::sInt32));
165 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoULong)))
166 buf->Append(const_cast<System::String^>(Constants::sUInt32));
167 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoHyper)))
168 buf->Append(const_cast<System::String^>(Constants::sInt64));
169 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoUHyper)))
170 buf->Append(const_cast<System::String^>(Constants::sUInt64));
171 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoFloat)))
172 buf->Append(const_cast<System::String^>(Constants::sSingle));
173 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoDouble)))
174 buf->Append(const_cast<System::String^>(Constants::sDouble));
175 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoString)))
176 buf->Append(const_cast<System::String^>(Constants::sString));
177 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoVoid)))
178 buf->Append(const_cast<System::String^>(Constants::sVoid));
179 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoType)))
180 buf->Append(const_cast<System::String^>(Constants::sType));
181 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoXInterface)))
182 buf->Append(const_cast<System::String^>(Constants::sObject));
183 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoAny)))
185 buf->Append(const_cast<System::String^>(Constants::sAny));
187 else
189 //put "unoidl." at the beginning
190 buf->Append(const_cast<System::String^>(Constants::sUnoidl));
191 buf->Append(mapUnoPolymorphicName(sUnoName));
193 // append []
194 for (;dims--;)
195 buf->Append(const_cast<System::String^>(Constants::sBrackets));
197 return buf->ToString();
201 /** For example, there is a uno type
202 com.sun.star.Foo<char, long>.
203 The values in the type list
204 are uno types and are replaced by cli types, such as System.Char,
205 System.Int32, etc.
207 Strings can be as complicated as this
208 test.MyStruct<char,test.MyStruct<long, []string>>
210 System::String^ mapUnoPolymorphicName(System::String^ unoName)
212 int index = unoName->IndexOf('<');
213 if (index == -1)
214 return unoName;
216 System::Text::StringBuilder ^ builder =
217 gcnew System::Text::StringBuilder(unoName->Substring(0, index +1 ));
219 //Find the first occurrence of ','
220 //If the parameter is a polymorphic struct then we need to ignore everything
221 //between the brackets because it can also contain commas
222 //get the type list within < and >
223 int endIndex = unoName->Length - 1;
224 index++;
225 int cur = index;
226 int countParams = 0;
227 while (cur <= endIndex)
229 System::Char c = unoName[cur];
230 if (c == ',' || c == '>')
232 //insert a comma if needed
233 if (countParams != 0)
234 builder->Append(",");
235 countParams++;
236 System::String ^ sParam = unoName->Substring(index, cur - index);
237 //skip the comma
238 cur++;
239 //the index to the beginning of the next param
240 index = cur;
241 builder->Append(mapUnoTypeName(sParam));
243 else if (c == '<')
245 cur++;
246 //continue until the matching '>'
247 int numNested = 0;
248 for (;;cur++)
250 System::Char curChar = unoName[cur];
251 if (curChar == '<')
253 numNested ++;
255 else if (curChar == '>')
257 if (numNested > 0)
258 numNested--;
259 else
260 break;
264 cur++;
267 builder->Append((System::Char) '>');
268 return builder->ToString();
272 Assembly ^ TypeEmitter::type_resolve(
273 ::System::Object ^, ::System::ResolveEventArgs ^ args )
275 ::System::String ^ cts_name = args->Name;
276 ::System::Type ^ ret_type = nullptr;
278 iface_entry ^ entry = dynamic_cast< iface_entry ^ >(m_incomplete_ifaces[cts_name] );
279 if (nullptr != entry)
280 ret_type = entry->m_type_builder;
282 if (nullptr == ret_type)
284 sal_Int32 len = m_extra_assemblies->Length;
285 for ( sal_Int32 pos = 0; pos < len; ++pos )
287 ret_type = m_extra_assemblies[ pos ]->GetType(
288 cts_name, false /* no exc */ );
289 if (nullptr != ret_type)
291 if (g_bVerbose)
293 ::System::Console::WriteLine(
294 "> resolving type {0} from {1}.",
295 cts_name, ret_type->Assembly->FullName );
297 break;
301 if (nullptr != ret_type)
302 return ret_type->Assembly;
303 return nullptr;
307 ::System::Type ^ TypeEmitter::get_type(
308 ::System::String ^ cts_name, bool throw_exc )
310 ::System::Type ^ ret_type = m_module_builder->GetType( cts_name, false );
311 //We get the type from the ModuleBuilder even if the type is not complete
312 //but have been defined.
313 //if (ret_type == 0)
315 // iface_entry * entry = dynamic_cast< iface_entry * >(
316 // m_incomplete_ifaces->get_Item( cts_name ) );
317 // if (0 != entry)
318 // ret_type = entry->m_type_builder;
320 //try the cli_basetypes assembly
321 if (ret_type == nullptr)
323 ::System::Text::StringBuilder ^ builder = gcnew ::System::Text::StringBuilder(cts_name);
324 builder->Append(",cli_basetypes");
325 ret_type = ::System::Type::GetType(builder->ToString());
328 if (ret_type == nullptr)
332 // may call on type_resolve()
333 return ::System::Type::GetType( cts_name, throw_exc );
335 catch (::System::Exception^ exc)
337 //If the type is not found one may have forgotten to specify assemblies with
338 //additional types
339 ::System::Text::StringBuilder ^ sb = gcnew ::System::Text::StringBuilder();
340 sb->Append(gcnew ::System::String("\nThe type "));
341 sb->Append(cts_name);
342 sb->Append(gcnew ::System::String(" \n could not be found. Did you forget to "
343 "specify an additional assembly with the --reference option?\n"));
344 if (throw_exc)
345 throw gcnew ::System::Exception(sb->ToString(), exc);
348 else
350 return ret_type;
355 ::System::Type ^ TypeEmitter::get_type_Exception()
357 if (nullptr == m_type_Exception)
359 m_type_Exception = get_type(
360 "unoidl.com.sun.star.uno.Exception", false /* no exc */ );
361 if (nullptr == m_type_Exception)
363 // define hardcoded type unoidl.com.sun.star.uno.Exception
364 Emit::TypeBuilder ^ type_builder =
365 m_module_builder->DefineType(
366 "unoidl.com.sun.star.uno.Exception",
367 (TypeAttributes) (TypeAttributes::Public |
368 TypeAttributes::BeforeFieldInit |
369 TypeAttributes::AnsiClass),
370 (::System::Exception::typeid) );
371 Emit::FieldBuilder ^ field_Context = type_builder->DefineField(
372 "Context", (::System::Object::typeid),
373 FieldAttributes::Public );
374 // default .ctor
375 type_builder->DefineDefaultConstructor( c_ctor_method_attr );
376 // .ctor
377 array< ::System::Type^>^ param_types =
378 gcnew array< ::System::Type^>(2);
379 param_types[ 0 ] = ::System::String::typeid;
380 param_types[ 1 ] = ::System::Object::typeid;
381 Emit::ConstructorBuilder ^ ctor_builder =
382 type_builder->DefineConstructor(
383 c_ctor_method_attr, CallingConventions::Standard,
384 param_types );
385 ctor_builder->DefineParameter(
386 1, ParameterAttributes::In, "Message" );
387 ctor_builder->DefineParameter(
388 2, ParameterAttributes::In, "Context" );
389 Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
390 code->Emit( Emit::OpCodes::Ldarg_0 );
391 code->Emit( Emit::OpCodes::Ldarg_1 );
392 param_types = gcnew array< ::System::Type^>(1);
393 param_types[ 0 ] = ::System::String::typeid;
394 code->Emit(
395 Emit::OpCodes::Call,
396 (::System::Exception::typeid)
397 ->GetConstructor( param_types ) );
398 code->Emit( Emit::OpCodes::Ldarg_0 );
399 code->Emit( Emit::OpCodes::Ldarg_2 );
400 code->Emit( Emit::OpCodes::Stfld, field_Context );
401 code->Emit( Emit::OpCodes::Ret );
403 if (g_bVerbose)
405 ::System::Console::WriteLine(
406 "> emitting exception type "
407 "unoidl.com.sun.star.uno.Exception" );
409 m_type_Exception = type_builder->CreateType();
412 return m_type_Exception;
416 ::System::Type ^ TypeEmitter::get_type_RuntimeException()
418 if (nullptr == m_type_RuntimeException)
420 m_type_RuntimeException = get_type(
421 "unoidl.com.sun.star.uno.RuntimeException", false /* no exc */ );
422 if (nullptr == m_type_RuntimeException)
424 // define hardcoded type unoidl.com.sun.star.uno.RuntimeException
425 ::System::Type ^ type_Exception = get_type_Exception();
426 Emit::TypeBuilder ^ type_builder =
427 m_module_builder->DefineType(
428 "unoidl.com.sun.star.uno.RuntimeException",
429 (TypeAttributes) (TypeAttributes::Public |
430 TypeAttributes::BeforeFieldInit |
431 TypeAttributes::AnsiClass),
432 type_Exception );
433 // default .ctor
434 type_builder->DefineDefaultConstructor( c_ctor_method_attr );
435 // .ctor
436 array< ::System::Type^>^ param_types =
437 gcnew 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 code->Emit( Emit::OpCodes::Ldarg_2 );
452 code->Emit(
453 Emit::OpCodes::Call,
454 type_Exception->GetConstructor( param_types ) );
455 code->Emit( Emit::OpCodes::Ret );
457 if (g_bVerbose)
459 ::System::Console::WriteLine(
460 "> emitting exception type "
461 "unoidl.com.sun.star.uno.RuntimeException" );
463 m_type_RuntimeException = type_builder->CreateType();
466 return m_type_RuntimeException;
470 ::System::Type ^ TypeEmitter::get_type(
471 Reference< reflection::XConstantTypeDescription > const & xType )
473 ::System::String ^ cts_name = to_cts_name( xType->getName() );
474 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
475 if (nullptr == ret_type)
477 Reference< reflection::XConstantTypeDescription > xConstant(
478 xType, UNO_SET_THROW );
479 ::System::Object ^ constant =
480 to_cli_constant( xConstant->getConstantValue() );
481 Emit::TypeBuilder ^ type_builder =
482 m_module_builder->DefineType(
483 cts_name,
484 (TypeAttributes) (TypeAttributes::Public |
485 TypeAttributes::Sealed |
486 TypeAttributes::BeforeFieldInit |
487 TypeAttributes::AnsiClass) );
489 Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
490 cts_name->Substring( cts_name->LastIndexOf( '.' ) +1 ),
491 constant->GetType(),
492 (FieldAttributes) (FieldAttributes::Public |
493 FieldAttributes::Static |
494 FieldAttributes::Literal) );
495 field_builder->SetConstant( constant );
497 if (g_bVerbose)
499 ::System::Console::WriteLine(
500 "> emitting constant type {0}", cts_name );
502 ret_type = type_builder->CreateType();
504 return ret_type;
508 ::System::Type ^ TypeEmitter::get_type(
509 Reference< reflection::XConstantsTypeDescription > const & xType )
511 ::System::String ^ cts_name = to_cts_name( xType->getName() );
512 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
513 if (nullptr == ret_type)
515 Emit::TypeBuilder ^ type_builder =
516 m_module_builder->DefineType(
517 cts_name,
518 (TypeAttributes) (TypeAttributes::Public |
519 TypeAttributes::Sealed |
520 TypeAttributes::BeforeFieldInit |
521 TypeAttributes::AnsiClass) );
523 Sequence< Reference<
524 reflection::XConstantTypeDescription > > seq_constants(
525 xType->getConstants() );
526 Reference< reflection::XConstantTypeDescription > const * constants =
527 seq_constants.getConstArray();
528 sal_Int32 constants_length = seq_constants.getLength();
529 for ( sal_Int32 constants_pos = 0;
530 constants_pos < constants_length; ++constants_pos )
532 Reference<
533 reflection::XConstantTypeDescription > const & xConstant =
534 constants[ constants_pos ];
535 ::System::Object ^ constant =
536 to_cli_constant( xConstant->getConstantValue() );
537 ::System::String ^ uno_name =
538 ustring_to_String( xConstant->getName() );
539 Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
540 uno_name->Substring( uno_name->LastIndexOf( '.' ) +1 ),
541 constant->GetType(),
542 (FieldAttributes) (FieldAttributes::Public |
543 FieldAttributes::Static |
544 FieldAttributes::Literal) );
545 field_builder->SetConstant( constant );
548 if (g_bVerbose)
550 ::System::Console::WriteLine(
551 "> emitting constants group type {0}", cts_name );
553 ret_type = type_builder->CreateType();
555 return ret_type;
559 ::System::Type ^ TypeEmitter::get_type(
560 Reference< reflection::XEnumTypeDescription > const & xType )
562 ::System::String ^ cts_name = to_cts_name( xType->getName() );
563 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
564 if (nullptr == ret_type)
566 // workaround enum builder bug
567 Emit::TypeBuilder ^ enum_builder =
568 m_module_builder->DefineType(
569 cts_name,
570 (TypeAttributes) (TypeAttributes::Public |
571 TypeAttributes::Sealed),
572 ::System::Enum::typeid );
573 enum_builder->DefineField(
574 "value__", ::System::Int32::typeid,
575 (FieldAttributes) (FieldAttributes::Private |
576 FieldAttributes::SpecialName |
577 FieldAttributes::RTSpecialName) );
578 Sequence< OUString > seq_enum_names( xType->getEnumNames() );
579 Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() );
580 sal_Int32 enum_length = seq_enum_names.getLength();
581 OSL_ASSERT( enum_length == seq_enum_values.getLength() );
582 OUString const * enum_names = seq_enum_names.getConstArray();
583 sal_Int32 const * enum_values = seq_enum_values.getConstArray();
584 for ( sal_Int32 enum_pos = 0; enum_pos < enum_length; ++enum_pos )
586 // enum_builder->DefineLiteral(
587 // ustring_to_String( enum_names[ enum_pos ] ),
588 // __box ((::System::Int32) enum_values[ enum_pos ]) );
589 Emit::FieldBuilder ^ field_builder =
590 enum_builder->DefineField(
591 ustring_to_String( enum_names[ enum_pos ] ),
592 enum_builder,
593 (FieldAttributes) (FieldAttributes::Public |
594 FieldAttributes::Static |
595 FieldAttributes::Literal) );
596 field_builder->SetConstant(
597 ((::System::Int32) enum_values[ enum_pos ]) );
600 if (g_bVerbose)
602 ::System::Console::WriteLine(
603 "> emitting enum type {0}", cts_name );
605 ret_type = enum_builder->CreateType();
607 return ret_type;
611 ::System::Type ^ TypeEmitter::get_type(
612 Reference< reflection::XCompoundTypeDescription > const & xType )
614 OUString uno_name( xType->getName() );
615 if (TypeClass_EXCEPTION == xType->getTypeClass())
617 if ( uno_name == "com.sun.star.uno.Exception" )
619 return get_type_Exception();
621 if ( uno_name == "com.sun.star.uno.RuntimeException" )
623 return get_type_RuntimeException();
626 ::System::String ^ cts_name = to_cts_name( uno_name );
627 // if the struct is an instantiated polymorphic struct then we create the simple struct name
628 // For example:
629 // void func ([in] PolyStruct<boolean> arg);
630 //PolyStruct<boolean> will be converted to PolyStruct
631 polymorphicStructNameToStructName( & cts_name);
633 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
634 if (nullptr == ret_type)
636 Reference< reflection::XCompoundTypeDescription > xBaseType(
637 xType->getBaseType(), UNO_QUERY );
638 ::System::Type ^ base_type = (xBaseType.is()
639 ? get_type( xBaseType )
640 : ::System::Object::typeid);
641 Emit::TypeBuilder ^ type_builder =
642 m_module_builder->DefineType(
643 cts_name,
644 (TypeAttributes) (TypeAttributes::Public |
645 TypeAttributes::BeforeFieldInit |
646 TypeAttributes::AnsiClass),
647 base_type );
650 // insert to be completed
651 struct_entry ^ entry = gcnew struct_entry();
652 xType->acquire();
653 entry->m_xType = xType.get();
654 entry->m_type_builder = type_builder;
655 entry->m_base_type = base_type;
656 m_incomplete_structs->Add( cts_name, entry );
658 // type is incomplete
659 ret_type = type_builder;
662 //In case of an instantiated polymorphic struct we want to return a
663 //uno.PolymorphicType (inherits Type) rather than Type. This is needed for constructing
664 //the service code. We can only do that if the struct is completed.
665 if (m_generated_structs[cts_name])
667 Reference< reflection::XStructTypeDescription> xStructTypeDesc(
668 xType, UNO_QUERY);
670 if (xStructTypeDesc.is())
672 Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments();
673 sal_Int32 numTypes = seqTypeArgs.getLength();
674 if (numTypes > 0)
676 //it is an instantiated polymorphic struct
677 ::System::String ^ sCliName = mapUnoTypeName(ustring_to_String(xType->getName()));
678 ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName);
682 return ret_type;
686 ::System::Type ^ TypeEmitter::get_type(
687 Reference< reflection::XInterfaceTypeDescription2 > const & xType )
689 OUString uno_name( xType->getName() );
690 if ( uno_name == "com.sun.star.uno.XInterface" )
692 return ::System::Object::typeid;
695 ::System::String ^ cts_name = to_cts_name( xType->getName() );
696 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
697 if (nullptr == ret_type)
699 Emit::TypeBuilder ^ type_builder;
701 TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
702 TypeAttributes::Interface |
703 TypeAttributes::Abstract |
704 TypeAttributes::AnsiClass);
706 std::vector<Reference<reflection::XInterfaceTypeDescription2> > vecBaseTypes;
707 Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes =
708 xType->getBaseTypes();
709 if (seqBaseTypes.getLength() > 0)
711 for (int i = 0; i < seqBaseTypes.getLength(); i++)
713 Reference<reflection::XInterfaceTypeDescription2> xIfaceTd =
714 resolveInterfaceTypedef(seqBaseTypes[i]);
716 if ( xIfaceTd->getName() != "com.sun.star.uno.XInterface" )
718 vecBaseTypes.push_back(xIfaceTd);
722 array< ::System::Type^>^ base_interfaces =
723 gcnew array< ::System::Type^>( vecBaseTypes.size() );
725 int index = 0;
726 for (auto const & vecBaseType : vecBaseTypes)
728 base_interfaces[ index ] = get_type( vecBaseType );
729 ++index;
731 type_builder = m_module_builder->DefineType(
732 cts_name, attr, nullptr, base_interfaces );
734 else
736 ::System::Console::WriteLine(
737 "warning: IDL interface {0} is not derived from "
738 "com.sun.star.uno.XInterface!",
739 ustring_to_String( uno_name ) );
741 type_builder = m_module_builder->DefineType( cts_name, attr );
744 // insert to be completed
745 iface_entry ^ entry = gcnew iface_entry();
746 xType->acquire();
747 entry->m_xType = xType.get();
748 entry->m_type_builder = type_builder;
749 m_incomplete_ifaces->Add( cts_name, entry );
751 // type is incomplete
752 ret_type = type_builder;
754 return ret_type;
758 ::System::Type ^ TypeEmitter::get_type(
759 Reference< reflection::XServiceTypeDescription2 > const & xType )
761 if (xType->isSingleInterfaceBased() == sal_False)
762 return nullptr;
764 System::String ^ cts_name = to_cts_name( xType->getName() );
765 System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
766 if (ret_type != nullptr)
767 return ret_type;
769 TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
770 TypeAttributes::Sealed |
771 TypeAttributes::BeforeFieldInit |
772 TypeAttributes::AnsiClass);
774 Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
775 cts_name, attr);
777 // insert to be completed
778 service_entry ^ entry = gcnew service_entry();
779 xType->acquire();
780 entry->m_xType = xType.get();
781 entry->m_type_builder = type_builder;
782 m_incomplete_services->Add(cts_name,entry );
784 return type_builder;
787 ::System::Type ^ TypeEmitter::get_type(
788 Reference<reflection::XSingletonTypeDescription2 > const & xType )
790 if (xType->isInterfaceBased() == sal_False)
791 return nullptr;
793 ::System::String^ cts_name = to_cts_name( xType->getName() );
794 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
795 if (ret_type != nullptr)
796 return ret_type;
798 TypeAttributes attr = static_cast<TypeAttributes>(
799 TypeAttributes::Public |
800 TypeAttributes::Sealed |
801 TypeAttributes::BeforeFieldInit |
802 TypeAttributes::AnsiClass);
804 Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
805 cts_name, attr);
807 // insert to be completed
808 singleton_entry ^ entry = gcnew singleton_entry();
809 xType->acquire();
810 entry->m_xType = xType.get();
811 entry->m_type_builder = type_builder;
812 m_incomplete_singletons->Add(cts_name,entry );
814 return type_builder;
819 ::System::Type ^ TypeEmitter::complete_iface_type( iface_entry ^ entry )
821 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
822 reflection::XInterfaceTypeDescription2 * xType = entry->m_xType;
824 Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes( xType->getBaseTypes() );
825 if (seqBaseTypes.getLength() > 0)
827 for (int i = 0; i < seqBaseTypes.getLength(); i++)
829 //make sure we get the interface rather than a typedef
830 Reference<reflection::XInterfaceTypeDescription2> aBaseType =
831 resolveInterfaceTypedef( seqBaseTypes[i]);
833 if ( aBaseType->getName() != "com.sun.star.uno.XInterface" )
835 ::System::String ^ basetype_name = to_cts_name( aBaseType->getName() );
836 iface_entry ^ base_entry = dynamic_cast< iface_entry ^ >(
837 m_incomplete_ifaces[basetype_name] );
838 if (nullptr != base_entry)
840 // complete uncompleted base type first
841 complete_iface_type( base_entry );
847 Sequence<
848 Reference< reflection::XInterfaceMemberTypeDescription > > seq_members(
849 xType->getMembers() );
850 Reference< reflection::XInterfaceMemberTypeDescription > const * members =
851 seq_members.getConstArray();
852 sal_Int32 members_length = seq_members.getLength();
853 for ( sal_Int32 members_pos = 0;
854 members_pos < members_length; ++members_pos )
856 Reference<
857 reflection::XInterfaceMemberTypeDescription > const & xMember =
858 members[ members_pos ];
859 Sequence< Reference< reflection::XTypeDescription > > seq_exceptions;
860 Emit::MethodBuilder ^ method_builder;
862 MethodAttributes c_method_attr = (MethodAttributes)
863 (MethodAttributes::Public |
864 MethodAttributes::Abstract |
865 MethodAttributes::Virtual |
866 MethodAttributes::NewSlot |
867 MethodAttributes::HideBySig);
869 if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass())
871 Reference< reflection::XInterfaceMethodTypeDescription > xMethod(
872 xMember, UNO_QUERY_THROW );
874 Sequence<
875 Reference< reflection::XMethodParameter > > seq_parameters(
876 xMethod->getParameters() );
877 sal_Int32 params_length = seq_parameters.getLength();
878 array< ::System::Type^>^ param_types =
879 gcnew array< ::System::Type^>( params_length );
880 Reference< reflection::XMethodParameter > const * parameters =
881 seq_parameters.getConstArray();
882 // first determine all types
883 //Make the first param type as return type
884 sal_Int32 params_pos = 0;
885 for ( ; params_pos < params_length; ++params_pos )
887 Reference< reflection::XMethodParameter > const & xParam =
888 parameters[ params_pos ];
889 ::System::Type ^ param_type = get_type( xParam->getType() );
890 ::System::String ^ param_type_name = param_type->FullName;
891 if (xParam->isOut())
893 param_type = get_type(
894 ::System::String::Concat(
895 param_type_name, "&" ), true );
897 param_types[ xParam->getPosition() ] = param_type;
901 // create method
902 // if (tb)
903 // method_builder = type_builder->DefineMethod(
904 // ustring_to_String( xMethod->getMemberName() ),
905 // c_method_attr, tb,
906 // param_types );
907 // else
908 method_builder = type_builder->DefineMethod(
909 ustring_to_String( xMethod->getMemberName() ),
910 c_method_attr, get_type( xMethod->getReturnType() ),
911 param_types );
912 // then define parameter infos
913 params_pos = 0;
914 for ( ; params_pos < params_length; ++params_pos )
916 Reference< reflection::XMethodParameter > const & xParam =
917 parameters[ params_pos ];
918 long param_flags = 0;
919 if (xParam->isIn())
920 param_flags |= (long)ParameterAttributes::In;
921 if (xParam->isOut())
922 param_flags |= (long)ParameterAttributes::Out;
923 OSL_ASSERT( 0 != param_flags );
924 method_builder->DefineParameter(
925 xParam->getPosition() +1 /* starts with 1 */,
926 (ParameterAttributes) param_flags,
927 ustring_to_String( xParam->getName() ) );
929 //Apply attribute TypeParametersAttribute to return value if it
930 //is a parameterized Type. Currently only structs can have parameters.
931 Reference<reflection::XStructTypeDescription> xReturnStruct(
932 xMethod->getReturnType(), UNO_QUERY);
934 if (xReturnStruct.is())
936 Sequence<Reference<reflection::XTypeDescription> > seq_type_args =
937 xReturnStruct->getTypeArguments();
938 if (seq_type_args.getLength() != 0)
940 //get th ctor of the attribute
941 array< ::System::Type^>^ arCtor = {::System::Type::GetType("System.Type[]")};
942 //Get the arguments for the attribute's ctor
943 Reference<reflection::XTypeDescription> const * arXTypeArgs =
944 seq_type_args.getConstArray();
945 int numTypes = seq_type_args.getLength();
946 array< ::System::Type^>^ arCtsTypes = gcnew array< ::System::Type^>(numTypes);
947 for (int i = 0; i < numTypes; i++)
948 arCtsTypes[i] = get_type(arXTypeArgs[i]);
949 array< ::System::Object^>^ arArgs = {arCtsTypes};
951 Emit::CustomAttributeBuilder ^ attrBuilder =
952 gcnew Emit::CustomAttributeBuilder(
953 ::uno::TypeArgumentsAttribute::typeid
954 ->GetConstructor( arCtor),
955 arArgs);
957 method_builder->SetCustomAttribute(attrBuilder);
961 //define UNO exception attribute (exceptions)--------------------------------------
962 Emit::CustomAttributeBuilder^ attrBuilder =
963 get_iface_method_exception_attribute(xMethod);
964 if (attrBuilder != nullptr)
965 method_builder->SetCustomAttribute(attrBuilder);
967 // oneway attribute
968 if (xMethod->isOneway())
970 array< ::System::Type^>^ arCtorOneway = gcnew array< ::System::Type^>(0);
971 array< ::System::Object^>^ arArgs = gcnew array< ::System::Object^>(0);
972 Emit::CustomAttributeBuilder ^ attrBuilder =
973 gcnew Emit::CustomAttributeBuilder(
974 ::uno::OnewayAttribute::typeid->GetConstructor( arCtorOneway),
975 arArgs);
976 method_builder->SetCustomAttribute(attrBuilder);
979 else // attribute
981 OSL_ASSERT(
982 TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() );
983 Reference<
984 reflection::XInterfaceAttributeTypeDescription2 > xAttribute(
985 xMember, UNO_QUERY_THROW );
987 MethodAttributes c_property_method_attr = (MethodAttributes)
988 (c_method_attr | MethodAttributes::SpecialName);
990 ::System::Type ^ attribute_type = get_type( xAttribute->getType() );
991 array< ::System::Type^>^ parameters =
992 gcnew array< ::System::Type^> ( 0 );
994 Emit::PropertyBuilder ^ property_builder =
995 type_builder->DefineProperty(
996 ustring_to_String( xAttribute->getMemberName() ),
997 PropertyAttributes::None,
998 attribute_type, parameters );
1000 //set BoundAttribute, if necessary
1001 if (xAttribute->isBound())
1003 ConstructorInfo ^ ctorBoundAttr =
1004 ::uno::BoundAttribute::typeid->GetConstructor(
1005 gcnew array<System::Type^>(0));
1006 Emit::CustomAttributeBuilder ^ attrBuilderBound =
1007 gcnew Emit::CustomAttributeBuilder(
1008 ctorBoundAttr, gcnew array< ::System::Object^>(0));
1009 property_builder->SetCustomAttribute(attrBuilderBound);
1012 // getter
1013 Emit::MethodBuilder ^ method_builder =
1014 type_builder->DefineMethod(
1015 ustring_to_String( "get_" +
1016 xAttribute->getMemberName() ),
1017 c_property_method_attr, attribute_type, parameters );
1019 //define UNO exception attribute (exceptions)--------------------------------------
1020 Emit::CustomAttributeBuilder^ attrBuilder =
1021 get_exception_attribute(xAttribute->getGetExceptions());
1022 if (attrBuilder != nullptr)
1023 method_builder->SetCustomAttribute(attrBuilder);
1025 property_builder->SetGetMethod( method_builder );
1027 if (! xAttribute->isReadOnly())
1029 // setter
1030 parameters = gcnew array< ::System::Type^> ( 1 );
1031 parameters[ 0 ] = attribute_type;
1032 method_builder =
1033 type_builder->DefineMethod(
1034 ustring_to_String( "set_" +
1035 xAttribute->getMemberName() ),
1036 c_property_method_attr, nullptr, parameters );
1037 // define parameter info
1038 method_builder->DefineParameter(
1039 1 /* starts with 1 */, ParameterAttributes::In, "value" );
1040 //define UNO exception attribute (exceptions)--------------------------------------
1041 Emit::CustomAttributeBuilder^ attrBuilder =
1042 get_exception_attribute(xAttribute->getSetExceptions());
1043 if (attrBuilder != nullptr)
1044 method_builder->SetCustomAttribute(attrBuilder);
1046 property_builder->SetSetMethod( method_builder );
1051 // remove from incomplete types map
1052 ::System::String ^ cts_name = type_builder->FullName;
1053 m_incomplete_ifaces->Remove( cts_name );
1054 xType->release();
1056 if (g_bVerbose)
1058 ::System::Console::WriteLine(
1059 "> emitting interface type {0}", cts_name );
1061 return type_builder->CreateType();
1064 ::System::Type ^ TypeEmitter::complete_struct_type( struct_entry ^ entry )
1066 OSL_ASSERT(entry);
1067 ::System::String ^ cts_name = entry->m_type_builder->FullName;
1069 //Polymorphic struct, define uno.TypeParametersAttribute
1070 //A polymorphic struct cannot have a basetype.
1071 //When we create the template of the struct then we have no exact types
1072 //and the name does not contain a parameter list
1073 Sequence< OUString > seq_type_parameters;
1074 Reference< reflection::XStructTypeDescription> xStructTypeDesc(
1075 entry->m_xType, UNO_QUERY);
1076 if (xStructTypeDesc.is())
1078 seq_type_parameters = xStructTypeDesc->getTypeParameters();
1079 int numTypes = 0;
1080 if ((numTypes = seq_type_parameters.getLength()) > 0)
1082 array< ::System::Object^>^ aArg = gcnew array< ::System::Object^>(numTypes);
1083 for (int i = 0; i < numTypes; i++)
1084 aArg[i] = ustring_to_String(seq_type_parameters.getConstArray()[i]);
1085 array< ::System::Object^>^ args = {aArg};
1087 array< ::System::Type^>^ arTypesCtor =
1088 {::System::Type::GetType("System.String[]")};
1089 Emit::CustomAttributeBuilder ^ attrBuilder =
1090 gcnew Emit::CustomAttributeBuilder(
1091 ::uno::TypeParametersAttribute::typeid->GetConstructor(arTypesCtor),
1092 args);
1093 entry->m_type_builder->SetCustomAttribute(attrBuilder);
1097 // optional: lookup base type whether generated entry of this session
1098 struct_entry ^ base_type_entry = nullptr;
1099 if (nullptr != entry->m_base_type)
1101 //ToDo maybe get from incomplete structs
1102 base_type_entry =
1103 dynamic_cast< struct_entry ^ >(
1104 m_generated_structs[
1105 entry->m_base_type->FullName ] );
1108 // members
1109 Sequence< Reference< reflection::XTypeDescription > > seq_members(
1110 entry->m_xType->getMemberTypes() );
1111 Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() );
1112 sal_Int32 members_length = seq_members.getLength();
1113 OSL_ASSERT( seq_member_names.getLength() == members_length );
1114 //check if we have a XTypeDescription for every member. If not then the user may
1115 //have forgotten to specify additional rdbs with the --extra option.
1116 Reference< reflection::XTypeDescription > const * pseq_members =
1117 seq_members.getConstArray();
1118 OUString const * pseq_member_names =
1119 seq_member_names.getConstArray();
1120 for (int i = 0; i < members_length; i++)
1122 const OUString sType(entry->m_xType->getName());
1123 const OUString sMemberName(pseq_member_names[i]);
1124 if ( ! pseq_members[i].is())
1125 throw RuntimeException("Missing type description . Check if you need to "
1126 "specify additional RDBs with the --extra option. Type missing for: " + sType +
1127 "::" + sMemberName,0);
1130 sal_Int32 all_members_length = 0;
1131 sal_Int32 member_pos;
1132 sal_Int32 type_param_pos = 0;
1134 // collect base types; wrong order
1135 ::System::Collections::ArrayList ^ base_types_list =
1136 gcnew ::System::Collections::ArrayList( 3 /* initial capacity */ );
1137 for (::System::Type ^ base_type_pos = entry->m_base_type;
1138 ! base_type_pos->Equals( ::System::Object::typeid );
1139 base_type_pos = base_type_pos->BaseType )
1141 base_types_list->Add( base_type_pos );
1142 if (base_type_pos->Equals( ::System::Exception::typeid ))
1144 // special Message member
1145 all_members_length += 1;
1146 break; // don't include System.Exception base classes
1148 else
1150 //ensure the base type is complete. Otherwise GetFields won't work
1151 get_complete_struct(base_type_pos->FullName);
1152 all_members_length +=
1153 base_type_pos->GetFields(
1154 (BindingFlags) (BindingFlags::Instance |
1155 BindingFlags::Public |
1156 BindingFlags::DeclaredOnly) )
1157 ->Length;
1161 // create all_members arrays; right order
1162 array< ::System::String^>^ all_member_names =
1163 gcnew array< ::System::String^> (all_members_length + members_length );
1164 array< ::System::Type^>^ all_param_types =
1165 gcnew array< ::System::Type^> (all_members_length + members_length );
1166 member_pos = 0;
1167 for ( sal_Int32 pos = base_types_list->Count; pos--; )
1169 ::System::Type ^ base_type = safe_cast< ::System::Type ^ >(
1170 base_types_list[pos] );
1171 if (base_type->Equals( ::System::Exception::typeid ))
1173 all_member_names[ member_pos ] = "Message";
1174 all_param_types[ member_pos ] = ::System::String::typeid;
1175 ++member_pos;
1177 else
1179 ::System::String ^ base_type_name = base_type->FullName;
1181 //ToDo m_generated_structs?
1182 struct_entry ^ entry =
1183 dynamic_cast< struct_entry ^ >(
1184 m_generated_structs[base_type_name] );
1185 if (nullptr == entry)
1187 // complete type
1188 array<FieldInfo^>^ fields =
1189 base_type->GetFields(
1190 (BindingFlags) (BindingFlags::Instance |
1191 BindingFlags::Public |
1192 BindingFlags::DeclaredOnly) );
1193 sal_Int32 len = fields->Length;
1194 for ( sal_Int32 pos = 0; pos < len; ++pos )
1196 FieldInfo ^ field = fields[ pos ];
1197 all_member_names[ member_pos ] = field->Name;
1198 all_param_types[ member_pos ] = field->FieldType;
1199 ++member_pos;
1202 else // generated during this session:
1203 // members may be incomplete ifaces
1205 sal_Int32 len = entry->m_member_names->Length;
1206 for ( sal_Int32 pos = 0; pos < len; ++pos )
1208 all_member_names[ member_pos ] =
1209 entry->m_member_names[ pos ];
1210 all_param_types[ member_pos ] =
1211 entry->m_param_types[ pos ];
1212 ++member_pos;
1217 OSL_ASSERT( all_members_length == member_pos );
1219 // build up entry
1220 // struct_entry * entry = new struct_entry();
1221 entry->m_member_names = gcnew array< ::System::String^> ( members_length );
1222 entry->m_param_types = gcnew array< ::System::Type^> ( members_length );
1224 // add members
1225 array<Emit::FieldBuilder^>^ members = gcnew array<Emit::FieldBuilder^> ( members_length );
1226 //Reference< reflection::XTypeDescription > const * pseq_members =
1227 // seq_members.getConstArray();
1228 //OUString const * pseq_member_names =
1229 // seq_member_names.getConstArray();
1231 int curParamIndex = 0; //count the fields which have parameterized types
1232 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1234 ::System::String ^ field_name =
1235 ustring_to_String( pseq_member_names[ member_pos ] );
1236 ::System::Type ^ field_type;
1237 //Special handling of struct parameter types
1238 bool bParameterizedType = false;
1239 if (pseq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN)
1241 bParameterizedType = true;
1242 if (type_param_pos < seq_type_parameters.getLength())
1244 field_type = ::System::Object::typeid;
1245 type_param_pos++;
1247 else
1249 throw RuntimeException(
1250 "unexpected member type in " + entry->m_xType->getName() );
1253 else
1255 field_type = get_type( pseq_members[ member_pos ] );
1257 if (field_type->IsArray
1258 && m_incomplete_structs[cts_name]
1259 && !field_type->Namespace->Equals("System"))
1261 //Find the value type. In case of sequence<sequence< ... > > find the actual value type
1262 ::System::Type ^ value = field_type;
1263 while ((value = value->GetElementType())->IsArray);
1264 //If the value type is a struct then make sure it is fully created.
1265 get_complete_struct(value->FullName);
1266 field_type = get_type(pseq_members[member_pos]);
1269 members[ member_pos ] =
1270 entry->m_type_builder->DefineField(
1271 field_name, field_type, FieldAttributes::Public );
1273 //parameterized type (polymorphic struct) ?
1274 if (bParameterizedType && xStructTypeDesc.is())
1276 //get the name
1277 OSL_ASSERT(seq_type_parameters.getLength() > curParamIndex);
1278 ::System::String^ sTypeName = ustring_to_String(
1279 seq_type_parameters.getConstArray()[curParamIndex++]);
1280 array< ::System::Object^>^ args = {sTypeName};
1281 //set ParameterizedTypeAttribute
1282 array< ::System::Type^>^ arCtorTypes = {::System::String::typeid};
1284 Emit::CustomAttributeBuilder ^ attrBuilder =
1285 gcnew Emit::CustomAttributeBuilder(
1286 ::uno::ParameterizedTypeAttribute::typeid
1287 ->GetConstructor(arCtorTypes),
1288 args);
1290 members[member_pos]->SetCustomAttribute(attrBuilder);
1292 // add to all_members
1293 all_member_names[ all_members_length + member_pos ] = field_name;
1294 all_param_types[ all_members_length + member_pos ] = field_type;
1295 // add to entry
1296 entry->m_member_names[ member_pos ] = field_name;
1297 entry->m_param_types[ member_pos ] = field_type;
1299 all_members_length += members_length;
1301 // default .ctor
1302 Emit::ConstructorBuilder ^ ctor_builder =
1303 entry->m_type_builder->DefineConstructor(
1304 c_ctor_method_attr, CallingConventions::Standard,
1305 gcnew array< ::System::Type^> ( 0 ) );
1306 Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
1307 code->Emit( Emit::OpCodes::Ldarg_0 );
1308 code->Emit(
1309 Emit::OpCodes::Call,
1310 nullptr == base_type_entry
1311 ? entry->m_base_type->GetConstructor( gcnew array< ::System::Type^> ( 0 ) )
1312 : base_type_entry->m_default_ctor );
1313 // default initialize members
1314 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1316 FieldInfo ^ field = members[ member_pos ];
1317 ::System::Type ^ field_type = field->FieldType;
1318 // ::System::Type * new_field_type = m_module_builder->GetType(field_type->FullName, false);
1319 // default initialize:
1320 // string, type, enum, sequence, struct, exception, any
1321 if (field_type->Equals( ::System::String::typeid ))
1323 code->Emit( Emit::OpCodes::Ldarg_0 );
1324 code->Emit( Emit::OpCodes::Ldstr, "" );
1325 code->Emit( Emit::OpCodes::Stfld, field );
1327 else if (field_type->Equals( ::System::Type::typeid ))
1329 code->Emit( Emit::OpCodes::Ldarg_0 );
1330 code->Emit(
1331 Emit::OpCodes::Ldtoken, ::System::Void::typeid );
1332 code->Emit(
1333 Emit::OpCodes::Call, m_method_info_Type_GetTypeFromHandle );
1334 code->Emit( Emit::OpCodes::Stfld, field );
1336 else if (field_type->IsArray)
1338 code->Emit( Emit::OpCodes::Ldarg_0 );
1339 code->Emit( Emit::OpCodes::Ldc_I4_0 );
1340 code->Emit(
1341 Emit::OpCodes::Newarr, field_type->GetElementType() );
1342 code->Emit( Emit::OpCodes::Stfld, field );
1344 else if (field_type->IsValueType)
1346 if (field_type->FullName->Equals( "uno.Any" ))
1348 code->Emit( Emit::OpCodes::Ldarg_0 );
1349 code->Emit( Emit::OpCodes::Ldsfld, ::uno::Any::typeid->GetField("VOID"));
1350 code->Emit( Emit::OpCodes::Stfld, field );
1353 else if (field_type->IsClass)
1355 /* may be XInterface */
1356 if (! field_type->Equals( ::System::Object::typeid ))
1358 // struct, exception
1359 //make sure the struct is already complete.
1360 get_complete_struct(field_type->FullName);
1361 code->Emit( Emit::OpCodes::Ldarg_0 );
1362 code->Emit(
1363 Emit::OpCodes::Newobj,
1364 //GetConstructor requires that the member types of the object which is to be constructed are already known.
1365 field_type->GetConstructor(
1366 gcnew array< ::System::Type^> ( 0 ) ) );
1367 code->Emit( Emit::OpCodes::Stfld, field );
1371 code->Emit( Emit::OpCodes::Ret );
1372 entry->m_default_ctor = ctor_builder;
1374 // parameterized .ctor including all base members
1375 ctor_builder = entry->m_type_builder->DefineConstructor(
1376 c_ctor_method_attr, CallingConventions::Standard, all_param_types );
1377 for ( member_pos = 0; member_pos < all_members_length; ++member_pos )
1379 ctor_builder->DefineParameter(
1380 member_pos +1 /* starts with 1 */, ParameterAttributes::In,
1381 all_member_names[ member_pos ] );
1383 code = ctor_builder->GetILGenerator();
1384 // call base .ctor
1385 code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1386 sal_Int32 base_members_length = all_members_length - members_length;
1387 array< ::System::Type^>^ param_types =
1388 gcnew array< ::System::Type^> ( base_members_length );
1389 for ( member_pos = 0; member_pos < base_members_length; ++member_pos )
1391 emit_ldarg( code, member_pos +1 );
1392 param_types[ member_pos ] = all_param_types[ member_pos ];
1394 code->Emit(
1395 Emit::OpCodes::Call,
1396 nullptr == base_type_entry
1397 ? entry->m_base_type->GetConstructor( param_types )
1398 : base_type_entry->m_ctor );
1399 // initialize members
1400 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1402 code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1403 emit_ldarg( code, member_pos + base_members_length +1 );
1404 code->Emit( Emit::OpCodes::Stfld, members[ member_pos ] );
1406 code->Emit( Emit::OpCodes::Ret );
1407 entry->m_ctor = ctor_builder;
1409 if (g_bVerbose)
1411 ::System::Console::WriteLine(
1412 "> emitting {0} type {1}",
1413 TypeClass_STRUCT == entry->m_xType->getTypeClass()
1414 ? "struct"
1415 : "exception",
1416 cts_name);
1418 // new entry
1419 m_generated_structs->Add(cts_name, entry );
1420 ::System::Type ^ ret_type = entry->m_type_builder->CreateType();
1422 // remove from incomplete types map
1423 m_incomplete_structs->Remove( cts_name );
1424 entry->m_xType->release();
1426 if (g_bVerbose)
1428 ::System::Console::WriteLine(
1429 "> emitting struct type {0}", cts_name);
1431 return ret_type;
1434 //Examples of generated code
1435 // public static XWeak constructor1(XComponentContext ctx)
1436 // {
1437 // XMultiComponentFactory factory = ctx.getServiceManager();
1438 // if (factory == null)
1439 // throw new com.sun.star.uno.DeploymentException("bla", null);
1440 // return (XWeak) factory.createInstanceWithContext("service_specifier", ctx);
1441 // }
1442 // public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c)
1443 // {
1444 // XMultiComponentFactory factory = ctx.getServiceManager();
1445 // if (factory == null)
1446 // throw new com.sun.star.uno.DeploymentException("bla", null);
1447 // Any[] arAny = new Any[3];
1448 // arAny[0] = new Any(typeof(int), a);
1449 // arAny[1] = new Any(typeof(int), b);
1450 // arAny[2] = new Any(c.Type, c.Value);
1451 // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx);
1452 // }
1453 // Notice that an any parameter is NOT wrapped by another any. Instead the new any is created with the type and value
1454 // of the parameter.
1456 // public static XWeak constructor3(XComponentContext ctx, params Any[] c)
1457 // {
1458 // XMultiComponentFactory factory = ctx.getServiceManager();
1459 // if (factory == null)
1460 // throw new com.sun.star.uno.DeploymentException("bla", null);
1461 // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx);
1462 // }
1463 ::System::Type ^ TypeEmitter::complete_service_type(service_entry ^ entry)
1465 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
1466 reflection::XServiceTypeDescription2 * xServiceType = entry->m_xType;
1468 //Create the private default constructor
1469 Emit::ConstructorBuilder^ ctor_builder =
1470 type_builder->DefineConstructor(
1471 (MethodAttributes) (MethodAttributes::Private |
1472 MethodAttributes::HideBySig |
1473 MethodAttributes::SpecialName |
1474 MethodAttributes::RTSpecialName),
1475 CallingConventions::Standard, nullptr);
1477 Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator();
1478 ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1479 ilGen->Emit(
1480 Emit::OpCodes::Call,
1481 type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
1482 ilGen->Emit( Emit::OpCodes::Ret );
1485 //Create the service constructors.
1486 //obtain the interface which makes up this service, it is the return
1487 //type of the constructor functions
1488 Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
1489 xServiceType->getInterface(), UNO_QUERY);
1490 if (xIfaceType.is () == sal_False)
1491 xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface());
1492 System::Type ^ retType = get_type(xIfaceType);
1494 //Create the ConstructorInfo for a DeploymentException
1495 ::System::Type ^ typeDeploymentExc =
1496 get_type("unoidl.com.sun.star.uno.DeploymentException", true);
1498 array< ::System::Type^>^ arTypeCtor = {::System::String::typeid,
1499 ::System::Object::typeid};
1500 ::System::Reflection::ConstructorInfo ^ ctorDeploymentException =
1501 typeDeploymentExc->GetConstructor(arTypeCtor);
1503 Sequence<Reference<reflection::XServiceConstructorDescription> > seqCtors =
1504 xServiceType->getConstructors();
1506 ::System::Type ^ type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception", true);
1508 for (int i = seqCtors.getLength() - 1; i >= 0; i--)
1510 bool bParameterArray = false;
1511 ::System::Type ^ typeAny = ::uno::Any::typeid;
1512 const Reference<reflection::XServiceConstructorDescription> & ctorDes =
1513 seqCtors[i];
1514 //obtain the parameter types
1515 Sequence<Reference<reflection::XParameter> > seqParams =
1516 ctorDes->getParameters();
1517 Reference<reflection::XParameter> const * arXParams = seqParams.getConstArray();
1518 sal_Int32 cParams = seqParams.getLength();
1519 array< ::System::Type^>^ arTypeParameters = gcnew array< ::System::Type^> (cParams + 1);
1520 arTypeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1521 for (int iparam = 0; iparam != cParams; iparam++)
1523 if (arXParams[iparam]->isRestParameter())
1524 arTypeParameters[iparam + 1] = array< ::uno::Any>::typeid;
1525 else
1526 arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType());
1528 //The array arTypeParameters can contain:
1529 //System.Type and uno.PolymorphicType.
1530 //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem.
1531 //The exception will read something like no on information for parameter # d
1532 //Maybe we need no override another Type method in PolymorphicType ...
1533 //Until we have figured this out, we will create another array of System.Type which
1534 //we pass on to DefineMethod.
1535 array< ::System::Type^>^ arParamTypes = gcnew array< ::System::Type^> (cParams + 1);
1536 // arParamTypes[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1537 for (int i = 0; i < cParams + 1; i++)
1539 ::uno::PolymorphicType ^ pT = dynamic_cast< ::uno::PolymorphicType ^ >(arTypeParameters[i]);
1540 if (pT)
1541 arParamTypes[i] = pT->OriginalType;
1542 else
1543 arParamTypes[i] = arTypeParameters[i];
1545 //define method
1546 System::String ^ ctorName;
1547 if (ctorDes->isDefaultConstructor())
1548 ctorName = gcnew ::System::String("create");
1549 else
1550 ctorName = ustring_to_String(ctorDes->getName());
1551 Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
1552 ctorName,
1553 static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
1554 MethodAttributes::Static),
1555 retType,
1556 // arTypeParameters);
1557 arParamTypes);
1559 //define UNO exception attribute (exceptions)--------------------------------------
1560 Emit::CustomAttributeBuilder^ attrBuilder = get_service_exception_attribute(ctorDes);
1561 if (attrBuilder != nullptr)
1562 method_builder->SetCustomAttribute(attrBuilder);
1565 //define parameter attributes (paramarray), names etc.
1566 //The first parameter is the XComponentContext, which cannot be obtained
1567 //from reflection.
1568 //The context is not part of the idl description
1569 method_builder->DefineParameter(
1570 1, ParameterAttributes::In, "the_context");
1572 array<Emit::ParameterBuilder^>^ arParameterBuilder =
1573 gcnew array<Emit::ParameterBuilder^> (cParams);
1574 for (int iparam = 0; iparam != cParams; iparam++)
1576 Reference<reflection::XParameter> const & aParam = arXParams[iparam];
1577 ::System::String ^ sParamName = ustring_to_String(aParam->getName());
1579 arParameterBuilder[iparam] = method_builder->DefineParameter(
1580 iparam + 2, ParameterAttributes::In, sParamName);
1582 if (aParam->isRestParameter())
1584 bParameterArray = true;
1585 //set the ParameterArrayAttribute
1586 ::System::Reflection::ConstructorInfo^ ctor_info =
1587 System::ParamArrayAttribute::typeid->GetConstructor(
1588 gcnew array< ::System::Type^>(0));
1589 Emit::CustomAttributeBuilder ^ attr_builder =
1590 gcnew Emit::CustomAttributeBuilder(ctor_info, gcnew array< ::System::Object^>(0));
1591 arParameterBuilder[iparam]->SetCustomAttribute(attr_builder);
1592 break;
1596 Emit::ILGenerator ^ ilGen = method_builder->GetILGenerator();
1598 //Define locals ---------------------------------
1599 //XMultiComponentFactory
1600 Emit::LocalBuilder^ local_factory =
1601 ilGen->DeclareLocal(
1602 get_type("unoidl.com.sun.star.lang.XMultiComponentFactory", true));
1604 //The return type
1605 Emit::LocalBuilder^ local_return_val =
1606 ilGen->DeclareLocal(retType);
1608 //Obtain the XMultiComponentFactory and throw an exception if we do not get one
1609 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1611 ::System::Reflection::MethodInfo ^ methodGetServiceManager = get_type(
1612 "unoidl.com.sun.star.uno.XComponentContext", true)
1613 ->GetMethod("getServiceManager");
1614 ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager);
1615 ilGen->Emit(Emit::OpCodes::Stloc, local_factory);
1616 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1617 Emit::Label label1 = ilGen->DefineLabel();
1618 ilGen->Emit(Emit::OpCodes::Brtrue, label1);
1619 //The string for the exception
1620 ::System::Text::StringBuilder ^ strbuilder = gcnew ::System::Text::StringBuilder(256);
1621 strbuilder->Append("The service ");
1622 strbuilder->Append(to_cts_name(xServiceType->getName()));
1623 strbuilder->Append(" could not be created. The context failed to supply the service manager.");
1625 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1626 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1627 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1628 ilGen->Emit(Emit::OpCodes::Throw);
1629 ilGen->MarkLabel(label1);
1631 //We create a try/ catch around the createInstanceWithContext, etc. functions
1632 //There are 3 cases
1633 //1. function do not specify exceptions. Then RuntimeExceptions are re-thrown and other
1634 // exceptions produce a DeploymentException.
1635 //2. function specify Exception. Then all exceptions fly through
1636 //3. function specifies exceptions but no Exception. Then these are rethrown
1637 // and other exceptions, except RuntimeException, produce a deployment exception.
1638 //In case there are no parameters we call
1639 //XMultiComponentFactory.createInstanceWithContext
1641 ::System::Collections::ArrayList ^ arExceptionTypes =
1642 get_service_ctor_method_exceptions_reduced(ctorDes->getExceptions());
1643 if (arExceptionTypes->Contains(
1644 type_uno_exception) == false)
1646 ilGen->BeginExceptionBlock();
1648 if (cParams == 0)
1650 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1651 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1652 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1654 ::System::Reflection::MethodInfo ^ methodCreate =
1655 local_factory->LocalType->GetMethod("createInstanceWithContext");
1656 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1658 else if(bParameterArray)
1660 //Service constructor with parameter array
1661 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1662 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1663 ilGen->Emit(Emit::OpCodes::Ldarg_1);
1664 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1665 ::System::Reflection::MethodInfo ^ methodCreate =
1666 local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1667 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1669 else
1671 // Any param1, Any param2, etc.
1672 // For each parameter,except the component context, and parameter array
1673 // and Any is created.
1674 array<Emit::LocalBuilder^>^ arLocalAny = gcnew array<Emit::LocalBuilder^> (cParams);
1676 for (int iParam = 0; iParam < cParams; iParam ++)
1678 arLocalAny[iParam] = ilGen->DeclareLocal(typeAny);
1681 //Any[]. This array is filled with the created Anys which contain the parameters
1682 //and the values contained in the parameter array
1683 Emit::LocalBuilder ^ local_anyParams =
1684 ilGen->DeclareLocal(array< ::uno::Any>::typeid);
1686 //Create the Any for every argument, except for the parameter array
1687 //arLocalAny contains the LocalBuilder for all these parameters.
1688 //we call the ctor Any(Type, Object)
1689 //If the parameter is an Any then the Any is created with Any(param.Type, param.Value);
1690 array< ::System::Type^>^ arTypesCtorAny = {::System::Type::typeid,
1691 ::System::Object::typeid};
1692 ::System::Reflection::ConstructorInfo ^ ctorAny =
1693 typeAny->GetConstructor( arTypesCtorAny);
1694 ::System::Reflection::MethodInfo ^ methodAnyGetType =
1695 typeAny->GetProperty("Type")->GetGetMethod();
1696 ::System::Reflection::MethodInfo ^ methodAnyGetValue =
1697 typeAny->GetProperty("Value")->GetGetMethod();
1698 for (int i = 0; i < arLocalAny->Length; i ++)
1700 //check if the parameter is a polymorphic struct
1701 ::uno::PolymorphicType ^polyType = dynamic_cast< ::uno::PolymorphicType^ >(arTypeParameters[i+1]);
1702 //arTypeParameters[i+1] = polyType->OriginalType;
1703 if (polyType)
1705 //It is a polymorphic struct
1706 //Load the uninitialized local Any on which we will call the ctor
1707 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1708 // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName)
1709 // Prepare the first parameter
1710 ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->OriginalType);
1711 array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1712 ilGen->Emit(Emit::OpCodes::Call,
1713 ::System::Type::typeid->GetMethod(
1714 "GetTypeFromHandle", arTypeParams));
1715 // Prepare the second parameter
1716 ilGen->Emit(Emit::OpCodes::Ldstr, polyType->PolymorphicName);
1717 // Make the actual call
1718 array< ::System::Type^>^ arTypeParam_GetType = {
1719 ::System::Type::typeid, ::System::String::typeid };
1720 ilGen->Emit(Emit::OpCodes::Call,
1721 ::uno::PolymorphicType::typeid->GetMethod(gcnew System::String("GetType"),
1722 arTypeParam_GetType));
1724 //Stack is: localAny, PolymorphicType
1725 //Call Any::Any(Type, Object)
1726 //Prepare the second parameter for the any ctor
1727 ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1728 // if the parameter is a value type then we need to box it, because
1729 // the Any ctor takes an Object
1730 if (arTypeParameters[i+1]->IsValueType)
1731 ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1732 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1734 else if (arTypeParameters[i+1] == typeAny)
1736 //Create the call new Any(param.Type,param,Value)
1737 //Stack must be Any,Type,Value
1738 //First load the Any which is to be constructed
1739 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1740 //Load the Type, which is obtained by calling param.Type
1741 ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1742 ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType);
1743 //Load the Value, which is obtained by calling param.Value
1744 ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1745 ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue);
1746 //Call the Any ctor.
1747 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1749 else
1751 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1752 ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]);
1754 array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1755 ilGen->Emit(Emit::OpCodes::Call,
1756 ::System::Type::typeid->GetMethod(
1757 "GetTypeFromHandle", arTypeParams));
1758 ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1759 // if the parameter is a value type then we need to box it, because
1760 // the Any ctor takes an Object
1761 if (arTypeParameters[i+1]->IsValueType)
1762 ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1763 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1767 //Create the Any[] that is passed to the
1768 //createInstanceWithContext[AndArguments] function
1769 ilGen->Emit(Emit::OpCodes::Ldc_I4, arLocalAny->Length);
1770 ilGen->Emit(Emit::OpCodes::Newarr, typeAny);
1771 ilGen->Emit(Emit::OpCodes::Stloc, local_anyParams);
1773 //Assign all anys created from the parameters
1774 //array to the Any[]
1775 for (int i = 0; i < arLocalAny->Length; i++)
1777 ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1778 ilGen->Emit(Emit::OpCodes::Ldc_I4, i);
1779 ilGen->Emit(Emit::OpCodes::Ldelema, typeAny);
1780 ilGen->Emit(Emit::OpCodes::Ldloc, arLocalAny[i]);
1781 ilGen->Emit(Emit::OpCodes::Stobj, typeAny);
1783 // call createInstanceWithArgumentsAndContext
1784 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1785 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1786 ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1787 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1788 ::System::Reflection::MethodInfo ^ methodCreate =
1789 local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1790 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1792 //cast the object returned by the functions createInstanceWithContext or
1793 //createInstanceWithArgumentsAndContext to the interface type
1794 ilGen->Emit(Emit::OpCodes::Castclass, retType);
1795 ilGen->Emit(Emit::OpCodes::Stloc, local_return_val);
1797 //catch exceptions thrown by createInstanceWithArgumentsAndContext and createInstanceWithContext
1798 if (arExceptionTypes->Contains(type_uno_exception) == false)
1800 // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;}
1801 ilGen->BeginCatchBlock(get_type("unoidl.com.sun.star.uno.RuntimeException", true));
1802 ilGen->Emit(Emit::OpCodes::Pop);
1803 ilGen->Emit(Emit::OpCodes::Rethrow);
1805 //catch and rethrow all other defined Exceptions
1806 for (int i = 0; i < arExceptionTypes->Count; i++)
1808 ::System::Type ^ excType = safe_cast< ::System::Type^ >(
1809 arExceptionTypes[i]);
1810 if (excType->IsInstanceOfType(
1811 get_type("unoidl.com.sun.star.uno.RuntimeException", true)))
1812 {// we have a catch for RuntimeException already defined
1813 continue;
1816 //catch Exception and rethrow
1817 ilGen->BeginCatchBlock(excType);
1818 ilGen->Emit(Emit::OpCodes::Pop);
1819 ilGen->Emit(Emit::OpCodes::Rethrow);
1821 //catch (unoidl.com.sun.star.uno.Exception) {throw DeploymentException...}
1822 ilGen->BeginCatchBlock(type_uno_exception);
1824 //Define the local variable that keeps the exception
1825 Emit::LocalBuilder ^ local_exception = ilGen->DeclareLocal(
1826 type_uno_exception);
1828 //Store the exception
1829 ilGen->Emit(Emit::OpCodes::Stloc, local_exception);
1831 //prepare the construction of the exception
1832 strbuilder = gcnew ::System::Text::StringBuilder(256);
1833 strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1834 strbuilder->Append(to_cts_name(xServiceType->getName()));
1835 strbuilder->Append(": ");
1837 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1839 //add to the string the Exception.Message
1840 ilGen->Emit(Emit::OpCodes::Ldloc, local_exception);
1841 ilGen->Emit(Emit::OpCodes::Callvirt,
1842 type_uno_exception->GetProperty("Message")->GetGetMethod());
1843 array< ::System::Type^>^ arConcatParams = {System::String::typeid,
1844 System::String::typeid};
1845 ilGen->Emit(Emit::OpCodes::Call,
1846 System::String::typeid->GetMethod("Concat", arConcatParams));
1847 //load contex argument
1848 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1849 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1850 ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1852 ilGen->EndExceptionBlock();
1856 //Check if the service instance was created and threw an exception if not
1857 Emit::Label label_service_created = ilGen->DefineLabel();
1858 ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1859 ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created);
1861 strbuilder = gcnew ::System::Text::StringBuilder(256);
1862 strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1863 strbuilder->Append(to_cts_name(xServiceType->getName()));
1864 strbuilder->Append(".");
1865 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1866 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1867 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1868 ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1870 ilGen->MarkLabel(label_service_created);
1871 ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1872 ilGen->Emit(Emit::OpCodes::Ret);
1875 // remove from incomplete types map
1876 ::System::String ^ cts_name = type_builder->FullName;
1877 m_incomplete_services->Remove( cts_name );
1878 xServiceType->release();
1879 if (g_bVerbose)
1881 ::System::Console::WriteLine(
1882 "> emitting service type {0}", cts_name );
1884 return type_builder->CreateType();
1888 Emit::CustomAttributeBuilder^ TypeEmitter::get_service_exception_attribute(
1889 const Reference<reflection::XServiceConstructorDescription> & ctorDes )
1891 return get_exception_attribute(ctorDes->getExceptions());
1894 Emit::CustomAttributeBuilder^ TypeEmitter::get_iface_method_exception_attribute(
1895 const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod )
1898 const Sequence<Reference<reflection::XTypeDescription> > seqTD = xMethod->getExceptions();
1899 int len = seqTD.getLength();
1900 Sequence<Reference<reflection::XCompoundTypeDescription> > seqCTD(len);
1901 Reference<reflection::XCompoundTypeDescription> * arCTD = seqCTD.getArray();
1902 for (int i = 0; i < len; i++)
1903 arCTD[i] = Reference<reflection::XCompoundTypeDescription>(seqTD[i], UNO_QUERY_THROW);
1904 return get_exception_attribute(seqCTD);
1907 Emit::CustomAttributeBuilder^ TypeEmitter::get_exception_attribute(
1909 const Sequence<Reference< reflection::XCompoundTypeDescription > >& seq_exceptionsTd )
1911 Emit::CustomAttributeBuilder ^ attr_builder = nullptr;
1913 Reference< reflection::XCompoundTypeDescription > const * exceptions =
1914 seq_exceptionsTd.getConstArray();
1916 array< ::System::Type^>^ arTypesCtor = {::System::Type::GetType("System.Type[]")};
1917 ConstructorInfo ^ ctor_ExceptionAttribute =
1918 ::uno::ExceptionAttribute::typeid->GetConstructor(arTypesCtor);
1920 sal_Int32 exc_length = seq_exceptionsTd.getLength();
1921 if (exc_length != 0) // opt
1923 array< ::System::Type^>^ exception_types =
1924 gcnew array< ::System::Type^> ( exc_length );
1925 for ( sal_Int32 exc_pos = 0; exc_pos < exc_length; ++exc_pos )
1927 Reference< reflection::XCompoundTypeDescription > const & xExc =
1928 exceptions[ exc_pos ];
1929 exception_types[ exc_pos ] = get_type( xExc );
1931 array< ::System::Object^>^ args = {exception_types};
1932 attr_builder = gcnew Emit::CustomAttributeBuilder(
1933 ctor_ExceptionAttribute, args );
1935 return attr_builder;
1939 ::System::Type ^ TypeEmitter::complete_singleton_type(singleton_entry ^ entry)
1941 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
1942 reflection::XSingletonTypeDescription2 * xSingletonType = entry->m_xType;
1943 ::System::String^ sSingletonName = to_cts_name(xSingletonType->getName());
1945 //Create the private default constructor
1946 Emit::ConstructorBuilder^ ctor_builder =
1947 type_builder->DefineConstructor(
1948 static_cast<MethodAttributes>(MethodAttributes::Private |
1949 MethodAttributes::HideBySig |
1950 MethodAttributes::SpecialName |
1951 MethodAttributes::RTSpecialName),
1952 CallingConventions::Standard, nullptr);
1954 Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator();
1955 ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1956 ilGen->Emit(
1957 Emit::OpCodes::Call,
1958 type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
1959 ilGen->Emit( Emit::OpCodes::Ret );
1962 //obtain the interface which makes up this service, it is the return
1963 //type of the constructor functions
1964 Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
1965 xSingletonType->getInterface(), UNO_QUERY);
1966 if (xIfaceType.is () == sal_False)
1967 xIfaceType = resolveInterfaceTypedef(xSingletonType->getInterface());
1968 System::Type ^ retType = get_type(xIfaceType);
1970 //define method
1971 array< ::System::Type^>^ arTypeParameters = {get_type("unoidl.com.sun.star.uno.XComponentContext", true)};
1972 Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
1973 gcnew System::String("get"),
1974 static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
1975 MethodAttributes::Static),
1976 retType,
1977 arTypeParameters);
1980 // method_builder->SetCustomAttribute(get_service_ctor_method_attribute(ctorDes));
1982 //The first parameter is the XComponentContext, which cannot be obtained
1983 //from reflection.
1984 //The context is not part of the idl description
1985 method_builder->DefineParameter(1, ParameterAttributes::In, "the_context");
1988 ilGen = method_builder->GetILGenerator();
1989 //Define locals ---------------------------------
1990 // Any, returned by XComponentContext.getValueByName
1991 Emit::LocalBuilder^ local_any =
1992 ilGen->DeclareLocal(::uno::Any::typeid);
1994 //Call XContext::getValueByName
1995 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1996 // build the singleton name : /singleton/unoidl.com.sun.star.XXX
1997 ::System::Text::StringBuilder^ sBuilder =
1998 gcnew ::System::Text::StringBuilder("/singletons/");
1999 sBuilder->Append(sSingletonName);
2000 ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
2002 ::System::Reflection::MethodInfo ^ methodGetValueByName =
2003 get_type("unoidl.com.sun.star.uno.XComponentContext", true)->GetMethod("getValueByName");
2004 ilGen->Emit(Emit::OpCodes::Callvirt, methodGetValueByName);
2005 ilGen->Emit(Emit::OpCodes::Stloc_0);
2007 //Contains the returned Any a value?
2008 ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
2009 ::System::Reflection::MethodInfo ^ methodHasValue =
2010 ::uno::Any::typeid->GetMethod("hasValue");
2011 ilGen->Emit(Emit::OpCodes::Call, methodHasValue);
2013 //If not, then throw a DeploymentException
2014 Emit::Label label_singleton_exists = ilGen->DefineLabel();
2015 ilGen->Emit(Emit::OpCodes::Brtrue_S, label_singleton_exists);
2016 sBuilder = gcnew ::System::Text::StringBuilder(
2017 "Component context fails to supply singleton ");
2018 sBuilder->Append(sSingletonName);
2019 sBuilder->Append(" of type ");
2020 sBuilder->Append(retType->FullName);
2021 sBuilder->Append(".");
2022 ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
2023 ilGen->Emit(Emit::OpCodes::Ldarg_0);
2024 array< ::System::Type^>^ arTypesCtorDeploymentException = {
2025 ::System::String::typeid, ::System::Object::typeid};
2026 ilGen->Emit(Emit::OpCodes::Newobj,
2027 get_type("unoidl.com.sun.star.uno.DeploymentException",true)
2028 ->GetConstructor(arTypesCtorDeploymentException));
2029 ilGen->Emit(Emit::OpCodes::Throw);
2030 ilGen->MarkLabel(label_singleton_exists);
2032 //Cast the singleton contained in the Any to the expected interface and return it.
2033 ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
2034 ilGen->Emit(Emit::OpCodes::Call, ::uno::Any::typeid->GetProperty("Value")->GetGetMethod());
2035 ilGen->Emit(Emit::OpCodes::Castclass, retType);
2036 ilGen->Emit(Emit::OpCodes::Ret);
2038 // remove from incomplete types map
2039 ::System::String ^ cts_name = type_builder->FullName;
2040 m_incomplete_singletons->Remove( cts_name );
2041 xSingletonType->release();
2042 if (g_bVerbose)
2044 ::System::Console::WriteLine(
2045 "> emitting singleton type {0}", cts_name );
2047 return type_builder->CreateType();
2051 ::System::Type ^ TypeEmitter::get_type(
2052 Reference< reflection::XTypeDescription > const & xType )
2054 switch (xType->getTypeClass())
2056 case TypeClass_VOID:
2057 return ::System::Void::typeid;
2058 case TypeClass_CHAR:
2059 return ::System::Char::typeid;
2060 case TypeClass_BOOLEAN:
2061 return ::System::Boolean::typeid;
2062 case TypeClass_BYTE:
2063 return ::System::Byte::typeid;
2064 case TypeClass_SHORT:
2065 return ::System::Int16::typeid;
2066 case TypeClass_UNSIGNED_SHORT:
2067 return ::System::UInt16::typeid;
2068 case TypeClass_LONG:
2069 return ::System::Int32::typeid;
2070 case TypeClass_UNSIGNED_LONG:
2071 return ::System::UInt32::typeid;
2072 case TypeClass_HYPER:
2073 return ::System::Int64::typeid;
2074 case TypeClass_UNSIGNED_HYPER:
2075 return ::System::UInt64::typeid;
2076 case TypeClass_FLOAT:
2077 return ::System::Single::typeid;
2078 case TypeClass_DOUBLE:
2079 return ::System::Double::typeid;
2080 case TypeClass_STRING:
2081 return ::System::String::typeid;
2082 case TypeClass_TYPE:
2083 return ::System::Type::typeid;
2084 case TypeClass_ANY:
2085 return ::uno::Any::typeid;
2086 case TypeClass_ENUM:
2087 return get_type( Reference< reflection::XEnumTypeDescription >(
2088 xType, UNO_QUERY_THROW ) );
2089 case TypeClass_TYPEDEF:
2090 // unwind typedefs
2091 return get_type(
2092 Reference< reflection::XIndirectTypeDescription >(
2093 xType, UNO_QUERY_THROW )->getReferencedType() );
2094 case TypeClass_STRUCT:
2095 case TypeClass_EXCEPTION:
2096 return get_type(
2097 Reference< reflection::XCompoundTypeDescription >(
2098 xType, UNO_QUERY_THROW ) );
2099 case TypeClass_SEQUENCE:
2101 ::System::Type ^ element_type = get_type(
2102 Reference< reflection::XIndirectTypeDescription >(
2103 xType, UNO_QUERY_THROW )->getReferencedType() );
2104 ::System::Type ^ retType = get_type(
2105 ::System::String::Concat(
2106 element_type->FullName, "[]" ), true );
2108 ::uno::PolymorphicType ^ pt = dynamic_cast< ::uno::PolymorphicType ^ >(element_type);
2109 if (pt)
2111 ::System::String ^ sName = ::System::String::Concat(pt->PolymorphicName, "[]");
2112 retType = ::uno::PolymorphicType::GetType(retType, sName);
2114 return retType;
2116 case TypeClass_INTERFACE:
2117 return get_type(
2118 Reference< reflection::XInterfaceTypeDescription2 >(
2119 xType, UNO_QUERY_THROW ) );
2120 case TypeClass_CONSTANT:
2121 return get_type(
2122 Reference< reflection::XConstantTypeDescription >(
2123 xType, UNO_QUERY_THROW ) );
2124 case TypeClass_CONSTANTS:
2125 return get_type(
2126 Reference< reflection::XConstantsTypeDescription >(
2127 xType, UNO_QUERY_THROW ) );
2128 case TypeClass_SERVICE:
2129 return get_type(
2130 Reference< reflection::XServiceTypeDescription2 >(
2131 xType, UNO_QUERY_THROW) );
2132 case TypeClass_SINGLETON:
2133 return get_type(
2134 Reference< reflection::XSingletonTypeDescription2 >(
2135 xType, UNO_QUERY_THROW) );
2136 case TypeClass_MODULE:
2137 // ignore these
2138 return nullptr;
2139 default:
2140 throw RuntimeException(
2141 "unexpected type " + xType->getName() );
2146 ::System::Type ^ TypeEmitter::get_complete_struct( ::System::String ^ sName)
2148 struct_entry ^ pStruct = safe_cast< struct_entry ^>(
2149 m_incomplete_structs[sName]);
2150 if (pStruct)
2152 complete_struct_type(pStruct);
2154 //get_type will asked the module builder for the type or otherwise all known assemblies.
2155 return get_type(sName, true);
2157 TypeEmitter::~TypeEmitter()
2159 while (true)
2161 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2162 m_incomplete_ifaces->GetEnumerator();
2163 if (! enumerator->MoveNext())
2164 break;
2165 complete_iface_type(
2166 safe_cast< iface_entry ^ >( enumerator->Value ) );
2169 while (true)
2171 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2172 m_incomplete_structs->GetEnumerator();
2173 if (! enumerator->MoveNext())
2174 break;
2175 complete_struct_type(
2176 safe_cast< struct_entry ^ >( enumerator->Value ) );
2180 while (true)
2182 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2183 m_incomplete_services->GetEnumerator();
2184 if (! enumerator->MoveNext())
2185 break;
2186 complete_service_type(
2187 safe_cast< service_entry ^ >( enumerator->Value ) );
2190 while (true)
2192 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2193 m_incomplete_singletons->GetEnumerator();
2194 if (! enumerator->MoveNext())
2195 break;
2196 complete_singleton_type(
2197 safe_cast< singleton_entry ^ >( enumerator->Value ) );
2201 TypeEmitter::TypeEmitter(
2202 ::System::Reflection::Emit::ModuleBuilder ^ module_builder,
2203 array< ::System::Reflection::Assembly^>^ extra_assemblies )
2204 : m_module_builder( module_builder ),
2205 m_extra_assemblies( extra_assemblies ),
2206 m_method_info_Type_GetTypeFromHandle( nullptr ),
2207 m_type_Exception( nullptr ),
2208 m_type_RuntimeException( nullptr ),
2209 m_incomplete_ifaces( gcnew ::System::Collections::Hashtable() ),
2210 m_incomplete_structs( gcnew ::System::Collections::Hashtable() ),
2211 m_incomplete_services(gcnew ::System::Collections::Hashtable() ),
2212 m_incomplete_singletons(gcnew ::System::Collections::Hashtable() ),
2213 m_generated_structs( gcnew ::System::Collections::Hashtable() )
2215 array< ::System::Type^>^ param_types = gcnew array< ::System::Type^> ( 1 );
2216 param_types[ 0 ] = ::System::RuntimeTypeHandle::typeid;
2217 m_method_info_Type_GetTypeFromHandle =
2218 ::System::Type::typeid
2219 ->GetMethod( "GetTypeFromHandle", param_types );
2222 ::System::Collections::ArrayList ^ TypeEmitter::get_service_ctor_method_exceptions_reduced(
2223 const Sequence<Reference<reflection::XCompoundTypeDescription> > & seqExceptionsTd)
2225 if (seqExceptionsTd.getLength() == 0)
2226 return gcnew ::System::Collections::ArrayList();
2228 ::System::Collections::ArrayList ^ arTypes = gcnew ::System::Collections::ArrayList();
2229 for (int i = 0; i < seqExceptionsTd.getLength(); i++)
2230 arTypes->Add(get_type(to_cts_name(seqExceptionsTd[i]->getName()), true));
2232 int start = 0;
2233 while (true)
2235 bool bRemove = false;
2236 for (int i = start; i < arTypes->Count; i++)
2238 ::System::Type ^ t = safe_cast< ::System::Type^ >(arTypes[i]);
2239 for (int j = 0; j < arTypes->Count; j++)
2241 if (t->IsSubclassOf(safe_cast< ::System::Type^ >(arTypes[j])))
2243 arTypes->RemoveAt(i);
2244 bRemove = true;
2245 break;
2248 if (bRemove)
2249 break;
2250 start++;
2253 if (bRemove == false)
2254 break;
2256 return arTypes;
2260 css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
2261 resolveInterfaceTypedef(
2262 const css::uno::Reference<css::reflection::XTypeDescription>& type)
2264 Reference<reflection::XInterfaceTypeDescription2>
2265 xIfaceTd(type, UNO_QUERY);
2267 if (xIfaceTd.is())
2268 return xIfaceTd;
2270 Reference<reflection::XIndirectTypeDescription> xIndTd(
2271 type, UNO_QUERY_THROW);
2273 return resolveInterfaceTypedef(xIndTd->getReferencedType());
2279 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */