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); } }
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); }
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(); }
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(); }