summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRüdiger Timm <rt@openoffice.org>2006-03-09 09:52:08 +0000
committerRüdiger Timm <rt@openoffice.org>2006-03-09 09:52:08 +0000
commitf9077c218b90903ddf2b326376b502b672ca8b15 (patch)
treec2b52c9f121ebb0ce13bb08d5cd00c53acefffa0
parentd7aca34802e47d04af3be83ed7333261a2685ae2 (diff)
INTEGRATION: CWS jl31 (1.12.26); FILE MERGED
2006/02/03 16:37:50 jl 1.12.26.1: #i61436# generated service code contained bugs, in particular when polymorphic structs are used
-rw-r--r--cli_ure/source/climaker/climaker_emit.cxx356
1 files changed, 312 insertions, 44 deletions
diff --git a/cli_ure/source/climaker/climaker_emit.cxx b/cli_ure/source/climaker/climaker_emit.cxx
index 68e23e1c3278..826fe1c81c1a 100644
--- a/cli_ure/source/climaker/climaker_emit.cxx
+++ b/cli_ure/source/climaker/climaker_emit.cxx
@@ -4,9 +4,9 @@
*
* $RCSfile: climaker_emit.cxx,v $
*
- * $Revision: 1.12 $
+ * $Revision: 1.13 $
*
- * last change: $Author: rt $ $Date: 2005-09-08 02:00:52 $
+ * last change: $Author: rt $ $Date: 2006-03-09 10:52:08 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
@@ -53,7 +53,7 @@ using namespace ::com::sun::star::uno;
namespace climaker
{
-
+System::String* mapUnoPolymorphicName(System::String* unoName);
//------------------------------------------------------------------------------
static inline ::System::String * to_cts_name(
OUString const & uno_name )
@@ -155,10 +155,150 @@ void polymorphicStructNameToStructName(::System::String ** sPolyName)
if ((*sPolyName)->EndsWith(S">") == false)
return;
- int index = (*sPolyName)->LastIndexOf('<');
+ int index = (*sPolyName)->IndexOf('<');
OSL_ASSERT(index != -1);
*sPolyName = (*sPolyName)->Substring(0, index);
}
+
+
+System::String* mapUnoTypeName(System::String * typeName)
+{
+ ::System::Text::StringBuilder* buf= new System::Text::StringBuilder();
+ ::System::String * sUnoName = ::System::String::Copy(typeName);
+ //determine if the type is a sequence and its dimensions
+ int dims= 0;
+ if (typeName->StartsWith(S"["))//if (usUnoName[0] == '[')
+ {
+ int index= 1;
+ while (true)
+ {
+ if (typeName->get_Chars(index++) == ']')//if (usUnoName[index++] == ']')
+ dims++;
+ if (typeName->get_Chars(index++) != '[')//usUnoName[index++] != '[')
+ break;
+ }
+ sUnoName = sUnoName->Substring(index - 1);//usUnoName = usUnoName.copy(index - 1);
+ }
+ if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoBool)))
+ buf->Append(const_cast<System::String*>(Constants::sBoolean));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoChar)))
+ buf->Append(const_cast<System::String*>(Constants::sChar));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoByte)))
+ buf->Append(const_cast<System::String*>(Constants::sByte));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoShort)))
+ buf->Append(const_cast<System::String*>(Constants::sInt16));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoUShort)))
+ buf->Append(const_cast<System::String*>(Constants::sUInt16));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoLong)))
+ buf->Append(const_cast<System::String*>(Constants::sInt32));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoULong)))
+ buf->Append(const_cast<System::String*>(Constants::sUInt32));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoHyper)))
+ buf->Append(const_cast<System::String*>(Constants::sInt64));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoUHyper)))
+ buf->Append(const_cast<System::String*>(Constants::sUInt64));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoFloat)))
+ buf->Append(const_cast<System::String*>(Constants::sSingle));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoDouble)))
+ buf->Append(const_cast<System::String*>(Constants::sDouble));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoString)))
+ buf->Append(const_cast<System::String*>(Constants::sString));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoVoid)))
+ buf->Append(const_cast<System::String*>(Constants::sVoid));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoType)))
+ buf->Append(const_cast<System::String*>(Constants::sType));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoXInterface)))
+ buf->Append(const_cast<System::String*>(Constants::sObject));
+ else if (sUnoName->Equals(const_cast<System::String*>(Constants::sUnoAny)))
+ {
+ buf->Append(const_cast<System::String*>(Constants::sAny));
+ }
+ else
+ {
+ //put "unoidl." at the beginning
+ buf->Append(const_cast<System::String*>(Constants::sUnoidl));
+ buf->Append(mapUnoPolymorphicName(sUnoName));
+ }
+ // apend []
+ for (;dims--;)
+ buf->Append(const_cast<System::String*>(Constants::sBrackets));
+
+ return buf->ToString();
+}
+
+
+/** For example, there is a uno type
+ com.sun.star.Foo<char, long>.
+ The values in the type list
+ are uno types and are replaced by cli types, such as System.Char,
+ System.Int32, etc.
+
+ Strings can be as complicated as this
+ test.MyStruct<char,test.MyStruct<long, []string>>
+ */
+System::String* mapUnoPolymorphicName(System::String* unoName)
+{
+ int index = unoName->IndexOf('<');
+ if (index == -1)
+ return unoName;
+
+ System::Text::StringBuilder * builder =
+ new System::Text::StringBuilder(unoName->Substring(0, index +1 ));
+
+ //Find the first occurrence of ','
+ //If the parameter is a polymorphic struct then we neede to ignore everything
+ //between the brackets because it can also contain commas
+ //get the type list within < and >
+ int endIndex = unoName->Length - 1;
+ index++;
+ int cur = index;
+ int countParams = 0;
+ while (cur <= endIndex)
+ {
+ System::Char c = unoName->Chars[cur];
+ if (c == ',' || c == '>')
+ {
+ //insert a comma if needed
+ if (countParams != 0)
+ builder->Append(S",");
+ countParams++;
+ System::String * sParam = unoName->Substring(index, cur - index);
+ //skip the comma
+ cur++;
+ //the the index to the beginning of the next param
+ index = cur;
+ builder->Append(mapUnoTypeName(sParam));
+ }
+ else if (c == '<')
+ {
+ cur++;
+ //continue until the matching '>'
+ int numNested = 0;
+ for (;;cur++)
+ {
+ System::Char curChar = unoName->Chars[cur];
+ if (curChar == '<')
+ {
+ numNested ++;
+ }
+ else if (curChar == '>')
+ {
+ if (numNested > 0)
+ numNested--;
+ else
+ break;
+ }
+ }
+ }
+ cur++;
+ }
+
+ builder->Append((System::Char) '>');
+ return builder->ToString();
+}
+
+
+
//______________________________________________________________________________
Assembly * TypeEmitter::type_resolve(
::System::Object * sender, ::System::ResolveEventArgs * args )
@@ -219,8 +359,23 @@ Assembly * TypeEmitter::type_resolve(
if (ret_type == 0)
{
- // may call on type_resolve()
- return ::System::Type::GetType( cts_name, throw_exc );
+ try
+ {
+ // may call on type_resolve()
+ return ::System::Type::GetType( cts_name, throw_exc );
+ }
+ catch (::System::Exception* exc)
+ {
+ //If the type is not found one may have forgotten to specify assemblies with
+ //additional types
+ ::System::Text::StringBuilder * sb = new ::System::Text::StringBuilder();
+ sb->Append(new ::System::String(S"\nThe type "));
+ sb->Append(cts_name);
+ sb->Append(new ::System::String(S" \n could not be found. Did you forget to " \
+ S"specify an additional assembly with the --reference option?\n"));
+ if (throw_exc)
+ throw new ::System::Exception(sb->ToString(), exc);
+ }
}
else
{
@@ -509,9 +664,7 @@ Assembly * TypeEmitter::type_resolve(
return get_type_RuntimeException();
}
}
-
::System::String * cts_name = to_cts_name( uno_name );
-
// if the struct is an instantiated polymorpic struct then we create the simple struct name
// For example:
// void func ([in] PolyStruct<boolean> arg);
@@ -535,6 +688,9 @@ Assembly * TypeEmitter::type_resolve(
base_type );
//Polymorphic struct, define uno.TypeParametersAttribute
+ //A polymorphic struct cannot have a basetype.
+ //When we create the template of the struct then we have no exact types
+ //and the name does not contain a parameter list
Sequence< OUString > seq_type_parameters;
Reference< reflection::XStructTypeDescription> xStructTypeDesc(
xType, UNO_QUERY);
@@ -575,7 +731,21 @@ Assembly * TypeEmitter::type_resolve(
Sequence< OUString > seq_member_names( xType->getMemberNames() );
sal_Int32 members_length = seq_members.getLength();
OSL_ASSERT( seq_member_names.getLength() == members_length );
-
+ //check if we have a XTypeDescription for every member. If not then the user may
+ //have forgotten to specify additional rdbs with the --extra option.
+ Reference< reflection::XTypeDescription > const * pseq_members =
+ seq_members.getConstArray();
+ OUString const * pseq_member_names =
+ seq_member_names.getConstArray();
+ for (int i = 0; i < members_length; i++)
+ {
+ OUString sType = xType->getName();
+ OUString sMemberName = pseq_member_names[i];
+ if ( ! pseq_members[i].is())
+ throw RuntimeException(OUSTR("Missing type description . Check if you need to " \
+ "specify additional RDBs with the --extra option. Type missing for: ") + sType +
+ OUSTR("::") + sMemberName,0);
+ }
sal_Int32 all_members_length = 0;
sal_Int32 member_pos;
@@ -669,10 +839,10 @@ Assembly * TypeEmitter::type_resolve(
// add members
Emit::FieldBuilder * members[] = new Emit::FieldBuilder * [ members_length ];
- Reference< reflection::XTypeDescription > const * pseq_members =
- seq_members.getConstArray();
- OUString const * pseq_member_names =
- seq_member_names.getConstArray();
+ //Reference< reflection::XTypeDescription > const * pseq_members =
+ // seq_members.getConstArray();
+ //OUString const * pseq_member_names =
+ // seq_member_names.getConstArray();
int curParamIndex = 0; //count the fields which have parameterized types
for ( member_pos = 0; member_pos < members_length; ++member_pos )
@@ -851,6 +1021,23 @@ Assembly * TypeEmitter::type_resolve(
m_generated_structs->Add( cts_name, entry );
ret_type = type_builder->CreateType();
}
+
+ //In case of an instantiated polymorphic struct we want to return a
+ //uno.PolymorphicType (inherits Type) rather then Type.
+ Reference< reflection::XStructTypeDescription> xStructTypeDesc(
+ xType, UNO_QUERY);
+ if (xStructTypeDesc.is())
+ {
+ Sequence< Reference< reflection::XTypeDescription > > seqTypeArgs = xStructTypeDesc->getTypeArguments();
+ sal_Int32 numTypes = seqTypeArgs.getLength();
+ if (numTypes > 0)
+ {
+ //it is an instantiated polymorphic struct
+ ::System::String * sCliName = mapUnoTypeName(ustring_to_String(xType->getName()));
+ ret_type = ::uno::PolymorphicType::GetType(ret_type, sCliName);
+ }
+ }
+
return ret_type;
}
@@ -1247,20 +1434,19 @@ Assembly * TypeEmitter::type_resolve(
// throw new com.sun.star.uno.DeploymentException("bla", null);
// return (XWeak) factory.createInstanceWithContext("service_specifier", ctx);
// }
-// public static XWeak constructor2(XComponentContext ctx, int a, int b)
+// public static XWeak constructor2(XComponentContext ctx, int a, int b, Any c)
// {
// XMultiComponentFactory factory = ctx.getServiceManager();
// if (factory == null)
// throw new com.sun.star.uno.DeploymentException("bla", null);
-// Any a1;
-// a1 = new Any( typeof(int), a);
-// Any a2;
-// a2 = new Any( typeof(int), b);
-// Any[] arAny = new Any[2];
-// arAny[0] = a1;
-// arAny[1] = a2;
+// Any[] arAny = new Any[3];
+// arAny[0] = new Any(typeof(int), a);
+// arAny[1] = new Any(typeof(int), b);
+// arAny[2] = new Any(c.Type, c.Value);
// return (XWeak) factory.createInstanceWithArgumentsAndContext("service_specifier", arAny, ctx);
// }
+// Notice that a any parameter is NOT wrapped by another any. Instead the new any is created with the type and value
+// of the parameter.
// public static XWeak constructor3(XComponentContext ctx, params Any[] c)
// {
@@ -1332,9 +1518,25 @@ Assembly * TypeEmitter::type_resolve(
if (arXParams[iparam]->isRestParameter())
arTypeParameters[iparam + 1] = __typeof(::uno::Any[]);
else
- arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType());
+ arTypeParameters[iparam + 1] = get_type(arXParams[iparam]->getType());
+ }
+ //The array arTypeParameters can contain:
+ //System.Type and uno.PolymorphicType.
+ //Passing PolymorphicType to MethodBuilder.DefineMethod will cause a problem.
+ //The exception will read something like no on information for parameter # d
+ //Maybe we need no override another Type method in PolymorphicType ...
+ //Until we have figured this out, we will create another array of System.Type which
+ //we pass on to DefineMethod.
+ ::System::Type * arParamTypes[] = new ::System::Type * [cParams + 1];
+// arParamTypes[0] = get_type(S"unoidl.com.sun.star.uno.XComponentContext", true);
+ for (int i = 0; i < cParams + 1; i++)
+ {
+ ::uno::PolymorphicType * pT = dynamic_cast<::uno::PolymorphicType *>(arTypeParameters[i]);
+ if (pT)
+ arParamTypes[i] = pT->OriginalType;
+ else
+ arParamTypes[i] = arTypeParameters[i];
}
-
//define method
System::String * ctorName;
if (ctorDes->isDefaultConstructor())
@@ -1346,7 +1548,8 @@ Assembly * TypeEmitter::type_resolve(
static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::HideBySig |
MethodAttributes::Static),
retType,
- arTypeParameters);
+// arTypeParameters);
+ arParamTypes);
//define UNO exception attribute (exceptions)--------------------------------------
Emit::CustomAttributeBuilder* attrBuilder = get_service_exception_attribute(ctorDes);
@@ -1410,7 +1613,7 @@ Assembly * TypeEmitter::type_resolve(
ilGen->Emit(Emit::OpCodes::Brtrue, label1);
//The string for the exception
::System::Text::StringBuilder * strbuilder = new ::System::Text::StringBuilder(256);
- strbuilder->Append(S"The service unoidl.");
+ strbuilder->Append(S"The service ");
strbuilder->Append(to_cts_name(xServiceType->getName()));
strbuilder->Append(S" could not be created. The context failed to supply the service manager.");
@@ -1440,7 +1643,7 @@ Assembly * TypeEmitter::type_resolve(
if (cParams == 0)
{
ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
- ilGen->Emit(Emit::OpCodes::Ldstr, to_cts_name(xServiceType->getName()));
+ ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
ilGen->Emit(Emit::OpCodes::Ldarg_0);
::System::Reflection::MethodInfo * methodCreate =
@@ -1451,7 +1654,7 @@ Assembly * TypeEmitter::type_resolve(
{
//Service constructor with parameter array
ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
- ilGen->Emit(Emit::OpCodes::Ldstr, to_cts_name(xServiceType->getName()));
+ ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
ilGen->Emit(Emit::OpCodes::Ldarg_1);
ilGen->Emit(Emit::OpCodes::Ldarg_0);
::System::Reflection::MethodInfo * methodCreate =
@@ -1479,25 +1682,82 @@ Assembly * TypeEmitter::type_resolve(
//Create the Any for every argument, except for the parameter array
//arLocalAny contains the LocalBuilder for all these parameters.
//we call the ctor Any(Type, Object)
+ //If the parameter is an Any then the Any is created with Any(param.Type, param.Value);
::System::Type * arTypesCtorAny[] = {__typeof(::System::Type),
__typeof(::System::Object)};
::System::Reflection::ConstructorInfo * ctorAny =
- typeAny->GetConstructor( arTypesCtorAny);
+ typeAny->GetConstructor( arTypesCtorAny);
+ ::System::Reflection::MethodInfo * methodAnyGetType =
+ typeAny->GetProperty(S"Type")->GetGetMethod();
+ ::System::Reflection::MethodInfo * methodAnyGetValue =
+ typeAny->GetProperty(S"Value")->GetGetMethod();
for (int i = 0; i < arLocalAny->Length; i ++)
{
- ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
- ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]);
-
- ::System::Type * arTypeParams[] = {__typeof(::System::RuntimeTypeHandle)};
- ilGen->Emit(Emit::OpCodes::Call,
- __typeof(::System::Type)->GetMethod(
- S"GetTypeFromHandle", arTypeParams));
- ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
- // if the parameter is a value type then we need to box it, because
- // the Any ctor takes an Object
- if (arTypeParameters[i+1]->IsValueType)
- ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
- ilGen->Emit(Emit::OpCodes::Call, ctorAny);
+ //check if the parameter is a polymorphic struct
+ ::uno::PolymorphicType *polyType = dynamic_cast<::uno::PolymorphicType*>(arTypeParameters[i+1]);
+ //arTypeParameters[i+1] = polyType->OriginalType;
+ if (polyType)
+ {
+ //It is a polymorphic struct
+ //Load the uninitialized local Any on which we will call the ctor
+ ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
+ // Call PolymorphicType PolymorphicType::GetType(Type t, String polyName)
+ // Prepare the first parameter
+ ilGen->Emit(Emit::OpCodes::Ldtoken, polyType->get_OriginalType());
+ ::System::Type * arTypeParams[] = {__typeof(::System::RuntimeTypeHandle)};
+ ilGen->Emit(Emit::OpCodes::Call,
+ __typeof(::System::Type)->GetMethod(
+ S"GetTypeFromHandle", arTypeParams));
+ // Prepare the second parameter
+ ilGen->Emit(Emit::OpCodes::Ldstr, polyType->get_PolymorphicName());
+ // Make the actual call
+ ::System::Type * arTypeParam_GetType[] = {
+ __typeof(::System::Type), __typeof(::System::String) };
+ ilGen->Emit(Emit::OpCodes::Call,
+ __typeof(::uno::PolymorphicType)->GetMethod(new System::String(S"GetType"),
+ arTypeParam_GetType));
+
+ //Stack is: localAny, PolymorphicType
+ //Call Any::Any(Type, Object)
+ //Prepare the second parameter for the any ctor
+ ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
+ // if the parameter is a value type then we need to box it, because
+ // the Any ctor takes an Object
+ if (arTypeParameters[i+1]->IsValueType)
+ ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
+ ilGen->Emit(Emit::OpCodes::Call, ctorAny);
+ }
+ else if (arTypeParameters[i+1] == typeAny)
+ {
+ //Create the call new Any(param.Type,param,Value)
+ //Stack must be Any,Type,Value
+ //First load the Any which is to be constructed
+ ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
+ //Load the Type, which is obtained by calling param.Type
+ ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
+ ilGen->Emit(Emit::OpCodes::Call, methodAnyGetType);
+ //Load the Value, which is obtained by calling param.Value
+ ilGen->Emit(Emit::OpCodes::Ldarga, i + 1);
+ ilGen->Emit(Emit::OpCodes::Call, methodAnyGetValue);
+ //Call the Any ctor.
+ ilGen->Emit(Emit::OpCodes::Call, ctorAny);
+ }
+ else
+ {
+ ilGen->Emit(Emit::OpCodes::Ldloca, arLocalAny[i]);
+ ilGen->Emit(Emit::OpCodes::Ldtoken, arTypeParameters[i+1]);
+
+ ::System::Type * arTypeParams[] = {__typeof(::System::RuntimeTypeHandle)};
+ ilGen->Emit(Emit::OpCodes::Call,
+ __typeof(::System::Type)->GetMethod(
+ S"GetTypeFromHandle", arTypeParams));
+ ilGen->Emit(Emit::OpCodes::Ldarg, i + 1);
+ // if the parameter is a value type then we need to box it, because
+ // the Any ctor takes an Object
+ if (arTypeParameters[i+1]->IsValueType)
+ ilGen->Emit(Emit::OpCodes::Box, arTypeParameters[i+1]);
+ ilGen->Emit(Emit::OpCodes::Call, ctorAny);
+ }
}
//Create the Any[] that is passed to the
@@ -1518,7 +1778,7 @@ Assembly * TypeEmitter::type_resolve(
}
// call createInstanceWithContextAndArguments
ilGen->Emit(Emit::OpCodes::Ldloc, local_factory);
- ilGen->Emit(Emit::OpCodes::Ldstr, to_cts_name(xServiceType->getName()));
+ ilGen->Emit(Emit::OpCodes::Ldstr, ustring_to_String(xServiceType->getName()));
ilGen->Emit(Emit::OpCodes::Ldloc, local_anyParams);
ilGen->Emit(Emit::OpCodes::Ldarg_0);
::System::Reflection::MethodInfo * methodCreate =
@@ -1595,7 +1855,7 @@ Assembly * TypeEmitter::type_resolve(
ilGen->Emit(Emit::OpCodes::Brtrue_S, label_service_created);
strbuilder = new ::System::Text::StringBuilder(256);
- strbuilder->Append(S"The context (com.sun.star.uno.XComponentContext) failed to supply the service unoidl.");
+ strbuilder->Append(S"The context (com.sun.star.uno.XComponentContext) failed to supply the service ");
strbuilder->Append(to_cts_name(xServiceType->getName()));
strbuilder->Append(S".");
ilGen->Emit(Emit::OpCodes::Ldstr, strbuilder->ToString());
@@ -1848,9 +2108,17 @@ Emit::CustomAttributeBuilder* TypeEmitter::get_exception_attribute(
::System::Type * element_type = get_type(
Reference< reflection::XIndirectTypeDescription >(
xType, UNO_QUERY_THROW )->getReferencedType() );
- return get_type(
+ ::System::Type * retType = get_type(
::System::String::Concat(
element_type->get_FullName(), S"[]" ), true );
+
+ ::uno::PolymorphicType * pt = dynamic_cast<::uno::PolymorphicType *>(element_type);
+ if (pt)
+ {
+ ::System::String * sName = ::System::String::Concat(pt->PolymorphicName, S"[]");
+ retType = ::uno::PolymorphicType::GetType(retType, sName);
+ }
+ return retType;
}
case TypeClass_INTERFACE:
return get_type(