diff --git a/ReactiveGenerator/ReactiveGenerator.cs b/ReactiveGenerator/ReactiveGenerator.cs index 0c11190..02f8475 100644 --- a/ReactiveGenerator/ReactiveGenerator.cs +++ b/ReactiveGenerator/ReactiveGenerator.cs @@ -175,7 +175,7 @@ private static bool HasReactivePropertiesInHierarchy(INamedTypeSymbol typeSymbol return typeSymbol.BaseType != null && HasReactivePropertiesInHierarchy(typeSymbol.BaseType); } - private static string GenerateClassSource( + private static string GenerateClassSource( Compilation compilation, INamedTypeSymbol classSymbol, List allProperties, @@ -245,6 +245,7 @@ private static string GenerateClassSource( if (typeProperties.Any()) sb.AppendLine(); + // Generate backing fields and properties foreach (var property in typeProperties) { @@ -253,21 +254,36 @@ private static string GenerateClassSource( var backingFieldName = GetBackingFieldName(propertyName); var eventArgsFieldName = GetEventArgsFieldName(propertyName); + // Backing field should be private regardless of property accessibility sb.AppendLine($" private {propertyType} {backingFieldName};"); sb.AppendLine(); + // Get property accessors' modifiers + var getterAccessibility = GetAccessorAccessibility(property.GetMethod); + var setterAccessibility = GetAccessorAccessibility(property.SetMethod); var propertyAccessibility = property.DeclaredAccessibility.ToString().ToLowerInvariant(); + sb.AppendLine($" {propertyAccessibility} partial {propertyType} {propertyName}"); sb.AppendLine(" {"); - sb.AppendLine($" get => {backingFieldName};"); - sb.AppendLine(" set"); - sb.AppendLine(" {"); - sb.AppendLine($" if (!Equals({backingFieldName}, value))"); - sb.AppendLine(" {"); - sb.AppendLine($" {backingFieldName} = value;"); - sb.AppendLine($" OnPropertyChanged({eventArgsFieldName});"); - sb.AppendLine(" }"); - sb.AppendLine(" }"); + + // Generate getter + var getterModifier = getterAccessibility != propertyAccessibility ? $"{getterAccessibility} " : ""; + sb.AppendLine($" {getterModifier}get => {backingFieldName};"); + + // Generate setter if it exists + if (property.SetMethod != null) + { + var setterModifier = setterAccessibility != propertyAccessibility ? $"{setterAccessibility} " : ""; + sb.AppendLine($" {setterModifier}set"); + sb.AppendLine(" {"); + sb.AppendLine($" if (!Equals({backingFieldName}, value))"); + sb.AppendLine(" {"); + sb.AppendLine($" {backingFieldName} = value;"); + sb.AppendLine($" OnPropertyChanged({eventArgsFieldName});"); + sb.AppendLine(" }"); + sb.AppendLine(" }"); + } + sb.AppendLine(" }"); sb.AppendLine(); } @@ -281,7 +297,23 @@ private static string GenerateClassSource( return sb.ToString(); } - + + private static string GetAccessorAccessibility(IMethodSymbol accessor) + { + if (accessor == null) + return "private"; + + return accessor.DeclaredAccessibility switch + { + Accessibility.Private => "private", + Accessibility.Protected => "protected", + Accessibility.Internal => "internal", + Accessibility.ProtectedOrInternal => "protected internal", + Accessibility.ProtectedAndInternal => "private protected", + _ => accessor.DeclaredAccessibility.ToString().ToLowerInvariant() + }; + } + private static string GetBackingFieldName(string propertyName) { return "_" + char.ToLowerInvariant(propertyName[0]) + propertyName.Substring(1); @@ -300,4 +332,4 @@ sealed class ReactiveAttribute : Attribute public ReactiveAttribute() { } }"; } -} \ No newline at end of file +}