Skip to content

Commit 8782e14

Browse files
committed
Handle more explicit 'null'-s in code fixer, add tests
1 parent 76d17fe commit 8782e14

File tree

2 files changed

+154
-1
lines changed

2 files changed

+154
-1
lines changed

components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.SourceGenerators/Diagnostics/Analyzers/UseGeneratedDependencyPropertyOnManualPropertyAnalyzer.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,9 +460,12 @@ void HandleSetAccessor(IPropertySymbol propertySymbol, PropertyFlags propertyFla
460460
{
461461
// This is only allowed for reference or nullable types. This 'null' is redundant, but support it nonetheless.
462462
// It's not that uncommon for especially legacy codebases to have this kind of pattern in dependency properties.
463+
// If the type is not actually nullable, make it explicit. This still allows rewriting the property to use the
464+
// attribute, but it will cause the other analyzer to emit a diagnostic. This guarantees that even in this case,
465+
// the original semantics are preserved (and developers can fix the code), rather than the fixer altering things.
463466
if (!propertyTypeSymbol.IsReferenceType && !isNullableValueType)
464467
{
465-
return;
468+
fieldFlags.DefaultValue = TypedConstantInfo.Null.Instance;
466469
}
467470
}
468471
else if (TypedConstantInfo.TryCreate(conversionOperation.Operand, out fieldFlags.DefaultValue))

components/DependencyPropertyGenerator/CommunityToolkit.DependencyPropertyGenerator.Tests/Test_UseGeneratedDependencyPropertyOnManualPropertyCodeFixer.cs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,4 +2226,154 @@ public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
22262226

22272227
await test.RunAsync();
22282228
}
2229+
2230+
[TestMethod]
2231+
[DataRow("string?", "string", "")]
2232+
[DataRow("int", "int", "")]
2233+
[DataRow("int?", "int?", "")]
2234+
[DataRow("T1?", "T1", "")]
2235+
[DataRow("T2", "T2", "(DefaultValue = null)")]
2236+
[DataRow("T2?", "T2", "(DefaultValue = null)")]
2237+
[DataRow("T4", "T4", "(DefaultValue = null)")]
2238+
[DataRow("T4?", "T4?", "")]
2239+
[DataRow("T5", "T5", "(DefaultValue = null)")]
2240+
[DataRow("T5?", "T5", "(DefaultValue = null)")]
2241+
public async Task SimpleProperty_WithinGenericType_WithNullMetadata(
2242+
string declaredType,
2243+
string propertyType,
2244+
string attributeArguments)
2245+
{
2246+
string original = $$"""
2247+
using System;
2248+
using Windows.UI.Xaml;
2249+
using Windows.UI.Xaml.Controls;
2250+
2251+
#nullable enable
2252+
2253+
namespace MyApp;
2254+
2255+
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
2256+
where T1 : class
2257+
where T3 : T2, new()
2258+
where T4 : unmanaged
2259+
where T5 : IDisposable
2260+
{
2261+
public static readonly DependencyProperty NameProperty = DependencyProperty.Register(
2262+
nameof(Name),
2263+
typeof({{propertyType}}),
2264+
typeof(MyObject<T1, T2, T3, T4, T5>),
2265+
null);
2266+
2267+
public {{declaredType}} [|Name|]
2268+
{
2269+
get => ({{declaredType}})GetValue(NameProperty);
2270+
set => SetValue(NameProperty, value);
2271+
}
2272+
}
2273+
""";
2274+
2275+
string @fixed = $$"""
2276+
using System;
2277+
using CommunityToolkit.WinUI;
2278+
using Windows.UI.Xaml;
2279+
using Windows.UI.Xaml.Controls;
2280+
2281+
#nullable enable
2282+
2283+
namespace MyApp;
2284+
2285+
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
2286+
where T1 : class
2287+
where T3 : T2, new()
2288+
where T4 : unmanaged
2289+
where T5 : IDisposable
2290+
{
2291+
[GeneratedDependencyProperty{{attributeArguments}}]
2292+
public partial {{declaredType}} {|CS9248:Name|} { get; set; }
2293+
}
2294+
""";
2295+
2296+
CSharpCodeFixTest test = new(LanguageVersion.Preview)
2297+
{
2298+
TestCode = original,
2299+
FixedCode = @fixed
2300+
};
2301+
2302+
await test.RunAsync();
2303+
}
2304+
2305+
[TestMethod]
2306+
[DataRow("string?", "string", "")]
2307+
[DataRow("int", "int", "(DefaultValue = null)")]
2308+
[DataRow("int?", "int?", "")]
2309+
[DataRow("T1?", "T1", "")]
2310+
[DataRow("T2", "T2", "(DefaultValue = null)")]
2311+
[DataRow("T2?", "T2", "(DefaultValue = null)")]
2312+
[DataRow("T4", "T4", "(DefaultValue = null)")]
2313+
[DataRow("T4?", "T4?", "")]
2314+
[DataRow("T5", "T5", "(DefaultValue = null)")]
2315+
[DataRow("T5?", "T5", "(DefaultValue = null)")]
2316+
public async Task SimpleProperty_WithinGenericType_WithExplicitNullDefaultValue(
2317+
string declaredType,
2318+
string propertyType,
2319+
string attributeArguments)
2320+
{
2321+
string original = $$"""
2322+
using System;
2323+
using Windows.UI.Xaml;
2324+
using Windows.UI.Xaml.Controls;
2325+
2326+
#nullable enable
2327+
2328+
namespace MyApp;
2329+
2330+
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
2331+
where T1 : class
2332+
where T3 : T2, new()
2333+
where T4 : unmanaged
2334+
where T5 : IDisposable
2335+
{
2336+
public static readonly DependencyProperty NameProperty = DependencyProperty.Register(
2337+
nameof(Name),
2338+
typeof({{propertyType}}),
2339+
typeof(MyObject<T1, T2, T3, T4, T5>),
2340+
new PropertyMetadata(null));
2341+
2342+
public {{declaredType}} [|Name|]
2343+
{
2344+
get => ({{declaredType}})GetValue(NameProperty);
2345+
set => SetValue(NameProperty, value);
2346+
}
2347+
}
2348+
""";
2349+
2350+
string @fixed = $$"""
2351+
using System;
2352+
using CommunityToolkit.WinUI;
2353+
using Windows.UI.Xaml;
2354+
using Windows.UI.Xaml.Controls;
2355+
2356+
#nullable enable
2357+
2358+
namespace MyApp;
2359+
2360+
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
2361+
where T1 : class
2362+
where T3 : T2, new()
2363+
where T4 : unmanaged
2364+
where T5 : IDisposable
2365+
{
2366+
[GeneratedDependencyProperty{{attributeArguments}}]
2367+
public partial {{declaredType}} {|CS9248:Name|} { get; set; }
2368+
}
2369+
""";
2370+
2371+
CSharpCodeFixTest test = new(LanguageVersion.Preview)
2372+
{
2373+
TestCode = original,
2374+
FixedCode = @fixed
2375+
};
2376+
2377+
await test.RunAsync();
2378+
}
22292379
}

0 commit comments

Comments
 (0)