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