Skip to content

Commit

Permalink
Merge pull request #44 from wieslawsoltes/FixTypeConstrains
Browse files Browse the repository at this point in the history
Fix type constrains
  • Loading branch information
wieslawsoltes authored Jan 15, 2025
2 parents 6051434 + 66a97ee commit b278bc2
Show file tree
Hide file tree
Showing 10 changed files with 727 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1577,6 +1577,96 @@ public partial class Person
return TestAndVerify(source);
}

[Fact]
public Task ClassWithNotNullConstraint()
{
var source = @"
[Reactive]
public partial class Cache<TKey, TValue>
where TKey : notnull
where TValue : class
{
public partial TValue? Value { get; set; }
public partial TKey Key { get; set; }
}";

return TestAndVerify(source);
}

[Fact]
public Task ClassWithMultipleComplexConstraints()
{
var source = @"
[Reactive]
public partial class AdvancedCache<T, TKey, TValue>
where T : class, IDisposable
where TKey : notnull
where TValue : struct, IComparable<TValue>
{
public partial T? Instance { get; set; }
public partial TKey Key { get; set; }
public partial TValue Value { get; set; }
}";

return TestAndVerify(source);
}

[Fact]
public Task ClassWithNullableReferenceConstraint()
{
var source = @"
[Reactive]
public partial class Container<T>
where T : class?
{
public partial T? Value { get; set; }
}";

return TestAndVerify(source);
}

[Fact]
public Task ClassWithUnmanagedConstraint()
{
var source = @"
[Reactive]
public partial class UnmanagedContainer<T>
where T : unmanaged
{
public partial T Value { get; set; }
}";

return TestAndVerify(source);
}

[Fact]
public Task AllPossibleConstraints()
{
var source = @"
public interface ITestInterface { }
public class BaseClass { }
[Reactive]
public partial class ConstraintsTest<T1, T2, T3, T4, T5, T6, T7>
where T1 : class, ITestInterface, new() // Reference type + interface + constructor
where T2 : struct, IComparable<T2> // Value type + interface with self
where T3 : notnull // Non-null constraint
where T4 : unmanaged // Unmanaged constraint
where T5 : BaseClass // Base class constraint
where T6 : T1 // Another type parameter constraint
where T7 : class? // Nullable reference type constraint
{
public partial T1? Property1 { get; set; }
public partial T2 Property2 { get; set; }
public partial T3 Property3 { get; set; }
public partial T4 Property4 { get; set; }
public partial T5? Property5 { get; set; }
public partial T6? Property6 { get; set; }
public partial T7? Property7 { get; set; }
}";

return TestAndVerify(source);
}
/* TODO:
[Fact]
public Task ReadOnlyPropertyTest()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
{
Sources: [
{
FileName: ConstraintsTest.INPC.g.cs,
Source:
// <auto-generated/>
#nullable enable

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

public partial class ConstraintsTest<T1, T2, T3, T4, T5, T6, T7> : INotifyPropertyChanged where T1 : class, global::ITestInterface, new() where T2 : struct, IComparable<T2> where T3 : notnull where T4 : unmanaged, struct where T5 : global::BaseClass where T6 : T1 where T7 : 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: ConstraintsTest.ReactiveProperties.g.cs,
Source:
// <auto-generated/>
#nullable enable

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

/// <summary>
/// A partial class implementation for ConstraintsTest{T1, T2, T3, T4, T5, T6, T7}.
/// </summary>
public partial class ConstraintsTest<T1, T2, T3, T4, T5, T6, T7> where T1 : class, global::ITestInterface, new() where T2 : struct, IComparable<T2> where T3 : notnull where T4 : unmanaged, struct where T5 : global::BaseClass where T6 : T1 where T7 : class?
{
private static readonly PropertyChangedEventArgs _property1ChangedEventArgs = new PropertyChangedEventArgs(nameof(Property1));
private static readonly PropertyChangedEventArgs _property2ChangedEventArgs = new PropertyChangedEventArgs(nameof(Property2));
private static readonly PropertyChangedEventArgs _property3ChangedEventArgs = new PropertyChangedEventArgs(nameof(Property3));
private static readonly PropertyChangedEventArgs _property4ChangedEventArgs = new PropertyChangedEventArgs(nameof(Property4));
private static readonly PropertyChangedEventArgs _property5ChangedEventArgs = new PropertyChangedEventArgs(nameof(Property5));
private static readonly PropertyChangedEventArgs _property6ChangedEventArgs = new PropertyChangedEventArgs(nameof(Property6));
private static readonly PropertyChangedEventArgs _property7ChangedEventArgs = new PropertyChangedEventArgs(nameof(Property7));

public partial T1? Property1
{
get => field;
set
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(_property1ChangedEventArgs);
}
}
}

public partial T2 Property2
{
get => field;
set
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(_property2ChangedEventArgs);
}
}
}

public partial T3 Property3
{
get => field;
set
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(_property3ChangedEventArgs);
}
}
}

public partial T4 Property4
{
get => field;
set
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(_property4ChangedEventArgs);
}
}
}

public partial T5? Property5
{
get => field;
set
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(_property5ChangedEventArgs);
}
}
}

public partial T6? Property6
{
get => field;
set
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(_property6ChangedEventArgs);
}
}
}

public partial T7? Property7
{
get => field;
set
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(_property7ChangedEventArgs);
}
}
}
}

},
{
FileName: IgnoreReactiveAttribute.g.cs,
Source:
// <auto-generated/>
using System;

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
sealed class IgnoreReactiveAttribute : Attribute
{
public IgnoreReactiveAttribute() { }
}
},
{
FileName: ReactiveAttribute.g.cs,
Source:
// <auto-generated/>
using System;

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
sealed class ReactiveAttribute : Attribute
{
public ReactiveAttribute() { }
}
}
],
Diagnostics: null
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ sealed class ReactiveAttribute : Attribute
using System.ComponentModel;
using System.Runtime.CompilerServices;

public partial class TestClass<T, U> : INotifyPropertyChanged where T : class, IDisposable where U : struct, IComparable<U>
public partial class TestClass<T, U> : INotifyPropertyChanged where T : class?, IDisposable where U : struct, IComparable<U>
{
public event PropertyChangedEventHandler? PropertyChanged;

Expand Down Expand Up @@ -61,7 +61,7 @@ using System.Runtime.CompilerServices;
/// <summary>
/// A partial class implementation for TestClass{T, U}.
/// </summary>
public partial class TestClass<T, U> where T : class, IDisposable where U : struct, IComparable<U>
public partial class TestClass<T, U> where T : class?, IDisposable where U : struct, IComparable<U>
{
private static readonly PropertyChangedEventArgs _nullableRefChangedEventArgs = new PropertyChangedEventArgs(nameof(NullableRef));
private static readonly PropertyChangedEventArgs _nullableStructChangedEventArgs = new PropertyChangedEventArgs(nameof(NullableStruct));
Expand Down
Loading

0 comments on commit b278bc2

Please sign in to comment.