Ejemplo n.º 1
0
    Type get_type(XCompoundTypeDescription xType)
    {
        string uno_name = xType.getName();
        if (xType.getTypeClass() == TypeClass.EXCEPTION)
        {
            switch (uno_name)
            {
            case "com.sun.star.uno.Exception":
                return get_type_Exception();
            case "com.sun.star.uno.RuntimeException":
                return get_type_RuntimeException();
            default:
                break;
            }
        }

        string cts_name = to_cts_name(uno_name);

        // if the struct is an instantiated polymorphic struct then we create
        // the simple struct name
        //
        // For example:
        // void func ([in] PolyStruct<boolean> arg9,
        // PolyStruct<boolean> will be converted to PolyStruct
        polymorphicStructNameToStructName(ref cts_name);

        Type ret_type = get_type(cts_name, false /* no exc */);
        if (ret_type == null)
        {
            XCompoundTypeDescription xBaseType =
                xType.getBaseType() as XCompoundTypeDescription;
            Type base_type = (xBaseType != null
                              ? get_type(xBaseType)
                              : typeof(Object));
            TypeBuilder type_builder = m_module_builder.DefineType(
                cts_name,
                (TypeAttributes.Public |
                 TypeAttributes.BeforeFieldInit |
                 TypeAttributes.AnsiClass),
                base_type);

            // Polymorphic struct, define uno.TypeParametersAttribute
            string[] type_parameters = null;
            XStructTypeDescription xStructTypeDesc =
                xType as XStructTypeDescription;
            if (xStructTypeDesc != null)
            {
                type_parameters = xStructTypeDesc.getTypeParameters();
                if (type_parameters.Length != 0)
                {
                    Type[] typesCtor =
                        new Type[] { Type.GetType("System.String[]") };
                    CustomAttributeBuilder attrBuilder =
                        new CustomAttributeBuilder(
                            typeof(uno.TypeParametersAttribute)
                            .GetConstructor(typesCtor),
                            type_parameters);
                    type_builder.SetCustomAttribute(attrBuilder);
                }
            }

            // FIXME huh? what does this  mean:
            // optional: lookup base type whether generated entry of this session
            struct_entry base_type_entry = null;
            if (base_type != null)
            {
                base_type_entry =
                    m_generated_structs[base_type.FullName] as struct_entry;
            }

            // members
            XTypeDescription[] seq_members = xType.getMemberTypes();
            string[] member_names = xType.getMemberNames();
            Trace.Assert(seq_members.Length == member_names.Length);

            int all_members_length = 0;
            int member_pos;
            int type_param_pos = 0;

            // collect base type; wrong order
            ArrayList base_types_list = new ArrayList(3 /* initial capacity */);
            for (Type base_type_pos = base_type_pos = base_type;
                 ! base_type_pos.Equals(typeof(System.Object));
                 base_type_pos = base_type_pos.BaseType)
            {
                base_types_list.Add(base_type_pos);
                if (base_type_pos.Equals(typeof(System.Exception)))
                {
                    // special Message member
                    all_members_length += 1;
                    break; // don't include System.Exception base classes
                }
                else
                {
                    all_members_length +=
                        base_type_pos.GetFields(BindingFlags.Instance |
                                                BindingFlags.Public |
                                                BindingFlags.DeclaredOnly).Length;
                }
            }

            // create all_members_arrays; right order
            string[] all_member_names =
                new string[all_members_length + seq_members.Length];
            Type[] all_param_types =
                new Type[all_members_length + seq_members.Length];
            member_pos =0;
            for (int pos = base_types_list.Count; pos-- != 0; )
            {
                Type ancestor = (Type) base_types_list[pos];
                if (ancestor.Equals(typeof(System.Exception)))
                {
                    all_member_names[member_pos] = "Message";
                    all_param_types[member_pos] = typeof (System.String);
                    ++member_pos;
                }
                else
                {
                    struct_entry existing_entry =
                        m_generated_structs[ancestor.FullName] as struct_entry;
                    if (existing_entry == null)
                    {
                        // complete type
                        FieldInfo[] fields = ancestor.GetFields(
                            BindingFlags.Instance |
                            BindingFlags.Public |
                            BindingFlags.DeclaredOnly);
                        foreach (FieldInfo field in fields)
                        {
                            all_member_names[member_pos] = field.Name;
                            all_param_types[member_pos] = field.FieldType;
                            ++member_pos;
                        }
                    }
                    else // generated during this session:
                         // members may be incomplete ifaces
                    {
                        for (int i = 0;
                             i < existing_entry.m_member_names.Length; ++i)
                        {
                            all_member_names[member_pos] =
                                existing_entry.m_member_names[i];
                            all_param_types[member_pos] =
                                existing_entry.m_param_types[i];
                            ++member_pos;
                        }
                    }
                }
            }
            Trace.Assert(all_members_length == member_pos);

            // build up entry
            struct_entry entry = new struct_entry();
            entry.m_member_names = new string[seq_members.Length];
            entry.m_param_types = new Type[seq_members.Length];

            // add members
            FieldBuilder[] members = new FieldBuilder[seq_members.Length];

            int curParamIndex = 0; // count the fields which have
                                   // parameterized types
            for (member_pos = 0; member_pos < seq_members.Length; ++member_pos)
            {
                string field_name = member_names[member_pos];
                Type field_type;
                // Special handling of struct parameter types
                bool bParameterizedType = false;
                if (seq_members[member_pos].getTypeClass() == TypeClass.UNKNOWN)
                {
                    bParameterizedType = true;
                    if (type_param_pos < type_parameters.Length)
                    {
                        field_type = typeof(System.Object);
                        type_param_pos++;
                    }
                    else
                    {
                        throw new System.Exception("unexpected member type in " +
                                                   xType.getName());
                    }
                }
                else
                {
                    field_type = get_type(seq_members[member_pos]);
                }
                members[member_pos] = type_builder.DefineField(
                    field_name, field_type, FieldAttributes.Public);

                // parameterized type (polymorphic struct) ?
                if (bParameterizedType && xStructTypeDesc != null)
                {
                    // get the name
                    Trace.Assert(type_parameters.Length > curParamIndex);
                    string sTypeName = type_parameters[curParamIndex++];
                    object[] args = new object[] { sTypeName };
                    // set ParameterizedTypeAttribute
                    Type[] ctorTypes = new Type[] { typeof(System.String) };

                    CustomAttributeBuilder attrBuilder =
                        new CustomAttributeBuilder(
                            typeof(uno.ParameterizedTypeAttribute)
                            .GetConstructor(ctorTypes),
                            args);

                    members[member_pos].SetCustomAttribute(attrBuilder);
                }
                // add to all_members
                all_member_names[all_members_length + member_pos] = field_name;
                all_param_types[all_members_length + member_pos] = field_type;
                // add to entry
                entry.m_member_names[member_pos] = field_name;
                entry.m_param_types[member_pos] = field_type;
            }
            all_members_length += members.Length;

            // default .ctor
            ConstructorBuilder ctor_builder =
                type_builder.DefineConstructor(
                    c_ctor_method_attr, CallingConventions.Standard,
                    new Type[0]);
            ILGenerator code = ctor_builder.GetILGenerator();
            code.Emit(OpCodes.Ldarg_0);
            code.Emit(OpCodes.Call,
                      base_type_entry == null
                      ? base_type.GetConstructor(new Type[0])
                      : base_type_entry.m_default_ctor);
            // default initialize members
            for (member_pos = 0; member_pos < seq_members.Length; ++member_pos)
            {
                FieldInfo field = members[member_pos];
                Type field_type = field.FieldType;
                // default initialize:
                // string, type, enum, sequence, struct, exception, any
                if (field_type.Equals(typeof(System.String)))
                {
                    code.Emit(OpCodes.Ldarg_0);
                    code.Emit(OpCodes.Ldstr, "");
                    code.Emit(OpCodes.Stfld, field);
                }
                else if (field_type.Equals(typeof(System.Type)))
                {
                    code.Emit(OpCodes.Ldarg_0);
                    code.Emit(OpCodes.Ldtoken, typeof(void));
                    code.Emit(OpCodes.Call, m_method_info_Type_GetTypeFromHandle);
                    code.Emit(OpCodes.Stfld, field);
                }
                else if (field_type.IsArray)
                {
                    code.Emit(OpCodes.Ldarg_0);
                    code.Emit(OpCodes.Ldc_I4_0);
                    code.Emit(OpCodes.Newarr, field_type.GetElementType());
                    code.Emit(OpCodes.Stfld, field);
                }
                else if (field_type.IsValueType)
                {
                    if (field_type.FullName.Equals("uno.Any"))
                    {
                        code.Emit(OpCodes.Ldarg_0);
                        code.Emit(OpCodes.Ldsfld, typeof(uno.Any).GetField("VOID"));
                        code.Emit(OpCodes.Stfld, field);
                    }
                }
                else if (field_type.IsClass)
                {
                    /* may be XInterface */
                    if (! field_type.Equals(typeof(System.Object)))
                    {
                        // struct, exception
                        code.Emit(OpCodes.Ldarg_0);
                        code.Emit(OpCodes.Newobj,
                                  field_type.GetConstructor(new Type[0]));
                        code.Emit(OpCodes.Stfld, field);
                    }
                }
            }
            code.Emit(OpCodes.Ret);
            entry.m_default_ctor = ctor_builder;

            // parameterized .ctor including all base members
            ctor_builder = type_builder.DefineConstructor(
                c_ctor_method_attr, CallingConventions.Standard, all_param_types);
            for (member_pos = 0; member_pos < all_members_length; ++member_pos)
            {
                ctor_builder.DefineParameter(
                    member_pos + 1 /* starts with 1 */, ParameterAttributes.In,
                    all_member_names[member_pos]);
            }
            code = ctor_builder.GetILGenerator();
            // call base .ctor
            code.Emit(OpCodes.Ldarg_0); // push this
            int base_members_length = all_members_length - seq_members.Length;
            Type[] param_types = new Type[base_members_length];
            for (member_pos = 0; member_pos < base_members_length; ++member_pos)
            {
                emit_ldarg(code, member_pos + 1);
                param_types[member_pos] = all_param_types[member_pos];
            }
            code.Emit(OpCodes.Call,
                      base_type_entry == null
                      ? base_type.GetConstructor(param_types)
                      : base_type_entry.m_ctor);
            // initialize members
            for (member_pos = 0; member_pos < seq_members.Length; ++member_pos)
            {
                code.Emit(OpCodes.Ldarg_0); // push this
                emit_ldarg(code, member_pos + base_members_length + 1);
                code.Emit(OpCodes.Stfld, members[member_pos]);
            }
            code.Emit(OpCodes.Ret);
            entry.m_ctor = ctor_builder;

            if (Climaker.g_verbose)
            {
                Console.WriteLine("> emitting {0} type {1}",
                                  xType.getTypeClass() == TypeClass.STRUCT
                                  ? "struct"
                                  : "exception",
                                  cts_name);
            }
            // new entry
            m_generated_structs.Add(cts_name, entry);
            ret_type = type_builder.CreateType();
        }
        return ret_type;
    }