Ejemplo n.º 1
0
 public void AddField(UField field, CollapsedMember collapsedMember)
 {
     Fields[field] = collapsedMember;
     if (collapsedMember != null)
     {
         List <UField> fields;
         if (!FieldsByCollapsedMember.TryGetValue(collapsedMember, out fields))
         {
             FieldsByCollapsedMember.Add(collapsedMember, fields = new List <UField>());
         }
         fields.Add(field);
     }
 }
Ejemplo n.º 2
0
                private void AddMember(UField field, string name, bool isResolvedName)
                {
                    CollapsedMember collapsedMember = null;

                    UProperty property = field as UProperty;

                    if (property != null)
                    {
                        structInfo.collapsedMembersByProperty.TryGetValue(property, out collapsedMember);
                    }

                    UFunction function = field as UFunction;

                    if (function != null)
                    {
                        structInfo.collapsedMembersByFunction.TryGetValue(function, out collapsedMember);
                    }

                    if (collapsedMember != null)
                    {
                        if (isResolvedName)
                        {
                            collapsedMember.ResolvedName = name;
                        }
                        else
                        {
                            name = collapsedMember.Name;
                        }
                    }

                    NameConflictFieldInfo fieldInfo;

                    if (!MembersByName.TryGetValue(name, out fieldInfo))
                    {
                        MembersByName.Add(name, fieldInfo = new NameConflictFieldInfo(name));
                    }
                    fieldInfo.AddField(field, collapsedMember);
                }
Ejemplo n.º 3
0
        private void GenerateCodeForProperty(UnrealModuleInfo module, CSharpTextBuilder builder, CSharpTextBuilder offsetsBuilder,
                                             CollapsedMember collapsedMember, bool isBlueprintType, List <string> namespaces)
        {
            StringBuilder modifiers = new StringBuilder();

            if (collapsedMember.BackingProperty != null)
            {
                UProperty property = collapsedMember.BackingProperty;

                if (property.HasAnyPropertyFlags(EPropertyFlags.DisableEditOnInstance) && !property.GetBoolMetaData(MDProp.AllowPrivateAccess))
                {
                    modifiers.Append("private");
                }
                else if (property.HasAnyPropertyFlags(EPropertyFlags.NativeAccessSpecifierProtected | EPropertyFlags.Protected))
                {
                    modifiers.Append("protected");
                }
                else
                {
                    modifiers.Append("public");
                }
            }
            else
            {
                UFunction function = collapsedMember.Getter != null ? collapsedMember.Getter : collapsedMember.Setter;

                if (function.HasAnyFunctionFlags(EFunctionFlags.Protected))
                {
                    modifiers.Append("protected");
                }
                else
                {
                    modifiers.Append("public");
                }
            }

            if (modifiers.Length > 0)
            {
                modifiers.Append(" ");
            }

            // Note: Potential issues with different categories/docs/attribute on BackingProperty/Getter/Setter

            UField field = collapsedMember.BackingProperty;

            if (field == null)
            {
                field = collapsedMember.Getter;
                if (field == null)
                {
                    field = collapsedMember.Setter;
                }
            }

            // Use either the backing property or the getter function for the documentation
            UField fieldForDocumentation = collapsedMember.BackingProperty != null ?
                                           (UField)collapsedMember.BackingProperty : collapsedMember.Getter;

            string name         = collapsedMember.ResolvedName != null ? collapsedMember.ResolvedName : collapsedMember.Name;
            string propertyName = GetName(field, name, Settings.MemberCasing, false, true);

            AppendGetterSetterOffsets(builder, offsetsBuilder, propertyName,
                                      collapsedMember.Getter == null || collapsedMember.Setter == null ? collapsedMember.BackingProperty : null, namespaces,
                                      collapsedMember.Getter, collapsedMember.Setter);

            AppendDocComment(builder, fieldForDocumentation, isBlueprintType);
            AppendAttribute(builder, field, module, true);
            builder.AppendLine(modifiers + GetTypeName(collapsedMember.Property, namespaces) + " " + propertyName);
            builder.OpenBrace();

            if (collapsedMember.Getter != null)
            {
                AppendGetter(builder, propertyName, collapsedMember.Getter, namespaces);
            }
            else if (collapsedMember.BackingProperty != null)
            {
                AppendGetter(builder, propertyName, collapsedMember.BackingProperty, namespaces);
            }

            if (collapsedMember.Setter != null)
            {
                AppendSetter(builder, propertyName, collapsedMember.Setter, namespaces);
            }
            else if (collapsedMember.BackingProperty != null)
            {
                AppendSetter(builder, propertyName, collapsedMember.BackingProperty, namespaces);
            }

            builder.CloseBrace();
            builder.AppendLine();
        }
Ejemplo n.º 4
0
            public void ResolveCollapsedMembers()
            {
                if (IsInterface)
                {
                    // Interface shouldn't have any C# properties, leave everything as functions
                    ResolveNameConflicts();
                    return;
                }

                collapsedMembers.Clear();
                collapsedMembersByFunction.Clear();
                collapsedMembersByProperty.Clear();

                var getters = new Dictionary <UFunction, CodeGeneratorSettings.CollapsedMemberSettings>();
                var setters = new Dictionary <UFunction, CodeGeneratorSettings.CollapsedMemberSettings>();

                // Conflicts aren't resolved at this point. May have multiple functions for a given name.
                // - If there are conflicts avoid collapsing those functions.
                Dictionary <string, List <UFunction> > gettersByName = new Dictionary <string, List <UFunction> >();
                Dictionary <string, List <UFunction> > settersByName = new Dictionary <string, List <UFunction> >();

                foreach (UFunction function in exportableFunctions)
                {
                    string functionName = codeGenerator.GetFunctionName(function, false);

                    // 1 param either as return value or parameter and no return
                    if (function.NumParms == 1)
                    {
                        UProperty returnProperty = function.GetReturnProperty();
                        if (returnProperty != null)
                        {
                            // Getter
                            foreach (var collapsedSetting in codeGenerator.Settings.CollapsedMembers)
                            {
                                if (!string.IsNullOrEmpty(collapsedSetting.GetPrefix) &&
                                    functionName.StartsWith(collapsedSetting.GetPrefix) &&
                                    (!collapsedSetting.RequiresBool || returnProperty.IsA <UBoolProperty>()))
                                {
                                    getters.Add(function, collapsedSetting);

                                    string trimmedName = functionName.Substring(collapsedSetting.GetPrefix.Length);
                                    if (trimmedName.Length > 0)
                                    {
                                        List <UFunction> functions;
                                        if (!gettersByName.TryGetValue(trimmedName, out functions))
                                        {
                                            gettersByName.Add(trimmedName, functions = new List <UFunction>());
                                        }
                                        functions.Add(function);
                                    }
                                    break;
                                }
                            }
                        }
                        else
                        {
                            // Setter
                            UProperty firstParam = function.GetFirstParam();
                            if (firstParam != null)
                            {
                                foreach (var collapsedSetting in codeGenerator.Settings.CollapsedMembers)
                                {
                                    if (!string.IsNullOrEmpty(collapsedSetting.SetPrefix) &&
                                        functionName.StartsWith(collapsedSetting.SetPrefix) &&
                                        (!collapsedSetting.RequiresBool || firstParam.IsA <UBoolProperty>()))
                                    {
                                        setters.Add(function, collapsedSetting);

                                        string trimmedName = functionName.Substring(collapsedSetting.GetPrefix.Length);
                                        if (trimmedName.Length > 0)
                                        {
                                            List <UFunction> functions;
                                            if (!settersByName.TryGetValue(trimmedName, out functions))
                                            {
                                                settersByName.Add(trimmedName, functions = new List <UFunction>());
                                            }
                                            functions.Add(function);
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                for (int i = 0; i < 2; i++)
                {
                    bool isGetter = i == 0;
                    Dictionary <string, List <UFunction> > collection = isGetter ? gettersByName : settersByName;

                    foreach (KeyValuePair <string, List <UFunction> > funcs in collection)
                    {
                        if (funcs.Value.Count != 1)
                        {
                            continue;
                        }

                        string    name   = funcs.Key;
                        UFunction getter = isGetter ? funcs.Value[0] : null;
                        UFunction setter = !isGetter ? funcs.Value[0] : null;
                        CodeGeneratorSettings.CollapsedMemberSettings settings = null;
                        UProperty paramOrRetValProperty = null;

                        Dictionary <string, List <UFunction> > otherCollection = isGetter ? settersByName : gettersByName;
                        List <UFunction> otherFuncs;
                        if (otherCollection.TryGetValue(funcs.Key, out otherFuncs))
                        {
                            if (otherFuncs.Count > 1)
                            {
                                // Other function has a conflict
                                continue;
                            }

                            if (isGetter)
                            {
                                setter = otherFuncs[0];
                            }
                            else
                            {
                                getter = otherFuncs[0];
                            }
                        }

                        if ((getter != null && collapsedMembersByFunction.ContainsKey(getter)) ||
                            (setter != null && collapsedMembersByFunction.ContainsKey(setter)))
                        {
                            continue;
                        }

                        if (getter != null && setter != null)
                        {
                            UProperty returnProperty = getter.GetReturnProperty();
                            UProperty firstParam     = setter.GetFirstParam();
                            if (returnProperty != null && firstParam != null && !returnProperty.SameType(firstParam))
                            {
                                // Property type mismatch on Get/Set functions
                                continue;
                            }
                        }

                        if (getter != null)
                        {
                            paramOrRetValProperty = getter.GetReturnProperty();
                            settings = getters[getter];
                        }
                        else if (setter != null)
                        {
                            paramOrRetValProperty = setter.GetFirstParam();
                            settings = setters[setter];
                        }

                        if (paramOrRetValProperty == null)
                        {
                            continue;
                        }

                        UProperty backingProperty           = null;
                        bool      backingPropertyExportable = false;

                        foreach (KeyValuePair <UProperty, string> property in exportableProperties)
                        {
                            if (name == codeGenerator.GetMemberName(property.Key, false, property.Value) &&
                                property.Key.SameType(paramOrRetValProperty))
                            {
                                if (backingProperty != null)
                                {
                                    // Skip conflicts
                                    continue;
                                }
                                backingProperty           = property.Key;
                                backingPropertyExportable = true;
                            }
                        }

                        if (backingProperty == null)
                        {
                            foreach (KeyValuePair <UProperty, string> property in nonExportableProperties)
                            {
                                if (name == codeGenerator.GetMemberName(property.Key, false, property.Value) &&
                                    property.Key.SameType(paramOrRetValProperty))
                                {
                                    if (backingProperty != null)
                                    {
                                        // Skip conflicts
                                        continue;
                                    }
                                    backingProperty           = property.Key;
                                    backingPropertyExportable = false;
                                }
                            }
                        }

                        if (getter == null && setter != null)
                        {
                            // SetXXX exists but there isn't a backing property or the backing property isn't
                            // exportable so there wouldn't be any way access the property. Leave the function
                            // as it is rather than creating a setter-only C# property unless the getter is injected.
                            if (backingProperty == null || (!backingPropertyExportable && !settings.InjectNonExportableProperty))
                            {
                                continue;
                            }
                            if (settings.SetRequiresGet)
                            {
                                continue;
                            }
                        }
                        else if (getter != null && setter == null)
                        {
                            if (settings.GetRequiresSet)
                            {
                                continue;
                            }
                        }

                        if ((getter != null && getter.HasAllFunctionFlags(EFunctionFlags.BlueprintEvent)) ||
                            (setter != null && setter.HasAnyFunctionFlags(EFunctionFlags.BlueprintEvent)))
                        {
                            // Skip events as they need a normal method body
                            continue;
                        }

                        string finalName = name;
                        if (!settings.StripPrefix && (getter == null || setter == null))
                        {
                            if (getter != null)
                            {
                                finalName = settings.GetPrefix + finalName;
                            }
                            else if (setter != null)
                            {
                                finalName = settings.SetPrefix + finalName;
                            }
                        }

                        if (backingProperty != null && backingProperty.HasAnyPropertyFlags(EPropertyFlags.BlueprintReadOnly) &&
                            IsCollectionProperty(backingProperty) && setter != null)
                        {
                            // If there is a backing property which is a readonly collection and there is a setter method then
                            // there will be type conflicts. Don't collapse them.
                            continue;
                        }

                        // Some validation on bool properties
                        {
                            UBoolProperty getterReturn = getter == null ? null : getter.GetReturnProperty() as UBoolProperty;
                            UBoolProperty setterParam  = setter == null ? null : setter.GetFirstParam() as UBoolProperty;

                            if (getterReturn != null && setterParam != null)
                            {
                                System.Diagnostics.Debug.Assert(getterReturn.ElementSize == setterParam.ElementSize,
                                                                "Get/Set use different bool size");
                            }

                            UBoolProperty backingBoolProperty = backingProperty as UBoolProperty;
                            if (backingBoolProperty != null)
                            {
                                if (getter != null)
                                {
                                    System.Diagnostics.Debug.Assert(backingBoolProperty.ElementSize == getterReturn.ElementSize,
                                                                    "BackingProperty/Get use different bool size");
                                }
                                else if (setter != null)
                                {
                                    System.Diagnostics.Debug.Assert(backingBoolProperty.ElementSize == setterParam.ElementSize,
                                                                    "BackingProperty/Set use different bool size");
                                }
                            }
                        }

                        CollapsedMember collapsedMember = new CollapsedMember(settings);
                        collapsedMember.BackingProperty             = backingProperty;
                        collapsedMember.IsBackingPropertyExportable = backingPropertyExportable;
                        collapsedMember.Getter   = getter;
                        collapsedMember.Setter   = setter;
                        collapsedMember.Name     = finalName;
                        collapsedMember.Property = paramOrRetValProperty;
                        collapsedMembers.Add(collapsedMember);
                        if (getter != null)
                        {
                            collapsedMembersByFunction.Add(getter, collapsedMember);
                        }
                        if (setter != null)
                        {
                            collapsedMembersByFunction.Add(setter, collapsedMember);
                        }
                        if (backingPropertyExportable)
                        {
                            collapsedMembersByProperty.Add(backingProperty, collapsedMember);
                        }
                    }
                }

                ResolveNameConflicts();
            }