diff --git a/src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/TypedConstantInfo.cs b/src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/TypedConstantInfo.cs
index 4538afaf..da13fd42 100644
--- a/src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/TypedConstantInfo.cs
+++ b/src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/TypedConstantInfo.cs
@@ -134,10 +134,9 @@ public sealed record Enum(string TypeName, object Value) : TypedConstantInfo
///
public override ExpressionSyntax GetSyntax()
{
- return
- CastExpression(
- IdentifierName(TypeName),
- LiteralExpression(SyntaxKind.NumericLiteralExpression, ParseToken(Value.ToString())));
+ // 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()));
}
}
diff --git a/tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsCodegen.cs b/tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsCodegen.cs
index 0062d61d..6edc38b5 100644
--- a/tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsCodegen.cs
+++ b/tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsCodegen.cs
@@ -1283,6 +1283,278 @@ partial class MyViewModel
VerifyGenerateSources(source, new[] { new RelayCommandGenerator() }, ("MyApp.MyViewModel.Test.g.cs", result));
}
+ // See https://github.com/CommunityToolkit/dotnet/issues/681
+ [TestMethod]
+ public void ObservablePropertyWithForwardedAttributesWithEnumWithNegativeValue_WorksCorrectly()
+ {
+ string source = """
+ using System.ComponentModel;
+ using CommunityToolkit.Mvvm.ComponentModel;
+
+ #nullable enable
+
+ namespace MyApp;
+
+ partial class MyViewModel : ObservableObject
+ {
+ [ObservableProperty]
+ [property: DefaultValue(NegativeEnum1.Problem)]
+ [property: DefaultValue(NegativeEnum2.Problem)]
+ [property: DefaultValue(NegativeEnum3.Problem)]
+ [property: DefaultValue(NegativeEnum4.Problem)]
+ private object? a;
+ }
+
+ public class DefaultValueAttribute : Attribute
+ {
+ public DefaultValueAttribute(object value)
+ {
+ }
+ }
+
+ public enum NegativeEnum1
+ {
+ Problem = -1073741824,
+ OK = 0
+ }
+
+ public enum NegativeEnum2 : long
+ {
+ Problem = long.MinValue,
+ OK = 0
+ }
+
+ public enum NegativeEnum3 : short
+ {
+ Problem = -1234,
+ OK = 0
+ }
+
+ public enum NegativeEnum4 : sbyte
+ {
+ Problem = -1,
+ OK = 0
+ }
+ """;
+
+ string result = """
+ //
+ #pragma warning disable
+ #nullable enable
+ namespace MyApp
+ {
+ ///
+ partial class MyViewModel
+ {
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.2.0.0")]
+ [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)]
+ public object? A
+ {
+ get => a;
+ set
+ {
+ if (!global::System.Collections.Generic.EqualityComparer