Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support inherited Reactive attribute #29

Merged
merged 2 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 208 additions & 8 deletions ReactiveGenerator.Tests/ReactiveGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ public class ReactiveGeneratorTests
private Task TestAndVerify(string source, Dictionary<string, string>? analyzerConfigOptions = null)
{
return SourceGeneratorTestHelper.TestAndVerify(
source,
analyzerConfigOptions,
source,
analyzerConfigOptions,
generators: new ReactiveGenerator());
}

Expand Down Expand Up @@ -186,10 +186,7 @@ public partial class TestClass
public partial string Name { get; set; }
}";

var analyzerConfigOptions = new Dictionary<string, string>
{
["build_property.UseBackingFields"] = "true"
};
var analyzerConfigOptions = new Dictionary<string, string> { ["build_property.UseBackingFields"] = "true" };

return TestAndVerify(source, analyzerConfigOptions);
}
Expand All @@ -206,7 +203,7 @@ public partial class GlobalClass

return TestAndVerify(source);
}

[Fact]
public Task ClassWithMultipleReactiveAttributes()
{
Expand Down Expand Up @@ -483,7 +480,7 @@ public partial class TestClass

return TestAndVerify(source);
}

[Fact]
public Task PropertyLevelReactiveWithMixedProperties()
{
Expand Down Expand Up @@ -1069,4 +1066,207 @@ internal partial class GenericViewModel<T>

return TestAndVerify(source);
}

[Fact]
public Task InheritedReactiveAttribute()
{
var source = @"
[Reactive]
public abstract partial class BaseViewModel
{
public partial string BaseProp { get; set; }
}

public partial class ViewModel : BaseViewModel
{
public partial string ViewModelProp { get; set; }
}

[IgnoreReactive]
public partial class NonReactiveViewModel : BaseViewModel
{
public partial string IgnoredProp { get; set; }
}

public partial class DerivedViewModel : ViewModel
{
public partial string DerivedProp { get; set; }
}";

return TestAndVerify(source);
}

[Fact]
public Task MultiLevelInheritanceWithMixedReactiveAttributes()
{
var source = @"
[Reactive]
public abstract partial class BaseViewModel
{
public partial string BaseProp { get; set; }
}

public partial class MiddleViewModel : BaseViewModel
{
public partial string MiddleProp { get; set; }

[IgnoreReactive]
public partial string IgnoredMiddleProp { get; set; }
}

[IgnoreReactive]
public partial class NonReactiveViewModel : MiddleViewModel
{
public partial string NonReactiveProp { get; set; }
}

[Reactive]
public partial class ReactiveDerivedViewModel : NonReactiveViewModel
{
public partial string ReactiveProp { get; set; }
}";

return TestAndVerify(source);
}

[Fact]
public Task ReactiveObjectWithSingleReactiveProperty()
{
var source = @"
using ReactiveUI;

public partial class Car : ReactiveObject
{
[Reactive]
public partial string? Make { get; set; }

public partial string Model { get; set; } // Should not be processed
}";

return TestAndVerify(source);
}

[Fact]
public Task ReactiveObjectWithClassLevelReactive()
{
var source = @"
using ReactiveUI;

[Reactive]
internal partial class ReactiveViewModel : ReactiveObject
{
public partial string FirstName { get; set; }
public partial string LastName { get; set; }
}";

return TestAndVerify(source);
}

[Fact]
public Task ReactiveObjectWithoutAnyReactiveAttribute()
{
var source = @"
using ReactiveUI;

public partial class OaphViewModel<T> : ReactiveObject
{
public partial string ComputedValue { get; } // Should not be processed
public partial string NormalProperty { get; set; } // Should not be processed
}";

return TestAndVerify(source);
}

[Fact]
public Task ReactiveObjectWithNullableGenerics()
{
var source = @"
using System;
using ReactiveUI;

public partial class NullableGenericsTest<T>
{
[Reactive]
public partial DateTime? StartDate { get; set; }

[Reactive]
public partial DateTime? EndDate { get; set; }
}";

return TestAndVerify(source);
}

[Fact]
public Task ReactiveObjectWithMixedReactiveProperties()
{
var source = @"
using ReactiveUI;

public partial class MixedViewModel : ReactiveObject
{
[Reactive]
public partial string ReactiveProperty { get; set; }

public partial string NonReactiveProperty { get; set; }

[Reactive]
public partial int? NullableReactiveProperty { get; set; }

[ObservableAsProperty]
public partial string ComputedProperty { get; }
}";

return TestAndVerify(source);
}

[Fact]
public Task ReactiveObjectWithClassLevelReactiveAndIgnoreOverride()
{
var source = @"
using ReactiveUI;

[Reactive]
public partial class AllReactiveViewModel : ReactiveObject
{
public partial string Property1 { get; set; }

[IgnoreReactive]
public partial string IgnoredProperty { get; set; }

public partial string Property2 { get; set; }
}";

return TestAndVerify(source);
}

[Fact]
public Task ReactiveObjectWithPropertyInitializer()
{
var source = @"
using ReactiveUI;

[Reactive]
public partial class InitializedViewModel : ReactiveObject
{
public partial string Name { get; set; } = string.Empty;
public partial int Count { get; set; } = 42;
}";

return TestAndVerify(source);
}

[Fact]
public Task NonReactiveObjectWithMixedProperties()
{
var source = @"
public partial class RegularClass
{
[Reactive]
public partial string ReactiveProperty { get; set; }

public partial string NonReactiveProperty { get; set; }
}";

return TestAndVerify(source);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,59 +21,24 @@ sealed class ReactiveAttribute : Attribute
{
public ReactiveAttribute() { }
}
},
{
FileName: TestClass.INPC.g.cs,
Source:
// <auto-generated/>
#nullable enable

using System.ComponentModel;
using System.Runtime.CompilerServices;

public partial class TestClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;

protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
{
PropertyChanged?.Invoke(this, args);
}
}

},
{
FileName: TestClass.ReactiveProperties.g.cs,
Source:
// <auto-generated/>
#nullable enable

using System.ComponentModel;
using System.Runtime.CompilerServices;
using ReactiveUI;

/// <summary>
/// A partial class implementation for TestClass.
/// </summary>
public partial class TestClass
{
private static readonly PropertyChangedEventArgs _nameChangedEventArgs = new PropertyChangedEventArgs(nameof(Name));

public partial string Name
{
get => field;
set
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(_nameChangedEventArgs);
}
}
set => this.RaiseAndSetIfChanged(ref field, value);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,54 +1,19 @@
{
Sources: [
{
FileName: GenericViewModel.INPC.g.cs,
Source:
// <auto-generated/>
#nullable enable

using System.ComponentModel;
using System.Runtime.CompilerServices;

internal partial class GenericViewModel<T> : INotifyPropertyChanged where T : class
{
public event PropertyChangedEventHandler? PropertyChanged;

protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
{
PropertyChanged?.Invoke(this, args);
}
}

},
{
FileName: GenericViewModel.ReactiveProperties.g.cs,
Source:
// <auto-generated/>
#nullable enable

using System.ComponentModel;
using System.Runtime.CompilerServices;
using ReactiveUI;

internal partial class GenericViewModel<T> where T : class
{
private static readonly PropertyChangedEventArgs _valueChangedEventArgs = new PropertyChangedEventArgs(nameof(Value));

public partial T? Value
{
get => field;
set
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(_valueChangedEventArgs);
}
}
set => this.RaiseAndSetIfChanged(ref field, value);
}
}

Expand Down
Loading
Loading