private static string GenerateInitializerFromProperty( PropertyTypeNode.TypeTag containerTypeTag, PropertyTypeNode propertyType) { // No initializer for structs if (containerTypeTag == PropertyTypeNode.TypeTag.Struct) { return(string.Empty); } var type = TypeDeclarationStringForProperty(propertyType); if (PropertyTypeNode.IsEnumerableType(propertyType.Tag) || propertyType.Tag == PropertyTypeNode.TypeTag.Struct) { // TODO value type etc. return($"new {type} {{}}"); } if (propertyType.Tag == PropertyTypeNode.TypeTag.Class) { return($"new {type} ()"); } return(!string.IsNullOrEmpty(propertyType.DefaultValue) ? propertyType.DefaultValue : string.Empty); }
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 PropertyTypeNode.TypeTag GetTypeTagFromPropertyName( string propertyTypeName, ContainerTypeTreePath context, PropertyTypeNode.TypeTag defaultTypeTag = PropertyTypeNode.TypeTag.Class) { var propertyTypeTag = defaultTypeTag; if (TypeResolver.IsPrimitiveType(propertyTypeName)) { propertyTypeTag = PropertyTypeNode.TypeTag.Primitive; } else if (_typeResolver != null) { propertyTypeTag = _typeResolver.Resolve(context, propertyTypeName); } return(propertyTypeTag); }
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 GeneratePropertyWrapperBackingVariable( string propertyWrapperTypeName, PropertyTypeNode.TypeTag containerTypeTag, PropertyTypeNode propertyType) { var accessModifiers = AccessModifiers.Static | AccessModifiers.Readonly; if (containerTypeTag == PropertyTypeNode.TypeTag.Class) { accessModifiers |= (propertyType.IsPublicProperty ? AccessModifiers.Public : AccessModifiers.Protected); } else { accessModifiers |= AccessModifiers.Private; } var modifiers = string.Join(" ", ModifiersToStrings(accessModifiers)); var propertyWrapperVariableName = GetPropertyWrapperVariableName(propertyType); return($@"{modifiers} {propertyWrapperTypeName} {propertyWrapperVariableName};"); }
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}>"); }
public void GenerateProperty( string containerName, PropertyTypeNode.TypeTag containerTypeTag, PropertyTypeNode propertyType, Scope code) { // Public C# Property & backing field GenerateClassPropertiesForPropertyAccessor(containerTypeTag, propertyType, code); var propertyWrapperTypeName = GetPropertyWrapperTypeFor( containerName, containerTypeTag, propertyType); code.AddLine(GeneratePropertyWrapperBackingVariable( propertyWrapperTypeName, containerTypeTag, propertyType)); // Backing field if any var propertyAccessorName = string.Empty; var backingField = GeneratePropertyBackingField( propertyType.PropertyName, 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(containerTypeTag, propertyType); var initializerFragment = backingField; if (!string.IsNullOrEmpty(initializer) && !propertyType.DontInitializeBackingField) { initializerFragment += $" = {initializer}"; } initializerFragment += ";"; code.AddLine(initializerFragment); } // -> Add constructor initializer fragments for later stage for that property var propertyTypeString = TypeDeclarationStringForProperty(propertyType); var propertyWrapperVariableName = GetPropertyWrapperVariableName(propertyType); { var initializer = GeneratePropertyWrapperInitializers( propertyType, containerName, containerTypeTag, propertyWrapperTypeName, propertyAccessorName, propertyTypeString, code); AddStaticConstructorInStageFragment( ConstructorStage.PropertyInitializationStage, new CSharpGenerationFragmentContext() { Scope = code, Fragment = $"{propertyWrapperVariableName} = {initializer};" }); } PropertyBagItemNames.Add(propertyWrapperVariableName); }
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);") } }}