Skip to content

Commit

Permalink
Merge pull request #31 from wieslawsoltes/FixModifiers
Browse files Browse the repository at this point in the history
Handle override, virtual and abstract property modifiers
  • Loading branch information
wieslawsoltes authored Dec 25, 2024
2 parents 1a5c2de + b85cfff commit 09f5cb4
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace MainLib
private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp));
private static readonly PropertyChangedEventArgs _derivedPropChangedEventArgs = new PropertyChangedEventArgs(nameof(DerivedProp));

public partial string VirtualProp
public override partial string VirtualProp
{
get => field;
set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public partial class TestClass
private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp));
private static readonly PropertyChangedEventArgs _nonVirtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(NonVirtualProp));

public partial string VirtualProp
public virtual partial string VirtualProp
{
get => field;
set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public partial class Container
{
private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp));

public partial string VirtualProp
public virtual partial string VirtualProp
{
get => field;
set
Expand Down Expand Up @@ -81,7 +81,7 @@ public partial class Container
private static readonly PropertyChangedEventArgs _virtualPropChangedEventArgs = new PropertyChangedEventArgs(nameof(VirtualProp));
private static readonly PropertyChangedEventArgs _regularPropChangedEventArgs = new PropertyChangedEventArgs(nameof(RegularProp));

public partial string VirtualProp
public override partial string VirtualProp
{
get => field;
set
Expand Down
79 changes: 58 additions & 21 deletions ReactiveGenerator/ReactiveGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,26 @@ namespace ReactiveGenerator;
[Generator]
public class ReactiveGenerator : IIncrementalGenerator
{
private record PropertyInfo(
private record PropertyInfo(
IPropertySymbol Property,
bool HasReactiveAttribute,
bool HasIgnoreAttribute,
bool HasImplementation);
bool HasImplementation)
{
public string GetPropertyModifiers()
{
var modifiers = new List<string>();

if (Property.IsOverride)
modifiers.Add("override");
else if (Property.IsVirtual)
modifiers.Add("virtual");
else if (Property.IsAbstract)
modifiers.Add("abstract");

return string.Join(" ", modifiers);
}
}

public void Initialize(IncrementalGeneratorInitializationContext context)
{
Expand Down Expand Up @@ -342,33 +357,37 @@ private static void Execute(
processedTypes.Add(type);
}
}

private static bool HasINPCImplementation(Compilation compilation, INamedTypeSymbol typeSymbol,
HashSet<INamedTypeSymbol> processedTypes)

private static bool HasINPCImplementation(Compilation compilation, INamedTypeSymbol typeSymbol, HashSet<INamedTypeSymbol> processedTypes)
{
var inpcType = compilation.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged");
if (inpcType is null)
return false;

// First check if current type implements INPC directly
if (typeSymbol.AllInterfaces.Contains(inpcType, SymbolEqualityComparer.Default))
return true;

// Check if current type is in processedTypes (will have INPC implemented)
if (processedTypes.Contains(typeSymbol))
// First check if current type implements INPC directly or is in processedTypes
if (typeSymbol.AllInterfaces.Contains(inpcType, SymbolEqualityComparer.Default) ||
processedTypes.Contains(typeSymbol))
return true;

// Check base types recursively
var current = typeSymbol.BaseType;
while (current is not null)
{
// Check if base type implements INPC directly
if (current.AllInterfaces.Contains(inpcType, SymbolEqualityComparer.Default))
return true;

// Check if base type is in processedTypes
if (processedTypes.Contains(current))
return true;
// If base type is in same assembly
if (current.ContainingAssembly == typeSymbol.ContainingAssembly)
{
// Check for INPC implementation or presence in processedTypes
if (current.AllInterfaces.Contains(inpcType, SymbolEqualityComparer.Default) ||
processedTypes.Contains(current))
return true;
}
// If base type is in different assembly
else
{
// For external types, only check for actual INPC implementation
if (current.AllInterfaces.Contains(inpcType, SymbolEqualityComparer.Default))
return true;
}

current = current.BaseType;
}
Expand Down Expand Up @@ -767,7 +786,15 @@ private static void GenerateLegacyProperty(
var getterAccessibility = GetAccessorAccessibility(property.GetMethod);
var setterAccessibility = GetAccessorAccessibility(property.SetMethod);

sb.AppendLine($"{indent}{propertyAccessibility} partial {propertyType} {propertyName}");
var propInfo = new PropertyInfo(property, false, false, false);
var modifiers = propInfo.GetPropertyModifiers();

var declarationModifiers = new List<string> { propertyAccessibility };
if (!string.IsNullOrEmpty(modifiers))
declarationModifiers.Add(modifiers);
declarationModifiers.Add("partial");

sb.AppendLine($"{indent}{string.Join(" ", declarationModifiers)} {propertyType} {propertyName}");
sb.AppendLine($"{indent}{{");

if (isReactiveObject)
Expand Down Expand Up @@ -817,8 +844,18 @@ private static void GenerateFieldKeywordProperty(
var propertyType = GetPropertyTypeWithNullability(property);
var getterAccessibility = GetAccessorAccessibility(property.GetMethod);
var setterAccessibility = GetAccessorAccessibility(property.SetMethod);

sb.AppendLine($"{indent}{propertyAccessibility} partial {propertyType} {propertyName}");

// Create PropertyInfo to get modifiers
var propInfo = new PropertyInfo(property, false, false, false);
var modifiers = propInfo.GetPropertyModifiers();

// Combine modifiers with accessibility and partial
var declarationModifiers = new List<string> { propertyAccessibility };
if (!string.IsNullOrEmpty(modifiers))
declarationModifiers.Add(modifiers);
declarationModifiers.Add("partial");

sb.AppendLine($"{indent}{string.Join(" ", declarationModifiers)} {propertyType} {propertyName}");
sb.AppendLine($"{indent}{{");

if (isReactiveObject)
Expand Down

0 comments on commit 09f5cb4

Please sign in to comment.