private static string GetPropertyWrapperTypeFor( string containerName, PropertyTypeNode.TypeTag containerTypeTag, PropertyTypeNode propertyType) { // @TODO warning we rely on type definitions here var propertyWrapperTypeStringPrefix = ""; if (containerTypeTag.HasFlag(PropertyTypeNode.TypeTag.Struct)) { propertyWrapperTypeStringPrefix = "Struct"; } switch (propertyType.Tag) { case PropertyTypeNode.TypeTag.Struct: return($"{propertyWrapperTypeStringPrefix}MutableContainerProperty<{containerName}, {propertyType.TypeName}>"); case PropertyTypeNode.TypeTag.Class: return($"{propertyWrapperTypeStringPrefix}ContainerProperty<{containerName}, {propertyType.TypeName}>"); case PropertyTypeNode.TypeTag.Enum: return($"{propertyWrapperTypeStringPrefix}EnumProperty<{containerName}, {propertyType.TypeName}>"); case PropertyTypeNode.TypeTag.List: { var t = TypeStringFromEnumerableProperty(propertyType); switch (propertyType.Of.Tag) { case PropertyTypeNode.TypeTag.Primitive: return($"{propertyWrapperTypeStringPrefix}ListProperty<{containerName}, {t}, {propertyType.Of.TypeName}>"); case PropertyTypeNode.TypeTag.Struct: return($"{propertyWrapperTypeStringPrefix}MutableContainerListProperty<{containerName}, {t}, {propertyType.Of.TypeName}>"); case PropertyTypeNode.TypeTag.Class: return($"{propertyWrapperTypeStringPrefix}ContainerListProperty<{containerName}, {t}, {propertyType.Of.TypeName}>"); case PropertyTypeNode.TypeTag.Enum: return($"{propertyWrapperTypeStringPrefix}EnumListProperty<{containerName}, {t}, {propertyType.Of.TypeName}>"); case PropertyTypeNode.TypeTag.Unknown: case PropertyTypeNode.TypeTag.List: default: throw new Exception($"Invalid property tag of list property name {propertyType.PropertyName}"); } } case PropertyTypeNode.TypeTag.Primitive: return($"{propertyWrapperTypeStringPrefix}Property<{containerName}, {propertyType.TypeName}>"); default: break; } return($"{propertyWrapperTypeStringPrefix}Property<{containerName}, {propertyType.TypeName}>"); }
private static string GeneratePropertyWrapperInitializers( PropertyTypeNode propertyType, string containerName, PropertyTypeNode.TypeTag containerTypeTag, string propertyWrapperTypeString, string propertyAccessorName, string propertyTypeString, Scope code ) { var initializerParams = new List <string>(); var accessors = GetPropertyWrapperAccessors( propertyType, containerName, containerTypeTag, propertyWrapperTypeString, propertyTypeString, propertyAccessorName); // @TODO shouldn't be done here, and be located in a cleaner place #if ENABLE_CUSTOM_PROPERTY_PARTIALS if (propertyType.IsCustomProperty) { var containerAsAParemeterType = containerTypeTag.HasFlag(PropertyTypeNode.TypeTag.Struct) ? $"ref {containerName}" : $"{containerName}"; code.AddLine(""); if (!string.IsNullOrEmpty(accessors.RefGetter)) { code.AddLine( $"partial void {accessors.RefGetter}({containerAsAParemeterType} value, IPropertyVisitor visitor);"); } code.AddLine($"partial void {accessors.ValueSetter}({containerAsAParemeterType} container, {propertyTypeString} value);"); code.AddLine( $"partial {propertyTypeString} {accessors.ValueGetter}({containerAsAParemeterType} container);"); code.AddLine(""); } #endif initializerParams.Add($"nameof({propertyType.PropertyName})"); initializerParams.Add(accessors.ValueGetter); initializerParams.Add(accessors.ValueSetter); if (!string.IsNullOrEmpty(accessors.RefGetter)) { initializerParams.Add(accessors.RefGetter); } return($@"new { propertyWrapperTypeString }( {string.Join(", ", initializerParams)} )"); }
private static PropertyWrapperAccessors GetPropertyWrapperAccessors( PropertyTypeNode propertyType, string containerName, PropertyTypeNode.TypeTag containerTypeTag, string propertyWrapperTypeString, string propertyTypeString, string propertyAccessorName) { if (propertyType.IsCustomProperty) { return(new PropertyWrapperAccessors() { ValueGetter = $"GetValue_{CleanupNameForMethod(propertyType.PropertyName)}", ValueSetter = $"SetValue_{CleanupNameForMethod(propertyType.PropertyName)}", RefGetter = propertyType.Tag == PropertyTypeNode.TypeTag.Struct ? $"GetRef_{CleanupNameForMethod(propertyType.PropertyName)}" : string.Empty }); } var containerAsAParemeterType = containerTypeTag.HasFlag(PropertyTypeNode.TypeTag.Struct) ? $"ref {containerName}" : $"{containerName}"; var propertySetter = "/* SET */ null"; if (!PropertyTypeNode.IsCompositeType(propertyType.Tag) && !propertyType.IsReadonly) { propertySetter = $"/* SET */ ({containerAsAParemeterType} container, {propertyTypeString} value) => container.{propertyAccessorName} = value"; } var propertyRefGetter = string.Empty; if (propertyType.Tag == PropertyTypeNode.TypeTag.Struct) { propertyRefGetter = $"/* REF */ ({containerAsAParemeterType} container, {propertyWrapperTypeString}.RefVisitMethod a, IPropertyVisitor v) => a(ref container.m_{propertyType.PropertyName}, v)"; } return(new PropertyWrapperAccessors() { ValueGetter = $"/* GET */ ({containerAsAParemeterType} container) => container.{propertyAccessorName}", ValueSetter = propertySetter, RefGetter = propertyRefGetter }); }
private static string GeneratePropertyWrapperInitializer( string propertyName, string containerName, PropertyTypeNode.TypeTag containerTypeTag, string propertyWrapperTypeString, bool isReadonlyProperty, string propertyAccessorName, string propertyTypeString, PropertyTypeNode.TypeTag propertyTypeTag ) { List <string> initializerParams = new List <string>(); var containerAsAParemeterType = containerTypeTag.HasFlag(PropertyTypeNode.TypeTag.Struct) ? $"ref {containerName}" : $"{containerName}"; initializerParams.Add($"nameof({propertyName})"); initializerParams.Add($"/* GET */ ({containerAsAParemeterType} container) => container.{propertyAccessorName}"); var propertySetter = "/* SET */ null"; if (!PropertyTypeNode.IsCompositeType(propertyTypeTag) && !isReadonlyProperty) { propertySetter = $"/* SET */ ({containerAsAParemeterType} container, {propertyTypeString} value) => container.{propertyAccessorName} = value"; } initializerParams.Add(propertySetter); if (propertyTypeTag == PropertyTypeNode.TypeTag.Struct) { initializerParams.Add( $"/* REF */ ({containerAsAParemeterType} container, {propertyWrapperTypeString}.RefVisitMethod a, IPropertyVisitor v) => a(ref container.m_{propertyName}, v)" ); } string parameters = string.Join(", ", initializerParams); return($@"new { propertyWrapperTypeString }( {parameters} )"); }
private static void GenerateClassPropertiesForPropertyAccessor( PropertyTypeNode.TypeTag containerTypeTag, PropertyTypeNode propertyType, Scope code ) { var containerAsAParamTokens = new List <string> { }; if (containerTypeTag.HasFlag(PropertyTypeNode.TypeTag.Struct)) { containerAsAParamTokens.Add("ref"); } containerAsAParamTokens.Add("this"); var getSetValueCallContainerParam = string.Join(" ", containerAsAParamTokens); var propertyWrapperVariableName = GetPropertyWrapperVariableName(propertyType); var propertyTypeString = TypeDeclarationStringForProperty(propertyType); var isCompositeType = PropertyTypeNode.IsCompositeType(propertyType.Tag); var modifiers = string.Join(" ", ModifiersToStrings(AccessModifiers.Public)); code.AddLine($"{modifiers} {propertyTypeString} {propertyType.PropertyName}"); { code.AddLine("{"); var accessorScope = new Scope(code); accessorScope.AddLine($"get {{ return {propertyWrapperVariableName}.GetValue({getSetValueCallContainerParam}); }}"); if (!isCompositeType) { accessorScope.AddLine($"set {{ {propertyWrapperVariableName}.SetValue({getSetValueCallContainerParam}, value); }}"); } code.AddLine("}"); } }
private static string GetPropertyWrapperTypeFor( string containerName, PropertyTypeNode.TypeTag containerTypeTag, PropertyTypeNode propertyType) { // TODO warning we rely on type definitions here var propertyWrapperTypeStringPrefix = ""; if (containerTypeTag.HasFlag(PropertyTypeNode.TypeTag.Struct)) { propertyWrapperTypeStringPrefix = "Struct"; } switch (propertyType.Tag) { case PropertyTypeNode.TypeTag.Struct: return($"{propertyWrapperTypeStringPrefix}MutableContainerProperty<{containerName}, {propertyType.TypeName}>"); case PropertyTypeNode.TypeTag.Class: return($"{propertyWrapperTypeStringPrefix}ContainerProperty<{containerName}, {propertyType.TypeName}>"); case PropertyTypeNode.TypeTag.Enum: return($"{propertyWrapperTypeStringPrefix}EnumProperty<{containerName}, {propertyType.TypeName}>"); case PropertyTypeNode.TypeTag.Array: case PropertyTypeNode.TypeTag.List: { var t = TypeStringFromEnumerableProperty(propertyType); return($"{propertyWrapperTypeStringPrefix}ListProperty<{containerName}, {t}, {propertyType.Of.TypeName}>"); } default: break; } return($"{propertyWrapperTypeStringPrefix}Property<{containerName}, {propertyType.TypeName}>"); }
private void GenerateProperty( string containerName, PropertyTypeNode.TypeTag containerTypeTag, PropertyTypeNode propertyType, StringBuffer gen) { var propertyWrapperVariableName = $"s_{propertyType.Name}Property"; var propertyTypeString = TypeDeclarationStringForProperty(propertyType); if (!string.IsNullOrWhiteSpace(propertyType.IsInheritedFrom)) { // Just add a propertybag member PropertyBagItemNames.Add( $"new InheritedProperty<{propertyType.IsInheritedFrom}, {containerName}, {propertyTypeString}>({propertyWrapperVariableName})" ); return; } var propertyWrapperTypeName = GetPropertyWrapperTypeFor( containerName, containerTypeTag, propertyType); bool isCompositeType = PropertyTypeNode.IsCompositeType(propertyType.Tag); // Backing field if any var propertyAccessorName = string.Empty; var backingField = GeneratePropertyBackingField( propertyType.Name, propertyType, out propertyAccessorName ); if (!string.IsNullOrEmpty(backingField)) { // If we have a class we delegate init to constructor otherwise we default construct here var initializer = GenerateInitializerFromProperty(propertyType); gen.Append(' ', Style.Space * 1); gen.Append(backingField); if (!string.IsNullOrEmpty(initializer)) { if (containerTypeTag == PropertyTypeNode.TypeTag.Struct) { gen.Append($"= {initializer}"); } else { // Add an initializer for that ConstructorInitializerFragments.Add(() => $"{propertyAccessorName} = {initializer};"); } } gen.Append($";{Environment.NewLine}"); } // Public C# Property // @TODO extract as a method var containerAsAParamTokens = new List <String> { }; if (containerTypeTag.HasFlag(PropertyTypeNode.TypeTag.Struct)) { containerAsAParamTokens.Add("ref"); } containerAsAParamTokens.Add("this"); var getSetValueCallContainerParam = string.Join(" ", containerAsAParamTokens); gen.Append(' ', Style.Space * 1); var modifiers = string.Join(" ", ModifiersToStrings(AccessModifiers.Public)); gen.Append($@"{modifiers} {propertyTypeString} {propertyType.Name} {{ get {{ return {propertyWrapperVariableName}.GetValue({getSetValueCallContainerParam}); }} set {{ { (isCompositeType ? string.Empty : $"{propertyWrapperVariableName}.SetValue({getSetValueCallContainerParam}, value);") } }}