bump product version to 4.2.0.1
[LibreOffice.git] / cli_ure / source / climaker / climaker_emit.cxx
blob628547135df925207d96fa15540e7c59149cb145
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 ::rtl;
35 using namespace ::com::sun::star;
36 using namespace ::com::sun::star::uno;
38 namespace climaker
40 System::String^ mapUnoPolymorphicName(System::String^ unoName);
41 //------------------------------------------------------------------------------
42 static inline ::System::String ^ to_cts_name(
43 OUString const & uno_name )
45 OUStringBuffer buf( 7 + uno_name.getLength() );
46 buf.append( "unoidl." );
47 buf.append( uno_name );
48 return ustring_to_String( buf.makeStringAndClear() );
51 //------------------------------------------------------------------------------
52 static inline ::System::Object ^ to_cli_constant( Any const & value )
54 switch (value.getValueTypeClass())
56 case TypeClass_CHAR:
57 return ((::System::Char) *reinterpret_cast< sal_Unicode const * >(
58 value.getValue() ));
59 case TypeClass_BOOLEAN:
60 return ((::System::Boolean)
61 sal_False != *reinterpret_cast< sal_Bool const * >(
62 value.getValue() ));
63 case TypeClass_BYTE:
64 return ((::System::Byte) *reinterpret_cast< sal_Int8 const * >(
65 value.getValue() ));
66 case TypeClass_SHORT:
67 return ((::System::Int16) *reinterpret_cast< sal_Int16 const * >(
68 value.getValue() ));
69 case TypeClass_UNSIGNED_SHORT:
70 return ((::System::UInt16) *reinterpret_cast< sal_uInt16 const * >(
71 value.getValue() ));
72 case TypeClass_LONG:
73 return ((::System::Int32) *reinterpret_cast< sal_Int32 const * >(
74 value.getValue() ));
75 case TypeClass_UNSIGNED_LONG:
76 return ((::System::UInt32) *reinterpret_cast< sal_uInt32 const * >(
77 value.getValue() ));
78 case TypeClass_HYPER:
79 return ((::System::Int64) *reinterpret_cast< sal_Int64 const * >(
80 value.getValue() ));
81 case TypeClass_UNSIGNED_HYPER:
82 return ((::System::UInt64) *reinterpret_cast< sal_uInt64 const * >(
83 value.getValue() ));
84 case TypeClass_FLOAT:
85 return ((::System::Single) *reinterpret_cast< float const * >(
86 value.getValue() ));
87 case TypeClass_DOUBLE:
88 return ((::System::Double) *reinterpret_cast< double const * >(
89 value.getValue() ));
90 default:
91 throw RuntimeException(
92 "unexpected constant type " +
93 value.getValueType().getTypeName(),
94 Reference< XInterface >() );
98 //------------------------------------------------------------------------------
99 static inline void emit_ldarg( Emit::ILGenerator ^ code, ::System::Int32 index )
101 switch (index)
103 case 0:
104 #pragma warning (push)
105 #pragma warning (disable: 4538)
106 code->Emit( Emit::OpCodes::Ldarg_0 );
107 #pragma warning (pop)
108 break;
109 case 1:
110 code->Emit( Emit::OpCodes::Ldarg_1 );
111 break;
112 case 2:
113 code->Emit( Emit::OpCodes::Ldarg_2 );
114 break;
115 case 3:
116 code->Emit( Emit::OpCodes::Ldarg_3 );
117 break;
118 default:
119 if (index < 0x100)
120 code->Emit( Emit::OpCodes::Ldarg_S, (::System::Byte) index );
121 else if (index < 0x8000)
122 code->Emit( Emit::OpCodes::Ldarg_S, (::System::Int16) index );
123 else
124 code->Emit( Emit::OpCodes::Ldarg, index );
125 break;
129 void polymorphicStructNameToStructName(::System::String ^* sPolyName)
131 if ((*sPolyName)->EndsWith(">") == false)
132 return;
134 int index = (*sPolyName)->IndexOf('<');
135 OSL_ASSERT(index != -1);
136 *sPolyName = (*sPolyName)->Substring(0, index);
140 System::String^ mapUnoTypeName(System::String ^ typeName)
142 ::System::Text::StringBuilder^ buf= gcnew System::Text::StringBuilder();
143 ::System::String ^ sUnoName = ::System::String::Copy(typeName);
144 //determine if the type is a sequence and its dimensions
145 int dims= 0;
146 if (typeName->StartsWith("["))//if (usUnoName[0] == '[')
148 int index= 1;
149 while (true)
151 if (typeName[index++] == ']')//if (usUnoName[index++] == ']')
152 dims++;
153 if (typeName[index++] != '[')//usUnoName[index++] != '[')
154 break;
156 sUnoName = sUnoName->Substring(index - 1);//usUnoName = usUnoName.copy(index - 1);
158 if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoBool)))
159 buf->Append(const_cast<System::String^>(Constants::sBoolean));
160 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoChar)))
161 buf->Append(const_cast<System::String^>(Constants::sChar));
162 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoByte)))
163 buf->Append(const_cast<System::String^>(Constants::sByte));
164 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoShort)))
165 buf->Append(const_cast<System::String^>(Constants::sInt16));
166 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoUShort)))
167 buf->Append(const_cast<System::String^>(Constants::sUInt16));
168 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoLong)))
169 buf->Append(const_cast<System::String^>(Constants::sInt32));
170 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoULong)))
171 buf->Append(const_cast<System::String^>(Constants::sUInt32));
172 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoHyper)))
173 buf->Append(const_cast<System::String^>(Constants::sInt64));
174 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoUHyper)))
175 buf->Append(const_cast<System::String^>(Constants::sUInt64));
176 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoFloat)))
177 buf->Append(const_cast<System::String^>(Constants::sSingle));
178 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoDouble)))
179 buf->Append(const_cast<System::String^>(Constants::sDouble));
180 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoString)))
181 buf->Append(const_cast<System::String^>(Constants::sString));
182 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoVoid)))
183 buf->Append(const_cast<System::String^>(Constants::sVoid));
184 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoType)))
185 buf->Append(const_cast<System::String^>(Constants::sType));
186 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoXInterface)))
187 buf->Append(const_cast<System::String^>(Constants::sObject));
188 else if (sUnoName->Equals(const_cast<System::String^>(Constants::sUnoAny)))
190 buf->Append(const_cast<System::String^>(Constants::sAny));
192 else
194 //put "unoidl." at the beginning
195 buf->Append(const_cast<System::String^>(Constants::sUnoidl));
196 buf->Append(mapUnoPolymorphicName(sUnoName));
198 // apend []
199 for (;dims--;)
200 buf->Append(const_cast<System::String^>(Constants::sBrackets));
202 return buf->ToString();
206 /** For example, there is a uno type
207 com.sun.star.Foo<char, long>.
208 The values in the type list
209 are uno types and are replaced by cli types, such as System.Char,
210 System.Int32, etc.
212 Strings can be as complicated as this
213 test.MyStruct<char,test.MyStruct<long, []string>>
215 System::String^ mapUnoPolymorphicName(System::String^ unoName)
217 int index = unoName->IndexOf('<');
218 if (index == -1)
219 return unoName;
221 System::Text::StringBuilder ^ builder =
222 gcnew System::Text::StringBuilder(unoName->Substring(0, index +1 ));
224 //Find the first occurrence of ','
225 //If the parameter is a polymorphic struct then we neede to ignore everything
226 //between the brackets because it can also contain commas
227 //get the type list within < and >
228 int endIndex = unoName->Length - 1;
229 index++;
230 int cur = index;
231 int countParams = 0;
232 while (cur <= endIndex)
234 System::Char c = unoName[cur];
235 if (c == ',' || c == '>')
237 //insert a comma if needed
238 if (countParams != 0)
239 builder->Append(",");
240 countParams++;
241 System::String ^ sParam = unoName->Substring(index, cur - index);
242 //skip the comma
243 cur++;
244 //the the index to the beginning of the next param
245 index = cur;
246 builder->Append(mapUnoTypeName(sParam));
248 else if (c == '<')
250 cur++;
251 //continue until the matching '>'
252 int numNested = 0;
253 for (;;cur++)
255 System::Char curChar = unoName[cur];
256 if (curChar == '<')
258 numNested ++;
260 else if (curChar == '>')
262 if (numNested > 0)
263 numNested--;
264 else
265 break;
269 cur++;
272 builder->Append((System::Char) '>');
273 return builder->ToString();
278 //______________________________________________________________________________
279 Assembly ^ TypeEmitter::type_resolve(
280 ::System::Object ^, ::System::ResolveEventArgs ^ args )
282 ::System::String ^ cts_name = args->Name;
283 ::System::Type ^ ret_type;
285 iface_entry ^ entry = dynamic_cast< iface_entry ^ >(m_incomplete_ifaces[cts_name] );
286 if (nullptr != entry)
287 ret_type = entry->m_type_builder;
289 if (nullptr == ret_type)
291 sal_Int32 len = m_extra_assemblies->Length;
292 for ( sal_Int32 pos = 0; pos < len; ++pos )
294 ret_type = m_extra_assemblies[ pos ]->GetType(
295 cts_name, false /* no exc */ );
296 if (nullptr != ret_type)
298 if (g_verbose)
300 ::System::Console::WriteLine(
301 "> resolving type {0} from {1}.",
302 cts_name, ret_type->Assembly->FullName );
304 break;
308 if (nullptr != ret_type)
309 return ret_type->Assembly;
310 return nullptr;
313 //______________________________________________________________________________
314 ::System::Type ^ TypeEmitter::get_type(
315 ::System::String ^ cts_name, bool throw_exc )
317 ::System::Type ^ ret_type = m_module_builder->GetType( cts_name, false );
318 //We get the type from the ModuleBuilder even if the type is not complete
319 //but have been defined.
320 //if (ret_type == 0)
322 // iface_entry * entry = dynamic_cast< iface_entry * >(
323 // m_incomplete_ifaces->get_Item( cts_name ) );
324 // if (0 != entry)
325 // ret_type = entry->m_type_builder;
327 //try the cli_basetypes assembly
328 if (ret_type == nullptr)
330 ::System::Text::StringBuilder ^ builder = gcnew ::System::Text::StringBuilder(cts_name);
331 builder->Append(",cli_basetypes");
332 ret_type = ::System::Type::GetType(builder->ToString());
335 if (ret_type == nullptr)
339 // may call on type_resolve()
340 return ::System::Type::GetType( cts_name, throw_exc );
342 catch (::System::Exception^ exc)
344 //If the type is not found one may have forgotten to specify assemblies with
345 //additional types
346 ::System::Text::StringBuilder ^ sb = gcnew ::System::Text::StringBuilder();
347 sb->Append(gcnew ::System::String("\nThe type "));
348 sb->Append(cts_name);
349 sb->Append(gcnew ::System::String(" \n could not be found. Did you forget to " \
350 "specify an additional assembly with the --reference option?\n"));
351 if (throw_exc)
352 throw gcnew ::System::Exception(sb->ToString(), exc);
355 else
357 return ret_type;
361 //______________________________________________________________________________
362 ::System::Type ^ TypeEmitter::get_type_Exception()
364 if (nullptr == m_type_Exception)
366 m_type_Exception = get_type(
367 "unoidl.com.sun.star.uno.Exception", false /* no exc */ );
368 if (nullptr == m_type_Exception)
370 // define hardcoded type unoidl.com.sun.star.uno.Exception
371 Emit::TypeBuilder ^ type_builder =
372 m_module_builder->DefineType(
373 "unoidl.com.sun.star.uno.Exception",
374 (TypeAttributes) (TypeAttributes::Public |
375 TypeAttributes::BeforeFieldInit |
376 TypeAttributes::AnsiClass),
377 (::System::Exception::typeid) );
378 Emit::FieldBuilder ^ field_Context = type_builder->DefineField(
379 "Context", (::System::Object::typeid),
380 FieldAttributes::Public );
381 // default .ctor
382 type_builder->DefineDefaultConstructor( c_ctor_method_attr );
383 // .ctor
384 array< ::System::Type^>^ param_types =
385 gcnew array< ::System::Type^>(2);
386 param_types[ 0 ] = ::System::String::typeid;
387 param_types[ 1 ] = ::System::Object::typeid;
388 Emit::ConstructorBuilder ^ ctor_builder =
389 type_builder->DefineConstructor(
390 c_ctor_method_attr, CallingConventions::Standard,
391 param_types );
392 ctor_builder->DefineParameter(
393 1, ParameterAttributes::In, "Message" );
394 ctor_builder->DefineParameter(
395 2, ParameterAttributes::In, "Context" );
396 Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
397 code->Emit( Emit::OpCodes::Ldarg_0 );
398 code->Emit( Emit::OpCodes::Ldarg_1 );
399 param_types = gcnew array< ::System::Type^>(1);
400 param_types[ 0 ] = ::System::String::typeid;
401 code->Emit(
402 Emit::OpCodes::Call,
403 (::System::Exception::typeid)
404 ->GetConstructor( param_types ) );
405 code->Emit( Emit::OpCodes::Ldarg_0 );
406 code->Emit( Emit::OpCodes::Ldarg_2 );
407 code->Emit( Emit::OpCodes::Stfld, field_Context );
408 code->Emit( Emit::OpCodes::Ret );
410 if (g_verbose)
412 ::System::Console::WriteLine(
413 "> emitting exception type "
414 "unoidl.com.sun.star.uno.Exception" );
416 m_type_Exception = type_builder->CreateType();
419 return m_type_Exception;
422 //______________________________________________________________________________
423 ::System::Type ^ TypeEmitter::get_type_RuntimeException()
425 if (nullptr == m_type_RuntimeException)
427 m_type_RuntimeException = get_type(
428 "unoidl.com.sun.star.uno.RuntimeException", false /* no exc */ );
429 if (nullptr == m_type_RuntimeException)
431 // define hardcoded type unoidl.com.sun.star.uno.RuntimeException
432 ::System::Type ^ type_Exception = get_type_Exception();
433 Emit::TypeBuilder ^ type_builder =
434 m_module_builder->DefineType(
435 "unoidl.com.sun.star.uno.RuntimeException",
436 (TypeAttributes) (TypeAttributes::Public |
437 TypeAttributes::BeforeFieldInit |
438 TypeAttributes::AnsiClass),
439 type_Exception );
440 // default .ctor
441 type_builder->DefineDefaultConstructor( c_ctor_method_attr );
442 // .ctor
443 array< ::System::Type^>^ param_types =
444 gcnew array< ::System::Type^>(2);
445 param_types[ 0 ] = ::System::String::typeid;
446 param_types[ 1 ] = ::System::Object::typeid;
447 Emit::ConstructorBuilder ^ ctor_builder =
448 type_builder->DefineConstructor(
449 c_ctor_method_attr, CallingConventions::Standard,
450 param_types );
451 ctor_builder->DefineParameter(
452 1, ParameterAttributes::In, "Message" );
453 ctor_builder->DefineParameter(
454 2, ParameterAttributes::In, "Context" );
455 Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
456 code->Emit( Emit::OpCodes::Ldarg_0 );
457 code->Emit( Emit::OpCodes::Ldarg_1 );
458 code->Emit( Emit::OpCodes::Ldarg_2 );
459 code->Emit(
460 Emit::OpCodes::Call,
461 type_Exception->GetConstructor( param_types ) );
462 code->Emit( Emit::OpCodes::Ret );
464 if (g_verbose)
466 ::System::Console::WriteLine(
467 "> emitting exception type "
468 "unoidl.com.sun.star.uno.RuntimeException" );
470 m_type_RuntimeException = type_builder->CreateType();
473 return m_type_RuntimeException;
476 //______________________________________________________________________________
477 ::System::Type ^ TypeEmitter::get_type(
478 Reference< reflection::XConstantTypeDescription > const & xType )
480 ::System::String ^ cts_name = to_cts_name( xType->getName() );
481 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
482 if (nullptr == ret_type)
484 Reference< reflection::XConstantTypeDescription > xConstant(
485 xType, UNO_QUERY_THROW );
486 ::System::Object ^ constant =
487 to_cli_constant( xConstant->getConstantValue() );
488 Emit::TypeBuilder ^ type_builder =
489 m_module_builder->DefineType(
490 cts_name,
491 (TypeAttributes) (TypeAttributes::Public |
492 TypeAttributes::Sealed |
493 TypeAttributes::BeforeFieldInit |
494 TypeAttributes::AnsiClass) );
496 Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
497 cts_name->Substring( cts_name->LastIndexOf( '.' ) +1 ),
498 constant->GetType(),
499 (FieldAttributes) (FieldAttributes::Public |
500 FieldAttributes::Static |
501 FieldAttributes::Literal) );
502 field_builder->SetConstant( constant );
504 if (g_verbose)
506 ::System::Console::WriteLine(
507 "> emitting constant type {0}", cts_name );
509 ret_type = type_builder->CreateType();
511 return ret_type;
514 //______________________________________________________________________________
515 ::System::Type ^ TypeEmitter::get_type(
516 Reference< reflection::XConstantsTypeDescription > const & xType )
518 ::System::String ^ cts_name = to_cts_name( xType->getName() );
519 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
520 if (nullptr == ret_type)
522 Emit::TypeBuilder ^ type_builder =
523 m_module_builder->DefineType(
524 cts_name,
525 (TypeAttributes) (TypeAttributes::Public |
526 TypeAttributes::Sealed |
527 TypeAttributes::BeforeFieldInit |
528 TypeAttributes::AnsiClass) );
530 Sequence< Reference<
531 reflection::XConstantTypeDescription > > seq_constants(
532 xType->getConstants() );
533 Reference< reflection::XConstantTypeDescription > const * constants =
534 seq_constants.getConstArray();
535 sal_Int32 constants_length = seq_constants.getLength();
536 for ( sal_Int32 constants_pos = 0;
537 constants_pos < constants_length; ++constants_pos )
539 Reference<
540 reflection::XConstantTypeDescription > const & xConstant =
541 constants[ constants_pos ];
542 ::System::Object ^ constant =
543 to_cli_constant( xConstant->getConstantValue() );
544 ::System::String ^ uno_name =
545 ustring_to_String( xConstant->getName() );
546 Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
547 uno_name->Substring( uno_name->LastIndexOf( '.' ) +1 ),
548 constant->GetType(),
549 (FieldAttributes) (FieldAttributes::Public |
550 FieldAttributes::Static |
551 FieldAttributes::Literal) );
552 field_builder->SetConstant( constant );
555 if (g_verbose)
557 ::System::Console::WriteLine(
558 "> emitting constants group type {0}", cts_name );
560 ret_type = type_builder->CreateType();
562 return ret_type;
565 //______________________________________________________________________________
566 ::System::Type ^ TypeEmitter::get_type(
567 Reference< reflection::XEnumTypeDescription > const & xType )
569 ::System::String ^ cts_name = to_cts_name( xType->getName() );
570 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
571 if (nullptr == ret_type)
573 // Emit::EnumBuilder * enum_builder =
574 // m_module_builder->DefineEnum(
575 // cts_name,
576 // (TypeAttributes) (TypeAttributes::Public |
577 // // TypeAttributes::Sealed |
578 // TypeAttributes::AnsiClass),
579 // __typeof (::System::Int32) );
580 // workaround enum builder bug
581 Emit::TypeBuilder ^ enum_builder =
582 m_module_builder->DefineType(
583 cts_name,
584 (TypeAttributes) (TypeAttributes::Public |
585 TypeAttributes::Sealed),
586 ::System::Enum::typeid );
587 enum_builder->DefineField(
588 "value__", ::System::Int32::typeid,
589 (FieldAttributes) (FieldAttributes::Private |
590 FieldAttributes::SpecialName |
591 FieldAttributes::RTSpecialName) );
592 Sequence< OUString > seq_enum_names( xType->getEnumNames() );
593 Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() );
594 sal_Int32 enum_length = seq_enum_names.getLength();
595 OSL_ASSERT( enum_length == seq_enum_values.getLength() );
596 OUString const * enum_names = seq_enum_names.getConstArray();
597 sal_Int32 const * enum_values = seq_enum_values.getConstArray();
598 for ( sal_Int32 enum_pos = 0; enum_pos < enum_length; ++enum_pos )
600 // enum_builder->DefineLiteral(
601 // ustring_to_String( enum_names[ enum_pos ] ),
602 // __box ((::System::Int32) enum_values[ enum_pos ]) );
603 Emit::FieldBuilder ^ field_builder =
604 enum_builder->DefineField(
605 ustring_to_String( enum_names[ enum_pos ] ),
606 enum_builder,
607 (FieldAttributes) (FieldAttributes::Public |
608 FieldAttributes::Static |
609 FieldAttributes::Literal) );
610 field_builder->SetConstant(
611 ((::System::Int32) enum_values[ enum_pos ]) );
614 if (g_verbose)
616 ::System::Console::WriteLine(
617 "> emitting enum type {0}", cts_name );
619 ret_type = enum_builder->CreateType();
621 return ret_type;
624 //______________________________________________________________________________
625 ::System::Type ^ TypeEmitter::get_type(
626 Reference< reflection::XCompoundTypeDescription > const & xType )
628 OUString uno_name( xType->getName() );
629 if (TypeClass_EXCEPTION == xType->getTypeClass())
631 if ( uno_name == "com.sun.star.uno.Exception" )
633 return get_type_Exception();
635 if ( uno_name == "com.sun.star.uno.RuntimeException" )
637 return get_type_RuntimeException();
640 ::System::String ^ cts_name = to_cts_name( uno_name );
641 // if the struct is an instantiated polymorpic struct then we create the simple struct name
642 // For example:
643 // void func ([in] PolyStruct<boolean> arg);
644 //PolyStruct<boolean> will be converted to PolyStruct
645 polymorphicStructNameToStructName( & cts_name);
647 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
648 if (nullptr == ret_type)
650 Reference< reflection::XCompoundTypeDescription > xBaseType(
651 xType->getBaseType(), UNO_QUERY );
652 ::System::Type ^ base_type = (xBaseType.is()
653 ? get_type( xBaseType )
654 : ::System::Object::typeid);
655 Emit::TypeBuilder ^ type_builder =
656 m_module_builder->DefineType(
657 cts_name,
658 (TypeAttributes) (TypeAttributes::Public |
659 TypeAttributes::BeforeFieldInit |
660 TypeAttributes::AnsiClass),
661 base_type );
664 // insert to be completed
665 struct_entry ^ entry = gcnew struct_entry();
666 xType->acquire();
667 entry->m_xType = xType.get();
668 entry->m_type_builder = type_builder;
669 entry->m_base_type = base_type;
670 m_incomplete_structs->Add( cts_name, entry );
672 // type is incomplete
673 ret_type = type_builder;
676 //In case of an instantiated polymorphic struct we want to return a
677 //uno.PolymorphicType (inherits Type) rather then Type. This is neaded for constructing
678 //the service code. We can only do that if the struct is completed.
679 if (m_generated_structs[cts_name])
681 Reference< reflection::XStructTypeDescription> xStructTypeDesc(
682 xType, UNO_QUERY);
684 if (xStructTypeDesc.is())
686 Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments();
687 sal_Int32 numTypes = seqTypeArgs.getLength();
688 if (numTypes > 0)
690 //it is an instantiated polymorphic struct
691 ::System::String ^ sCliName = mapUnoTypeName(ustring_to_String(xType->getName()));
692 ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName);
696 return ret_type;
699 //______________________________________________________________________________
700 ::System::Type ^ TypeEmitter::get_type(
701 Reference< reflection::XInterfaceTypeDescription2 > const & xType )
703 OUString uno_name( xType->getName() );
704 if ( uno_name == "com.sun.star.uno.XInterface" )
706 return ::System::Object::typeid;
709 ::System::String ^ cts_name = to_cts_name( xType->getName() );
710 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
711 if (nullptr == ret_type)
713 Emit::TypeBuilder ^ type_builder;
715 TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
716 TypeAttributes::Interface |
717 TypeAttributes::Abstract |
718 TypeAttributes::AnsiClass);
720 std::vector<Reference<reflection::XInterfaceTypeDescription2> > vecBaseTypes;
721 Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes =
722 xType->getBaseTypes();
723 if (seqBaseTypes.getLength() > 0)
725 for (int i = 0; i < seqBaseTypes.getLength(); i++)
727 Reference<reflection::XInterfaceTypeDescription2> xIfaceTd =
728 resolveInterfaceTypedef(seqBaseTypes[i]);
730 if ( xIfaceTd->getName() != "com.sun.star.uno.XInterface" )
732 vecBaseTypes.push_back(xIfaceTd);
736 array< ::System::Type^>^ base_interfaces =
737 gcnew array< ::System::Type^>( vecBaseTypes.size() );
739 typedef std::vector<Reference<reflection::XInterfaceTypeDescription2> >::const_iterator it;
740 int index = 0;
741 for (it i = vecBaseTypes.begin(); i != vecBaseTypes.end(); ++i, ++index)
742 base_interfaces[ index ] = get_type( *i );
743 type_builder = m_module_builder->DefineType(
744 cts_name, attr, nullptr, base_interfaces );
746 else
748 ::System::Console::WriteLine(
749 "warning: IDL interface {0} is not derived from "
750 "com.sun.star.uno.XInterface!",
751 ustring_to_String( uno_name ) );
753 type_builder = m_module_builder->DefineType( cts_name, attr );
756 // insert to be completed
757 iface_entry ^ entry = gcnew iface_entry();
758 xType->acquire();
759 entry->m_xType = xType.get();
760 entry->m_type_builder = type_builder;
761 m_incomplete_ifaces->Add( cts_name, entry );
763 // type is incomplete
764 ret_type = type_builder;
766 return ret_type;
770 //______________________________________________________________________________
771 ::System::Type ^ TypeEmitter::get_type(
772 Reference< reflection::XServiceTypeDescription2 > const & xType )
774 if (xType->isSingleInterfaceBased() == sal_False)
775 return nullptr;
777 System::String ^ cts_name = to_cts_name( xType->getName() );
778 System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
779 if (ret_type != nullptr)
780 return ret_type;
782 TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
783 TypeAttributes::Sealed |
784 TypeAttributes::BeforeFieldInit |
785 TypeAttributes::AnsiClass);
787 Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
788 cts_name, attr);
790 // insert to be completed
791 service_entry ^ entry = gcnew service_entry();
792 xType->acquire();
793 entry->m_xType = xType.get();
794 entry->m_type_builder = type_builder;
795 m_incomplete_services->Add(cts_name,entry );
797 return type_builder;
800 ::System::Type ^ TypeEmitter::get_type(
801 Reference<reflection::XSingletonTypeDescription2 > const & xType )
803 if (xType->isInterfaceBased() == sal_False)
804 return nullptr;
806 ::System::String^ cts_name = to_cts_name( xType->getName() );
807 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
808 if (ret_type != nullptr)
809 return ret_type;
811 TypeAttributes attr = static_cast<TypeAttributes>(
812 TypeAttributes::Public |
813 TypeAttributes::Sealed |
814 TypeAttributes::BeforeFieldInit |
815 TypeAttributes::AnsiClass);
817 Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
818 cts_name, attr);
820 // insert to be completed
821 singleton_entry ^ entry = gcnew singleton_entry();
822 xType->acquire();
823 entry->m_xType = xType.get();
824 entry->m_type_builder = type_builder;
825 m_incomplete_singletons->Add(cts_name,entry );
827 return type_builder;
831 //______________________________________________________________________________
832 ::System::Type ^ TypeEmitter::complete_iface_type( iface_entry ^ entry )
834 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
835 reflection::XInterfaceTypeDescription2 * xType = entry->m_xType;
837 Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes( xType->getBaseTypes() );
838 if (seqBaseTypes.getLength() > 0)
840 for (int i = 0; i < seqBaseTypes.getLength(); i++)
842 //make sure we get the interface rather then a typedef
843 Reference<reflection::XInterfaceTypeDescription2> aBaseType =
844 resolveInterfaceTypedef( seqBaseTypes[i]);
846 if ( aBaseType->getName() != "com.sun.star.uno.XInterface" )
848 ::System::String ^ basetype_name = to_cts_name( aBaseType->getName() );
849 iface_entry ^ base_entry = dynamic_cast< iface_entry ^ >(
850 m_incomplete_ifaces[basetype_name] );
851 if (nullptr != base_entry)
853 // complete uncompleted base type first
854 complete_iface_type( base_entry );
860 Sequence<
861 Reference< reflection::XInterfaceMemberTypeDescription > > seq_members(
862 xType->getMembers() );
863 Reference< reflection::XInterfaceMemberTypeDescription > const * members =
864 seq_members.getConstArray();
865 sal_Int32 members_length = seq_members.getLength();
866 for ( sal_Int32 members_pos = 0;
867 members_pos < members_length; ++members_pos )
869 Reference<
870 reflection::XInterfaceMemberTypeDescription > const & xMember =
871 members[ members_pos ];
872 Sequence< Reference< reflection::XTypeDescription > > seq_exceptions;
873 Emit::MethodBuilder ^ method_builder;
875 MethodAttributes c_method_attr = (MethodAttributes)
876 (MethodAttributes::Public |
877 MethodAttributes::Abstract |
878 MethodAttributes::Virtual |
879 MethodAttributes::NewSlot |
880 MethodAttributes::HideBySig);
881 //#if defined(_MSC_VER) && (_MSC_VER < 1400)
882 // MethodAttributes::Instance);
883 //#else
884 // Instance);
885 //#endif
887 if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass())
889 Reference< reflection::XInterfaceMethodTypeDescription > xMethod(
890 xMember, UNO_QUERY_THROW );
892 Sequence<
893 Reference< reflection::XMethodParameter > > seq_parameters(
894 xMethod->getParameters() );
895 sal_Int32 params_length = seq_parameters.getLength();
896 array< ::System::Type^>^ param_types =
897 gcnew array< ::System::Type^>( params_length );
898 Reference< reflection::XMethodParameter > const * parameters =
899 seq_parameters.getConstArray();
900 // first determine all types
901 //Make the first param type as return type
902 sal_Int32 params_pos = 0;
903 for ( ; params_pos < params_length; ++params_pos )
905 Reference< reflection::XMethodParameter > const & xParam =
906 parameters[ params_pos ];
907 ::System::Type ^ param_type = get_type( xParam->getType() );
908 ::System::String ^ param_type_name = param_type->FullName;
909 if (xParam->isOut())
911 param_type = get_type(
912 ::System::String::Concat(
913 param_type_name, "&" ), true );
915 param_types[ xParam->getPosition() ] = param_type;
919 // create method
920 // if (tb)
921 // method_builder = type_builder->DefineMethod(
922 // ustring_to_String( xMethod->getMemberName() ),
923 // c_method_attr, tb,
924 // param_types );
925 // else
926 method_builder = type_builder->DefineMethod(
927 ustring_to_String( xMethod->getMemberName() ),
928 c_method_attr, get_type( xMethod->getReturnType() ),
929 param_types );
930 // then define parameter infos
931 params_pos = 0;
932 for ( ; params_pos < params_length; ++params_pos )
934 Reference< reflection::XMethodParameter > const & xParam =
935 parameters[ params_pos ];
936 long param_flags = 0;
937 if (xParam->isIn())
938 param_flags |= (long)ParameterAttributes::In;
939 if (xParam->isOut())
940 param_flags |= (long)ParameterAttributes::Out;
941 OSL_ASSERT( 0 != param_flags );
942 method_builder->DefineParameter(
943 xParam->getPosition() +1 /* starts with 1 */,
944 (ParameterAttributes) param_flags,
945 ustring_to_String( xParam->getName() ) );
947 //Apply attribute TypeParametersAttribute to return value if it
948 //is a parameterized Type. Currently only structs can have parameters.
949 Reference<reflection::XStructTypeDescription> xReturnStruct(
950 xMethod->getReturnType(), UNO_QUERY);
952 if (xReturnStruct.is())
954 Sequence<Reference<reflection::XTypeDescription> > seq_type_args =
955 xReturnStruct->getTypeArguments();
956 if (seq_type_args.getLength() != 0)
958 //get th ctor of the attribute
959 array< ::System::Type^>^ arCtor = {::System::Type::GetType("System.Type[]")};
960 //Get the arguments for the attribute's ctor
961 Reference<reflection::XTypeDescription> const * arXTypeArgs =
962 seq_type_args.getConstArray();
963 int numTypes = seq_type_args.getLength();
964 array< ::System::Type^>^ arCtsTypes = gcnew array< ::System::Type^>(numTypes);
965 for (int i = 0; i < numTypes; i++)
966 arCtsTypes[i] = get_type(arXTypeArgs[i]);
967 array< ::System::Object^>^ arArgs = {arCtsTypes};
969 Emit::CustomAttributeBuilder ^ attrBuilder =
970 gcnew Emit::CustomAttributeBuilder(
971 ::uno::TypeArgumentsAttribute::typeid
972 ->GetConstructor( arCtor),
973 arArgs);
975 method_builder->SetCustomAttribute(attrBuilder);
979 //define UNO exception attribute (exceptions)--------------------------------------
980 Emit::CustomAttributeBuilder^ attrBuilder =
981 get_iface_method_exception_attribute(xMethod);
982 if (attrBuilder != nullptr)
983 method_builder->SetCustomAttribute(attrBuilder);
985 // oneway attribute
986 if (xMethod->isOneway())
988 array< ::System::Type^>^ arCtorOneway = gcnew array< ::System::Type^>(0);
989 array< ::System::Object^>^ arArgs = gcnew array< ::System::Object^>(0);
990 Emit::CustomAttributeBuilder ^ attrBuilder =
991 gcnew Emit::CustomAttributeBuilder(
992 ::uno::OnewayAttribute::typeid->GetConstructor( arCtorOneway),
993 arArgs);
994 method_builder->SetCustomAttribute(attrBuilder);
997 else // attribute
999 OSL_ASSERT(
1000 TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() );
1001 Reference<
1002 reflection::XInterfaceAttributeTypeDescription2 > xAttribute(
1003 xMember, UNO_QUERY_THROW );
1005 MethodAttributes c_property_method_attr = (MethodAttributes)
1006 (c_method_attr | MethodAttributes::SpecialName);
1008 ::System::Type ^ attribute_type = get_type( xAttribute->getType() );
1009 array< ::System::Type^>^ parameters =
1010 gcnew array< ::System::Type^> ( 0 );
1012 Emit::PropertyBuilder ^ property_builder =
1013 type_builder->DefineProperty(
1014 ustring_to_String( xAttribute->getMemberName() ),
1015 PropertyAttributes::None,
1016 attribute_type, parameters );
1018 //set BoundAttribute, if necessary
1019 if (xAttribute->isBound())
1021 ConstructorInfo ^ ctorBoundAttr =
1022 ::uno::BoundAttribute::typeid->GetConstructor(
1023 gcnew array<System::Type^>(0));
1024 Emit::CustomAttributeBuilder ^ attrBuilderBound =
1025 gcnew Emit::CustomAttributeBuilder(
1026 ctorBoundAttr, gcnew array< ::System::Object^>(0));
1027 property_builder->SetCustomAttribute(attrBuilderBound);
1030 // getter
1031 Emit::MethodBuilder ^ method_builder =
1032 type_builder->DefineMethod(
1033 ustring_to_String( "get_" +
1034 xAttribute->getMemberName() ),
1035 c_property_method_attr, attribute_type, parameters );
1037 //define UNO exception attribute (exceptions)--------------------------------------
1038 Emit::CustomAttributeBuilder^ attrBuilder =
1039 get_exception_attribute(xAttribute->getGetExceptions());
1040 if (attrBuilder != nullptr)
1041 method_builder->SetCustomAttribute(attrBuilder);
1043 property_builder->SetGetMethod( method_builder );
1045 if (! xAttribute->isReadOnly())
1047 // setter
1048 parameters = gcnew array< ::System::Type^> ( 1 );
1049 parameters[ 0 ] = attribute_type;
1050 method_builder =
1051 type_builder->DefineMethod(
1052 ustring_to_String( "set_" +
1053 xAttribute->getMemberName() ),
1054 c_property_method_attr, nullptr, parameters );
1055 // define parameter info
1056 method_builder->DefineParameter(
1057 1 /* starts with 1 */, ParameterAttributes::In, "value" );
1058 //define UNO exception attribute (exceptions)--------------------------------------
1059 Emit::CustomAttributeBuilder^ attrBuilder =
1060 get_exception_attribute(xAttribute->getSetExceptions());
1061 if (attrBuilder != nullptr)
1062 method_builder->SetCustomAttribute(attrBuilder);
1064 property_builder->SetSetMethod( method_builder );
1069 // remove from incomplete types map
1070 ::System::String ^ cts_name = type_builder->FullName;
1071 m_incomplete_ifaces->Remove( cts_name );
1072 xType->release();
1074 if (g_verbose)
1076 ::System::Console::WriteLine(
1077 "> emitting interface type {0}", cts_name );
1079 return type_builder->CreateType();
1082 ::System::Type ^ TypeEmitter::complete_struct_type( struct_entry ^ entry )
1084 OSL_ASSERT(entry);
1085 ::System::String ^ cts_name = entry->m_type_builder->FullName;
1087 //Polymorphic struct, define uno.TypeParametersAttribute
1088 //A polymorphic struct cannot have a basetype.
1089 //When we create the template of the struct then we have no exact types
1090 //and the name does not contain a parameter list
1091 Sequence< OUString > seq_type_parameters;
1092 Reference< reflection::XStructTypeDescription> xStructTypeDesc(
1093 entry->m_xType, UNO_QUERY);
1094 if (xStructTypeDesc.is())
1096 seq_type_parameters = xStructTypeDesc->getTypeParameters();
1097 int numTypes = 0;
1098 if ((numTypes = seq_type_parameters.getLength()) > 0)
1100 array< ::System::Object^>^ aArg = gcnew array< ::System::Object^>(numTypes);
1101 for (int i = 0; i < numTypes; i++)
1102 aArg[i] = ustring_to_String(seq_type_parameters.getConstArray()[i]);
1103 array< ::System::Object^>^ args = {aArg};
1105 array< ::System::Type^>^ arTypesCtor =
1106 {::System::Type::GetType("System.String[]")};
1107 Emit::CustomAttributeBuilder ^ attrBuilder =
1108 gcnew Emit::CustomAttributeBuilder(
1109 ::uno::TypeParametersAttribute::typeid->GetConstructor(arTypesCtor),
1110 args);
1111 entry->m_type_builder->SetCustomAttribute(attrBuilder);
1115 // optional: lookup base type whether generated entry of this session
1116 struct_entry ^ base_type_entry = nullptr;
1117 if (nullptr != entry->m_base_type)
1119 //ToDo maybe get from incomplete structs
1120 base_type_entry =
1121 dynamic_cast< struct_entry ^ >(
1122 m_generated_structs[
1123 entry->m_base_type->FullName ] );
1126 // members
1127 Sequence< Reference< reflection::XTypeDescription > > seq_members(
1128 entry->m_xType->getMemberTypes() );
1129 Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() );
1130 sal_Int32 members_length = seq_members.getLength();
1131 OSL_ASSERT( seq_member_names.getLength() == members_length );
1132 //check if we have a XTypeDescription for every member. If not then the user may
1133 //have forgotten to specify additional rdbs with the --extra option.
1134 Reference< reflection::XTypeDescription > const * pseq_members =
1135 seq_members.getConstArray();
1136 OUString const * pseq_member_names =
1137 seq_member_names.getConstArray();
1138 for (int i = 0; i < members_length; i++)
1140 const OUString sType(entry->m_xType->getName());
1141 const OUString sMemberName(pseq_member_names[i]);
1142 if ( ! pseq_members[i].is())
1143 throw RuntimeException("Missing type description . Check if you need to "
1144 "specify additional RDBs with the --extra option. Type missing for: " + sType +
1145 "::" + sMemberName,0);
1148 sal_Int32 all_members_length = 0;
1149 sal_Int32 member_pos;
1150 sal_Int32 type_param_pos = 0;
1152 // collect base types; wrong order
1153 ::System::Collections::ArrayList ^ base_types_list =
1154 gcnew ::System::Collections::ArrayList( 3 /* initial capacity */ );
1155 for (::System::Type ^ base_type_pos = entry->m_base_type;
1156 ! base_type_pos->Equals( ::System::Object::typeid );
1157 base_type_pos = base_type_pos->BaseType )
1159 base_types_list->Add( base_type_pos );
1160 if (base_type_pos->Equals( ::System::Exception::typeid ))
1162 // special Message member
1163 all_members_length += 1;
1164 break; // don't include System.Exception base classes
1166 else
1168 //ensure the base type is complete. Otherwise GetFields won't work
1169 get_complete_struct(base_type_pos->FullName);
1170 all_members_length +=
1171 base_type_pos->GetFields(
1172 (BindingFlags) (BindingFlags::Instance |
1173 BindingFlags::Public |
1174 BindingFlags::DeclaredOnly) )
1175 ->Length;
1179 // create all_members arrays; right order
1180 array< ::System::String^>^ all_member_names =
1181 gcnew array< ::System::String^> (all_members_length + members_length );
1182 array< ::System::Type^>^ all_param_types =
1183 gcnew array< ::System::Type^> (all_members_length + members_length );
1184 member_pos = 0;
1185 for ( sal_Int32 pos = base_types_list->Count; pos--; )
1187 ::System::Type ^ base_type = safe_cast< ::System::Type ^ >(
1188 base_types_list[pos] );
1189 if (base_type->Equals( ::System::Exception::typeid ))
1191 all_member_names[ member_pos ] = "Message";
1192 all_param_types[ member_pos ] = ::System::String::typeid;
1193 ++member_pos;
1195 else
1197 ::System::String ^ base_type_name = base_type->FullName;
1199 //ToDo m_generated_structs?
1200 struct_entry ^ entry =
1201 dynamic_cast< struct_entry ^ >(
1202 m_generated_structs[base_type_name] );
1203 if (nullptr == entry)
1205 // complete type
1206 array<FieldInfo^>^ fields =
1207 base_type->GetFields(
1208 (BindingFlags) (BindingFlags::Instance |
1209 BindingFlags::Public |
1210 BindingFlags::DeclaredOnly) );
1211 sal_Int32 len = fields->Length;
1212 for ( sal_Int32 pos = 0; pos < len; ++pos )
1214 FieldInfo ^ field = fields[ pos ];
1215 all_member_names[ member_pos ] = field->Name;
1216 all_param_types[ member_pos ] = field->FieldType;
1217 ++member_pos;
1220 else // generated during this session:
1221 // members may be incomplete ifaces
1223 sal_Int32 len = entry->m_member_names->Length;
1224 for ( sal_Int32 pos = 0; pos < len; ++pos )
1226 all_member_names[ member_pos ] =
1227 entry->m_member_names[ pos ];
1228 all_param_types[ member_pos ] =
1229 entry->m_param_types[ pos ];
1230 ++member_pos;
1235 OSL_ASSERT( all_members_length == member_pos );
1237 // build up entry
1238 // struct_entry * entry = new struct_entry();
1239 entry->m_member_names = gcnew array< ::System::String^> ( members_length );
1240 entry->m_param_types = gcnew array< ::System::Type^> ( members_length );
1242 // add members
1243 array<Emit::FieldBuilder^>^ members = gcnew array<Emit::FieldBuilder^> ( members_length );
1244 //Reference< reflection::XTypeDescription > const * pseq_members =
1245 // seq_members.getConstArray();
1246 //OUString const * pseq_member_names =
1247 // seq_member_names.getConstArray();
1249 int curParamIndex = 0; //count the fields which have parameterized types
1250 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1252 ::System::String ^ field_name =
1253 ustring_to_String( pseq_member_names[ member_pos ] );
1254 ::System::Type ^ field_type;
1255 //Special handling of struct parameter types
1256 bool bParameterizedType = false;
1257 if (pseq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN)
1259 bParameterizedType = true;
1260 if (type_param_pos < seq_type_parameters.getLength())
1262 field_type = ::System::Object::typeid;
1263 type_param_pos++;
1265 else
1267 throw RuntimeException(
1268 "unexpected member type in " + entry->m_xType->getName(),
1269 Reference< XInterface >() );
1272 else
1274 field_type =
1275 get_type( pseq_members[ member_pos ] );
1277 members[ member_pos ] =
1278 entry->m_type_builder->DefineField(
1279 field_name, field_type, FieldAttributes::Public );
1281 //parameterized type (polymorphic struct) ?
1282 if (bParameterizedType && xStructTypeDesc.is())
1284 //get the name
1285 OSL_ASSERT(seq_type_parameters.getLength() > curParamIndex);
1286 ::System::String^ sTypeName = ustring_to_String(
1287 seq_type_parameters.getConstArray()[curParamIndex++]);
1288 array< ::System::Object^>^ args = {sTypeName};
1289 //set ParameterizedTypeAttribute
1290 array< ::System::Type^>^ arCtorTypes = {::System::String::typeid};
1292 Emit::CustomAttributeBuilder ^ attrBuilder =
1293 gcnew Emit::CustomAttributeBuilder(
1294 ::uno::ParameterizedTypeAttribute::typeid
1295 ->GetConstructor(arCtorTypes),
1296 args);
1298 members[member_pos]->SetCustomAttribute(attrBuilder);
1300 // add to all_members
1301 all_member_names[ all_members_length + member_pos ] = field_name;
1302 all_param_types[ all_members_length + member_pos ] = field_type;
1303 // add to entry
1304 entry->m_member_names[ member_pos ] = field_name;
1305 entry->m_param_types[ member_pos ] = field_type;
1307 all_members_length += members_length;
1309 // default .ctor
1310 Emit::ConstructorBuilder ^ ctor_builder =
1311 entry->m_type_builder->DefineConstructor(
1312 c_ctor_method_attr, CallingConventions::Standard,
1313 gcnew array< ::System::Type^> ( 0 ) );
1314 Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
1315 code->Emit( Emit::OpCodes::Ldarg_0 );
1316 code->Emit(
1317 Emit::OpCodes::Call,
1318 nullptr == base_type_entry
1319 ? entry->m_base_type->GetConstructor( gcnew array< ::System::Type^> ( 0 ) )
1320 : base_type_entry->m_default_ctor );
1321 // default initialize members
1322 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1324 FieldInfo ^ field = members[ member_pos ];
1325 ::System::Type ^ field_type = field->FieldType;
1326 // ::System::Type * new_field_type = m_module_builder->GetType(field_type->FullName, false);
1327 // default initialize:
1328 // string, type, enum, sequence, struct, exception, any
1329 if (field_type->Equals( ::System::String::typeid ))
1331 code->Emit( Emit::OpCodes::Ldarg_0 );
1332 code->Emit( Emit::OpCodes::Ldstr, "" );
1333 code->Emit( Emit::OpCodes::Stfld, field );
1335 else if (field_type->Equals( ::System::Type::typeid ))
1337 code->Emit( Emit::OpCodes::Ldarg_0 );
1338 code->Emit(
1339 Emit::OpCodes::Ldtoken, ::System::Void::typeid );
1340 code->Emit(
1341 Emit::OpCodes::Call, m_method_info_Type_GetTypeFromHandle );
1342 code->Emit( Emit::OpCodes::Stfld, field );
1344 else if (field_type->IsArray)
1346 //Find the value type. In case of sequence<sequence< ... > > find the actual value type
1347 ::System::Type ^ value = field_type;
1348 while ((value = value->GetElementType())->IsArray);
1349 //If the value type is a struct then make sure it is fully created.
1350 get_complete_struct(value->FullName);
1352 code->Emit( Emit::OpCodes::Ldarg_0 );
1353 code->Emit( Emit::OpCodes::Ldc_I4_0 );
1354 code->Emit(
1355 Emit::OpCodes::Newarr, field_type->GetElementType() );
1356 code->Emit( Emit::OpCodes::Stfld, field );
1358 else if (field_type->IsValueType)
1360 if (field_type->FullName->Equals( "uno.Any" ))
1362 code->Emit( Emit::OpCodes::Ldarg_0 );
1363 code->Emit( Emit::OpCodes::Ldsfld, ::uno::Any::typeid->GetField("VOID"));
1364 code->Emit( Emit::OpCodes::Stfld, field );
1367 else if (field_type->IsClass)
1369 /* may be XInterface */
1370 if (! field_type->Equals( ::System::Object::typeid ))
1372 // struct, exception
1373 //make sure the struct is already complete.
1374 get_complete_struct(field_type->FullName);
1375 code->Emit( Emit::OpCodes::Ldarg_0 );
1376 code->Emit(
1377 Emit::OpCodes::Newobj,
1378 //GetConstructor requies that the member types of the object which is to be constructed are already known.
1379 field_type->GetConstructor(
1380 gcnew array< ::System::Type^> ( 0 ) ) );
1381 code->Emit( Emit::OpCodes::Stfld, field );
1385 code->Emit( Emit::OpCodes::Ret );
1386 entry->m_default_ctor = ctor_builder;
1388 // parameterized .ctor including all base members
1389 ctor_builder = entry->m_type_builder->DefineConstructor(
1390 c_ctor_method_attr, CallingConventions::Standard, all_param_types );
1391 for ( member_pos = 0; member_pos < all_members_length; ++member_pos )
1393 ctor_builder->DefineParameter(
1394 member_pos +1 /* starts with 1 */, ParameterAttributes::In,
1395 all_member_names[ member_pos ] );
1397 code = ctor_builder->GetILGenerator();
1398 // call base .ctor
1399 code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1400 sal_Int32 base_members_length = all_members_length - members_length;
1401 array< ::System::Type^>^ param_types =
1402 gcnew array< ::System::Type^> ( base_members_length );
1403 for ( member_pos = 0; member_pos < base_members_length; ++member_pos )
1405 emit_ldarg( code, member_pos +1 );
1406 param_types[ member_pos ] = all_param_types[ member_pos ];
1408 code->Emit(
1409 Emit::OpCodes::Call,
1410 nullptr == base_type_entry
1411 ? entry->m_base_type->GetConstructor( param_types )
1412 : base_type_entry->m_ctor );
1413 // initialize members
1414 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1416 code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1417 emit_ldarg( code, member_pos + base_members_length +1 );
1418 code->Emit( Emit::OpCodes::Stfld, members[ member_pos ] );
1420 code->Emit( Emit::OpCodes::Ret );
1421 entry->m_ctor = ctor_builder;
1423 if (g_verbose)
1425 ::System::Console::WriteLine(
1426 "> emitting {0} type {1}",
1427 TypeClass_STRUCT == entry->m_xType->getTypeClass()
1428 ? "struct"
1429 : "exception",
1430 cts_name);
1432 // new entry
1433 m_generated_structs->Add(cts_name, entry );
1434 ::System::Type ^ ret_type = entry->m_type_builder->CreateType();
1436 // remove from incomplete types map
1437 m_incomplete_structs->Remove( cts_name );
1438 entry->m_xType->release();
1440 if (g_verbose)
1442 ::System::Console::WriteLine(
1443 "> emitting struct type {0}", cts_name);
1445 return ret_type;
1448 //Examples of generated code
1449 // public static XWeak constructor1(XComponentContext ctx)
1450 // {
1451 // XMultiComponentFactory factory = ctx.getServiceManager();
1452 // if (factory == null)
1453 // throw new com.sun.star.uno.DeploymentException("bla", null);
1454 // return (XWeak) factory.createInstanceWithContext("service_specifier", ctx);
1455 // }
1456 // public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c)
1457 // {
1458 // XMultiComponentFactory factory = ctx.getServiceManager();
1459 // if (factory == null)
1460 // throw new com.sun.star.uno.DeploymentException("bla", null);
1461 // Any[] arAny = new Any[3];
1462 // arAny[0] = new Any(typeof(int), a);
1463 // arAny[1] = new Any(typeof(int), b);
1464 // arAny[2] = new Any(c.Type, c.Value);
1465 // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx);
1466 // }
1467 // Notice that a any parameter is NOT wrapped by another any. Instead the new any is created with the type and value
1468 // of the parameter.
1470 // public static XWeak constructor3(XComponentContext ctx, params Any[] c)
1471 // {
1472 // XMultiComponentFactory factory = ctx.getServiceManager();
1473 // if (factory == null)
1474 // throw new com.sun.star.uno.DeploymentException("bla", null);
1475 // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx);
1476 // }
1477 ::System::Type ^ TypeEmitter::complete_service_type(service_entry ^ entry)
1479 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
1480 reflection::XServiceTypeDescription2 * xServiceType = entry->m_xType;
1482 //Create the private default constructor
1483 Emit::ConstructorBuilder^ ctor_builder =
1484 type_builder->DefineConstructor(
1485 (MethodAttributes) (MethodAttributes::Private |
1486 MethodAttributes::HideBySig |
1487 MethodAttributes::SpecialName |
1488 MethodAttributes::RTSpecialName),
1489 CallingConventions::Standard, nullptr);
1491 Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator();
1492 ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1493 ilGen->Emit(
1494 Emit::OpCodes::Call,
1495 type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
1496 ilGen->Emit( Emit::OpCodes::Ret );
1499 //Create the service constructors.
1500 //obtain the interface which makes up this service, it is the return
1501 //type of the constructor functions
1502 Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
1503 xServiceType->getInterface(), UNO_QUERY);
1504 if (xIfaceType.is () == sal_False)
1505 xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface());
1506 System::Type ^ retType = get_type(xIfaceType);
1508 //Create the ConstructorInfo for a DeploymentException
1509 ::System::Type ^ typeDeploymentExc =
1510 get_type("unoidl.com.sun.star.uno.DeploymentException", true);
1512 array< ::System::Type^>^ arTypeCtor = {::System::String::typeid,
1513 ::System::Object::typeid};
1514 ::System::Reflection::ConstructorInfo ^ ctorDeploymentException =
1515 typeDeploymentExc->GetConstructor(arTypeCtor);
1517 Sequence<Reference<reflection::XServiceConstructorDescription> > seqCtors =
1518 xServiceType->getConstructors();
1520 ::System::Type ^ type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception", true);
1522 for (int i = seqCtors.getLength() - 1; i >= 0; i--)
1524 bool bParameterArray = false;
1525 ::System::Type ^ typeAny = ::uno::Any::typeid;
1526 const Reference<reflection::XServiceConstructorDescription> & ctorDes =
1527 seqCtors[i];
1528 //obtain the parameter types
1529 Sequence<Reference<reflection::XParameter> > seqParams =
1530 ctorDes->getParameters();
1531 Reference<reflection::XParameter> const * arXParams = seqParams.getConstArray();
1532 sal_Int32 cParams = seqParams.getLength();
1533 array< ::System::Type^>^ arTypeParameters = gcnew array< ::System::Type^> (cParams + 1);
1534 arTypeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1535 for (int iparam = 0; iparam != cParams; iparam++)
1537 if (arXParams[iparam]->isRestParameter())
1538 arTypeParameters[iparam + 1] = array< ::uno::Any>::typeid;
1539 else
1540 arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType());
1542 //The array arTypeParameters can contain:
1543 //System.Type and uno.PolymorphicType.
1544 //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem.
1545 //The exception will read something like no on information for parameter # d
1546 //Maybe we need no override another Type method in PolymorphicType ...
1547 //Until we have figured this out, we will create another array of System.Type which
1548 //we pass on to DefineMethod.
1549 array< ::System::Type^>^ arParamTypes = gcnew array< ::System::Type^> (cParams + 1);
1550 // arParamTypes[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1551 for (int i = 0; i < cParams + 1; i++)
1553 ::uno::PolymorphicType ^ pT = dynamic_cast< ::uno::PolymorphicType ^ >(arTypeParameters[i]);
1554 if (pT)
1555 arParamTypes[i] = pT->OriginalType;
1556 else
1557 arParamTypes[i] = arTypeParameters[i];
1559 //define method
1560 System::String ^ ctorName;
1561 if (ctorDes->isDefaultConstructor())
1562 ctorName = gcnew ::System::String("create");
1563 else
1564 ctorName = ustring_to_String(ctorDes->getName());
1565 Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
1566 ctorName,
1567 static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
1568 MethodAttributes::Static),
1569 retType,
1570 // arTypeParameters);
1571 arParamTypes);
1573 //define UNO exception attribute (exceptions)--------------------------------------
1574 Emit::CustomAttributeBuilder^ attrBuilder = get_service_exception_attribute(ctorDes);
1575 if (attrBuilder != nullptr)
1576 method_builder->SetCustomAttribute(attrBuilder);
1578 //-------------------------------------------------------------
1579 //define parameter attributes (paramarray), names etc.
1580 //The first parameter is the XComponentContext, which cannot be obtained
1581 //from reflection.
1582 //The context is not part of the idl description
1583 method_builder->DefineParameter(
1584 1, ParameterAttributes::In, "the_context");
1586 array<Emit::ParameterBuilder^>^ arParameterBuilder =
1587 gcnew array<Emit::ParameterBuilder^> (cParams);
1588 for (int iparam = 0; iparam != cParams; iparam++)
1590 Reference<reflection::XParameter> const & aParam = arXParams[iparam];
1591 ::System::String ^ sParamName = ustring_to_String(aParam->getName());
1593 arParameterBuilder[iparam] = method_builder->DefineParameter(
1594 iparam + 2, ParameterAttributes::In, sParamName);
1596 if (aParam->isRestParameter())
1598 bParameterArray = true;
1599 //set the ParameterArrayAttribute
1600 ::System::Reflection::ConstructorInfo^ ctor_info =
1601 System::ParamArrayAttribute::typeid->GetConstructor(
1602 gcnew array< ::System::Type^>(0));
1603 Emit::CustomAttributeBuilder ^ attr_builder =
1604 gcnew Emit::CustomAttributeBuilder(ctor_info, gcnew array< ::System::Object^>(0));
1605 arParameterBuilder[iparam]->SetCustomAttribute(attr_builder);
1606 break;
1610 Emit::ILGenerator ^ ilGen = method_builder->GetILGenerator();
1612 //Define locals ---------------------------------
1613 //XMultiComponentFactory
1614 Emit::LocalBuilder^ local_factory =
1615 ilGen->DeclareLocal(
1616 get_type("unoidl.com.sun.star.lang.XMultiComponentFactory", true));
1618 //The return type
1619 Emit::LocalBuilder^ local_return_val =
1620 ilGen->DeclareLocal(retType);
1622 //Obtain the XMultiComponentFactory and throw an exception if we do not get one
1623 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1625 ::System::Reflection::MethodInfo ^ methodGetServiceManager = get_type(
1626 "unoidl.com.sun.star.uno.XComponentContext", true)
1627 ->GetMethod("getServiceManager");
1628 ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager);
1629 ilGen->Emit(Emit::OpCodes::Stloc, local_factory);
1630 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1631 Emit::Label label1 = ilGen->DefineLabel();
1632 ilGen->Emit(Emit::OpCodes::Brtrue, label1);
1633 //The string for the exception
1634 ::System::Text::StringBuilder ^ strbuilder = gcnew ::System::Text::StringBuilder(256);
1635 strbuilder->Append("The service ");
1636 strbuilder->Append(to_cts_name(xServiceType->getName()));
1637 strbuilder->Append(" could not be created. The context failed to supply the service manager.");
1639 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1640 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1641 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1642 ilGen->Emit(Emit::OpCodes::Throw);
1643 ilGen->MarkLabel(label1);
1645 //We create a try/ catch around the createInstanceWithContext, etc. functions
1646 //There are 3 cases
1647 //1. function do not specify exceptions. Then RuntimeExceptions are retrhown and other
1648 // exceptions produce a DeploymentException.
1649 //2. function specify Exception. Then all exceptions fly through
1650 //3. function specifies exceptions but no Exception. Then these are rethrown
1651 // and other exceptions, except RuntimeException, produce a deployment exception.
1652 //In case there are no parameters we call
1653 //XMultiComponentFactory.createInstanceWithContext
1655 ::System::Collections::ArrayList ^ arExceptionTypes =
1656 get_service_ctor_method_exceptions_reduced(ctorDes->getExceptions());
1657 if (arExceptionTypes->Contains(
1658 type_uno_exception) == false)
1660 ilGen->BeginExceptionBlock();
1662 if (cParams == 0)
1664 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1665 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1666 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1668 ::System::Reflection::MethodInfo ^ methodCreate =
1669 local_factory->LocalType->GetMethod("createInstanceWithContext");
1670 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1672 else if(bParameterArray)
1674 //Service constructor with parameter array
1675 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1676 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1677 ilGen->Emit(Emit::OpCodes::Ldarg_1);
1678 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1679 ::System::Reflection::MethodInfo ^ methodCreate =
1680 local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1681 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1683 else
1685 // Any param1, Any param2, etc.
1686 // For each parameter,except the component context, and parameter array
1687 // and Any is created.
1688 array<Emit::LocalBuilder^>^ arLocalAny = gcnew array<Emit::LocalBuilder^> (cParams);
1690 for (int iParam = 0; iParam < cParams; iParam ++)
1692 arLocalAny[iParam] = ilGen->DeclareLocal(typeAny);
1695 //Any[]. This array is filled with the created Anys which contain the parameters
1696 //and the values contained in the parameter array
1697 Emit::LocalBuilder ^ local_anyParams =
1698 ilGen->DeclareLocal(array< ::uno::Any>::typeid);
1700 //Create the Any for every argument, except for the parameter array
1701 //arLocalAny contains the LocalBuilder for all these parameters.
1702 //we call the ctor Any(Type, Object)
1703 //If the parameter is an Any then the Any is created with Any(param.Type, param.Value);
1704 array< ::System::Type^>^ arTypesCtorAny = {::System::Type::typeid,
1705 ::System::Object::typeid};
1706 ::System::Reflection::ConstructorInfo ^ ctorAny =
1707 typeAny->GetConstructor( arTypesCtorAny);
1708 ::System::Reflection::MethodInfo ^ methodAnyGetType =
1709 typeAny->GetProperty("Type")->GetGetMethod();
1710 ::System::Reflection::MethodInfo ^ methodAnyGetValue =
1711 typeAny->GetProperty("Value")->GetGetMethod();
1712 for (int i = 0; i < arLocalAny->Length; i ++)
1714 //check if the parameter is a polymorphic struct
1715 ::uno::PolymorphicType ^polyType = dynamic_cast< ::uno::PolymorphicType^ >(arTypeParameters[i+1]);
1716 //arTypeParameters[i+1] = polyType->OriginalType;
1717 if (polyType)
1719 //It is a polymorphic struct
1720 //Load the uninitialized local Any on which we will call the ctor
1721 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1722 // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName)
1723 // Prepare the first parameter
1724 ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->OriginalType);
1725 array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1726 ilGen->Emit(Emit::OpCodes::Call,
1727 ::System::Type::typeid->GetMethod(
1728 "GetTypeFromHandle", arTypeParams));
1729 // Prepare the second parameter
1730 ilGen->Emit(Emit::OpCodes::Ldstr, polyType->PolymorphicName);
1731 // Make the actual call
1732 array< ::System::Type^>^ arTypeParam_GetType = {
1733 ::System::Type::typeid, ::System::String::typeid };
1734 ilGen->Emit(Emit::OpCodes::Call,
1735 ::uno::PolymorphicType::typeid->GetMethod(gcnew System::String("GetType"),
1736 arTypeParam_GetType));
1738 //Stack is: localAny, PolymorphicType
1739 //Call Any::Any(Type, Object)
1740 //Prepare the second parameter for the any ctor
1741 ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1742 // if the parameter is a value type then we need to box it, because
1743 // the Any ctor takes an Object
1744 if (arTypeParameters[i+1]->IsValueType)
1745 ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1746 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1748 else if (arTypeParameters[i+1] == typeAny)
1750 //Create the call new Any(param.Type,param,Value)
1751 //Stack must be Any,Type,Value
1752 //First load the Any which is to be constructed
1753 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1754 //Load the Type, which is obtained by calling param.Type
1755 ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1756 ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType);
1757 //Load the Value, which is obtained by calling param.Value
1758 ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1759 ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue);
1760 //Call the Any ctor.
1761 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1763 else
1765 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1766 ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]);
1768 array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1769 ilGen->Emit(Emit::OpCodes::Call,
1770 ::System::Type::typeid->GetMethod(
1771 "GetTypeFromHandle", arTypeParams));
1772 ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1773 // if the parameter is a value type then we need to box it, because
1774 // the Any ctor takes an Object
1775 if (arTypeParameters[i+1]->IsValueType)
1776 ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1777 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1781 //Create the Any[] that is passed to the
1782 //createInstanceWithContext[AndArguments] function
1783 ilGen->Emit(Emit::OpCodes::Ldc_I4, arLocalAny->Length);
1784 ilGen->Emit(Emit::OpCodes::Newarr, typeAny);
1785 ilGen->Emit(Emit::OpCodes::Stloc, local_anyParams);
1787 //Assign all anys created from the parameters
1788 //array to the Any[]
1789 for (int i = 0; i < arLocalAny->Length; i++)
1791 ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1792 ilGen->Emit(Emit::OpCodes::Ldc_I4, i);
1793 ilGen->Emit(Emit::OpCodes::Ldelema, typeAny);
1794 ilGen->Emit(Emit::OpCodes::Ldloc, arLocalAny[i]);
1795 ilGen->Emit(Emit::OpCodes::Stobj, typeAny);
1797 // call createInstanceWithContextAndArguments
1798 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1799 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1800 ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1801 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1802 ::System::Reflection::MethodInfo ^ methodCreate =
1803 local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1804 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1806 //cast the object returned by the functions createInstanceWithContext or
1807 //createInstanceWithArgumentsAndContext to the interface type
1808 ilGen->Emit(Emit::OpCodes::Castclass, retType);
1809 ilGen->Emit(Emit::OpCodes::Stloc, local_return_val);
1811 //catch exceptions thrown by createInstanceWithArgumentsAndContext and createInstanceWithContext
1812 if (arExceptionTypes->Contains(type_uno_exception) == false)
1814 // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;}
1815 ilGen->BeginCatchBlock(get_type("unoidl.com.sun.star.uno.RuntimeException", true));
1816 ilGen->Emit(Emit::OpCodes::Pop);
1817 ilGen->Emit(Emit::OpCodes::Rethrow);
1819 //catch and rethrow all other defined Exceptions
1820 for (int i = 0; i < arExceptionTypes->Count; i++)
1822 ::System::Type ^ excType = safe_cast< ::System::Type^ >(
1823 arExceptionTypes[i]);
1824 if (excType->IsInstanceOfType(
1825 get_type("unoidl.com.sun.star.uno.RuntimeException", true)))
1826 {// we have a catch for RuntimeException already defined
1827 continue;
1830 //catch Exception and rethrow
1831 ilGen->BeginCatchBlock(excType);
1832 ilGen->Emit(Emit::OpCodes::Pop);
1833 ilGen->Emit(Emit::OpCodes::Rethrow);
1835 //catch (unoidl.com.sun.star.uno.Exception) {throw DeploymentException...}
1836 ilGen->BeginCatchBlock(type_uno_exception);
1838 //Define the local variabe that keeps the exception
1839 Emit::LocalBuilder ^ local_exception = ilGen->DeclareLocal(
1840 type_uno_exception);
1842 //Store the exception
1843 ilGen->Emit(Emit::OpCodes::Stloc, local_exception);
1845 //prepare the construction of the exception
1846 strbuilder = gcnew ::System::Text::StringBuilder(256);
1847 strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1848 strbuilder->Append(to_cts_name(xServiceType->getName()));
1849 strbuilder->Append(": ");
1851 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1853 //add to the string the Exception.Message
1854 ilGen->Emit(Emit::OpCodes::Ldloc, local_exception);
1855 ilGen->Emit(Emit::OpCodes::Callvirt,
1856 type_uno_exception->GetProperty("Message")->GetGetMethod());
1857 array< ::System::Type^>^ arConcatParams = {System::String::typeid,
1858 System::String::typeid};
1859 ilGen->Emit(Emit::OpCodes::Call,
1860 System::String::typeid->GetMethod("Concat", arConcatParams));
1861 //load contex argument
1862 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1863 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1864 ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1866 ilGen->EndExceptionBlock();
1870 //Check if the service instance was create and throw a exception if not.
1871 Emit::Label label_service_created = ilGen->DefineLabel();
1872 ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1873 ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created);
1875 strbuilder = gcnew ::System::Text::StringBuilder(256);
1876 strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1877 strbuilder->Append(to_cts_name(xServiceType->getName()));
1878 strbuilder->Append(".");
1879 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1880 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1881 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1882 ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1884 ilGen->MarkLabel(label_service_created);
1885 ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1886 ilGen->Emit(Emit::OpCodes::Ret);
1889 // remove from incomplete types map
1890 ::System::String ^ cts_name = type_builder->FullName;
1891 m_incomplete_services->Remove( cts_name );
1892 xServiceType->release();
1893 if (g_verbose)
1895 ::System::Console::WriteLine(
1896 "> emitting service type {0}", cts_name );
1898 return type_builder->CreateType();
1902 Emit::CustomAttributeBuilder^ TypeEmitter::get_service_exception_attribute(
1903 const Reference<reflection::XServiceConstructorDescription> & ctorDes )
1905 return get_exception_attribute(ctorDes->getExceptions());
1908 Emit::CustomAttributeBuilder^ TypeEmitter::get_iface_method_exception_attribute(
1909 const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod )
1912 const Sequence<Reference<reflection::XTypeDescription> > seqTD = xMethod->getExceptions();
1913 int len = seqTD.getLength();
1914 Sequence<Reference<reflection::XCompoundTypeDescription> > seqCTD(len);
1915 Reference<reflection::XCompoundTypeDescription> * arCTD = seqCTD.getArray();
1916 for (int i = 0; i < len; i++)
1917 arCTD[i] = Reference<reflection::XCompoundTypeDescription>(seqTD[i], UNO_QUERY_THROW);
1918 return get_exception_attribute(seqCTD);
1921 Emit::CustomAttributeBuilder^ TypeEmitter::get_exception_attribute(
1923 const Sequence<Reference< reflection::XCompoundTypeDescription > >& seq_exceptionsTd )
1925 Emit::CustomAttributeBuilder ^ attr_builder = nullptr;
1927 Reference< reflection::XCompoundTypeDescription > const * exceptions =
1928 seq_exceptionsTd.getConstArray();
1930 array< ::System::Type^>^ arTypesCtor = {::System::Type::GetType("System.Type[]")};
1931 ConstructorInfo ^ ctor_ExceptionAttribute =
1932 ::uno::ExceptionAttribute::typeid->GetConstructor(arTypesCtor);
1934 sal_Int32 exc_length = seq_exceptionsTd.getLength();
1935 if (exc_length != 0) // opt
1937 array< ::System::Type^>^ exception_types =
1938 gcnew array< ::System::Type^> ( exc_length );
1939 for ( sal_Int32 exc_pos = 0; exc_pos < exc_length; ++exc_pos )
1941 Reference< reflection::XCompoundTypeDescription > const & xExc =
1942 exceptions[ exc_pos ];
1943 exception_types[ exc_pos ] = get_type( xExc );
1945 array< ::System::Object^>^ args = {exception_types};
1946 attr_builder = gcnew Emit::CustomAttributeBuilder(
1947 ctor_ExceptionAttribute, args );
1949 return attr_builder;
1953 ::System::Type ^ TypeEmitter::complete_singleton_type(singleton_entry ^ entry)
1955 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
1956 reflection::XSingletonTypeDescription2 * xSingletonType = entry->m_xType;
1957 ::System::String^ sSingletonName = to_cts_name(xSingletonType->getName());
1959 //Create the private default constructor
1960 Emit::ConstructorBuilder^ ctor_builder =
1961 type_builder->DefineConstructor(
1962 static_cast<MethodAttributes>(MethodAttributes::Private |
1963 MethodAttributes::HideBySig |
1964 MethodAttributes::SpecialName |
1965 MethodAttributes::RTSpecialName),
1966 CallingConventions::Standard, nullptr);
1968 Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator();
1969 ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1970 ilGen->Emit(
1971 Emit::OpCodes::Call,
1972 type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
1973 ilGen->Emit( Emit::OpCodes::Ret );
1976 //obtain the interface which makes up this service, it is the return
1977 //type of the constructor functions
1978 Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
1979 xSingletonType->getInterface(), UNO_QUERY);
1980 if (xIfaceType.is () == sal_False)
1981 xIfaceType = resolveInterfaceTypedef(xSingletonType->getInterface());
1982 System::Type ^ retType = get_type(xIfaceType);
1984 //define method
1985 array< ::System::Type^>^ arTypeParameters = {get_type("unoidl.com.sun.star.uno.XComponentContext", true)};
1986 Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
1987 gcnew System::String("get"),
1988 static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
1989 MethodAttributes::Static),
1990 retType,
1991 arTypeParameters);
1994 // method_builder->SetCustomAttribute(get_service_ctor_method_attribute(ctorDes));
1996 //The first parameter is the XComponentContext, which cannot be obtained
1997 //from reflection.
1998 //The context is not part of the idl description
1999 method_builder->DefineParameter(1, ParameterAttributes::In, "the_context");
2002 ilGen = method_builder->GetILGenerator();
2003 //Define locals ---------------------------------
2004 // Any, returned by XComponentContext.getValueByName
2005 Emit::LocalBuilder^ local_any =
2006 ilGen->DeclareLocal(::uno::Any::typeid);
2008 //Call XContext::getValueByName
2009 ilGen->Emit(Emit::OpCodes::Ldarg_0);
2010 // build the singleton name : /singleton/unoidl.com.sun.star.XXX
2011 ::System::Text::StringBuilder^ sBuilder =
2012 gcnew ::System::Text::StringBuilder("/singletons/");
2013 sBuilder->Append(sSingletonName);
2014 ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
2016 ::System::Reflection::MethodInfo ^ methodGetValueByName =
2017 get_type("unoidl.com.sun.star.uno.XComponentContext", true)->GetMethod("getValueByName");
2018 ilGen->Emit(Emit::OpCodes::Callvirt, methodGetValueByName);
2019 ilGen->Emit(Emit::OpCodes::Stloc_0);
2021 //Contains the returned Any a value?
2022 ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
2023 ::System::Reflection::MethodInfo ^ methodHasValue =
2024 ::uno::Any::typeid->GetMethod("hasValue");
2025 ilGen->Emit(Emit::OpCodes::Call, methodHasValue);
2027 //If not, then throw an DeploymentException
2028 Emit::Label label_singleton_exists = ilGen->DefineLabel();
2029 ilGen->Emit(Emit::OpCodes::Brtrue_S, label_singleton_exists);
2030 sBuilder = gcnew ::System::Text::StringBuilder(
2031 "Component context fails to supply singleton ");
2032 sBuilder->Append(sSingletonName);
2033 sBuilder->Append(" of type ");
2034 sBuilder->Append(retType->FullName);
2035 sBuilder->Append(".");
2036 ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
2037 ilGen->Emit(Emit::OpCodes::Ldarg_0);
2038 array< ::System::Type^>^ arTypesCtorDeploymentException = {
2039 ::System::String::typeid, ::System::Object::typeid};
2040 ilGen->Emit(Emit::OpCodes::Newobj,
2041 get_type("unoidl.com.sun.star.uno.DeploymentException",true)
2042 ->GetConstructor(arTypesCtorDeploymentException));
2043 ilGen->Emit(Emit::OpCodes::Throw);
2044 ilGen->MarkLabel(label_singleton_exists);
2046 //Cast the singleton contained in the Any to the expected interface and return it.
2047 ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
2048 ilGen->Emit(Emit::OpCodes::Call, ::uno::Any::typeid->GetProperty("Value")->GetGetMethod());
2049 ilGen->Emit(Emit::OpCodes::Castclass, retType);
2050 ilGen->Emit(Emit::OpCodes::Ret);
2052 // remove from incomplete types map
2053 ::System::String ^ cts_name = type_builder->FullName;
2054 m_incomplete_singletons->Remove( cts_name );
2055 xSingletonType->release();
2056 if (g_verbose)
2058 ::System::Console::WriteLine(
2059 "> emitting singleton type {0}", cts_name );
2061 return type_builder->CreateType();
2065 //______________________________________________________________________________
2066 ::System::Type ^ TypeEmitter::get_type(
2067 Reference< reflection::XTypeDescription > const & xType )
2069 switch (xType->getTypeClass())
2071 case TypeClass_VOID:
2072 return ::System::Void::typeid;
2073 case TypeClass_CHAR:
2074 return ::System::Char::typeid;
2075 case TypeClass_BOOLEAN:
2076 return ::System::Boolean::typeid;
2077 case TypeClass_BYTE:
2078 return ::System::Byte::typeid;
2079 case TypeClass_SHORT:
2080 return ::System::Int16::typeid;
2081 case TypeClass_UNSIGNED_SHORT:
2082 return ::System::UInt16::typeid;
2083 case TypeClass_LONG:
2084 return ::System::Int32::typeid;
2085 case TypeClass_UNSIGNED_LONG:
2086 return ::System::UInt32::typeid;
2087 case TypeClass_HYPER:
2088 return ::System::Int64::typeid;
2089 case TypeClass_UNSIGNED_HYPER:
2090 return ::System::UInt64::typeid;
2091 case TypeClass_FLOAT:
2092 return ::System::Single::typeid;
2093 case TypeClass_DOUBLE:
2094 return ::System::Double::typeid;
2095 case TypeClass_STRING:
2096 return ::System::String::typeid;
2097 case TypeClass_TYPE:
2098 return ::System::Type::typeid;
2099 case TypeClass_ANY:
2100 return ::uno::Any::typeid;
2101 case TypeClass_ENUM:
2102 return get_type( Reference< reflection::XEnumTypeDescription >(
2103 xType, UNO_QUERY_THROW ) );
2104 case TypeClass_TYPEDEF:
2105 // unwind typedefs
2106 return get_type(
2107 Reference< reflection::XIndirectTypeDescription >(
2108 xType, UNO_QUERY_THROW )->getReferencedType() );
2109 case TypeClass_STRUCT:
2110 case TypeClass_EXCEPTION:
2111 return get_type(
2112 Reference< reflection::XCompoundTypeDescription >(
2113 xType, UNO_QUERY_THROW ) );
2114 case TypeClass_SEQUENCE:
2116 ::System::Type ^ element_type = get_type(
2117 Reference< reflection::XIndirectTypeDescription >(
2118 xType, UNO_QUERY_THROW )->getReferencedType() );
2119 ::System::Type ^ retType = get_type(
2120 ::System::String::Concat(
2121 element_type->FullName, "[]" ), true );
2123 ::uno::PolymorphicType ^ pt = dynamic_cast< ::uno::PolymorphicType ^ >(element_type);
2124 if (pt)
2126 ::System::String ^ sName = ::System::String::Concat(pt->PolymorphicName, "[]");
2127 retType = ::uno::PolymorphicType::GetType(retType, sName);
2129 return retType;
2131 case TypeClass_INTERFACE:
2132 return get_type(
2133 Reference< reflection::XInterfaceTypeDescription2 >(
2134 xType, UNO_QUERY_THROW ) );
2135 case TypeClass_CONSTANT:
2136 return get_type(
2137 Reference< reflection::XConstantTypeDescription >(
2138 xType, UNO_QUERY_THROW ) );
2139 case TypeClass_CONSTANTS:
2140 return get_type(
2141 Reference< reflection::XConstantsTypeDescription >(
2142 xType, UNO_QUERY_THROW ) );
2143 case TypeClass_SERVICE:
2144 return get_type(
2145 Reference< reflection::XServiceTypeDescription2 >(
2146 xType, UNO_QUERY_THROW) );
2147 case TypeClass_SINGLETON:
2148 return get_type(
2149 Reference< reflection::XSingletonTypeDescription2 >(
2150 xType, UNO_QUERY_THROW) );
2151 case TypeClass_MODULE:
2152 // ignore these
2153 return nullptr;
2154 default:
2155 throw RuntimeException(
2156 "unexpected type " + xType->getName(),
2157 Reference< XInterface >() );
2161 //______________________________________________________________________________
2162 ::System::Type ^ TypeEmitter::get_complete_struct( ::System::String ^ sName)
2164 struct_entry ^ pStruct = safe_cast< struct_entry ^>(
2165 m_incomplete_structs[sName]);
2166 if (pStruct)
2168 complete_struct_type(pStruct);
2170 //get_type will asked the module builder for the type or otherwise all known assemblies.
2171 return get_type(sName, true);
2173 TypeEmitter::~TypeEmitter()
2175 while (true)
2177 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2178 m_incomplete_ifaces->GetEnumerator();
2179 if (! enumerator->MoveNext())
2180 break;
2181 complete_iface_type(
2182 safe_cast< iface_entry ^ >( enumerator->Value ) );
2185 while (true)
2187 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2188 m_incomplete_structs->GetEnumerator();
2189 if (! enumerator->MoveNext())
2190 break;
2191 complete_struct_type(
2192 safe_cast< struct_entry ^ >( enumerator->Value ) );
2196 while (true)
2198 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2199 m_incomplete_services->GetEnumerator();
2200 if (! enumerator->MoveNext())
2201 break;
2202 complete_service_type(
2203 safe_cast< service_entry ^ >( enumerator->Value ) );
2206 while (true)
2208 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2209 m_incomplete_singletons->GetEnumerator();
2210 if (! enumerator->MoveNext())
2211 break;
2212 complete_singleton_type(
2213 safe_cast< singleton_entry ^ >( enumerator->Value ) );
2216 //______________________________________________________________________________
2217 TypeEmitter::TypeEmitter(
2218 ::System::Reflection::Emit::ModuleBuilder ^ module_builder,
2219 array< ::System::Reflection::Assembly^>^ extra_assemblies )
2220 : m_module_builder( module_builder ),
2221 m_extra_assemblies( extra_assemblies ),
2222 m_method_info_Type_GetTypeFromHandle( nullptr ),
2223 m_type_Exception( nullptr ),
2224 m_type_RuntimeException( nullptr ),
2225 m_incomplete_ifaces( gcnew ::System::Collections::Hashtable() ),
2226 m_incomplete_structs( gcnew ::System::Collections::Hashtable() ),
2227 m_incomplete_services(gcnew ::System::Collections::Hashtable() ),
2228 m_incomplete_singletons(gcnew ::System::Collections::Hashtable() ),
2229 m_generated_structs( gcnew ::System::Collections::Hashtable() )
2231 array< ::System::Type^>^ param_types = gcnew array< ::System::Type^> ( 1 );
2232 param_types[ 0 ] = ::System::RuntimeTypeHandle::typeid;
2233 m_method_info_Type_GetTypeFromHandle =
2234 ::System::Type::typeid
2235 ->GetMethod( "GetTypeFromHandle", param_types );
2238 ::System::Collections::ArrayList ^ TypeEmitter::get_service_ctor_method_exceptions_reduced(
2239 const Sequence<Reference<reflection::XCompoundTypeDescription> > & seqExceptionsTd)
2241 if (seqExceptionsTd.getLength() == 0)
2242 return gcnew ::System::Collections::ArrayList();
2244 ::System::Collections::ArrayList ^ arTypes = gcnew ::System::Collections::ArrayList();
2245 for (int i = 0; i < seqExceptionsTd.getLength(); i++)
2246 arTypes->Add(get_type(to_cts_name(seqExceptionsTd[i]->getName()), true));
2248 int start = 0;
2249 while (true)
2251 bool bRemove = false;
2252 for (int i = start; i < arTypes->Count; i++)
2254 ::System::Type ^ t = safe_cast< ::System::Type^ >(arTypes[i]);
2255 for (int j = 0; j < arTypes->Count; j++)
2257 if (t->IsSubclassOf(safe_cast< ::System::Type^ >(arTypes[j])))
2259 arTypes->RemoveAt(i);
2260 bRemove = true;
2261 break;
2264 if (bRemove)
2265 break;
2266 start++;
2269 if (bRemove == false)
2270 break;
2272 return arTypes;
2276 css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
2277 resolveInterfaceTypedef(
2278 const css::uno::Reference<css::reflection::XTypeDescription>& type)
2280 Reference<reflection::XInterfaceTypeDescription2>
2281 xIfaceTd(type, UNO_QUERY);
2283 if (xIfaceTd.is())
2284 return xIfaceTd;
2286 Reference<reflection::XIndirectTypeDescription> xIndTd(
2287 type, UNO_QUERY);
2288 if (xIndTd.is() == sal_False)
2289 throw css::uno::Exception(
2290 "resolveInterfaceTypedef was called with an invalid argument", 0);
2292 return resolveInterfaceTypedef(xIndTd->getReferencedType());
2298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */