Skip to content

Commit 63ba418

Browse files
authored
Merge pull request #603 from CommunityToolkit/dev/fix-double-attribute-params
Fix forwarded double attribute parameters
2 parents af3cb96 + b4b2227 commit 63ba418

File tree

2 files changed

+107
-1
lines changed

2 files changed

+107
-1
lines changed

src/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/TypedConstantInfo.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using System.Globalization;
67
using System.Linq;
78
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
89
using Microsoft.CodeAnalysis;
@@ -89,7 +90,13 @@ public override ExpressionSyntax GetSyntax()
8990
{
9091
byte b => Literal(b),
9192
char c => Literal(c),
92-
double d => Literal(d),
93+
94+
// For doubles, we need to manually format it and always add the trailing "D" suffix.
95+
// This ensures that the correct type is produced if the expression was assigned to
96+
// an object (eg. the literal was used in an attribute object parameter/property).
97+
double d => Literal(d.ToString("R", CultureInfo.InvariantCulture) + "D", d),
98+
99+
// For floats, Roslyn will automatically add the "F" suffix, so no extra work is needed
93100
float f => Literal(f),
94101
int i => Literal(i),
95102
long l => Literal(l),

tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsCodegen.cs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,105 @@ public string Name
9494
VerifyGenerateSources(source, new[] { new ObservablePropertyGenerator() }, ("MyApp.MyViewModel.g.cs", result));
9595
}
9696

97+
// See https://github.com/CommunityToolkit/dotnet/issues/601
98+
[TestMethod]
99+
public void ObservablePropertyWithForwardedAttributesWithNumberLiterals_PreservesType()
100+
{
101+
string source = """
102+
using System.ComponentModel;
103+
using CommunityToolkit.Mvvm.ComponentModel;
104+
105+
#nullable enable
106+
107+
namespace MyApp;
108+
109+
partial class MyViewModel : ObservableObject
110+
{
111+
const double MyDouble = 3.14;
112+
const float MyFloat = 3.14f;
113+
114+
[ObservableProperty]
115+
[property: DefaultValue(0.0)]
116+
[property: DefaultValue(1.24)]
117+
[property: DefaultValue(0.0f)]
118+
[property: DefaultValue(0.0f)]
119+
[property: DefaultValue(MyDouble)]
120+
[property: DefaultValue(MyFloat)]
121+
private object? a;
122+
}
123+
124+
public class DefaultValueAttribute : Attribute
125+
{
126+
public DefaultValueAttribute(object value)
127+
{
128+
}
129+
}
130+
""";
131+
132+
string result = """
133+
// <auto-generated/>
134+
#pragma warning disable
135+
#nullable enable
136+
namespace MyApp
137+
{
138+
partial class MyViewModel
139+
{
140+
/// <inheritdoc cref="a"/>
141+
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.1.0.0")]
142+
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
143+
[global::MyApp.DefaultValueAttribute(0D)]
144+
[global::MyApp.DefaultValueAttribute(1.24D)]
145+
[global::MyApp.DefaultValueAttribute(0F)]
146+
[global::MyApp.DefaultValueAttribute(0F)]
147+
[global::MyApp.DefaultValueAttribute(3.14D)]
148+
[global::MyApp.DefaultValueAttribute(3.14F)]
149+
public object? A
150+
{
151+
get => a;
152+
set
153+
{
154+
if (!global::System.Collections.Generic.EqualityComparer<object?>.Default.Equals(a, value))
155+
{
156+
OnAChanging(value);
157+
OnAChanging(default, value);
158+
OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.A);
159+
a = value;
160+
OnAChanged(value);
161+
OnAChanged(default, value);
162+
OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.A);
163+
}
164+
}
165+
}
166+
167+
/// <summary>Executes the logic for when <see cref="A"/> is changing.</summary>
168+
/// <param name="value">The new property value being set.</param>
169+
/// <remarks>This method is invoked right before the value of <see cref="A"/> is changed.</remarks>
170+
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.1.0.0")]
171+
partial void OnAChanging(object? value);
172+
/// <summary>Executes the logic for when <see cref="A"/> is changing.</summary>
173+
/// <param name="oldValue">The previous property value that is being replaced.</param>
174+
/// <param name="newValue">The new property value being set.</param>
175+
/// <remarks>This method is invoked right before the value of <see cref="A"/> is changed.</remarks>
176+
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.1.0.0")]
177+
partial void OnAChanging(object? oldValue, object? newValue);
178+
/// <summary>Executes the logic for when <see cref="A"/> just changed.</summary>
179+
/// <param name="value">The new property value that was set.</param>
180+
/// <remarks>This method is invoked right after the value of <see cref="A"/> is changed.</remarks>
181+
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.1.0.0")]
182+
partial void OnAChanged(object? value);
183+
/// <summary>Executes the logic for when <see cref="A"/> just changed.</summary>
184+
/// <param name="oldValue">The previous property value that was replaced.</param>
185+
/// <param name="newValue">The new property value that was set.</param>
186+
/// <remarks>This method is invoked right after the value of <see cref="A"/> is changed.</remarks>
187+
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.1.0.0")]
188+
partial void OnAChanged(object? oldValue, object? newValue);
189+
}
190+
}
191+
""";
192+
193+
VerifyGenerateSources(source, new[] { new ObservablePropertyGenerator() }, ("MyApp.MyViewModel.g.cs", result));
194+
}
195+
97196
/// <summary>
98197
/// Generates the requested sources
99198
/// </summary>

0 commit comments

Comments
 (0)