Skip to content

Commit

Permalink
Merge pull request #736 from CommunityToolkit/dev/negative-forwarded-…
Browse files Browse the repository at this point in the history
…attributes

Fix forwarding enum values with negative values in attributes
  • Loading branch information
Sergio0694 committed Jul 21, 2023
2 parents e071ed2 + 9f7d0bd commit 1d98dba
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,17 @@ public sealed record Enum(string TypeName, object Value) : TypedConstantInfo
public override ExpressionSyntax GetSyntax()
{
// We let Roslyn parse the value expression, so that it can automatically handle both positive and negative values. This
// is needed because negative values have a different syntax tree (UnaryMinuxExpression holding the numeric expression).
return CastExpression(IdentifierName(TypeName), ParseExpression(Value.ToString()));
// is needed because negative values have a different syntax tree (UnaryMinusExpression holding the numeric expression).
ExpressionSyntax valueExpression = ParseExpression(Value.ToString());

// If the value is negative, we have to put parentheses around them (to avoid CS0075 errors)
if (valueExpression is PrefixUnaryExpressionSyntax unaryExpression && unaryExpression.IsKind(SyntaxKind.UnaryMinusExpression))
{
valueExpression = ParenthesizedExpression(valueExpression);
}

// Now we can safely return the cast expression for the target enum type (with optional parentheses if needed)
return CastExpression(IdentifierName(TypeName), valueExpression);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1349,10 +1349,10 @@ partial class MyViewModel
/// <inheritdoc cref="a"/>
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", <ASSEMBLY_VERSION>)]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)-1073741824)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)-9223372036854775808)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)-1234)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)-1)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)(-1073741824))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)(-9223372036854775808))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)(-1234))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)(-1))]
public object? A
{
get => a;
Expand Down Expand Up @@ -1489,24 +1489,24 @@ partial class MyViewModel
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", <ASSEMBLY_VERSION>)]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)0)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)-1073741824)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)(-1073741824))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)42)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)456)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)123)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)0)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)-9223372036854775808)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)(-9223372036854775808))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)42)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)456)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)123)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)1)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)-1234)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)(-1234))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)42)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)456)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)123)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)1)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)-1)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)(-1))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)42)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)-56)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)(-56))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)123)]
public object? A
{
Expand Down Expand Up @@ -1792,18 +1792,18 @@ partial class MyViewModel
{
/// <summary>The backing field for <see cref="TestCommand"/>.</summary>
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator", <ASSEMBLY_VERSION>)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)-1073741824)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)-9223372036854775808)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)-1234)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)-1)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)(-1073741824))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)(-9223372036854775808))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)(-1234))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)(-1))]
private global::CommunityToolkit.Mvvm.Input.RelayCommand? testCommand;
/// <summary>Gets an <see cref="global::CommunityToolkit.Mvvm.Input.IRelayCommand"/> instance wrapping <see cref="Test"/>.</summary>
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator", <ASSEMBLY_VERSION>)]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)-1073741824)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)-9223372036854775808)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)-1234)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)-1)]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum1)(-1073741824))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum2)(-9223372036854775808))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum3)(-1234))]
[global::MyApp.DefaultValueAttribute((global::MyApp.NegativeEnum4)(-1))]
public global::CommunityToolkit.Mvvm.Input.IRelayCommand TestCommand => testCommand ??= new global::CommunityToolkit.Mvvm.Input.RelayCommand(new global::System.Action(Test));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,23 @@ public void Test_ObservableProperty_MemberNotNullAttributeIsPresent()
}
#endif

// See https://github.com/CommunityToolkit/dotnet/issues/731
[TestMethod]
public void Test_ObservableProperty_ForwardedAttributesWithNegativeValues()
{
Assert.AreEqual(PositiveEnum.Something,
typeof(ModelWithForwardedAttributesWithNegativeValues)
.GetProperty(nameof(ModelWithForwardedAttributesWithNegativeValues.Test2))!
.GetCustomAttribute<DefaultValueAttribute>()!
.Value);

Assert.AreEqual(NegativeEnum.Problem,
typeof(ModelWithForwardedAttributesWithNegativeValues)
.GetProperty(nameof(ModelWithForwardedAttributesWithNegativeValues.Test3))!
.GetCustomAttribute<DefaultValueAttribute>()!
.Value);
}

public abstract partial class BaseViewModel : ObservableObject
{
public string? Content { get; set; }
Expand Down Expand Up @@ -1693,4 +1710,39 @@ public ModelWithNonNullableObservableProperty()
internal string name;
}
#endif

private partial class ModelWithForwardedAttributesWithNegativeValues : ObservableObject
{
[ObservableProperty]
private bool _test1;

[ObservableProperty]
[property: DefaultValue(PositiveEnum.Something)]
private PositiveEnum _test2;

[ObservableProperty]
[property: DefaultValue(NegativeEnum.Problem)]
private NegativeEnum _test3;

[ObservableProperty]
private int _test4;

public ModelWithForwardedAttributesWithNegativeValues()
{
Test1 = true;
Test2 = PositiveEnum.Else;
}
}

public enum PositiveEnum
{
Something = 0,
Else = 1
}

public enum NegativeEnum
{
Problem = -1,
OK = 0
}
}

0 comments on commit 1d98dba

Please sign in to comment.