private bool IsBlittablePropertyType(UProperty property) { return(property.IsBlittableType || (property.IsA <UObjectProperty>() && Settings.UObjectAsBlittableType) || (property.IsA <UStructProperty>() && IsBlittableStructProperty(property as UStructProperty))); }
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(); }