fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / cli_ure / source / climaker / climaker_emit.cxx
blob51bed9ab4ac059857ee80f0d0b85037ee0385e8e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "climaker_share.h"
22 #include "rtl/string.hxx"
23 #include "rtl/ustrbuf.hxx"
24 #include "com/sun/star/reflection/XIndirectTypeDescription.hpp"
25 #include "com/sun/star/reflection/XStructTypeDescription.hpp"
26 #include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp"
27 #include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp"
28 #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription.hpp"
29 #include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp"
30 #include <vector>
32 using namespace ::System::Reflection;
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno;
37 namespace climaker
39 System::String^ mapUnoPolymorphicName(System::String^ unoName);
41 static inline ::System::String ^ to_cts_name(
42 OUString const & uno_name )
44 return ustring_to_String("unoidl." + uno_name);
48 static inline ::System::Object ^ to_cli_constant( Any const & value )
50 switch (value.getValueTypeClass())
52 case TypeClass_CHAR:
53 return ((::System::Char) *reinterpret_cast< sal_Unicode const * >(
54 value.getValue() ));
55 case TypeClass_BOOLEAN:
56 return ((::System::Boolean)
57 sal_False != *reinterpret_cast< sal_Bool const * >(
58 value.getValue() ));
59 case TypeClass_BYTE:
60 return ((::System::Byte) *reinterpret_cast< sal_Int8 const * >(
61 value.getValue() ));
62 case TypeClass_SHORT:
63 return ((::System::Int16) *reinterpret_cast< sal_Int16 const * >(
64 value.getValue() ));
65 case TypeClass_UNSIGNED_SHORT:
66 return ((::System::UInt16) *reinterpret_cast< sal_uInt16 const * >(
67 value.getValue() ));
68 case TypeClass_LONG:
69 return ((::System::Int32) *reinterpret_cast< sal_Int32 const * >(
70 value.getValue() ));
71 case TypeClass_UNSIGNED_LONG:
72 return ((::System::UInt32) *reinterpret_cast< sal_uInt32 const * >(
73 value.getValue() ));
74 case TypeClass_HYPER:
75 return ((::System::Int64) *reinterpret_cast< sal_Int64 const * >(
76 value.getValue() ));
77 case TypeClass_UNSIGNED_HYPER:
78 return ((::System::UInt64) *reinterpret_cast< sal_uInt64 const * >(
79 value.getValue() ));
80 case TypeClass_FLOAT:
81 return ((::System::Single) *reinterpret_cast< float const * >(
82 value.getValue() ));
83 case TypeClass_DOUBLE:
84 return ((::System::Double) *reinterpret_cast< double const * >(
85 value.getValue() ));
86 default:
87 throw RuntimeException(
88 "unexpected constant type " +
89 value.getValueType().getTypeName() );
94 static inline void emit_ldarg( Emit::ILGenerator ^ code, ::System::Int32 index )
96 switch (index)
98 case 0:
99 #pragma warning (push)
100 #pragma warning (disable: 4538)
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 neede 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();
274 Assembly ^ TypeEmitter::type_resolve(
275 ::System::Object ^, ::System::ResolveEventArgs ^ args )
277 ::System::String ^ cts_name = args->Name;
278 ::System::Type ^ ret_type;
280 iface_entry ^ entry = dynamic_cast< iface_entry ^ >(m_incomplete_ifaces[cts_name] );
281 if (nullptr != entry)
282 ret_type = entry->m_type_builder;
284 if (nullptr == ret_type)
286 sal_Int32 len = m_extra_assemblies->Length;
287 for ( sal_Int32 pos = 0; pos < len; ++pos )
289 ret_type = m_extra_assemblies[ pos ]->GetType(
290 cts_name, false /* no exc */ );
291 if (nullptr != ret_type)
293 if (g_verbose)
295 ::System::Console::WriteLine(
296 "> resolving type {0} from {1}.",
297 cts_name, ret_type->Assembly->FullName );
299 break;
303 if (nullptr != ret_type)
304 return ret_type->Assembly;
305 return nullptr;
309 ::System::Type ^ TypeEmitter::get_type(
310 ::System::String ^ cts_name, bool throw_exc )
312 ::System::Type ^ ret_type = m_module_builder->GetType( cts_name, false );
313 //We get the type from the ModuleBuilder even if the type is not complete
314 //but have been defined.
315 //if (ret_type == 0)
317 // iface_entry * entry = dynamic_cast< iface_entry * >(
318 // m_incomplete_ifaces->get_Item( cts_name ) );
319 // if (0 != entry)
320 // ret_type = entry->m_type_builder;
322 //try the cli_basetypes assembly
323 if (ret_type == nullptr)
325 ::System::Text::StringBuilder ^ builder = gcnew ::System::Text::StringBuilder(cts_name);
326 builder->Append(",cli_basetypes");
327 ret_type = ::System::Type::GetType(builder->ToString());
330 if (ret_type == nullptr)
334 // may call on type_resolve()
335 return ::System::Type::GetType( cts_name, throw_exc );
337 catch (::System::Exception^ exc)
339 //If the type is not found one may have forgotten to specify assemblies with
340 //additional types
341 ::System::Text::StringBuilder ^ sb = gcnew ::System::Text::StringBuilder();
342 sb->Append(gcnew ::System::String("\nThe type "));
343 sb->Append(cts_name);
344 sb->Append(gcnew ::System::String(" \n could not be found. Did you forget to " \
345 "specify an additional assembly with the --reference option?\n"));
346 if (throw_exc)
347 throw gcnew ::System::Exception(sb->ToString(), exc);
350 else
352 return ret_type;
357 ::System::Type ^ TypeEmitter::get_type_Exception()
359 if (nullptr == m_type_Exception)
361 m_type_Exception = get_type(
362 "unoidl.com.sun.star.uno.Exception", false /* no exc */ );
363 if (nullptr == m_type_Exception)
365 // define hardcoded type unoidl.com.sun.star.uno.Exception
366 Emit::TypeBuilder ^ type_builder =
367 m_module_builder->DefineType(
368 "unoidl.com.sun.star.uno.Exception",
369 (TypeAttributes) (TypeAttributes::Public |
370 TypeAttributes::BeforeFieldInit |
371 TypeAttributes::AnsiClass),
372 (::System::Exception::typeid) );
373 Emit::FieldBuilder ^ field_Context = type_builder->DefineField(
374 "Context", (::System::Object::typeid),
375 FieldAttributes::Public );
376 // default .ctor
377 type_builder->DefineDefaultConstructor( c_ctor_method_attr );
378 // .ctor
379 array< ::System::Type^>^ param_types =
380 gcnew array< ::System::Type^>(2);
381 param_types[ 0 ] = ::System::String::typeid;
382 param_types[ 1 ] = ::System::Object::typeid;
383 Emit::ConstructorBuilder ^ ctor_builder =
384 type_builder->DefineConstructor(
385 c_ctor_method_attr, CallingConventions::Standard,
386 param_types );
387 ctor_builder->DefineParameter(
388 1, ParameterAttributes::In, "Message" );
389 ctor_builder->DefineParameter(
390 2, ParameterAttributes::In, "Context" );
391 Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
392 code->Emit( Emit::OpCodes::Ldarg_0 );
393 code->Emit( Emit::OpCodes::Ldarg_1 );
394 param_types = gcnew array< ::System::Type^>(1);
395 param_types[ 0 ] = ::System::String::typeid;
396 code->Emit(
397 Emit::OpCodes::Call,
398 (::System::Exception::typeid)
399 ->GetConstructor( param_types ) );
400 code->Emit( Emit::OpCodes::Ldarg_0 );
401 code->Emit( Emit::OpCodes::Ldarg_2 );
402 code->Emit( Emit::OpCodes::Stfld, field_Context );
403 code->Emit( Emit::OpCodes::Ret );
405 if (g_verbose)
407 ::System::Console::WriteLine(
408 "> emitting exception type "
409 "unoidl.com.sun.star.uno.Exception" );
411 m_type_Exception = type_builder->CreateType();
414 return m_type_Exception;
418 ::System::Type ^ TypeEmitter::get_type_RuntimeException()
420 if (nullptr == m_type_RuntimeException)
422 m_type_RuntimeException = get_type(
423 "unoidl.com.sun.star.uno.RuntimeException", false /* no exc */ );
424 if (nullptr == m_type_RuntimeException)
426 // define hardcoded type unoidl.com.sun.star.uno.RuntimeException
427 ::System::Type ^ type_Exception = get_type_Exception();
428 Emit::TypeBuilder ^ type_builder =
429 m_module_builder->DefineType(
430 "unoidl.com.sun.star.uno.RuntimeException",
431 (TypeAttributes) (TypeAttributes::Public |
432 TypeAttributes::BeforeFieldInit |
433 TypeAttributes::AnsiClass),
434 type_Exception );
435 // default .ctor
436 type_builder->DefineDefaultConstructor( c_ctor_method_attr );
437 // .ctor
438 array< ::System::Type^>^ param_types =
439 gcnew array< ::System::Type^>(2);
440 param_types[ 0 ] = ::System::String::typeid;
441 param_types[ 1 ] = ::System::Object::typeid;
442 Emit::ConstructorBuilder ^ ctor_builder =
443 type_builder->DefineConstructor(
444 c_ctor_method_attr, CallingConventions::Standard,
445 param_types );
446 ctor_builder->DefineParameter(
447 1, ParameterAttributes::In, "Message" );
448 ctor_builder->DefineParameter(
449 2, ParameterAttributes::In, "Context" );
450 Emit::ILGenerator ^ code = ctor_builder->GetILGenerator();
451 code->Emit( Emit::OpCodes::Ldarg_0 );
452 code->Emit( Emit::OpCodes::Ldarg_1 );
453 code->Emit( Emit::OpCodes::Ldarg_2 );
454 code->Emit(
455 Emit::OpCodes::Call,
456 type_Exception->GetConstructor( param_types ) );
457 code->Emit( Emit::OpCodes::Ret );
459 if (g_verbose)
461 ::System::Console::WriteLine(
462 "> emitting exception type "
463 "unoidl.com.sun.star.uno.RuntimeException" );
465 m_type_RuntimeException = type_builder->CreateType();
468 return m_type_RuntimeException;
472 ::System::Type ^ TypeEmitter::get_type(
473 Reference< reflection::XConstantTypeDescription > const & xType )
475 ::System::String ^ cts_name = to_cts_name( xType->getName() );
476 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
477 if (nullptr == ret_type)
479 Reference< reflection::XConstantTypeDescription > xConstant(
480 xType, UNO_QUERY_THROW );
481 ::System::Object ^ constant =
482 to_cli_constant( xConstant->getConstantValue() );
483 Emit::TypeBuilder ^ type_builder =
484 m_module_builder->DefineType(
485 cts_name,
486 (TypeAttributes) (TypeAttributes::Public |
487 TypeAttributes::Sealed |
488 TypeAttributes::BeforeFieldInit |
489 TypeAttributes::AnsiClass) );
491 Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
492 cts_name->Substring( cts_name->LastIndexOf( '.' ) +1 ),
493 constant->GetType(),
494 (FieldAttributes) (FieldAttributes::Public |
495 FieldAttributes::Static |
496 FieldAttributes::Literal) );
497 field_builder->SetConstant( constant );
499 if (g_verbose)
501 ::System::Console::WriteLine(
502 "> emitting constant type {0}", cts_name );
504 ret_type = type_builder->CreateType();
506 return ret_type;
510 ::System::Type ^ TypeEmitter::get_type(
511 Reference< reflection::XConstantsTypeDescription > const & xType )
513 ::System::String ^ cts_name = to_cts_name( xType->getName() );
514 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
515 if (nullptr == ret_type)
517 Emit::TypeBuilder ^ type_builder =
518 m_module_builder->DefineType(
519 cts_name,
520 (TypeAttributes) (TypeAttributes::Public |
521 TypeAttributes::Sealed |
522 TypeAttributes::BeforeFieldInit |
523 TypeAttributes::AnsiClass) );
525 Sequence< Reference<
526 reflection::XConstantTypeDescription > > seq_constants(
527 xType->getConstants() );
528 Reference< reflection::XConstantTypeDescription > const * constants =
529 seq_constants.getConstArray();
530 sal_Int32 constants_length = seq_constants.getLength();
531 for ( sal_Int32 constants_pos = 0;
532 constants_pos < constants_length; ++constants_pos )
534 Reference<
535 reflection::XConstantTypeDescription > const & xConstant =
536 constants[ constants_pos ];
537 ::System::Object ^ constant =
538 to_cli_constant( xConstant->getConstantValue() );
539 ::System::String ^ uno_name =
540 ustring_to_String( xConstant->getName() );
541 Emit::FieldBuilder ^ field_builder = type_builder->DefineField(
542 uno_name->Substring( uno_name->LastIndexOf( '.' ) +1 ),
543 constant->GetType(),
544 (FieldAttributes) (FieldAttributes::Public |
545 FieldAttributes::Static |
546 FieldAttributes::Literal) );
547 field_builder->SetConstant( constant );
550 if (g_verbose)
552 ::System::Console::WriteLine(
553 "> emitting constants group type {0}", cts_name );
555 ret_type = type_builder->CreateType();
557 return ret_type;
561 ::System::Type ^ TypeEmitter::get_type(
562 Reference< reflection::XEnumTypeDescription > const & xType )
564 ::System::String ^ cts_name = to_cts_name( xType->getName() );
565 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
566 if (nullptr == ret_type)
568 // Emit::EnumBuilder * enum_builder =
569 // m_module_builder->DefineEnum(
570 // cts_name,
571 // (TypeAttributes) (TypeAttributes::Public |
572 // // TypeAttributes::Sealed |
573 // TypeAttributes::AnsiClass),
574 // __typeof (::System::Int32) );
575 // workaround enum builder bug
576 Emit::TypeBuilder ^ enum_builder =
577 m_module_builder->DefineType(
578 cts_name,
579 (TypeAttributes) (TypeAttributes::Public |
580 TypeAttributes::Sealed),
581 ::System::Enum::typeid );
582 enum_builder->DefineField(
583 "value__", ::System::Int32::typeid,
584 (FieldAttributes) (FieldAttributes::Private |
585 FieldAttributes::SpecialName |
586 FieldAttributes::RTSpecialName) );
587 Sequence< OUString > seq_enum_names( xType->getEnumNames() );
588 Sequence< sal_Int32 > seq_enum_values( xType->getEnumValues() );
589 sal_Int32 enum_length = seq_enum_names.getLength();
590 OSL_ASSERT( enum_length == seq_enum_values.getLength() );
591 OUString const * enum_names = seq_enum_names.getConstArray();
592 sal_Int32 const * enum_values = seq_enum_values.getConstArray();
593 for ( sal_Int32 enum_pos = 0; enum_pos < enum_length; ++enum_pos )
595 // enum_builder->DefineLiteral(
596 // ustring_to_String( enum_names[ enum_pos ] ),
597 // __box ((::System::Int32) enum_values[ enum_pos ]) );
598 Emit::FieldBuilder ^ field_builder =
599 enum_builder->DefineField(
600 ustring_to_String( enum_names[ enum_pos ] ),
601 enum_builder,
602 (FieldAttributes) (FieldAttributes::Public |
603 FieldAttributes::Static |
604 FieldAttributes::Literal) );
605 field_builder->SetConstant(
606 ((::System::Int32) enum_values[ enum_pos ]) );
609 if (g_verbose)
611 ::System::Console::WriteLine(
612 "> emitting enum type {0}", cts_name );
614 ret_type = enum_builder->CreateType();
616 return ret_type;
620 ::System::Type ^ TypeEmitter::get_type(
621 Reference< reflection::XCompoundTypeDescription > const & xType )
623 OUString uno_name( xType->getName() );
624 if (TypeClass_EXCEPTION == xType->getTypeClass())
626 if ( uno_name == "com.sun.star.uno.Exception" )
628 return get_type_Exception();
630 if ( uno_name == "com.sun.star.uno.RuntimeException" )
632 return get_type_RuntimeException();
635 ::System::String ^ cts_name = to_cts_name( uno_name );
636 // if the struct is an instantiated polymorpic struct then we create the simple struct name
637 // For example:
638 // void func ([in] PolyStruct<boolean> arg);
639 //PolyStruct<boolean> will be converted to PolyStruct
640 polymorphicStructNameToStructName( & cts_name);
642 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
643 if (nullptr == ret_type)
645 Reference< reflection::XCompoundTypeDescription > xBaseType(
646 xType->getBaseType(), UNO_QUERY );
647 ::System::Type ^ base_type = (xBaseType.is()
648 ? get_type( xBaseType )
649 : ::System::Object::typeid);
650 Emit::TypeBuilder ^ type_builder =
651 m_module_builder->DefineType(
652 cts_name,
653 (TypeAttributes) (TypeAttributes::Public |
654 TypeAttributes::BeforeFieldInit |
655 TypeAttributes::AnsiClass),
656 base_type );
659 // insert to be completed
660 struct_entry ^ entry = gcnew struct_entry();
661 xType->acquire();
662 entry->m_xType = xType.get();
663 entry->m_type_builder = type_builder;
664 entry->m_base_type = base_type;
665 m_incomplete_structs->Add( cts_name, entry );
667 // type is incomplete
668 ret_type = type_builder;
671 //In case of an instantiated polymorphic struct we want to return a
672 //uno.PolymorphicType (inherits Type) rather then Type. This is neaded for constructing
673 //the service code. We can only do that if the struct is completed.
674 if (m_generated_structs[cts_name])
676 Reference< reflection::XStructTypeDescription> xStructTypeDesc(
677 xType, UNO_QUERY);
679 if (xStructTypeDesc.is())
681 Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments();
682 sal_Int32 numTypes = seqTypeArgs.getLength();
683 if (numTypes > 0)
685 //it is an instantiated polymorphic struct
686 ::System::String ^ sCliName = mapUnoTypeName(ustring_to_String(xType->getName()));
687 ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName);
691 return ret_type;
695 ::System::Type ^ TypeEmitter::get_type(
696 Reference< reflection::XInterfaceTypeDescription2 > const & xType )
698 OUString uno_name( xType->getName() );
699 if ( uno_name == "com.sun.star.uno.XInterface" )
701 return ::System::Object::typeid;
704 ::System::String ^ cts_name = to_cts_name( xType->getName() );
705 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
706 if (nullptr == ret_type)
708 Emit::TypeBuilder ^ type_builder;
710 TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
711 TypeAttributes::Interface |
712 TypeAttributes::Abstract |
713 TypeAttributes::AnsiClass);
715 std::vector<Reference<reflection::XInterfaceTypeDescription2> > vecBaseTypes;
716 Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes =
717 xType->getBaseTypes();
718 if (seqBaseTypes.getLength() > 0)
720 for (int i = 0; i < seqBaseTypes.getLength(); i++)
722 Reference<reflection::XInterfaceTypeDescription2> xIfaceTd =
723 resolveInterfaceTypedef(seqBaseTypes[i]);
725 if ( xIfaceTd->getName() != "com.sun.star.uno.XInterface" )
727 vecBaseTypes.push_back(xIfaceTd);
731 array< ::System::Type^>^ base_interfaces =
732 gcnew array< ::System::Type^>( vecBaseTypes.size() );
734 typedef std::vector<Reference<reflection::XInterfaceTypeDescription2> >::const_iterator it;
735 int index = 0;
736 for (it i = vecBaseTypes.begin(); i != vecBaseTypes.end(); ++i, ++index)
737 base_interfaces[ index ] = get_type( *i );
738 type_builder = m_module_builder->DefineType(
739 cts_name, attr, nullptr, base_interfaces );
741 else
743 ::System::Console::WriteLine(
744 "warning: IDL interface {0} is not derived from "
745 "com.sun.star.uno.XInterface!",
746 ustring_to_String( uno_name ) );
748 type_builder = m_module_builder->DefineType( cts_name, attr );
751 // insert to be completed
752 iface_entry ^ entry = gcnew iface_entry();
753 xType->acquire();
754 entry->m_xType = xType.get();
755 entry->m_type_builder = type_builder;
756 m_incomplete_ifaces->Add( cts_name, entry );
758 // type is incomplete
759 ret_type = type_builder;
761 return ret_type;
766 ::System::Type ^ TypeEmitter::get_type(
767 Reference< reflection::XServiceTypeDescription2 > const & xType )
769 if (xType->isSingleInterfaceBased() == sal_False)
770 return nullptr;
772 System::String ^ cts_name = to_cts_name( xType->getName() );
773 System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
774 if (ret_type != nullptr)
775 return ret_type;
777 TypeAttributes attr = (TypeAttributes) (TypeAttributes::Public |
778 TypeAttributes::Sealed |
779 TypeAttributes::BeforeFieldInit |
780 TypeAttributes::AnsiClass);
782 Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
783 cts_name, attr);
785 // insert to be completed
786 service_entry ^ entry = gcnew service_entry();
787 xType->acquire();
788 entry->m_xType = xType.get();
789 entry->m_type_builder = type_builder;
790 m_incomplete_services->Add(cts_name,entry );
792 return type_builder;
795 ::System::Type ^ TypeEmitter::get_type(
796 Reference<reflection::XSingletonTypeDescription2 > const & xType )
798 if (xType->isInterfaceBased() == sal_False)
799 return nullptr;
801 ::System::String^ cts_name = to_cts_name( xType->getName() );
802 ::System::Type ^ ret_type = get_type( cts_name, false /* no exc */ );
803 if (ret_type != nullptr)
804 return ret_type;
806 TypeAttributes attr = static_cast<TypeAttributes>(
807 TypeAttributes::Public |
808 TypeAttributes::Sealed |
809 TypeAttributes::BeforeFieldInit |
810 TypeAttributes::AnsiClass);
812 Emit::TypeBuilder ^ type_builder = m_module_builder->DefineType(
813 cts_name, attr);
815 // insert to be completed
816 singleton_entry ^ entry = gcnew singleton_entry();
817 xType->acquire();
818 entry->m_xType = xType.get();
819 entry->m_type_builder = type_builder;
820 m_incomplete_singletons->Add(cts_name,entry );
822 return type_builder;
827 ::System::Type ^ TypeEmitter::complete_iface_type( iface_entry ^ entry )
829 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
830 reflection::XInterfaceTypeDescription2 * xType = entry->m_xType;
832 Sequence<Reference< reflection::XTypeDescription > > seqBaseTypes( xType->getBaseTypes() );
833 if (seqBaseTypes.getLength() > 0)
835 for (int i = 0; i < seqBaseTypes.getLength(); i++)
837 //make sure we get the interface rather then a typedef
838 Reference<reflection::XInterfaceTypeDescription2> aBaseType =
839 resolveInterfaceTypedef( seqBaseTypes[i]);
841 if ( aBaseType->getName() != "com.sun.star.uno.XInterface" )
843 ::System::String ^ basetype_name = to_cts_name( aBaseType->getName() );
844 iface_entry ^ base_entry = dynamic_cast< iface_entry ^ >(
845 m_incomplete_ifaces[basetype_name] );
846 if (nullptr != base_entry)
848 // complete uncompleted base type first
849 complete_iface_type( base_entry );
855 Sequence<
856 Reference< reflection::XInterfaceMemberTypeDescription > > seq_members(
857 xType->getMembers() );
858 Reference< reflection::XInterfaceMemberTypeDescription > const * members =
859 seq_members.getConstArray();
860 sal_Int32 members_length = seq_members.getLength();
861 for ( sal_Int32 members_pos = 0;
862 members_pos < members_length; ++members_pos )
864 Reference<
865 reflection::XInterfaceMemberTypeDescription > const & xMember =
866 members[ members_pos ];
867 Sequence< Reference< reflection::XTypeDescription > > seq_exceptions;
868 Emit::MethodBuilder ^ method_builder;
870 MethodAttributes c_method_attr = (MethodAttributes)
871 (MethodAttributes::Public |
872 MethodAttributes::Abstract |
873 MethodAttributes::Virtual |
874 MethodAttributes::NewSlot |
875 MethodAttributes::HideBySig);
877 if (TypeClass_INTERFACE_METHOD == xMember->getTypeClass())
879 Reference< reflection::XInterfaceMethodTypeDescription > xMethod(
880 xMember, UNO_QUERY_THROW );
882 Sequence<
883 Reference< reflection::XMethodParameter > > seq_parameters(
884 xMethod->getParameters() );
885 sal_Int32 params_length = seq_parameters.getLength();
886 array< ::System::Type^>^ param_types =
887 gcnew array< ::System::Type^>( params_length );
888 Reference< reflection::XMethodParameter > const * parameters =
889 seq_parameters.getConstArray();
890 // first determine all types
891 //Make the first param type as return type
892 sal_Int32 params_pos = 0;
893 for ( ; params_pos < params_length; ++params_pos )
895 Reference< reflection::XMethodParameter > const & xParam =
896 parameters[ params_pos ];
897 ::System::Type ^ param_type = get_type( xParam->getType() );
898 ::System::String ^ param_type_name = param_type->FullName;
899 if (xParam->isOut())
901 param_type = get_type(
902 ::System::String::Concat(
903 param_type_name, "&" ), true );
905 param_types[ xParam->getPosition() ] = param_type;
909 // create method
910 // if (tb)
911 // method_builder = type_builder->DefineMethod(
912 // ustring_to_String( xMethod->getMemberName() ),
913 // c_method_attr, tb,
914 // param_types );
915 // else
916 method_builder = type_builder->DefineMethod(
917 ustring_to_String( xMethod->getMemberName() ),
918 c_method_attr, get_type( xMethod->getReturnType() ),
919 param_types );
920 // then define parameter infos
921 params_pos = 0;
922 for ( ; params_pos < params_length; ++params_pos )
924 Reference< reflection::XMethodParameter > const & xParam =
925 parameters[ params_pos ];
926 long param_flags = 0;
927 if (xParam->isIn())
928 param_flags |= (long)ParameterAttributes::In;
929 if (xParam->isOut())
930 param_flags |= (long)ParameterAttributes::Out;
931 OSL_ASSERT( 0 != param_flags );
932 method_builder->DefineParameter(
933 xParam->getPosition() +1 /* starts with 1 */,
934 (ParameterAttributes) param_flags,
935 ustring_to_String( xParam->getName() ) );
937 //Apply attribute TypeParametersAttribute to return value if it
938 //is a parameterized Type. Currently only structs can have parameters.
939 Reference<reflection::XStructTypeDescription> xReturnStruct(
940 xMethod->getReturnType(), UNO_QUERY);
942 if (xReturnStruct.is())
944 Sequence<Reference<reflection::XTypeDescription> > seq_type_args =
945 xReturnStruct->getTypeArguments();
946 if (seq_type_args.getLength() != 0)
948 //get th ctor of the attribute
949 array< ::System::Type^>^ arCtor = {::System::Type::GetType("System.Type[]")};
950 //Get the arguments for the attribute's ctor
951 Reference<reflection::XTypeDescription> const * arXTypeArgs =
952 seq_type_args.getConstArray();
953 int numTypes = seq_type_args.getLength();
954 array< ::System::Type^>^ arCtsTypes = gcnew array< ::System::Type^>(numTypes);
955 for (int i = 0; i < numTypes; i++)
956 arCtsTypes[i] = get_type(arXTypeArgs[i]);
957 array< ::System::Object^>^ arArgs = {arCtsTypes};
959 Emit::CustomAttributeBuilder ^ attrBuilder =
960 gcnew Emit::CustomAttributeBuilder(
961 ::uno::TypeArgumentsAttribute::typeid
962 ->GetConstructor( arCtor),
963 arArgs);
965 method_builder->SetCustomAttribute(attrBuilder);
969 //define UNO exception attribute (exceptions)--------------------------------------
970 Emit::CustomAttributeBuilder^ attrBuilder =
971 get_iface_method_exception_attribute(xMethod);
972 if (attrBuilder != nullptr)
973 method_builder->SetCustomAttribute(attrBuilder);
975 // oneway attribute
976 if (xMethod->isOneway())
978 array< ::System::Type^>^ arCtorOneway = gcnew array< ::System::Type^>(0);
979 array< ::System::Object^>^ arArgs = gcnew array< ::System::Object^>(0);
980 Emit::CustomAttributeBuilder ^ attrBuilder =
981 gcnew Emit::CustomAttributeBuilder(
982 ::uno::OnewayAttribute::typeid->GetConstructor( arCtorOneway),
983 arArgs);
984 method_builder->SetCustomAttribute(attrBuilder);
987 else // attribute
989 OSL_ASSERT(
990 TypeClass_INTERFACE_ATTRIBUTE == xMember->getTypeClass() );
991 Reference<
992 reflection::XInterfaceAttributeTypeDescription2 > xAttribute(
993 xMember, UNO_QUERY_THROW );
995 MethodAttributes c_property_method_attr = (MethodAttributes)
996 (c_method_attr | MethodAttributes::SpecialName);
998 ::System::Type ^ attribute_type = get_type( xAttribute->getType() );
999 array< ::System::Type^>^ parameters =
1000 gcnew array< ::System::Type^> ( 0 );
1002 Emit::PropertyBuilder ^ property_builder =
1003 type_builder->DefineProperty(
1004 ustring_to_String( xAttribute->getMemberName() ),
1005 PropertyAttributes::None,
1006 attribute_type, parameters );
1008 //set BoundAttribute, if necessary
1009 if (xAttribute->isBound())
1011 ConstructorInfo ^ ctorBoundAttr =
1012 ::uno::BoundAttribute::typeid->GetConstructor(
1013 gcnew array<System::Type^>(0));
1014 Emit::CustomAttributeBuilder ^ attrBuilderBound =
1015 gcnew Emit::CustomAttributeBuilder(
1016 ctorBoundAttr, gcnew array< ::System::Object^>(0));
1017 property_builder->SetCustomAttribute(attrBuilderBound);
1020 // getter
1021 Emit::MethodBuilder ^ method_builder =
1022 type_builder->DefineMethod(
1023 ustring_to_String( "get_" +
1024 xAttribute->getMemberName() ),
1025 c_property_method_attr, attribute_type, parameters );
1027 //define UNO exception attribute (exceptions)--------------------------------------
1028 Emit::CustomAttributeBuilder^ attrBuilder =
1029 get_exception_attribute(xAttribute->getGetExceptions());
1030 if (attrBuilder != nullptr)
1031 method_builder->SetCustomAttribute(attrBuilder);
1033 property_builder->SetGetMethod( method_builder );
1035 if (! xAttribute->isReadOnly())
1037 // setter
1038 parameters = gcnew array< ::System::Type^> ( 1 );
1039 parameters[ 0 ] = attribute_type;
1040 method_builder =
1041 type_builder->DefineMethod(
1042 ustring_to_String( "set_" +
1043 xAttribute->getMemberName() ),
1044 c_property_method_attr, nullptr, parameters );
1045 // define parameter info
1046 method_builder->DefineParameter(
1047 1 /* starts with 1 */, ParameterAttributes::In, "value" );
1048 //define UNO exception attribute (exceptions)--------------------------------------
1049 Emit::CustomAttributeBuilder^ attrBuilder =
1050 get_exception_attribute(xAttribute->getSetExceptions());
1051 if (attrBuilder != nullptr)
1052 method_builder->SetCustomAttribute(attrBuilder);
1054 property_builder->SetSetMethod( method_builder );
1059 // remove from incomplete types map
1060 ::System::String ^ cts_name = type_builder->FullName;
1061 m_incomplete_ifaces->Remove( cts_name );
1062 xType->release();
1064 if (g_verbose)
1066 ::System::Console::WriteLine(
1067 "> emitting interface type {0}", cts_name );
1069 return type_builder->CreateType();
1072 ::System::Type ^ TypeEmitter::complete_struct_type( struct_entry ^ entry )
1074 OSL_ASSERT(entry);
1075 ::System::String ^ cts_name = entry->m_type_builder->FullName;
1077 //Polymorphic struct, define uno.TypeParametersAttribute
1078 //A polymorphic struct cannot have a basetype.
1079 //When we create the template of the struct then we have no exact types
1080 //and the name does not contain a parameter list
1081 Sequence< OUString > seq_type_parameters;
1082 Reference< reflection::XStructTypeDescription> xStructTypeDesc(
1083 entry->m_xType, UNO_QUERY);
1084 if (xStructTypeDesc.is())
1086 seq_type_parameters = xStructTypeDesc->getTypeParameters();
1087 int numTypes = 0;
1088 if ((numTypes = seq_type_parameters.getLength()) > 0)
1090 array< ::System::Object^>^ aArg = gcnew array< ::System::Object^>(numTypes);
1091 for (int i = 0; i < numTypes; i++)
1092 aArg[i] = ustring_to_String(seq_type_parameters.getConstArray()[i]);
1093 array< ::System::Object^>^ args = {aArg};
1095 array< ::System::Type^>^ arTypesCtor =
1096 {::System::Type::GetType("System.String[]")};
1097 Emit::CustomAttributeBuilder ^ attrBuilder =
1098 gcnew Emit::CustomAttributeBuilder(
1099 ::uno::TypeParametersAttribute::typeid->GetConstructor(arTypesCtor),
1100 args);
1101 entry->m_type_builder->SetCustomAttribute(attrBuilder);
1105 // optional: lookup base type whether generated entry of this session
1106 struct_entry ^ base_type_entry = nullptr;
1107 if (nullptr != entry->m_base_type)
1109 //ToDo maybe get from incomplete structs
1110 base_type_entry =
1111 dynamic_cast< struct_entry ^ >(
1112 m_generated_structs[
1113 entry->m_base_type->FullName ] );
1116 // members
1117 Sequence< Reference< reflection::XTypeDescription > > seq_members(
1118 entry->m_xType->getMemberTypes() );
1119 Sequence< OUString > seq_member_names( entry->m_xType->getMemberNames() );
1120 sal_Int32 members_length = seq_members.getLength();
1121 OSL_ASSERT( seq_member_names.getLength() == members_length );
1122 //check if we have a XTypeDescription for every member. If not then the user may
1123 //have forgotten to specify additional rdbs with the --extra option.
1124 Reference< reflection::XTypeDescription > const * pseq_members =
1125 seq_members.getConstArray();
1126 OUString const * pseq_member_names =
1127 seq_member_names.getConstArray();
1128 for (int i = 0; i < members_length; i++)
1130 const OUString sType(entry->m_xType->getName());
1131 const OUString sMemberName(pseq_member_names[i]);
1132 if ( ! pseq_members[i].is())
1133 throw RuntimeException("Missing type description . Check if you need to "
1134 "specify additional RDBs with the --extra option. Type missing for: " + sType +
1135 "::" + sMemberName,0);
1138 sal_Int32 all_members_length = 0;
1139 sal_Int32 member_pos;
1140 sal_Int32 type_param_pos = 0;
1142 // collect base types; wrong order
1143 ::System::Collections::ArrayList ^ base_types_list =
1144 gcnew ::System::Collections::ArrayList( 3 /* initial capacity */ );
1145 for (::System::Type ^ base_type_pos = entry->m_base_type;
1146 ! base_type_pos->Equals( ::System::Object::typeid );
1147 base_type_pos = base_type_pos->BaseType )
1149 base_types_list->Add( base_type_pos );
1150 if (base_type_pos->Equals( ::System::Exception::typeid ))
1152 // special Message member
1153 all_members_length += 1;
1154 break; // don't include System.Exception base classes
1156 else
1158 //ensure the base type is complete. Otherwise GetFields won't work
1159 get_complete_struct(base_type_pos->FullName);
1160 all_members_length +=
1161 base_type_pos->GetFields(
1162 (BindingFlags) (BindingFlags::Instance |
1163 BindingFlags::Public |
1164 BindingFlags::DeclaredOnly) )
1165 ->Length;
1169 // create all_members arrays; right order
1170 array< ::System::String^>^ all_member_names =
1171 gcnew array< ::System::String^> (all_members_length + members_length );
1172 array< ::System::Type^>^ all_param_types =
1173 gcnew array< ::System::Type^> (all_members_length + members_length );
1174 member_pos = 0;
1175 for ( sal_Int32 pos = base_types_list->Count; pos--; )
1177 ::System::Type ^ base_type = safe_cast< ::System::Type ^ >(
1178 base_types_list[pos] );
1179 if (base_type->Equals( ::System::Exception::typeid ))
1181 all_member_names[ member_pos ] = "Message";
1182 all_param_types[ member_pos ] = ::System::String::typeid;
1183 ++member_pos;
1185 else
1187 ::System::String ^ base_type_name = base_type->FullName;
1189 //ToDo m_generated_structs?
1190 struct_entry ^ entry =
1191 dynamic_cast< struct_entry ^ >(
1192 m_generated_structs[base_type_name] );
1193 if (nullptr == entry)
1195 // complete type
1196 array<FieldInfo^>^ fields =
1197 base_type->GetFields(
1198 (BindingFlags) (BindingFlags::Instance |
1199 BindingFlags::Public |
1200 BindingFlags::DeclaredOnly) );
1201 sal_Int32 len = fields->Length;
1202 for ( sal_Int32 pos = 0; pos < len; ++pos )
1204 FieldInfo ^ field = fields[ pos ];
1205 all_member_names[ member_pos ] = field->Name;
1206 all_param_types[ member_pos ] = field->FieldType;
1207 ++member_pos;
1210 else // generated during this session:
1211 // members may be incomplete ifaces
1213 sal_Int32 len = entry->m_member_names->Length;
1214 for ( sal_Int32 pos = 0; pos < len; ++pos )
1216 all_member_names[ member_pos ] =
1217 entry->m_member_names[ pos ];
1218 all_param_types[ member_pos ] =
1219 entry->m_param_types[ pos ];
1220 ++member_pos;
1225 OSL_ASSERT( all_members_length == member_pos );
1227 // build up entry
1228 // struct_entry * entry = new struct_entry();
1229 entry->m_member_names = gcnew array< ::System::String^> ( members_length );
1230 entry->m_param_types = gcnew array< ::System::Type^> ( members_length );
1232 // add members
1233 array<Emit::FieldBuilder^>^ members = gcnew array<Emit::FieldBuilder^> ( members_length );
1234 //Reference< reflection::XTypeDescription > const * pseq_members =
1235 // seq_members.getConstArray();
1236 //OUString const * pseq_member_names =
1237 // seq_member_names.getConstArray();
1239 int curParamIndex = 0; //count the fields which have parameterized types
1240 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1242 ::System::String ^ field_name =
1243 ustring_to_String( pseq_member_names[ member_pos ] );
1244 ::System::Type ^ field_type;
1245 //Special handling of struct parameter types
1246 bool bParameterizedType = false;
1247 if (pseq_members[ member_pos ]->getTypeClass() == TypeClass_UNKNOWN)
1249 bParameterizedType = true;
1250 if (type_param_pos < seq_type_parameters.getLength())
1252 field_type = ::System::Object::typeid;
1253 type_param_pos++;
1255 else
1257 throw RuntimeException(
1258 "unexpected member type in " + entry->m_xType->getName() );
1261 else
1263 field_type = get_type( pseq_members[ member_pos ] );
1265 if (field_type->IsArray
1266 && m_incomplete_structs[cts_name]
1267 && !field_type->Namespace->Equals("System"))
1269 //Find the value type. In case of sequence<sequence< ... > > find the actual value type
1270 ::System::Type ^ value = field_type;
1271 while ((value = value->GetElementType())->IsArray);
1272 //If the value type is a struct then make sure it is fully created.
1273 get_complete_struct(value->FullName);
1274 field_type = 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 code->Emit( Emit::OpCodes::Ldarg_0 );
1347 code->Emit( Emit::OpCodes::Ldc_I4_0 );
1348 code->Emit(
1349 Emit::OpCodes::Newarr, field_type->GetElementType() );
1350 code->Emit( Emit::OpCodes::Stfld, field );
1352 else if (field_type->IsValueType)
1354 if (field_type->FullName->Equals( "uno.Any" ))
1356 code->Emit( Emit::OpCodes::Ldarg_0 );
1357 code->Emit( Emit::OpCodes::Ldsfld, ::uno::Any::typeid->GetField("VOID"));
1358 code->Emit( Emit::OpCodes::Stfld, field );
1361 else if (field_type->IsClass)
1363 /* may be XInterface */
1364 if (! field_type->Equals( ::System::Object::typeid ))
1366 // struct, exception
1367 //make sure the struct is already complete.
1368 get_complete_struct(field_type->FullName);
1369 code->Emit( Emit::OpCodes::Ldarg_0 );
1370 code->Emit(
1371 Emit::OpCodes::Newobj,
1372 //GetConstructor requies that the member types of the object which is to be constructed are already known.
1373 field_type->GetConstructor(
1374 gcnew array< ::System::Type^> ( 0 ) ) );
1375 code->Emit( Emit::OpCodes::Stfld, field );
1379 code->Emit( Emit::OpCodes::Ret );
1380 entry->m_default_ctor = ctor_builder;
1382 // parameterized .ctor including all base members
1383 ctor_builder = entry->m_type_builder->DefineConstructor(
1384 c_ctor_method_attr, CallingConventions::Standard, all_param_types );
1385 for ( member_pos = 0; member_pos < all_members_length; ++member_pos )
1387 ctor_builder->DefineParameter(
1388 member_pos +1 /* starts with 1 */, ParameterAttributes::In,
1389 all_member_names[ member_pos ] );
1391 code = ctor_builder->GetILGenerator();
1392 // call base .ctor
1393 code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1394 sal_Int32 base_members_length = all_members_length - members_length;
1395 array< ::System::Type^>^ param_types =
1396 gcnew array< ::System::Type^> ( base_members_length );
1397 for ( member_pos = 0; member_pos < base_members_length; ++member_pos )
1399 emit_ldarg( code, member_pos +1 );
1400 param_types[ member_pos ] = all_param_types[ member_pos ];
1402 code->Emit(
1403 Emit::OpCodes::Call,
1404 nullptr == base_type_entry
1405 ? entry->m_base_type->GetConstructor( param_types )
1406 : base_type_entry->m_ctor );
1407 // initialize members
1408 for ( member_pos = 0; member_pos < members_length; ++member_pos )
1410 code->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1411 emit_ldarg( code, member_pos + base_members_length +1 );
1412 code->Emit( Emit::OpCodes::Stfld, members[ member_pos ] );
1414 code->Emit( Emit::OpCodes::Ret );
1415 entry->m_ctor = ctor_builder;
1417 if (g_verbose)
1419 ::System::Console::WriteLine(
1420 "> emitting {0} type {1}",
1421 TypeClass_STRUCT == entry->m_xType->getTypeClass()
1422 ? "struct"
1423 : "exception",
1424 cts_name);
1426 // new entry
1427 m_generated_structs->Add(cts_name, entry );
1428 ::System::Type ^ ret_type = entry->m_type_builder->CreateType();
1430 // remove from incomplete types map
1431 m_incomplete_structs->Remove( cts_name );
1432 entry->m_xType->release();
1434 if (g_verbose)
1436 ::System::Console::WriteLine(
1437 "> emitting struct type {0}", cts_name);
1439 return ret_type;
1442 //Examples of generated code
1443 // public static XWeak constructor1(XComponentContext ctx)
1444 // {
1445 // XMultiComponentFactory factory = ctx.getServiceManager();
1446 // if (factory == null)
1447 // throw new com.sun.star.uno.DeploymentException("bla", null);
1448 // return (XWeak) factory.createInstanceWithContext("service_specifier", ctx);
1449 // }
1450 // public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c)
1451 // {
1452 // XMultiComponentFactory factory = ctx.getServiceManager();
1453 // if (factory == null)
1454 // throw new com.sun.star.uno.DeploymentException("bla", null);
1455 // Any[] arAny = new Any[3];
1456 // arAny[0] = new Any(typeof(int), a);
1457 // arAny[1] = new Any(typeof(int), b);
1458 // arAny[2] = new Any(c.Type, c.Value);
1459 // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx);
1460 // }
1461 // Notice that a any parameter is NOT wrapped by another any. Instead the new any is created with the type and value
1462 // of the parameter.
1464 // public static XWeak constructor3(XComponentContext ctx, params Any[] c)
1465 // {
1466 // XMultiComponentFactory factory = ctx.getServiceManager();
1467 // if (factory == null)
1468 // throw new com.sun.star.uno.DeploymentException("bla", null);
1469 // return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", c, ctx);
1470 // }
1471 ::System::Type ^ TypeEmitter::complete_service_type(service_entry ^ entry)
1473 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
1474 reflection::XServiceTypeDescription2 * xServiceType = entry->m_xType;
1476 //Create the private default constructor
1477 Emit::ConstructorBuilder^ ctor_builder =
1478 type_builder->DefineConstructor(
1479 (MethodAttributes) (MethodAttributes::Private |
1480 MethodAttributes::HideBySig |
1481 MethodAttributes::SpecialName |
1482 MethodAttributes::RTSpecialName),
1483 CallingConventions::Standard, nullptr);
1485 Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator();
1486 ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1487 ilGen->Emit(
1488 Emit::OpCodes::Call,
1489 type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
1490 ilGen->Emit( Emit::OpCodes::Ret );
1493 //Create the service constructors.
1494 //obtain the interface which makes up this service, it is the return
1495 //type of the constructor functions
1496 Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
1497 xServiceType->getInterface(), UNO_QUERY);
1498 if (xIfaceType.is () == sal_False)
1499 xIfaceType = resolveInterfaceTypedef(xServiceType->getInterface());
1500 System::Type ^ retType = get_type(xIfaceType);
1502 //Create the ConstructorInfo for a DeploymentException
1503 ::System::Type ^ typeDeploymentExc =
1504 get_type("unoidl.com.sun.star.uno.DeploymentException", true);
1506 array< ::System::Type^>^ arTypeCtor = {::System::String::typeid,
1507 ::System::Object::typeid};
1508 ::System::Reflection::ConstructorInfo ^ ctorDeploymentException =
1509 typeDeploymentExc->GetConstructor(arTypeCtor);
1511 Sequence<Reference<reflection::XServiceConstructorDescription> > seqCtors =
1512 xServiceType->getConstructors();
1514 ::System::Type ^ type_uno_exception = get_type("unoidl.com.sun.star.uno.Exception", true);
1516 for (int i = seqCtors.getLength() - 1; i >= 0; i--)
1518 bool bParameterArray = false;
1519 ::System::Type ^ typeAny = ::uno::Any::typeid;
1520 const Reference<reflection::XServiceConstructorDescription> & ctorDes =
1521 seqCtors[i];
1522 //obtain the parameter types
1523 Sequence<Reference<reflection::XParameter> > seqParams =
1524 ctorDes->getParameters();
1525 Reference<reflection::XParameter> const * arXParams = seqParams.getConstArray();
1526 sal_Int32 cParams = seqParams.getLength();
1527 array< ::System::Type^>^ arTypeParameters = gcnew array< ::System::Type^> (cParams + 1);
1528 arTypeParameters[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1529 for (int iparam = 0; iparam != cParams; iparam++)
1531 if (arXParams[iparam]->isRestParameter())
1532 arTypeParameters[iparam + 1] = array< ::uno::Any>::typeid;
1533 else
1534 arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType());
1536 //The array arTypeParameters can contain:
1537 //System.Type and uno.PolymorphicType.
1538 //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem.
1539 //The exception will read something like no on information for parameter # d
1540 //Maybe we need no override another Type method in PolymorphicType ...
1541 //Until we have figured this out, we will create another array of System.Type which
1542 //we pass on to DefineMethod.
1543 array< ::System::Type^>^ arParamTypes = gcnew array< ::System::Type^> (cParams + 1);
1544 // arParamTypes[0] = get_type("unoidl.com.sun.star.uno.XComponentContext", true);
1545 for (int i = 0; i < cParams + 1; i++)
1547 ::uno::PolymorphicType ^ pT = dynamic_cast< ::uno::PolymorphicType ^ >(arTypeParameters[i]);
1548 if (pT)
1549 arParamTypes[i] = pT->OriginalType;
1550 else
1551 arParamTypes[i] = arTypeParameters[i];
1553 //define method
1554 System::String ^ ctorName;
1555 if (ctorDes->isDefaultConstructor())
1556 ctorName = gcnew ::System::String("create");
1557 else
1558 ctorName = ustring_to_String(ctorDes->getName());
1559 Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
1560 ctorName,
1561 static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
1562 MethodAttributes::Static),
1563 retType,
1564 // arTypeParameters);
1565 arParamTypes);
1567 //define UNO exception attribute (exceptions)--------------------------------------
1568 Emit::CustomAttributeBuilder^ attrBuilder = get_service_exception_attribute(ctorDes);
1569 if (attrBuilder != nullptr)
1570 method_builder->SetCustomAttribute(attrBuilder);
1573 //define parameter attributes (paramarray), names etc.
1574 //The first parameter is the XComponentContext, which cannot be obtained
1575 //from reflection.
1576 //The context is not part of the idl description
1577 method_builder->DefineParameter(
1578 1, ParameterAttributes::In, "the_context");
1580 array<Emit::ParameterBuilder^>^ arParameterBuilder =
1581 gcnew array<Emit::ParameterBuilder^> (cParams);
1582 for (int iparam = 0; iparam != cParams; iparam++)
1584 Reference<reflection::XParameter> const & aParam = arXParams[iparam];
1585 ::System::String ^ sParamName = ustring_to_String(aParam->getName());
1587 arParameterBuilder[iparam] = method_builder->DefineParameter(
1588 iparam + 2, ParameterAttributes::In, sParamName);
1590 if (aParam->isRestParameter())
1592 bParameterArray = true;
1593 //set the ParameterArrayAttribute
1594 ::System::Reflection::ConstructorInfo^ ctor_info =
1595 System::ParamArrayAttribute::typeid->GetConstructor(
1596 gcnew array< ::System::Type^>(0));
1597 Emit::CustomAttributeBuilder ^ attr_builder =
1598 gcnew Emit::CustomAttributeBuilder(ctor_info, gcnew array< ::System::Object^>(0));
1599 arParameterBuilder[iparam]->SetCustomAttribute(attr_builder);
1600 break;
1604 Emit::ILGenerator ^ ilGen = method_builder->GetILGenerator();
1606 //Define locals ---------------------------------
1607 //XMultiComponentFactory
1608 Emit::LocalBuilder^ local_factory =
1609 ilGen->DeclareLocal(
1610 get_type("unoidl.com.sun.star.lang.XMultiComponentFactory", true));
1612 //The return type
1613 Emit::LocalBuilder^ local_return_val =
1614 ilGen->DeclareLocal(retType);
1616 //Obtain the XMultiComponentFactory and throw an exception if we do not get one
1617 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1619 ::System::Reflection::MethodInfo ^ methodGetServiceManager = get_type(
1620 "unoidl.com.sun.star.uno.XComponentContext", true)
1621 ->GetMethod("getServiceManager");
1622 ilGen->Emit(Emit::OpCodes::Callvirt, methodGetServiceManager);
1623 ilGen->Emit(Emit::OpCodes::Stloc, local_factory);
1624 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1625 Emit::Label label1 = ilGen->DefineLabel();
1626 ilGen->Emit(Emit::OpCodes::Brtrue, label1);
1627 //The string for the exception
1628 ::System::Text::StringBuilder ^ strbuilder = gcnew ::System::Text::StringBuilder(256);
1629 strbuilder->Append("The service ");
1630 strbuilder->Append(to_cts_name(xServiceType->getName()));
1631 strbuilder->Append(" could not be created. The context failed to supply the service manager.");
1633 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1634 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1635 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1636 ilGen->Emit(Emit::OpCodes::Throw);
1637 ilGen->MarkLabel(label1);
1639 //We create a try/ catch around the createInstanceWithContext, etc. functions
1640 //There are 3 cases
1641 //1. function do not specify exceptions. Then RuntimeExceptions are retrhown and other
1642 // exceptions produce a DeploymentException.
1643 //2. function specify Exception. Then all exceptions fly through
1644 //3. function specifies exceptions but no Exception. Then these are rethrown
1645 // and other exceptions, except RuntimeException, produce a deployment exception.
1646 //In case there are no parameters we call
1647 //XMultiComponentFactory.createInstanceWithContext
1649 ::System::Collections::ArrayList ^ arExceptionTypes =
1650 get_service_ctor_method_exceptions_reduced(ctorDes->getExceptions());
1651 if (arExceptionTypes->Contains(
1652 type_uno_exception) == false)
1654 ilGen->BeginExceptionBlock();
1656 if (cParams == 0)
1658 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1659 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1660 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1662 ::System::Reflection::MethodInfo ^ methodCreate =
1663 local_factory->LocalType->GetMethod("createInstanceWithContext");
1664 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1666 else if(bParameterArray)
1668 //Service constructor with parameter array
1669 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1670 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1671 ilGen->Emit(Emit::OpCodes::Ldarg_1);
1672 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1673 ::System::Reflection::MethodInfo ^ methodCreate =
1674 local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1675 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1677 else
1679 // Any param1, Any param2, etc.
1680 // For each parameter,except the component context, and parameter array
1681 // and Any is created.
1682 array<Emit::LocalBuilder^>^ arLocalAny = gcnew array<Emit::LocalBuilder^> (cParams);
1684 for (int iParam = 0; iParam < cParams; iParam ++)
1686 arLocalAny[iParam] = ilGen->DeclareLocal(typeAny);
1689 //Any[]. This array is filled with the created Anys which contain the parameters
1690 //and the values contained in the parameter array
1691 Emit::LocalBuilder ^ local_anyParams =
1692 ilGen->DeclareLocal(array< ::uno::Any>::typeid);
1694 //Create the Any for every argument, except for the parameter array
1695 //arLocalAny contains the LocalBuilder for all these parameters.
1696 //we call the ctor Any(Type, Object)
1697 //If the parameter is an Any then the Any is created with Any(param.Type, param.Value);
1698 array< ::System::Type^>^ arTypesCtorAny = {::System::Type::typeid,
1699 ::System::Object::typeid};
1700 ::System::Reflection::ConstructorInfo ^ ctorAny =
1701 typeAny->GetConstructor( arTypesCtorAny);
1702 ::System::Reflection::MethodInfo ^ methodAnyGetType =
1703 typeAny->GetProperty("Type")->GetGetMethod();
1704 ::System::Reflection::MethodInfo ^ methodAnyGetValue =
1705 typeAny->GetProperty("Value")->GetGetMethod();
1706 for (int i = 0; i < arLocalAny->Length; i ++)
1708 //check if the parameter is a polymorphic struct
1709 ::uno::PolymorphicType ^polyType = dynamic_cast< ::uno::PolymorphicType^ >(arTypeParameters[i+1]);
1710 //arTypeParameters[i+1] = polyType->OriginalType;
1711 if (polyType)
1713 //It is a polymorphic struct
1714 //Load the uninitialized local Any on which we will call the ctor
1715 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1716 // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName)
1717 // Prepare the first parameter
1718 ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->OriginalType);
1719 array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1720 ilGen->Emit(Emit::OpCodes::Call,
1721 ::System::Type::typeid->GetMethod(
1722 "GetTypeFromHandle", arTypeParams));
1723 // Prepare the second parameter
1724 ilGen->Emit(Emit::OpCodes::Ldstr, polyType->PolymorphicName);
1725 // Make the actual call
1726 array< ::System::Type^>^ arTypeParam_GetType = {
1727 ::System::Type::typeid, ::System::String::typeid };
1728 ilGen->Emit(Emit::OpCodes::Call,
1729 ::uno::PolymorphicType::typeid->GetMethod(gcnew System::String("GetType"),
1730 arTypeParam_GetType));
1732 //Stack is: localAny, PolymorphicType
1733 //Call Any::Any(Type, Object)
1734 //Prepare the second parameter for the any ctor
1735 ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1736 // if the parameter is a value type then we need to box it, because
1737 // the Any ctor takes an Object
1738 if (arTypeParameters[i+1]->IsValueType)
1739 ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1740 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1742 else if (arTypeParameters[i+1] == typeAny)
1744 //Create the call new Any(param.Type,param,Value)
1745 //Stack must be Any,Type,Value
1746 //First load the Any which is to be constructed
1747 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1748 //Load the Type, which is obtained by calling param.Type
1749 ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1750 ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType);
1751 //Load the Value, which is obtained by calling param.Value
1752 ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
1753 ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue);
1754 //Call the Any ctor.
1755 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1757 else
1759 ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
1760 ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]);
1762 array< ::System::Type^>^ arTypeParams = {::System::RuntimeTypeHandle::typeid};
1763 ilGen->Emit(Emit::OpCodes::Call,
1764 ::System::Type::typeid->GetMethod(
1765 "GetTypeFromHandle", arTypeParams));
1766 ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
1767 // if the parameter is a value type then we need to box it, because
1768 // the Any ctor takes an Object
1769 if (arTypeParameters[i+1]->IsValueType)
1770 ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
1771 ilGen->Emit(Emit::OpCodes::Call, ctorAny);
1775 //Create the Any[] that is passed to the
1776 //createInstanceWithContext[AndArguments] function
1777 ilGen->Emit(Emit::OpCodes::Ldc_I4, arLocalAny->Length);
1778 ilGen->Emit(Emit::OpCodes::Newarr, typeAny);
1779 ilGen->Emit(Emit::OpCodes::Stloc, local_anyParams);
1781 //Assign all anys created from the parameters
1782 //array to the Any[]
1783 for (int i = 0; i < arLocalAny->Length; i++)
1785 ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1786 ilGen->Emit(Emit::OpCodes::Ldc_I4, i);
1787 ilGen->Emit(Emit::OpCodes::Ldelema, typeAny);
1788 ilGen->Emit(Emit::OpCodes::Ldloc, arLocalAny[i]);
1789 ilGen->Emit(Emit::OpCodes::Stobj, typeAny);
1791 // call createInstanceWithContextAndArguments
1792 ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
1793 ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
1794 ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
1795 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1796 ::System::Reflection::MethodInfo ^ methodCreate =
1797 local_factory->LocalType->GetMethod("createInstanceWithArgumentsAndContext");
1798 ilGen->Emit(Emit::OpCodes::Callvirt, methodCreate);
1800 //cast the object returned by the functions createInstanceWithContext or
1801 //createInstanceWithArgumentsAndContext to the interface type
1802 ilGen->Emit(Emit::OpCodes::Castclass, retType);
1803 ilGen->Emit(Emit::OpCodes::Stloc, local_return_val);
1805 //catch exceptions thrown by createInstanceWithArgumentsAndContext and createInstanceWithContext
1806 if (arExceptionTypes->Contains(type_uno_exception) == false)
1808 // catch (unoidl.com.sun.star.uno.RuntimeException) {throw;}
1809 ilGen->BeginCatchBlock(get_type("unoidl.com.sun.star.uno.RuntimeException", true));
1810 ilGen->Emit(Emit::OpCodes::Pop);
1811 ilGen->Emit(Emit::OpCodes::Rethrow);
1813 //catch and rethrow all other defined Exceptions
1814 for (int i = 0; i < arExceptionTypes->Count; i++)
1816 ::System::Type ^ excType = safe_cast< ::System::Type^ >(
1817 arExceptionTypes[i]);
1818 if (excType->IsInstanceOfType(
1819 get_type("unoidl.com.sun.star.uno.RuntimeException", true)))
1820 {// we have a catch for RuntimeException already defined
1821 continue;
1824 //catch Exception and rethrow
1825 ilGen->BeginCatchBlock(excType);
1826 ilGen->Emit(Emit::OpCodes::Pop);
1827 ilGen->Emit(Emit::OpCodes::Rethrow);
1829 //catch (unoidl.com.sun.star.uno.Exception) {throw DeploymentException...}
1830 ilGen->BeginCatchBlock(type_uno_exception);
1832 //Define the local variabe that keeps the exception
1833 Emit::LocalBuilder ^ local_exception = ilGen->DeclareLocal(
1834 type_uno_exception);
1836 //Store the exception
1837 ilGen->Emit(Emit::OpCodes::Stloc, local_exception);
1839 //prepare the construction of the exception
1840 strbuilder = gcnew ::System::Text::StringBuilder(256);
1841 strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1842 strbuilder->Append(to_cts_name(xServiceType->getName()));
1843 strbuilder->Append(": ");
1845 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1847 //add to the string the Exception.Message
1848 ilGen->Emit(Emit::OpCodes::Ldloc, local_exception);
1849 ilGen->Emit(Emit::OpCodes::Callvirt,
1850 type_uno_exception->GetProperty("Message")->GetGetMethod());
1851 array< ::System::Type^>^ arConcatParams = {System::String::typeid,
1852 System::String::typeid};
1853 ilGen->Emit(Emit::OpCodes::Call,
1854 System::String::typeid->GetMethod("Concat", arConcatParams));
1855 //load contex argument
1856 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1857 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1858 ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1860 ilGen->EndExceptionBlock();
1864 //Check if the service instance was create and throw a exception if not.
1865 Emit::Label label_service_created = ilGen->DefineLabel();
1866 ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1867 ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created);
1869 strbuilder = gcnew ::System::Text::StringBuilder(256);
1870 strbuilder->Append("The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
1871 strbuilder->Append(to_cts_name(xServiceType->getName()));
1872 strbuilder->Append(".");
1873 ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
1874 ilGen->Emit(Emit::OpCodes::Ldarg_0);
1875 ilGen->Emit(Emit::OpCodes::Newobj, ctorDeploymentException);
1876 ilGen->Emit(Emit::OpCodes::Throw);//Exception(typeDeploymentExc);
1878 ilGen->MarkLabel(label_service_created);
1879 ilGen->Emit(Emit::OpCodes::Ldloc, local_return_val);
1880 ilGen->Emit(Emit::OpCodes::Ret);
1883 // remove from incomplete types map
1884 ::System::String ^ cts_name = type_builder->FullName;
1885 m_incomplete_services->Remove( cts_name );
1886 xServiceType->release();
1887 if (g_verbose)
1889 ::System::Console::WriteLine(
1890 "> emitting service type {0}", cts_name );
1892 return type_builder->CreateType();
1896 Emit::CustomAttributeBuilder^ TypeEmitter::get_service_exception_attribute(
1897 const Reference<reflection::XServiceConstructorDescription> & ctorDes )
1899 return get_exception_attribute(ctorDes->getExceptions());
1902 Emit::CustomAttributeBuilder^ TypeEmitter::get_iface_method_exception_attribute(
1903 const Reference< reflection::XInterfaceMethodTypeDescription >& xMethod )
1906 const Sequence<Reference<reflection::XTypeDescription> > seqTD = xMethod->getExceptions();
1907 int len = seqTD.getLength();
1908 Sequence<Reference<reflection::XCompoundTypeDescription> > seqCTD(len);
1909 Reference<reflection::XCompoundTypeDescription> * arCTD = seqCTD.getArray();
1910 for (int i = 0; i < len; i++)
1911 arCTD[i] = Reference<reflection::XCompoundTypeDescription>(seqTD[i], UNO_QUERY_THROW);
1912 return get_exception_attribute(seqCTD);
1915 Emit::CustomAttributeBuilder^ TypeEmitter::get_exception_attribute(
1917 const Sequence<Reference< reflection::XCompoundTypeDescription > >& seq_exceptionsTd )
1919 Emit::CustomAttributeBuilder ^ attr_builder = nullptr;
1921 Reference< reflection::XCompoundTypeDescription > const * exceptions =
1922 seq_exceptionsTd.getConstArray();
1924 array< ::System::Type^>^ arTypesCtor = {::System::Type::GetType("System.Type[]")};
1925 ConstructorInfo ^ ctor_ExceptionAttribute =
1926 ::uno::ExceptionAttribute::typeid->GetConstructor(arTypesCtor);
1928 sal_Int32 exc_length = seq_exceptionsTd.getLength();
1929 if (exc_length != 0) // opt
1931 array< ::System::Type^>^ exception_types =
1932 gcnew array< ::System::Type^> ( exc_length );
1933 for ( sal_Int32 exc_pos = 0; exc_pos < exc_length; ++exc_pos )
1935 Reference< reflection::XCompoundTypeDescription > const & xExc =
1936 exceptions[ exc_pos ];
1937 exception_types[ exc_pos ] = get_type( xExc );
1939 array< ::System::Object^>^ args = {exception_types};
1940 attr_builder = gcnew Emit::CustomAttributeBuilder(
1941 ctor_ExceptionAttribute, args );
1943 return attr_builder;
1947 ::System::Type ^ TypeEmitter::complete_singleton_type(singleton_entry ^ entry)
1949 Emit::TypeBuilder ^ type_builder = entry->m_type_builder;
1950 reflection::XSingletonTypeDescription2 * xSingletonType = entry->m_xType;
1951 ::System::String^ sSingletonName = to_cts_name(xSingletonType->getName());
1953 //Create the private default constructor
1954 Emit::ConstructorBuilder^ ctor_builder =
1955 type_builder->DefineConstructor(
1956 static_cast<MethodAttributes>(MethodAttributes::Private |
1957 MethodAttributes::HideBySig |
1958 MethodAttributes::SpecialName |
1959 MethodAttributes::RTSpecialName),
1960 CallingConventions::Standard, nullptr);
1962 Emit::ILGenerator^ ilGen = ctor_builder->GetILGenerator();
1963 ilGen->Emit( Emit::OpCodes::Ldarg_0 ); // push this
1964 ilGen->Emit(
1965 Emit::OpCodes::Call,
1966 type_builder->BaseType->GetConstructor(gcnew array< ::System::Type^>(0)));
1967 ilGen->Emit( Emit::OpCodes::Ret );
1970 //obtain the interface which makes up this service, it is the return
1971 //type of the constructor functions
1972 Reference<reflection::XInterfaceTypeDescription2> xIfaceType(
1973 xSingletonType->getInterface(), UNO_QUERY);
1974 if (xIfaceType.is () == sal_False)
1975 xIfaceType = resolveInterfaceTypedef(xSingletonType->getInterface());
1976 System::Type ^ retType = get_type(xIfaceType);
1978 //define method
1979 array< ::System::Type^>^ arTypeParameters = {get_type("unoidl.com.sun.star.uno.XComponentContext", true)};
1980 Emit::MethodBuilder^ method_builder = type_builder->DefineMethod(
1981 gcnew System::String("get"),
1982 static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
1983 MethodAttributes::Static),
1984 retType,
1985 arTypeParameters);
1988 // method_builder->SetCustomAttribute(get_service_ctor_method_attribute(ctorDes));
1990 //The first parameter is the XComponentContext, which cannot be obtained
1991 //from reflection.
1992 //The context is not part of the idl description
1993 method_builder->DefineParameter(1, ParameterAttributes::In, "the_context");
1996 ilGen = method_builder->GetILGenerator();
1997 //Define locals ---------------------------------
1998 // Any, returned by XComponentContext.getValueByName
1999 Emit::LocalBuilder^ local_any =
2000 ilGen->DeclareLocal(::uno::Any::typeid);
2002 //Call XContext::getValueByName
2003 ilGen->Emit(Emit::OpCodes::Ldarg_0);
2004 // build the singleton name : /singleton/unoidl.com.sun.star.XXX
2005 ::System::Text::StringBuilder^ sBuilder =
2006 gcnew ::System::Text::StringBuilder("/singletons/");
2007 sBuilder->Append(sSingletonName);
2008 ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
2010 ::System::Reflection::MethodInfo ^ methodGetValueByName =
2011 get_type("unoidl.com.sun.star.uno.XComponentContext", true)->GetMethod("getValueByName");
2012 ilGen->Emit(Emit::OpCodes::Callvirt, methodGetValueByName);
2013 ilGen->Emit(Emit::OpCodes::Stloc_0);
2015 //Contains the returned Any a value?
2016 ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
2017 ::System::Reflection::MethodInfo ^ methodHasValue =
2018 ::uno::Any::typeid->GetMethod("hasValue");
2019 ilGen->Emit(Emit::OpCodes::Call, methodHasValue);
2021 //If not, then throw an DeploymentException
2022 Emit::Label label_singleton_exists = ilGen->DefineLabel();
2023 ilGen->Emit(Emit::OpCodes::Brtrue_S, label_singleton_exists);
2024 sBuilder = gcnew ::System::Text::StringBuilder(
2025 "Component context fails to supply singleton ");
2026 sBuilder->Append(sSingletonName);
2027 sBuilder->Append(" of type ");
2028 sBuilder->Append(retType->FullName);
2029 sBuilder->Append(".");
2030 ilGen->Emit(Emit::OpCodes::Ldstr, sBuilder->ToString());
2031 ilGen->Emit(Emit::OpCodes::Ldarg_0);
2032 array< ::System::Type^>^ arTypesCtorDeploymentException = {
2033 ::System::String::typeid, ::System::Object::typeid};
2034 ilGen->Emit(Emit::OpCodes::Newobj,
2035 get_type("unoidl.com.sun.star.uno.DeploymentException",true)
2036 ->GetConstructor(arTypesCtorDeploymentException));
2037 ilGen->Emit(Emit::OpCodes::Throw);
2038 ilGen->MarkLabel(label_singleton_exists);
2040 //Cast the singleton contained in the Any to the expected interface and return it.
2041 ilGen->Emit(Emit::OpCodes::Ldloca_S, local_any);
2042 ilGen->Emit(Emit::OpCodes::Call, ::uno::Any::typeid->GetProperty("Value")->GetGetMethod());
2043 ilGen->Emit(Emit::OpCodes::Castclass, retType);
2044 ilGen->Emit(Emit::OpCodes::Ret);
2046 // remove from incomplete types map
2047 ::System::String ^ cts_name = type_builder->FullName;
2048 m_incomplete_singletons->Remove( cts_name );
2049 xSingletonType->release();
2050 if (g_verbose)
2052 ::System::Console::WriteLine(
2053 "> emitting singleton type {0}", cts_name );
2055 return type_builder->CreateType();
2060 ::System::Type ^ TypeEmitter::get_type(
2061 Reference< reflection::XTypeDescription > const & xType )
2063 switch (xType->getTypeClass())
2065 case TypeClass_VOID:
2066 return ::System::Void::typeid;
2067 case TypeClass_CHAR:
2068 return ::System::Char::typeid;
2069 case TypeClass_BOOLEAN:
2070 return ::System::Boolean::typeid;
2071 case TypeClass_BYTE:
2072 return ::System::Byte::typeid;
2073 case TypeClass_SHORT:
2074 return ::System::Int16::typeid;
2075 case TypeClass_UNSIGNED_SHORT:
2076 return ::System::UInt16::typeid;
2077 case TypeClass_LONG:
2078 return ::System::Int32::typeid;
2079 case TypeClass_UNSIGNED_LONG:
2080 return ::System::UInt32::typeid;
2081 case TypeClass_HYPER:
2082 return ::System::Int64::typeid;
2083 case TypeClass_UNSIGNED_HYPER:
2084 return ::System::UInt64::typeid;
2085 case TypeClass_FLOAT:
2086 return ::System::Single::typeid;
2087 case TypeClass_DOUBLE:
2088 return ::System::Double::typeid;
2089 case TypeClass_STRING:
2090 return ::System::String::typeid;
2091 case TypeClass_TYPE:
2092 return ::System::Type::typeid;
2093 case TypeClass_ANY:
2094 return ::uno::Any::typeid;
2095 case TypeClass_ENUM:
2096 return get_type( Reference< reflection::XEnumTypeDescription >(
2097 xType, UNO_QUERY_THROW ) );
2098 case TypeClass_TYPEDEF:
2099 // unwind typedefs
2100 return get_type(
2101 Reference< reflection::XIndirectTypeDescription >(
2102 xType, UNO_QUERY_THROW )->getReferencedType() );
2103 case TypeClass_STRUCT:
2104 case TypeClass_EXCEPTION:
2105 return get_type(
2106 Reference< reflection::XCompoundTypeDescription >(
2107 xType, UNO_QUERY_THROW ) );
2108 case TypeClass_SEQUENCE:
2110 ::System::Type ^ element_type = get_type(
2111 Reference< reflection::XIndirectTypeDescription >(
2112 xType, UNO_QUERY_THROW )->getReferencedType() );
2113 ::System::Type ^ retType = get_type(
2114 ::System::String::Concat(
2115 element_type->FullName, "[]" ), true );
2117 ::uno::PolymorphicType ^ pt = dynamic_cast< ::uno::PolymorphicType ^ >(element_type);
2118 if (pt)
2120 ::System::String ^ sName = ::System::String::Concat(pt->PolymorphicName, "[]");
2121 retType = ::uno::PolymorphicType::GetType(retType, sName);
2123 return retType;
2125 case TypeClass_INTERFACE:
2126 return get_type(
2127 Reference< reflection::XInterfaceTypeDescription2 >(
2128 xType, UNO_QUERY_THROW ) );
2129 case TypeClass_CONSTANT:
2130 return get_type(
2131 Reference< reflection::XConstantTypeDescription >(
2132 xType, UNO_QUERY_THROW ) );
2133 case TypeClass_CONSTANTS:
2134 return get_type(
2135 Reference< reflection::XConstantsTypeDescription >(
2136 xType, UNO_QUERY_THROW ) );
2137 case TypeClass_SERVICE:
2138 return get_type(
2139 Reference< reflection::XServiceTypeDescription2 >(
2140 xType, UNO_QUERY_THROW) );
2141 case TypeClass_SINGLETON:
2142 return get_type(
2143 Reference< reflection::XSingletonTypeDescription2 >(
2144 xType, UNO_QUERY_THROW) );
2145 case TypeClass_MODULE:
2146 // ignore these
2147 return nullptr;
2148 default:
2149 throw RuntimeException(
2150 "unexpected type " + xType->getName() );
2155 ::System::Type ^ TypeEmitter::get_complete_struct( ::System::String ^ sName)
2157 struct_entry ^ pStruct = safe_cast< struct_entry ^>(
2158 m_incomplete_structs[sName]);
2159 if (pStruct)
2161 complete_struct_type(pStruct);
2163 //get_type will asked the module builder for the type or otherwise all known assemblies.
2164 return get_type(sName, true);
2166 TypeEmitter::~TypeEmitter()
2168 while (true)
2170 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2171 m_incomplete_ifaces->GetEnumerator();
2172 if (! enumerator->MoveNext())
2173 break;
2174 complete_iface_type(
2175 safe_cast< iface_entry ^ >( enumerator->Value ) );
2178 while (true)
2180 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2181 m_incomplete_structs->GetEnumerator();
2182 if (! enumerator->MoveNext())
2183 break;
2184 complete_struct_type(
2185 safe_cast< struct_entry ^ >( enumerator->Value ) );
2189 while (true)
2191 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2192 m_incomplete_services->GetEnumerator();
2193 if (! enumerator->MoveNext())
2194 break;
2195 complete_service_type(
2196 safe_cast< service_entry ^ >( enumerator->Value ) );
2199 while (true)
2201 ::System::Collections::IDictionaryEnumerator ^ enumerator =
2202 m_incomplete_singletons->GetEnumerator();
2203 if (! enumerator->MoveNext())
2204 break;
2205 complete_singleton_type(
2206 safe_cast< singleton_entry ^ >( enumerator->Value ) );
2210 TypeEmitter::TypeEmitter(
2211 ::System::Reflection::Emit::ModuleBuilder ^ module_builder,
2212 array< ::System::Reflection::Assembly^>^ extra_assemblies )
2213 : m_module_builder( module_builder ),
2214 m_extra_assemblies( extra_assemblies ),
2215 m_method_info_Type_GetTypeFromHandle( nullptr ),
2216 m_type_Exception( nullptr ),
2217 m_type_RuntimeException( nullptr ),
2218 m_incomplete_ifaces( gcnew ::System::Collections::Hashtable() ),
2219 m_incomplete_structs( gcnew ::System::Collections::Hashtable() ),
2220 m_incomplete_services(gcnew ::System::Collections::Hashtable() ),
2221 m_incomplete_singletons(gcnew ::System::Collections::Hashtable() ),
2222 m_generated_structs( gcnew ::System::Collections::Hashtable() )
2224 array< ::System::Type^>^ param_types = gcnew array< ::System::Type^> ( 1 );
2225 param_types[ 0 ] = ::System::RuntimeTypeHandle::typeid;
2226 m_method_info_Type_GetTypeFromHandle =
2227 ::System::Type::typeid
2228 ->GetMethod( "GetTypeFromHandle", param_types );
2231 ::System::Collections::ArrayList ^ TypeEmitter::get_service_ctor_method_exceptions_reduced(
2232 const Sequence<Reference<reflection::XCompoundTypeDescription> > & seqExceptionsTd)
2234 if (seqExceptionsTd.getLength() == 0)
2235 return gcnew ::System::Collections::ArrayList();
2237 ::System::Collections::ArrayList ^ arTypes = gcnew ::System::Collections::ArrayList();
2238 for (int i = 0; i < seqExceptionsTd.getLength(); i++)
2239 arTypes->Add(get_type(to_cts_name(seqExceptionsTd[i]->getName()), true));
2241 int start = 0;
2242 while (true)
2244 bool bRemove = false;
2245 for (int i = start; i < arTypes->Count; i++)
2247 ::System::Type ^ t = safe_cast< ::System::Type^ >(arTypes[i]);
2248 for (int j = 0; j < arTypes->Count; j++)
2250 if (t->IsSubclassOf(safe_cast< ::System::Type^ >(arTypes[j])))
2252 arTypes->RemoveAt(i);
2253 bRemove = true;
2254 break;
2257 if (bRemove)
2258 break;
2259 start++;
2262 if (bRemove == false)
2263 break;
2265 return arTypes;
2269 css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >
2270 resolveInterfaceTypedef(
2271 const css::uno::Reference<css::reflection::XTypeDescription>& type)
2273 Reference<reflection::XInterfaceTypeDescription2>
2274 xIfaceTd(type, UNO_QUERY);
2276 if (xIfaceTd.is())
2277 return xIfaceTd;
2279 Reference<reflection::XIndirectTypeDescription> xIndTd(
2280 type, UNO_QUERY);
2281 if (xIndTd.is() == sal_False)
2282 throw css::uno::Exception(
2283 "resolveInterfaceTypedef was called with an invalid argument", 0);
2285 return resolveInterfaceTypedef(xIndTd->getReferencedType());
2291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */