tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / cli_ure / source / climaker / climaker_emit.cxx
blobedde6a04db5737702f1961f8a75f96ade83b87e2
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.getValueTypeName() );
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 const Sequence< Reference<
524 reflection::XConstantTypeDescription > > seq_constants(
525 xType->getConstants() );
526 sal_Int32 constants_length = seq_constants.getLength();
527 for ( sal_Int32 constants_pos = 0;
528 constants_pos < constants_length; ++constants_pos )
530 Reference<
531 reflection::XConstantTypeDescription > const & xConstant =
532 seq_constants[ constants_pos ];
533 ::System::Object ^ constant =
534 to_cli_constant( xConstant->getConstantValue() );
535 ::System::String ^ uno_name =
536 ustring_to_String( xConstant->getName() );
537 Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
538 uno_name->Substring( uno_name->LastIndexOf( '.' ) +1 ),
539 constant->GetType(),
540 (FieldAttributes) (FieldAttributes::Public |
541 FieldAttributes::Static |
542 FieldAttributes::Literal) );
543 field_builder->SetConstant( constant );
546 if (g_bVerbose)
548 ::System::Console::WriteLine(
549 "> emitting constants group type {0}", cts_name );
551 ret_type = type_builder->CreateType();
553 return ret_type;
557 ::System::Type ^ TypeEmitter::get_type(
558 Reference< reflection::XEnumTypeDescription > const & xType )
560 ::System::String ^ cts_name = to_cts_name( xType->getName() );
561 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
562 if (nullptr == ret_type)
564 // workaround enum builder bug
565 Emit::TypeBuilder ^ enum_builder =
566 m_module_builder->DefineType(
567 cts_name,
568 (TypeAttributes) (TypeAttributes::Public |
569 TypeAttributes::Sealed),
570 ::System::Enum::typeid );
571 enum_builder->DefineField(
572 "value__", ::System::Int32::typeid,
573 (FieldAttributes) (FieldAttributes::Private |
574 FieldAttributes::SpecialName |
575 FieldAttributes::RTSpecialName) );
576 const Sequence< OUString > seq_enum_names( xType->getEnumNames() );
577 const Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() );
578 sal_Int32 enum_length = seq_enum_names.getLength();
579 OSL_ASSERT( enum_length == seq_enum_values.getLength() );
580 for ( sal_Int32 enum_pos = 0; enum_pos < enum_length; ++enum_pos )
582 // enum_builder->DefineLiteral(
583 // ustring_to_String( enum_names[ enum_pos ] ),
584 // __box ((::System::Int32) enum_values[ enum_pos ]) );
585 Emit::FieldBuilder ^ field_builder =
586 enum_builder->DefineField(
587 ustring_to_String( seq_enum_names[ enum_pos ] ),
588 enum_builder,
589 (FieldAttributes) (FieldAttributes::Public |
590 FieldAttributes::Static |
591 FieldAttributes::Literal) );
592 field_builder->SetConstant(
593 ((::System::Int32) seq_enum_values[ enum_pos ]) );
596 if (g_bVerbose)
598 ::System::Console::WriteLine(
599 "> emitting enum type {0}", cts_name );
601 ret_type = enum_builder->CreateType();
603 return ret_type;
607 ::System::Type ^ TypeEmitter::get_type(
608 Reference< reflection::XCompoundTypeDescription > const & xType )
610 OUString uno_name( xType->getName() );
611 if (TypeClass_EXCEPTION == xType->getTypeClass())
613 if ( uno_name == "com.sun.star.uno.Exception" )
615 return get_type_Exception();
617 if ( uno_name == "com.sun.star.uno.RuntimeException" )
619 return get_type_RuntimeException();
622 ::System::String ^ cts_name = to_cts_name( uno_name );
623 // if the struct is an instantiated polymorphic struct then we create the simple struct name
624 // For example:
625 // void func ([in] PolyStruct<boolean> arg);
626 //PolyStruct<boolean> will be converted to PolyStruct
627 polymorphicStructNameToStructName( & cts_name);
629 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
630 if (nullptr == ret_type)
632 Reference< reflection::XCompoundTypeDescription > xBaseType(
633 xType->getBaseType(), UNO_QUERY );
634 ::System::Type ^ base_type = (xBaseType.is()
635 ? get_type( xBaseType )
636 : ::System::Object::typeid);
637 Emit::TypeBuilder ^ type_builder =
638 m_module_builder->DefineType(
639 cts_name,
640 (TypeAttributes) (TypeAttributes::Public |
641 TypeAttributes::BeforeFieldInit |
642 TypeAttributes::AnsiClass),
643 base_type );
646 // insert to be completed
647 struct_entry ^ entry = gcnew struct_entry();
648 xType->acquire();
649 entry->m_xType = xType.get();
650 entry->m_type_builder = type_builder;
651 entry->m_base_type = base_type;
652 m_incomplete_structs->Add( cts_name, entry );
654 // type is incomplete
655 ret_type = type_builder;
658 //In case of an instantiated polymorphic struct we want to return a
659 //uno.PolymorphicType (inherits Type) rather than Type. This is needed for constructing
660 //the service code. We can only do that if the struct is completed.
661 if (m_generated_structs[cts_name])
663 Reference< reflection::XStructTypeDescription> xStructTypeDesc(
664 xType, UNO_QUERY);
666 if (xStructTypeDesc.is())
668 Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments();
669 sal_Int32 numTypes = seqTypeArgs.getLength();
670 if (numTypes > 0)
672 //it is an instantiated polymorphic struct
673 ::System::String ^ sCliName = mapUnoTypeName(ustring_to_String(xType->getName()));
674 ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName);
678 return ret_type;
682 ::System::Type ^ TypeEmitter::get_type(
683 Reference< reflection::XInterfaceTypeDescription2 > const & xType )
685 OUString uno_name( xType->getName() );
686 if ( uno_name == "com.sun.star.uno.XInterface" )
688 return ::System::Object::typeid;
691 ::System::String ^ cts_name = to_cts_name( xType->getName() );
692 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
693 if (nullptr == ret_type)
695 Emit::TypeBuilder ^ type_builder;
697 TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
698 TypeAttributes::Interface |
699 TypeAttributes::Abstract |
700 TypeAttributes::AnsiClass);
702 std::vector<Reference<reflection::XInterfaceTypeDescription2> > vecBaseTypes;
703 Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes =
704 xType->getBaseTypes();
705 if (seqBaseTypes.getLength() > 0)
707 for (int i = 0; i < seqBaseTypes.getLength(); i++)
709 Reference<reflection::XInterfaceTypeDescription2> xIfaceTd =
710 resolveInterfaceTypedef(seqBaseTypes[i]);
712 if ( xIfaceTd->getName() != "com.sun.star.uno.XInterface" )
714 vecBaseTypes.push_back(xIfaceTd);
718 array< ::System::Type^>^ base_interfaces =
719 gcnew array< ::System::Type^>( vecBaseTypes.size() );
721 int index = 0;
722 for (auto const & vecBaseType : vecBaseTypes)
724 base_interfaces[ index ] = get_type( vecBaseType );
725 ++index;
727 type_builder = m_module_builder->DefineType(
728 cts_name, attr, nullptr, base_interfaces );
730 else
732 ::System::Console::WriteLine(
733 "warning: IDL interface {0} is not derived from "
734 "com.sun.star.uno.XInterface!",
735 ustring_to_String( uno_name ) );
737 type_builder = m_module_builder->DefineType( cts_name, attr );
740 // insert to be completed
741 iface_entry ^ entry = gcnew iface_entry();
742 xType->acquire();
743 entry->m_xType = xType.get();
744 entry->m_type_builder = type_builder;
745 m_incomplete_ifaces->Add( cts_name, entry );
747 // type is incomplete
748 ret_type = type_builder;
750 return ret_type;
754 ::System::Type ^ TypeEmitter::get_type(
755 Reference< reflection::XServiceTypeDescription2 > const & xType )
757 if (xType->isSingleInterfaceBased() == sal_False)
758 return nullptr;
760 System::String ^ cts_name = to_cts_name( xType->getName() );
761 System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
762 if (ret_type != nullptr)
763 return ret_type;
765 TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
766 TypeAttributes::Sealed |
767 TypeAttributes::BeforeFieldInit |
768 TypeAttributes::AnsiClass);
770 Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
771 cts_name, attr);
773 // insert to be completed
774 service_entry ^ entry = gcnew service_entry();
775 xType->acquire();
776 entry->m_xType = xType.get();
777 entry->m_type_builder = type_builder;
778 m_incomplete_services->Add(cts_name,entry );
780 return type_builder;
783 ::System::Type ^ TypeEmitter::get_type(
784 Reference<reflection::XSingletonTypeDescription2 > const & xType )
786 if (xType->isInterfaceBased() == sal_False)
787 return nullptr;
789 ::System::String^ cts_name = to_cts_name( xType->getName() );
790 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
791 if (ret_type != nullptr)
792 return ret_type;
794 TypeAttributes attr = static_cast<TypeAttributes>(
795 TypeAttributes::Public |
796 TypeAttributes::Sealed |
797 TypeAttributes::BeforeFieldInit |
798 TypeAttributes::AnsiClass);
800 Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
801 cts_name, attr);
803 // insert to be completed
804 singleton_entry ^ entry = gcnew singleton_entry();
805 xType->acquire();
806 entry->m_xType = xType.get();
807 entry->m_type_builder = type_builder;
808 m_incomplete_singletons->Add(cts_name,entry );
810 return type_builder;
815 ::System::Type ^ TypeEmitter::complete_iface_type( iface_entry ^ entry )
817 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
818 reflection::XInterfaceTypeDescription2 * xType = entry->m_xType;
820 Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes( xType->getBaseTypes() );
821 if (seqBaseTypes.getLength() > 0)
823 for (int i = 0; i < seqBaseTypes.getLength(); i++)
825 //make sure we get the interface rather than a typedef
826 Reference<reflection::XInterfaceTypeDescription2> aBaseType =
827 resolveInterfaceTypedef( seqBaseTypes[i]);
829 if ( aBaseType->getName() != "com.sun.star.uno.XInterface" )
831 ::System::String ^ basetype_name = to_cts_name( aBaseType->getName() );
832 iface_entry ^ base_entry = dynamic_cast< iface_entry ^ >(
833 m_incomplete_ifaces[basetype_name] );
834 if (nullptr != base_entry)
836 // complete uncompleted base type first
837 complete_iface_type( base_entry );
843 const Sequence<
844 Reference< reflection::XInterfaceMemberTypeDescription > > seq_members(
845 xType->getMembers() );
846 sal_Int32 members_length = seq_members.getLength();
847 for ( sal_Int32 members_pos = 0;
848 members_pos < members_length; ++members_pos )
850 Reference<
851 reflection::XInterfaceMemberTypeDescription > const & xMember =
852 seq_members[ members_pos ];
853 Sequence< Reference< reflection::XTypeDescription > > seq_exceptions;
855 MethodAttributes c_method_attr = (MethodAttributes)
856 (MethodAttributes::Public |
857 MethodAttributes::Abstract |
858 MethodAttributes::Virtual |
859 MethodAttributes::NewSlot |
860 MethodAttributes::HideBySig);
862 if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass())
864 Reference< reflection::XInterfaceMethodTypeDescription > xMethod(
865 xMember, UNO_QUERY_THROW );
867 const Sequence<
868 Reference< reflection::XMethodParameter > > seq_parameters(
869 xMethod->getParameters() );
870 sal_Int32 params_length = seq_parameters.getLength();
871 array< ::System::Type^>^ param_types =
872 gcnew array< ::System::Type^>( params_length );
873 // first determine all types
874 //Make the first param type as return type
875 sal_Int32 params_pos = 0;
876 for ( ; params_pos < params_length; ++params_pos )
878 Reference< reflection::XMethodParameter > const & xParam =
879 seq_parameters[ params_pos ];
880 ::System::Type ^ param_type = get_type( xParam->getType() );
881 ::System::String ^ param_type_name = param_type->FullName;
882 if (xParam->isOut())
884 param_type = get_type(
885 ::System::String::Concat(
886 param_type_name, "&" ), true );
888 param_types[ xParam->getPosition() ] = param_type;
892 // create method
893 // if (tb)
894 // method_builder = type_builder->DefineMethod(
895 // ustring_to_String( xMethod->getMemberName() ),
896 // c_method_attr, tb,
897 // param_types );
898 // else
899 Emit::MethodBuilder ^ method_builder = type_builder->DefineMethod(
900 ustring_to_String( xMethod->getMemberName() ),
901 c_method_attr, get_type( xMethod->getReturnType() ),
902 param_types );
903 // then define parameter infos
904 params_pos = 0;
905 for ( ; params_pos < params_length; ++params_pos )
907 Reference< reflection::XMethodParameter > const & xParam =
908 seq_parameters[ params_pos ];
909 long param_flags = 0;
910 if (xParam->isIn())
911 param_flags |= (long)ParameterAttributes::In;
912 if (xParam->isOut())
913 param_flags |= (long)ParameterAttributes::Out;
914 OSL_ASSERT( 0 != param_flags );
915 method_builder->DefineParameter(
916 xParam->getPosition() +1 /* starts with 1 */,
917 (ParameterAttributes) param_flags,
918 ustring_to_String( xParam->getName() ) );
920 //Apply attribute TypeParametersAttribute to return value if it
921 //is a parameterized Type. Currently only structs can have parameters.
922 Reference<reflection::XStructTypeDescription> xReturnStruct(
923 xMethod->getReturnType(), UNO_QUERY);
925 if (xReturnStruct.is())
927 const Sequence<Reference<reflection::XTypeDescription> > seq_type_args =
928 xReturnStruct->getTypeArguments();
929 if (seq_type_args.getLength() != 0)
931 //get the ctor of the attribute
932 array< ::System::Type^>^ arCtor = {::System::Type::GetType("System.Type[]")};
933 //Get the arguments for the attribute's ctor
934 int numTypes = seq_type_args.getLength();
935 array< ::System::Type^>^ arCtsTypes = gcnew array< ::System::Type^>(numTypes);
936 for (int i = 0; i < numTypes; i++)
937 arCtsTypes[i] = get_type(seq_type_args[i]);
938 array< ::System::Object^>^ arArgs = {arCtsTypes};
940 Emit::CustomAttributeBuilder ^ attrBuilder =
941 gcnew Emit::CustomAttributeBuilder(
942 ::uno::TypeArgumentsAttribute::typeid
943 ->GetConstructor( arCtor),
944 arArgs);
946 method_builder->SetCustomAttribute(attrBuilder);
950 //define UNO exception attribute (exceptions)--------------------------------------
951 Emit::CustomAttributeBuilder^ attrBuilder =
952 get_iface_method_exception_attribute(xMethod);
953 if (attrBuilder != nullptr)
954 method_builder->SetCustomAttribute(attrBuilder);
956 // oneway attribute
957 if (xMethod->isOneway())
959 array< ::System::Type^>^ arCtorOneway = gcnew array< ::System::Type^>(0);
960 array< ::System::Object^>^ arArgs = gcnew array< ::System::Object^>(0);
961 Emit::CustomAttributeBuilder ^ attrBuilder2 =
962 gcnew Emit::CustomAttributeBuilder(
963 ::uno::OnewayAttribute::typeid->GetConstructor( arCtorOneway),
964 arArgs);
965 method_builder->SetCustomAttribute(attrBuilder2);
968 else // attribute
970 OSL_ASSERT(
971 TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() );
972 Reference<
973 reflection::XInterfaceAttributeTypeDescription2 > xAttribute(
974 xMember, UNO_QUERY_THROW );
976 MethodAttributes c_property_method_attr = (MethodAttributes)
977 (c_method_attr | MethodAttributes::SpecialName);
979 ::System::Type ^ attribute_type = get_type( xAttribute->getType() );
980 array< ::System::Type^>^ parameters =
981 gcnew array< ::System::Type^> ( 0 );
983 Emit::PropertyBuilder ^ property_builder =
984 type_builder->DefineProperty(
985 ustring_to_String( xAttribute->getMemberName() ),
986 PropertyAttributes::None,
987 attribute_type, parameters );
989 //set BoundAttribute, if necessary
990 if (xAttribute->isBound())
992 ConstructorInfo ^ ctorBoundAttr =
993 ::uno::BoundAttribute::typeid->GetConstructor(
994 gcnew array<System::Type^>(0));
995 Emit::CustomAttributeBuilder ^ attrBuilderBound =
996 gcnew Emit::CustomAttributeBuilder(
997 ctorBoundAttr, gcnew array< ::System::Object^>(0));
998 property_builder->SetCustomAttribute(attrBuilderBound);
1001 // getter
1002 Emit::MethodBuilder ^ method_builder =
1003 type_builder->DefineMethod(
1004 ustring_to_String( "get_" +
1005 xAttribute->getMemberName() ),
1006 c_property_method_attr, attribute_type, parameters );
1008 //define UNO exception attribute (exceptions)--------------------------------------
1009 Emit::CustomAttributeBuilder^ attrBuilder =
1010 get_exception_attribute(xAttribute->getGetExceptions());
1011 if (attrBuilder != nullptr)
1012 method_builder->SetCustomAttribute(attrBuilder);
1014 property_builder->SetGetMethod( method_builder );
1016 if (! xAttribute->isReadOnly())
1018 // setter
1019 parameters = gcnew array< ::System::Type^> ( 1 );
1020 parameters[ 0 ] = attribute_type;
1021 method_builder =
1022 type_builder->DefineMethod(
1023 ustring_to_String( "set_" +
1024 xAttribute->getMemberName() ),
1025 c_property_method_attr, nullptr, parameters );
1026 // define parameter info
1027 method_builder->DefineParameter(
1028 1 /* starts with 1 */, ParameterAttributes::In, "value" );
1029 //define UNO exception attribute (exceptions)--------------------------------------
1030 Emit::CustomAttributeBuilder^ attrBuilder2 =
1031 get_exception_attribute(xAttribute->getSetExceptions());
1032 if (attrBuilder2 != nullptr)
1033 method_builder->SetCustomAttribute(attrBuilder2);
1035 property_builder->SetSetMethod( method_builder );
1040 // remove from incomplete types map
1041 ::System::String ^ cts_name = type_builder->FullName;
1042 m_incomplete_ifaces->Remove( cts_name );
1043 xType->release();
1045 if (g_bVerbose)
1047 ::System::Console::WriteLine(
1048 "> emitting interface type {0}", cts_name );
1050 return type_builder->CreateType();
1053 ::System::Type ^ TypeEmitter::complete_struct_type( struct_entry ^ entry )
1055 OSL_ASSERT(entry);
1056 ::System::String ^ cts_name = entry->m_type_builder->FullName;
1058 //Polymorphic struct, define uno.TypeParametersAttribute
1059 //A polymorphic struct cannot have a basetype.
1060 //When we create the template of the struct then we have no exact types
1061 //and the name does not contain a parameter list
1062 Sequence< OUString > seq_type_parameters;
1063 Reference< reflection::XStructTypeDescription> xStructTypeDesc(
1064 entry->m_xType, UNO_QUERY);
1065 if (xStructTypeDesc.is())
1067 seq_type_parameters = xStructTypeDesc->getTypeParameters();
1068 int numTypes = 0;
1069 if ((numTypes = seq_type_parameters.getLength()) > 0)
1071 array< ::System::Object^>^ aArg = gcnew array< ::System::Object^>(numTypes);
1072 for (int i = 0; i < numTypes; i++)
1073 aArg[i] = ustring_to_String(seq_type_parameters[i]);
1074 array< ::System::Object^>^ args = {aArg};
1076 array< ::System::Type^>^ arTypesCtor =
1077 {::System::Type::GetType("System.String[]")};
1078 Emit::CustomAttributeBuilder ^ attrBuilder =
1079 gcnew Emit::CustomAttributeBuilder(
1080 ::uno::TypeParametersAttribute::typeid->GetConstructor(arTypesCtor),
1081 args);
1082 entry->m_type_builder->SetCustomAttribute(attrBuilder);
1086 // optional: lookup base type whether generated entry of this session
1087 struct_entry ^ base_type_entry = nullptr;
1088 if (nullptr != entry->m_base_type)
1090 //ToDo maybe get from incomplete structs
1091 base_type_entry =
1092 dynamic_cast< struct_entry ^ >(
1093 m_generated_structs[
1094 entry->m_base_type->FullName ] );
1097 // members
1098 const Sequence< Reference< reflection::XTypeDescription > > seq_members(
1099 entry->m_xType->getMemberTypes() );
1100 const Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() );
1101 sal_Int32 members_length = seq_members.getLength();
1102 OSL_ASSERT( seq_member_names.getLength() == members_length );
1103 //check if we have a XTypeDescription for every member. If not then the user may
1104 //have forgotten to specify additional rdbs with the --extra option.
1105 for (int i = 0; i < members_length; i++)
1107 const OUString sType(entry->m_xType->getName());
1108 const OUString sMemberName(seq_member_names[i]);
1109 if ( ! seq_members[i].is())
1110 throw RuntimeException("Missing type description . Check if you need to "
1111 "specify additional RDBs with the --extra option. Type missing for: " + sType +
1112 "::" + sMemberName,0);
1115 sal_Int32 all_members_length = 0;
1116 sal_Int32 member_pos;
1117 sal_Int32 type_param_pos = 0;
1119 // collect base types; wrong order
1120 ::System::Collections::ArrayList ^ base_types_list =
1121 gcnew ::System::Collections::ArrayList( 3 /* initial capacity */ );
1122 for (::System::Type ^ base_type_pos = entry->m_base_type;
1123 ! base_type_pos->Equals( ::System::Object::typeid );
1124 base_type_pos = base_type_pos->BaseType )
1126 base_types_list->Add( base_type_pos );
1127 if (base_type_pos->Equals( ::System::Exception::typeid ))
1129 // special Message member
1130 all_members_length += 1;
1131 break; // don't include System.Exception base classes
1133 else
1135 //ensure the base type is complete. Otherwise GetFields won't work
1136 get_complete_struct(base_type_pos->FullName);
1137 all_members_length +=
1138 base_type_pos->GetFields(
1139 (BindingFlags) (BindingFlags::Instance |
1140 BindingFlags::Public |
1141 BindingFlags::DeclaredOnly) )
1142 ->Length;
1146 // create all_members arrays; right order
1147 array< ::System::String^>^ all_member_names =
1148 gcnew array< ::System::String^> (all_members_length + members_length );
1149 array< ::System::Type^>^ all_param_types =
1150 gcnew array< ::System::Type^> (all_members_length + members_length );
1151 member_pos = 0;
1152 for ( sal_Int32 pos = base_types_list->Count; pos--; )
1154 ::System::Type ^ base_type = safe_cast< ::System::Type ^ >(
1155 base_types_list[pos] );
1156 if (base_type->Equals( ::System::Exception::typeid ))
1158 all_member_names[ member_pos ] = "Message";
1159 all_param_types[ member_pos ] = ::System::String::typeid;
1160 ++member_pos;
1162 else
1164 ::System::String ^ base_type_name = base_type->FullName;
1166 //ToDo m_generated_structs?
1167 struct_entry ^ entry2 =
1168 dynamic_cast< struct_entry ^ >(
1169 m_generated_structs[base_type_name] );
1170 if (nullptr == entry2)
1172 // complete type
1173 array<FieldInfo^>^ fields =
1174 base_type->GetFields(
1175 (BindingFlags) (BindingFlags::Instance |
1176 BindingFlags::Public |
1177 BindingFlags::DeclaredOnly) );
1178 sal_Int32 len = fields->Length;
1179 for ( sal_Int32 pos2 = 0; pos2 < len; ++pos2 )
1181 FieldInfo ^ field = fields[ pos2 ];
1182 all_member_names[ member_pos ] = field->Name;
1183 all_param_types[ member_pos ] = field->FieldType;
1184 ++member_pos;
1187 else // generated during this session:
1188 // members may be incomplete ifaces
1190 sal_Int32 len = entry2->m_member_names->Length;
1191 for ( sal_Int32 pos2 = 0; pos2 < len; ++pos2 )
1193 all_member_names[ member_pos ] =
1194 entry2->m_member_names[ pos2 ];
1195 all_param_types[ member_pos ] =
1196 entry2->m_param_types[ pos2 ];
1197 ++member_pos;
1202 OSL_ASSERT( all_members_length == member_pos );
1204 // build up entry
1205 // struct_entry * entry = new struct_entry();
1206 entry->m_member_names = gcnew array< ::System::String^> ( members_length );
1207 entry->m_param_types = gcnew array< ::System::Type^> ( members_length );
1209 // add members
1210 array<Emit::FieldBuilder^>^ members = gcnew array<Emit::FieldBuilder^> ( members_length );
1211 //Reference< reflection::XTypeDescription > const * pseq_members =
1212 // seq_members.getConstArray();
1213 //OUString const * pseq_member_names =
1214 // seq_member_names.getConstArray();
1216 int curParamIndex = 0; //count the fields which have parameterized types
1217 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1219 ::System::String ^ field_name =
1220 ustring_to_String( seq_member_names[ member_pos ] );
1221 ::System::Type ^ field_type;
1222 //Special handling of struct parameter types
1223 bool bParameterizedType = false;
1224 if (seq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN)
1226 bParameterizedType = true;
1227 if (type_param_pos < seq_type_parameters.getLength())
1229 field_type = ::System::Object::typeid;
1230 type_param_pos++;
1232 else
1234 throw RuntimeException(
1235 "unexpected member type in " + entry->m_xType->getName() );
1238 else
1240 field_type = get_type( seq_members[ member_pos ] );
1242 if (field_type->IsArray
1243 && m_incomplete_structs[cts_name]
1244 && !field_type->Namespace->Equals("System"))
1246 //Find the value type. In case of sequence<sequence< ... > > find the actual value type
1247 ::System::Type ^ value = field_type;
1248 while ((value = value->GetElementType())->IsArray);
1249 //If the value type is a struct then make sure it is fully created.
1250 get_complete_struct(value->FullName);
1251 field_type = get_type(seq_members[member_pos]);
1254 members[ member_pos ] =
1255 entry->m_type_builder->DefineField(
1256 field_name, field_type, FieldAttributes::Public );
1258 //parameterized type (polymorphic struct) ?
1259 if (bParameterizedType && xStructTypeDesc.is())
1261 //get the name
1262 OSL_ASSERT(seq_type_parameters.getLength() > curParamIndex);
1263 ::System::String^ sTypeName = ustring_to_String(
1264 seq_type_parameters[curParamIndex++]);
1265 array< ::System::Object^>^ args = {sTypeName};
1266 //set ParameterizedTypeAttribute
1267 array< ::System::Type^>^ arCtorTypes = {::System::String::typeid};
1269 Emit::CustomAttributeBuilder ^ attrBuilder =
1270 gcnew Emit::CustomAttributeBuilder(
1271 ::uno::ParameterizedTypeAttribute::typeid
1272 ->GetConstructor(arCtorTypes),
1273 args);
1275 members[member_pos]->SetCustomAttribute(attrBuilder);
1277 // add to all_members
1278 all_member_names[ all_members_length + member_pos ] = field_name;
1279 all_param_types[ all_members_length + member_pos ] = field_type;
1280 // add to entry
1281 entry->m_member_names[ member_pos ] = field_name;
1282 entry->m_param_types[ member_pos ] = field_type;
1284 all_members_length += members_length;
1286 // default .ctor
1287 Emit::ConstructorBuilder ^ ctor_builder =
1288 entry->m_type_builder->DefineConstructor(
1289 c_ctor_method_attr, CallingConventions::Standard,
1290 gcnew array< ::System::Type^> ( 0 ) );
1291 Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
1292 code->Emit( Emit::OpCodes::Ldarg_0 );
1293 code->Emit(
1294 Emit::OpCodes::Call,
1295 nullptr == base_type_entry
1296 ? entry->m_base_type->GetConstructor( gcnew array< ::System::Type^> ( 0 ) )
1297 : base_type_entry->m_default_ctor );
1298 // default initialize members
1299 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1301 FieldInfo ^ field = members[ member_pos ];
1302 ::System::Type ^ field_type = field->FieldType;
1303 // ::System::Type * new_field_type = m_module_builder->GetType(field_type->FullName, false);
1304 // default initialize:
1305 // string, type, enum, sequence, struct, exception, any
1306 if (field_type->Equals( ::System::String::typeid ))
1308 code->Emit( Emit::OpCodes::Ldarg_0 );
1309 code->Emit( Emit::OpCodes::Ldstr, "" );
1310 code->Emit( Emit::OpCodes::Stfld, field );
1312 else if (field_type->Equals( ::System::Type::typeid ))
1314 code->Emit( Emit::OpCodes::Ldarg_0 );
1315 code->Emit(
1316 Emit::OpCodes::Ldtoken, ::System::Void::typeid );
1317 code->Emit(
1318 Emit::OpCodes::Call, m_method_info_Type_GetTypeFromHandle );
1319 code->Emit( Emit::OpCodes::Stfld, field );
1321 else if (field_type->IsArray)
1323 code->Emit( Emit::OpCodes::Ldarg_0 );
1324 code->Emit( Emit::OpCodes::Ldc_I4_0 );
1325 code->Emit(
1326 Emit::OpCodes::Newarr, field_type->GetElementType() );
1327 code->Emit( Emit::OpCodes::Stfld, field );
1329 else if (field_type->IsValueType)
1331 if (field_type->FullName->Equals( "uno.Any" ))
1333 code->Emit( Emit::OpCodes::Ldarg_0 );
1334 code->Emit( Emit::OpCodes::Ldsfld, ::uno::Any::typeid->GetField("VOID"));
1335 code->Emit( Emit::OpCodes::Stfld, field );
1338 else if (field_type->IsClass)
1340 /* may be XInterface */
1341 if (! field_type->Equals( ::System::Object::typeid ))
1343 // struct, exception
1344 //make sure the struct is already complete.
1345 get_complete_struct(field_type->FullName);
1346 code->Emit( Emit::OpCodes::Ldarg_0 );
1347 code->Emit(
1348 Emit::OpCodes::Newobj,
1349 //GetConstructor requires that the member types of the object which is to be constructed are already known.
1350 field_type->GetConstructor(
1351 gcnew array< ::System::Type^> ( 0 ) ) );
1352 code->Emit( Emit::OpCodes::Stfld, field );
1356 code->Emit( Emit::OpCodes::Ret );
1357 entry->m_default_ctor = ctor_builder;
1359 // parameterized .ctor including all base members
1360 ctor_builder = entry->m_type_builder->DefineConstructor(
1361 c_ctor_method_attr, CallingConventions::Standard, all_param_types );
1362 for ( member_pos = 0; member_pos < all_members_length; ++member_pos )
1364 ctor_builder->DefineParameter(
1365 member_pos +1 /* starts with 1 */, ParameterAttributes::In,
1366 all_member_names[ member_pos ] );
1368 code = ctor_builder->GetILGenerator();
1369 // call base .ctor
1370 code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1371 sal_Int32 base_members_length = all_members_length - members_length;
1372 array< ::System::Type^>^ param_types =
1373 gcnew array< ::System::Type^> ( base_members_length );
1374 for ( member_pos = 0; member_pos < base_members_length; ++member_pos )
1376 emit_ldarg( code, member_pos +1 );
1377 param_types[ member_pos ] = all_param_types[ member_pos ];
1379 code->Emit(
1380 Emit::OpCodes::Call,
1381 nullptr == base_type_entry
1382 ? entry->m_base_type->GetConstructor( param_types )
1383 : base_type_entry->m_ctor );
1384 // initialize members
1385 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1387 code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1388 emit_ldarg( code, member_pos + base_members_length +1 );
1389 code->Emit( Emit::OpCodes::Stfld, members[ member_pos ] );
1391 code->Emit( Emit::OpCodes::Ret );
1392 entry->m_ctor = ctor_builder;
1394 if (g_bVerbose)
1396 ::System::Console::WriteLine(
1397 "> emitting {0} type {1}",
1398 TypeClass_STRUCT == entry->m_xType->getTypeClass()
1399 ? "struct"
1400 : "exception",
1401 cts_name);
1403 // new entry
1404 m_generated_structs->Add(cts_name, entry );
1405 ::System::Type ^ ret_type = entry->m_type_builder->CreateType();
1407 // remove from incomplete types map
1408 m_incomplete_structs->Remove( cts_name );
1409 entry->m_xType->release();
1411 if (g_bVerbose)
1413 ::System::Console::WriteLine(
1414 "> emitting struct type {0}", cts_name);
1416 return ret_type;
1419 //Examples of generated code
1420 // public static XWeak constructor1(XComponentContext ctx)
1421 // {
1422 // XMultiComponentFactory factory = ctx.getServiceManager();
1423 // if (factory == null)
1424 // throw new com.sun.star.uno.DeploymentException("bla", null);
1425 // return (XWeak) factory.createInstanceWithContext("service_specifier", ctx);
1426 // }
1427 // public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c)
1428 // {
1429 // XMultiComponentFactory factory = ctx.getServiceManager();
1430 // if (factory == null)
1431 // throw new com.sun.star.uno.DeploymentException("bla", null);
1432 // Any[] arAny = new Any[3];
1433 // arAny[0] = new Any(typeof(int), a);
1434 // arAny[1] = new Any(typeof(int), b);
1435 // arAny[2] = new Any(c.Type, c.Value);
1436 // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx);
1437 // }
1438 // Notice that an any parameter is NOT wrapped by another any. Instead the new any is created with the type and value
1439 // of the parameter.
1441 // public static XWeak constructor3(XComponentContext ctx, params Any[] c)
1442 // {
1443 // XMultiComponentFactory factory = ctx.getServiceManager();
1444 // if (factory == null)
1445 // throw new com.sun.star.uno.DeploymentException("bla", null);
1446 // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx);
1447 // }
1448 ::System::Type ^ TypeEmitter::complete_service_type(service_entry ^ entry)
1450 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
1451 reflection::XServiceTypeDescription2 * xServiceType = entry->m_xType;
1453 //Create the private default constructor
1454 Emit::ConstructorBuilder^ ctor_builder =
1455 type_builder->DefineConstructor(
1456 (MethodAttributes) (MethodAttributes::Private |
1457 MethodAttributes::HideBySig |
1458 MethodAttributes::SpecialName |
1459 MethodAttributes::RTSpecialName),
1460 CallingConventions::Standard, nullptr);
1462 Emit::ILGenerator^ ilGen1 = ctor_builder->GetILGenerator();
1463 ilGen1->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1464 ilGen1->Emit(
1465 Emit::OpCodes::Call,
1466 type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
1467 ilGen1->Emit( Emit::OpCodes::Ret );
1470 //Create the service constructors.
1471 //obtain the interface which makes up this service, it is the return
1472 //type of the constructor functions
1473 Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
1474 xServiceType->getInterface(), UNO_QUERY);
1475 if (xIfaceType.is () == sal_False)
1476 xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface());
1477 System::Type ^ retType = get_type(xIfaceType);
1479 //Create the ConstructorInfo for a DeploymentException
1480 ::System::Type ^ typeDeploymentExc =
1481 get_type("unoidl.com.sun.star.uno.DeploymentException", true);
1483 array< ::System::Type^>^ arTypeCtor = {::System::String::typeid,
1484 ::System::Object::typeid};
1485 ::System::Reflection::ConstructorInfo ^ ctorDeploymentException =
1486 typeDeploymentExc->GetConstructor(arTypeCtor);
1488 Sequence<Reference<reflection::XServiceConstructorDescription> > seqCtors =
1489 xServiceType->getConstructors();
1491 ::System::Type ^ type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception", true);
1493 for (int j = seqCtors.getLength() - 1; j >= 0; j--)
1495 bool bParameterArray = false;
1496 ::System::Type ^ typeAny = ::uno::Any::typeid;
1497 const Reference<reflection::XServiceConstructorDescription> & ctorDes =
1498 seqCtors[j];
1499 //obtain the parameter types
1500 const Sequence<Reference<reflection::XParameter> > seqParams =
1501 ctorDes->getParameters();
1502 sal_Int32 cParams = seqParams.getLength();
1503 array< ::System::Type^>^ arTypeParameters = gcnew array< ::System::Type^> (cParams + 1);
1504 arTypeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1505 for (int iparam = 0; iparam != cParams; iparam++)
1507 if (seqParams[iparam]->isRestParameter())
1508 arTypeParameters[iparam + 1] = array< ::uno::Any>::typeid;
1509 else
1510 arTypeParameters[iparam + 1] = get_type(seqParams[iparam]->getType());
1512 //The array arTypeParameters can contain:
1513 //System.Type and uno.PolymorphicType.
1514 //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem.
1515 //The exception will read something like no on information for parameter # d
1516 //Maybe we need no override another Type method in PolymorphicType ...
1517 //Until we have figured this out, we will create another array of System.Type which
1518 //we pass on to DefineMethod.
1519 array< ::System::Type^>^ arParamTypes = gcnew array< ::System::Type^> (cParams + 1);
1520 // arParamTypes[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1521 for (int i = 0; i < cParams + 1; i++)
1523 ::uno::PolymorphicType ^ pT = dynamic_cast< ::uno::PolymorphicType ^ >(arTypeParameters[i]);
1524 if (pT)
1525 arParamTypes[i] = pT->OriginalType;
1526 else
1527 arParamTypes[i] = arTypeParameters[i];
1529 //define method
1530 System::String ^ ctorName;
1531 if (ctorDes->isDefaultConstructor())
1532 ctorName = gcnew ::System::String("create");
1533 else
1534 ctorName = ustring_to_String(ctorDes->getName());
1535 Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
1536 ctorName,
1537 static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
1538 MethodAttributes::Static),
1539 retType,
1540 // arTypeParameters);
1541 arParamTypes);
1543 //define UNO exception attribute (exceptions)--------------------------------------
1544 Emit::CustomAttributeBuilder^ attrBuilder = get_service_exception_attribute(ctorDes);
1545 if (attrBuilder != nullptr)
1546 method_builder->SetCustomAttribute(attrBuilder);
1549 //define parameter attributes (paramarray), names etc.
1550 //The first parameter is the XComponentContext, which cannot be obtained
1551 //from reflection.
1552 //The context is not part of the idl description
1553 method_builder->DefineParameter(
1554 1, ParameterAttributes::In, "the_context");
1556 array<Emit::ParameterBuilder^>^ arParameterBuilder =
1557 gcnew array<Emit::ParameterBuilder^> (cParams);
1558 for (int iparam = 0; iparam != cParams; iparam++)
1560 Reference<reflection::XParameter> const & aParam = seqParams[iparam];
1561 ::System::String ^ sParamName = ustring_to_String(aParam->getName());
1563 arParameterBuilder[iparam] = method_builder->DefineParameter(
1564 iparam + 2, ParameterAttributes::In, sParamName);
1566 if (aParam->isRestParameter())
1568 bParameterArray = true;
1569 //set the ParameterArrayAttribute
1570 ::System::Reflection::ConstructorInfo^ ctor_info =
1571 System::ParamArrayAttribute::typeid->GetConstructor(
1572 gcnew array< ::System::Type^>(0));
1573 Emit::CustomAttributeBuilder ^ attr_builder =
1574 gcnew Emit::CustomAttributeBuilder(ctor_info, gcnew array< ::System::Object^>(0));
1575 arParameterBuilder[iparam]->SetCustomAttribute(attr_builder);
1576 break;
1580 Emit::ILGenerator ^ ilGen = method_builder->GetILGenerator();
1582 //Define locals ---------------------------------
1583 //XMultiComponentFactory
1584 Emit::LocalBuilder^ local_factory =
1585 ilGen->DeclareLocal(
1586 get_type("unoidl.com.sun.star.lang.XMultiComponentFactory", true));
1588 //The return type
1589 Emit::LocalBuilder^ local_return_val =
1590 ilGen->DeclareLocal(retType);
1592 //Obtain the XMultiComponentFactory and throw an exception if we do not get one
1593 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1595 ::System::Reflection::MethodInfo ^ methodGetServiceManager = get_type(
1596 "unoidl.com.sun.star.uno.XComponentContext", true)
1597 ->GetMethod("getServiceManager");
1598 ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager);
1599 ilGen->Emit(Emit::OpCodes::Stloc, local_factory);
1600 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1601 Emit::Label label1 = ilGen->DefineLabel();
1602 ilGen->Emit(Emit::OpCodes::Brtrue, label1);
1603 //The string for the exception
1604 ::System::Text::StringBuilder ^ strbuilder = gcnew ::System::Text::StringBuilder(256);
1605 strbuilder->Append("The service ");
1606 strbuilder->Append(to_cts_name(xServiceType->getName()));
1607 strbuilder->Append(" could not be created. The context failed to supply the service manager.");
1609 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1610 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1611 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1612 ilGen->Emit(Emit::OpCodes::Throw);
1613 ilGen->MarkLabel(label1);
1615 //We create a try/ catch around the createInstanceWithContext, etc. functions
1616 //There are 3 cases
1617 //1. function do not specify exceptions. Then RuntimeExceptions are re-thrown and other
1618 // exceptions produce a DeploymentException.
1619 //2. function specify Exception. Then all exceptions fly through
1620 //3. function specifies exceptions but no Exception. Then these are rethrown
1621 // and other exceptions, except RuntimeException, produce a deployment exception.
1622 //In case there are no parameters we call
1623 //XMultiComponentFactory.createInstanceWithContext
1625 ::System::Collections::ArrayList ^ arExceptionTypes =
1626 get_service_ctor_method_exceptions_reduced(ctorDes->getExceptions());
1627 if (arExceptionTypes->Contains(
1628 type_uno_exception) == false)
1630 ilGen->BeginExceptionBlock();
1632 if (cParams == 0)
1634 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1635 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1636 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1638 ::System::Reflection::MethodInfo ^ methodCreate =
1639 local_factory->LocalType->GetMethod("createInstanceWithContext");
1640 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1642 else if(bParameterArray)
1644 //Service constructor with parameter array
1645 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1646 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1647 ilGen->Emit(Emit::OpCodes::Ldarg_1);
1648 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1649 ::System::Reflection::MethodInfo ^ methodCreate =
1650 local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1651 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1653 else
1655 // Any param1, Any param2, etc.
1656 // For each parameter,except the component context, and parameter array
1657 // and Any is created.
1658 array<Emit::LocalBuilder^>^ arLocalAny = gcnew array<Emit::LocalBuilder^> (cParams);
1660 for (int iParam = 0; iParam < cParams; iParam ++)
1662 arLocalAny[iParam] = ilGen->DeclareLocal(typeAny);
1665 //Any[]. This array is filled with the created Anys which contain the parameters
1666 //and the values contained in the parameter array
1667 Emit::LocalBuilder ^ local_anyParams =
1668 ilGen->DeclareLocal(array< ::uno::Any>::typeid);
1670 //Create the Any for every argument, except for the parameter array
1671 //arLocalAny contains the LocalBuilder for all these parameters.
1672 //we call the ctor Any(Type, Object)
1673 //If the parameter is an Any then the Any is created with Any(param.Type, param.Value);
1674 array< ::System::Type^>^ arTypesCtorAny = {::System::Type::typeid,
1675 ::System::Object::typeid};
1676 ::System::Reflection::ConstructorInfo ^ ctorAny =
1677 typeAny->GetConstructor( arTypesCtorAny);
1678 ::System::Reflection::MethodInfo ^ methodAnyGetType =
1679 typeAny->GetProperty("Type")->GetGetMethod();
1680 ::System::Reflection::MethodInfo ^ methodAnyGetValue =
1681 typeAny->GetProperty("Value")->GetGetMethod();
1682 for (int i = 0; i < arLocalAny->Length; i ++)
1684 //check if the parameter is a polymorphic struct
1685 ::uno::PolymorphicType ^polyType = dynamic_cast< ::uno::PolymorphicType^ >(arTypeParameters[i+1]);
1686 //arTypeParameters[i+1] = polyType->OriginalType;
1687 if (polyType)
1689 //It is a polymorphic struct
1690 //Load the uninitialized local Any on which we will call the ctor
1691 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1692 // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName)
1693 // Prepare the first parameter
1694 ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->OriginalType);
1695 array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1696 ilGen->Emit(Emit::OpCodes::Call,
1697 ::System::Type::typeid->GetMethod(
1698 "GetTypeFromHandle", arTypeParams));
1699 // Prepare the second parameter
1700 ilGen->Emit(Emit::OpCodes::Ldstr, polyType->PolymorphicName);
1701 // Make the actual call
1702 array< ::System::Type^>^ arTypeParam_GetType = {
1703 ::System::Type::typeid, ::System::String::typeid };
1704 ilGen->Emit(Emit::OpCodes::Call,
1705 ::uno::PolymorphicType::typeid->GetMethod(gcnew System::String("GetType"),
1706 arTypeParam_GetType));
1708 //Stack is: localAny, PolymorphicType
1709 //Call Any::Any(Type, Object)
1710 //Prepare the second parameter for the any ctor
1711 ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1712 // if the parameter is a value type then we need to box it, because
1713 // the Any ctor takes an Object
1714 if (arTypeParameters[i+1]->IsValueType)
1715 ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1716 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1718 else if (arTypeParameters[i+1] == typeAny)
1720 //Create the call new Any(param.Type,param,Value)
1721 //Stack must be Any,Type,Value
1722 //First load the Any which is to be constructed
1723 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1724 //Load the Type, which is obtained by calling param.Type
1725 ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1726 ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType);
1727 //Load the Value, which is obtained by calling param.Value
1728 ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1729 ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue);
1730 //Call the Any ctor.
1731 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1733 else
1735 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1736 ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]);
1738 array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1739 ilGen->Emit(Emit::OpCodes::Call,
1740 ::System::Type::typeid->GetMethod(
1741 "GetTypeFromHandle", arTypeParams));
1742 ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1743 // if the parameter is a value type then we need to box it, because
1744 // the Any ctor takes an Object
1745 if (arTypeParameters[i+1]->IsValueType)
1746 ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1747 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1751 //Create the Any[] that is passed to the
1752 //createInstanceWithContext[AndArguments] function
1753 ilGen->Emit(Emit::OpCodes::Ldc_I4, arLocalAny->Length);
1754 ilGen->Emit(Emit::OpCodes::Newarr, typeAny);
1755 ilGen->Emit(Emit::OpCodes::Stloc, local_anyParams);
1757 //Assign all anys created from the parameters
1758 //array to the Any[]
1759 for (int i = 0; i < arLocalAny->Length; i++)
1761 ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1762 ilGen->Emit(Emit::OpCodes::Ldc_I4, i);
1763 ilGen->Emit(Emit::OpCodes::Ldelema, typeAny);
1764 ilGen->Emit(Emit::OpCodes::Ldloc, arLocalAny[i]);
1765 ilGen->Emit(Emit::OpCodes::Stobj, typeAny);
1767 // call createInstanceWithArgumentsAndContext
1768 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1769 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1770 ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1771 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1772 ::System::Reflection::MethodInfo ^ methodCreate =
1773 local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1774 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1776 //cast the object returned by the functions createInstanceWithContext or
1777 //createInstanceWithArgumentsAndContext to the interface type
1778 ilGen->Emit(Emit::OpCodes::Castclass, retType);
1779 ilGen->Emit(Emit::OpCodes::Stloc, local_return_val);
1781 //catch exceptions thrown by createInstanceWithArgumentsAndContext and createInstanceWithContext
1782 if (arExceptionTypes->Contains(type_uno_exception) == false)
1784 // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;}
1785 ilGen->BeginCatchBlock(get_type("unoidl.com.sun.star.uno.RuntimeException", true));
1786 ilGen->Emit(Emit::OpCodes::Pop);
1787 ilGen->Emit(Emit::OpCodes::Rethrow);
1789 //catch and rethrow all other defined Exceptions
1790 for (int i = 0; i < arExceptionTypes->Count; i++)
1792 ::System::Type ^ excType = safe_cast< ::System::Type^ >(
1793 arExceptionTypes[i]);
1794 if (excType->IsInstanceOfType(
1795 get_type("unoidl.com.sun.star.uno.RuntimeException", true)))
1796 {// we have a catch for RuntimeException already defined
1797 continue;
1800 //catch Exception and rethrow
1801 ilGen->BeginCatchBlock(excType);
1802 ilGen->Emit(Emit::OpCodes::Pop);
1803 ilGen->Emit(Emit::OpCodes::Rethrow);
1805 //catch (unoidl.com.sun.star.uno.Exception) {throw DeploymentException...}
1806 ilGen->BeginCatchBlock(type_uno_exception);
1808 //Define the local variable that keeps the exception
1809 Emit::LocalBuilder ^ local_exception = ilGen->DeclareLocal(
1810 type_uno_exception);
1812 //Store the exception
1813 ilGen->Emit(Emit::OpCodes::Stloc, local_exception);
1815 //prepare the construction of the exception
1816 strbuilder = gcnew ::System::Text::StringBuilder(256);
1817 strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1818 strbuilder->Append(to_cts_name(xServiceType->getName()));
1819 strbuilder->Append(": ");
1821 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1823 //add to the string the Exception.Message
1824 ilGen->Emit(Emit::OpCodes::Ldloc, local_exception);
1825 ilGen->Emit(Emit::OpCodes::Callvirt,
1826 type_uno_exception->GetProperty("Message")->GetGetMethod());
1827 array< ::System::Type^>^ arConcatParams = {System::String::typeid,
1828 System::String::typeid};
1829 ilGen->Emit(Emit::OpCodes::Call,
1830 System::String::typeid->GetMethod("Concat", arConcatParams));
1831 //load context argument
1832 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1833 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1834 ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1836 ilGen->EndExceptionBlock();
1840 //Check if the service instance was created and threw an exception if not
1841 Emit::Label label_service_created = ilGen->DefineLabel();
1842 ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1843 ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created);
1845 strbuilder = gcnew ::System::Text::StringBuilder(256);
1846 strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1847 strbuilder->Append(to_cts_name(xServiceType->getName()));
1848 strbuilder->Append(".");
1849 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1850 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1851 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1852 ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1854 ilGen->MarkLabel(label_service_created);
1855 ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1856 ilGen->Emit(Emit::OpCodes::Ret);
1859 // remove from incomplete types map
1860 ::System::String ^ cts_name = type_builder->FullName;
1861 m_incomplete_services->Remove( cts_name );
1862 xServiceType->release();
1863 if (g_bVerbose)
1865 ::System::Console::WriteLine(
1866 "> emitting service type {0}", cts_name );
1868 return type_builder->CreateType();
1872 Emit::CustomAttributeBuilder^ TypeEmitter::get_service_exception_attribute(
1873 const Reference<reflection::XServiceConstructorDescription> & ctorDes )
1875 return get_exception_attribute(ctorDes->getExceptions());
1878 Emit::CustomAttributeBuilder^ TypeEmitter::get_iface_method_exception_attribute(
1879 const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod )
1882 const Sequence<Reference<reflection::XTypeDescription> > seqTD = xMethod->getExceptions();
1883 int len = seqTD.getLength();
1884 Sequence<Reference<reflection::XCompoundTypeDescription> > seqCTD(len);
1885 Reference<reflection::XCompoundTypeDescription> * arCTD = seqCTD.getArray();
1886 for (int i = 0; i < len; i++)
1887 arCTD[i] = Reference<reflection::XCompoundTypeDescription>(seqTD[i], UNO_QUERY_THROW);
1888 return get_exception_attribute(seqCTD);
1891 Emit::CustomAttributeBuilder^ TypeEmitter::get_exception_attribute(
1893 const Sequence<Reference< reflection::XCompoundTypeDescription > >& seq_exceptionsTd )
1895 Emit::CustomAttributeBuilder ^ attr_builder = nullptr;
1897 array< ::System::Type^>^ arTypesCtor = {::System::Type::GetType("System.Type[]")};
1898 ConstructorInfo ^ ctor_ExceptionAttribute =
1899 ::uno::ExceptionAttribute::typeid->GetConstructor(arTypesCtor);
1901 sal_Int32 exc_length = seq_exceptionsTd.getLength();
1902 if (exc_length != 0) // opt
1904 array< ::System::Type^>^ exception_types =
1905 gcnew array< ::System::Type^> ( exc_length );
1906 for ( sal_Int32 exc_pos = 0; exc_pos < exc_length; ++exc_pos )
1908 Reference< reflection::XCompoundTypeDescription > const & xExc =
1909 seq_exceptionsTd[ exc_pos ];
1910 exception_types[ exc_pos ] = get_type( xExc );
1912 array< ::System::Object^>^ args = {exception_types};
1913 attr_builder = gcnew Emit::CustomAttributeBuilder(
1914 ctor_ExceptionAttribute, args );
1916 return attr_builder;
1920 ::System::Type ^ TypeEmitter::complete_singleton_type(singleton_entry ^ entry)
1922 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
1923 reflection::XSingletonTypeDescription2 * xSingletonType = entry->m_xType;
1924 ::System::String^ sSingletonName = to_cts_name(xSingletonType->getName());
1926 //Create the private default constructor
1927 Emit::ConstructorBuilder^ ctor_builder =
1928 type_builder->DefineConstructor(
1929 static_cast<MethodAttributes>(MethodAttributes::Private |
1930 MethodAttributes::HideBySig |
1931 MethodAttributes::SpecialName |
1932 MethodAttributes::RTSpecialName),
1933 CallingConventions::Standard, nullptr);
1935 Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator();
1936 ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1937 ilGen->Emit(
1938 Emit::OpCodes::Call,
1939 type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
1940 ilGen->Emit( Emit::OpCodes::Ret );
1943 //obtain the interface which makes up this service, it is the return
1944 //type of the constructor functions
1945 Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
1946 xSingletonType->getInterface(), UNO_QUERY);
1947 if (xIfaceType.is () == sal_False)
1948 xIfaceType = resolveInterfaceTypedef(xSingletonType->getInterface());
1949 System::Type ^ retType = get_type(xIfaceType);
1951 //define method
1952 array< ::System::Type^>^ arTypeParameters = {get_type("unoidl.com.sun.star.uno.XComponentContext", true)};
1953 Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
1954 gcnew System::String("get"),
1955 static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
1956 MethodAttributes::Static),
1957 retType,
1958 arTypeParameters);
1961 // method_builder->SetCustomAttribute(get_service_ctor_method_attribute(ctorDes));
1963 //The first parameter is the XComponentContext, which cannot be obtained
1964 //from reflection.
1965 //The context is not part of the idl description
1966 method_builder->DefineParameter(1, ParameterAttributes::In, "the_context");
1969 ilGen = method_builder->GetILGenerator();
1970 //Define locals ---------------------------------
1971 // Any, returned by XComponentContext.getValueByName
1972 Emit::LocalBuilder^ local_any =
1973 ilGen->DeclareLocal(::uno::Any::typeid);
1975 //Call XContext::getValueByName
1976 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1977 // build the singleton name : /singleton/unoidl.com.sun.star.XXX
1978 ::System::Text::StringBuilder^ sBuilder =
1979 gcnew ::System::Text::StringBuilder("/singletons/");
1980 sBuilder->Append(sSingletonName);
1981 ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
1983 ::System::Reflection::MethodInfo ^ methodGetValueByName =
1984 get_type("unoidl.com.sun.star.uno.XComponentContext", true)->GetMethod("getValueByName");
1985 ilGen->Emit(Emit::OpCodes::Callvirt, methodGetValueByName);
1986 ilGen->Emit(Emit::OpCodes::Stloc_0);
1988 //Contains the returned Any a value?
1989 ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
1990 ::System::Reflection::MethodInfo ^ methodHasValue =
1991 ::uno::Any::typeid->GetMethod("hasValue");
1992 ilGen->Emit(Emit::OpCodes::Call, methodHasValue);
1994 //If not, then throw a DeploymentException
1995 Emit::Label label_singleton_exists = ilGen->DefineLabel();
1996 ilGen->Emit(Emit::OpCodes::Brtrue_S, label_singleton_exists);
1997 sBuilder = gcnew ::System::Text::StringBuilder(
1998 "Component context fails to supply singleton ");
1999 sBuilder->Append(sSingletonName);
2000 sBuilder->Append(" of type ");
2001 sBuilder->Append(retType->FullName);
2002 sBuilder->Append(".");
2003 ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
2004 ilGen->Emit(Emit::OpCodes::Ldarg_0);
2005 array< ::System::Type^>^ arTypesCtorDeploymentException = {
2006 ::System::String::typeid, ::System::Object::typeid};
2007 ilGen->Emit(Emit::OpCodes::Newobj,
2008 get_type("unoidl.com.sun.star.uno.DeploymentException",true)
2009 ->GetConstructor(arTypesCtorDeploymentException));
2010 ilGen->Emit(Emit::OpCodes::Throw);
2011 ilGen->MarkLabel(label_singleton_exists);
2013 //Cast the singleton contained in the Any to the expected interface and return it.
2014 ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
2015 ilGen->Emit(Emit::OpCodes::Call, ::uno::Any::typeid->GetProperty("Value")->GetGetMethod());
2016 ilGen->Emit(Emit::OpCodes::Castclass, retType);
2017 ilGen->Emit(Emit::OpCodes::Ret);
2019 // remove from incomplete types map
2020 ::System::String ^ cts_name = type_builder->FullName;
2021 m_incomplete_singletons->Remove( cts_name );
2022 xSingletonType->release();
2023 if (g_bVerbose)
2025 ::System::Console::WriteLine(
2026 "> emitting singleton type {0}", cts_name );
2028 return type_builder->CreateType();
2032 ::System::Type ^ TypeEmitter::get_type(
2033 Reference< reflection::XTypeDescription > const & xType )
2035 switch (xType->getTypeClass())
2037 case TypeClass_VOID:
2038 return ::System::Void::typeid;
2039 case TypeClass_CHAR:
2040 return ::System::Char::typeid;
2041 case TypeClass_BOOLEAN:
2042 return ::System::Boolean::typeid;
2043 case TypeClass_BYTE:
2044 return ::System::Byte::typeid;
2045 case TypeClass_SHORT:
2046 return ::System::Int16::typeid;
2047 case TypeClass_UNSIGNED_SHORT:
2048 return ::System::UInt16::typeid;
2049 case TypeClass_LONG:
2050 return ::System::Int32::typeid;
2051 case TypeClass_UNSIGNED_LONG:
2052 return ::System::UInt32::typeid;
2053 case TypeClass_HYPER:
2054 return ::System::Int64::typeid;
2055 case TypeClass_UNSIGNED_HYPER:
2056 return ::System::UInt64::typeid;
2057 case TypeClass_FLOAT:
2058 return ::System::Single::typeid;
2059 case TypeClass_DOUBLE:
2060 return ::System::Double::typeid;
2061 case TypeClass_STRING:
2062 return ::System::String::typeid;
2063 case TypeClass_TYPE:
2064 return ::System::Type::typeid;
2065 case TypeClass_ANY:
2066 return ::uno::Any::typeid;
2067 case TypeClass_ENUM:
2068 return get_type( Reference< reflection::XEnumTypeDescription >(
2069 xType, UNO_QUERY_THROW ) );
2070 case TypeClass_TYPEDEF:
2071 // unwind typedefs
2072 return get_type(
2073 Reference< reflection::XIndirectTypeDescription >(
2074 xType, UNO_QUERY_THROW )->getReferencedType() );
2075 case TypeClass_STRUCT:
2076 case TypeClass_EXCEPTION:
2077 return get_type(
2078 Reference< reflection::XCompoundTypeDescription >(
2079 xType, UNO_QUERY_THROW ) );
2080 case TypeClass_SEQUENCE:
2082 ::System::Type ^ element_type = get_type(
2083 Reference< reflection::XIndirectTypeDescription >(
2084 xType, UNO_QUERY_THROW )->getReferencedType() );
2085 ::System::Type ^ retType = get_type(
2086 ::System::String::Concat(
2087 element_type->FullName, "[]" ), true );
2089 ::uno::PolymorphicType ^ pt = dynamic_cast< ::uno::PolymorphicType ^ >(element_type);
2090 if (pt)
2092 ::System::String ^ sName = ::System::String::Concat(pt->PolymorphicName, "[]");
2093 retType = ::uno::PolymorphicType::GetType(retType, sName);
2095 return retType;
2097 case TypeClass_INTERFACE:
2098 return get_type(
2099 Reference< reflection::XInterfaceTypeDescription2 >(
2100 xType, UNO_QUERY_THROW ) );
2101 case TypeClass_CONSTANT:
2102 return get_type(
2103 Reference< reflection::XConstantTypeDescription >(
2104 xType, UNO_QUERY_THROW ) );
2105 case TypeClass_CONSTANTS:
2106 return get_type(
2107 Reference< reflection::XConstantsTypeDescription >(
2108 xType, UNO_QUERY_THROW ) );
2109 case TypeClass_SERVICE:
2110 return get_type(
2111 Reference< reflection::XServiceTypeDescription2 >(
2112 xType, UNO_QUERY_THROW) );
2113 case TypeClass_SINGLETON:
2114 return get_type(
2115 Reference< reflection::XSingletonTypeDescription2 >(
2116 xType, UNO_QUERY_THROW) );
2117 case TypeClass_MODULE:
2118 // ignore these
2119 return nullptr;
2120 default:
2121 throw RuntimeException(
2122 "unexpected type " + xType->getName() );
2127 ::System::Type ^ TypeEmitter::get_complete_struct( ::System::String ^ sName)
2129 struct_entry ^ pStruct = safe_cast< struct_entry ^>(
2130 m_incomplete_structs[sName]);
2131 if (pStruct)
2133 complete_struct_type(pStruct);
2135 //get_type will asked the module builder for the type or otherwise all known assemblies.
2136 return get_type(sName, true);
2138 void TypeEmitter::finish()
2140 while (true)
2142 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2143 m_incomplete_ifaces->GetEnumerator();
2144 if (! enumerator->MoveNext())
2145 break;
2146 complete_iface_type(
2147 safe_cast< iface_entry ^ >( enumerator->Value ) );
2150 while (true)
2152 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2153 m_incomplete_structs->GetEnumerator();
2154 if (! enumerator->MoveNext())
2155 break;
2156 complete_struct_type(
2157 safe_cast< struct_entry ^ >( enumerator->Value ) );
2161 while (true)
2163 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2164 m_incomplete_services->GetEnumerator();
2165 if (! enumerator->MoveNext())
2166 break;
2167 complete_service_type(
2168 safe_cast< service_entry ^ >( enumerator->Value ) );
2171 while (true)
2173 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2174 m_incomplete_singletons->GetEnumerator();
2175 if (! enumerator->MoveNext())
2176 break;
2177 complete_singleton_type(
2178 safe_cast< singleton_entry ^ >( enumerator->Value ) );
2182 TypeEmitter::TypeEmitter(
2183 ::System::Reflection::Emit::ModuleBuilder ^ module_builder,
2184 array< ::System::Reflection::Assembly^>^ extra_assemblies )
2185 : m_module_builder( module_builder ),
2186 m_extra_assemblies( extra_assemblies ),
2187 m_method_info_Type_GetTypeFromHandle( nullptr ),
2188 m_type_Exception( nullptr ),
2189 m_type_RuntimeException( nullptr ),
2190 m_incomplete_ifaces( gcnew ::System::Collections::Hashtable() ),
2191 m_incomplete_structs( gcnew ::System::Collections::Hashtable() ),
2192 m_incomplete_services(gcnew ::System::Collections::Hashtable() ),
2193 m_incomplete_singletons(gcnew ::System::Collections::Hashtable() ),
2194 m_generated_structs( gcnew ::System::Collections::Hashtable() )
2196 array< ::System::Type^>^ param_types = gcnew array< ::System::Type^> ( 1 );
2197 param_types[ 0 ] = ::System::RuntimeTypeHandle::typeid;
2198 m_method_info_Type_GetTypeFromHandle =
2199 ::System::Type::typeid
2200 ->GetMethod( "GetTypeFromHandle", param_types );
2203 ::System::Collections::ArrayList ^ TypeEmitter::get_service_ctor_method_exceptions_reduced(
2204 const Sequence<Reference<reflection::XCompoundTypeDescription> > & seqExceptionsTd)
2206 if (seqExceptionsTd.getLength() == 0)
2207 return gcnew ::System::Collections::ArrayList();
2209 ::System::Collections::ArrayList ^ arTypes = gcnew ::System::Collections::ArrayList();
2210 for (int i = 0; i < seqExceptionsTd.getLength(); i++)
2211 arTypes->Add(get_type(to_cts_name(seqExceptionsTd[i]->getName()), true));
2213 int start = 0;
2214 while (true)
2216 bool bRemove = false;
2217 for (int i = start; i < arTypes->Count; i++)
2219 ::System::Type ^ t = safe_cast< ::System::Type^ >(arTypes[i]);
2220 for (int j = 0; j < arTypes->Count; j++)
2222 if (t->IsSubclassOf(safe_cast< ::System::Type^ >(arTypes[j])))
2224 arTypes->RemoveAt(i);
2225 bRemove = true;
2226 break;
2229 if (bRemove)
2230 break;
2231 start++;
2234 if (bRemove == false)
2235 break;
2237 return arTypes;
2241 css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
2242 resolveInterfaceTypedef(
2243 const css::uno::Reference<css::reflection::XTypeDescription>& type)
2245 Reference<reflection::XInterfaceTypeDescription2>
2246 xIfaceTd(type, UNO_QUERY);
2248 if (xIfaceTd.is())
2249 return xIfaceTd;
2251 Reference<reflection::XIndirectTypeDescription> xIndTd(
2252 type, UNO_QUERY_THROW);
2254 return resolveInterfaceTypedef(xIndTd->getReferencedType());
2260 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */