Skip to content

Commit

Permalink
Handle more explicit 'null'-s in code fixer, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 committed Jan 2, 2025
1 parent 76d17fe commit 8782e14
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,12 @@ void HandleSetAccessor(IPropertySymbol propertySymbol, PropertyFlags propertyFla
{
// This is only allowed for reference or nullable types. This 'null' is redundant, but support it nonetheless.
// It's not that uncommon for especially legacy codebases to have this kind of pattern in dependency properties.
// If the type is not actually nullable, make it explicit. This still allows rewriting the property to use the
// attribute, but it will cause the other analyzer to emit a diagnostic. This guarantees that even in this case,
// the original semantics are preserved (and developers can fix the code), rather than the fixer altering things.
if (!propertyTypeSymbol.IsReferenceType && !isNullableValueType)
{
return;
fieldFlags.DefaultValue = TypedConstantInfo.Null.Instance;
}
}
else if (TypedConstantInfo.TryCreate(conversionOperation.Operand, out fieldFlags.DefaultValue))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2226,4 +2226,154 @@ public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject

await test.RunAsync();
}

[TestMethod]
[DataRow("string?", "string", "")]
[DataRow("int", "int", "")]
[DataRow("int?", "int?", "")]
[DataRow("T1?", "T1", "")]
[DataRow("T2", "T2", "(DefaultValue = null)")]
[DataRow("T2?", "T2", "(DefaultValue = null)")]
[DataRow("T4", "T4", "(DefaultValue = null)")]
[DataRow("T4?", "T4?", "")]
[DataRow("T5", "T5", "(DefaultValue = null)")]
[DataRow("T5?", "T5", "(DefaultValue = null)")]
public async Task SimpleProperty_WithinGenericType_WithNullMetadata(
string declaredType,
string propertyType,
string attributeArguments)
{
string original = $$"""
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#nullable enable
namespace MyApp;
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
where T1 : class
where T3 : T2, new()
where T4 : unmanaged
where T5 : IDisposable
{
public static readonly DependencyProperty NameProperty = DependencyProperty.Register(
nameof(Name),
typeof({{propertyType}}),
typeof(MyObject<T1, T2, T3, T4, T5>),
null);
public {{declaredType}} [|Name|]
{
get => ({{declaredType}})GetValue(NameProperty);
set => SetValue(NameProperty, value);
}
}
""";

string @fixed = $$"""
using System;
using CommunityToolkit.WinUI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#nullable enable
namespace MyApp;
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
where T1 : class
where T3 : T2, new()
where T4 : unmanaged
where T5 : IDisposable
{
[GeneratedDependencyProperty{{attributeArguments}}]
public partial {{declaredType}} {|CS9248:Name|} { get; set; }
}
""";

CSharpCodeFixTest test = new(LanguageVersion.Preview)
{
TestCode = original,
FixedCode = @fixed
};

await test.RunAsync();
}

[TestMethod]
[DataRow("string?", "string", "")]
[DataRow("int", "int", "(DefaultValue = null)")]
[DataRow("int?", "int?", "")]
[DataRow("T1?", "T1", "")]
[DataRow("T2", "T2", "(DefaultValue = null)")]
[DataRow("T2?", "T2", "(DefaultValue = null)")]
[DataRow("T4", "T4", "(DefaultValue = null)")]
[DataRow("T4?", "T4?", "")]
[DataRow("T5", "T5", "(DefaultValue = null)")]
[DataRow("T5?", "T5", "(DefaultValue = null)")]
public async Task SimpleProperty_WithinGenericType_WithExplicitNullDefaultValue(
string declaredType,
string propertyType,
string attributeArguments)
{
string original = $$"""
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#nullable enable
namespace MyApp;
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
where T1 : class
where T3 : T2, new()
where T4 : unmanaged
where T5 : IDisposable
{
public static readonly DependencyProperty NameProperty = DependencyProperty.Register(
nameof(Name),
typeof({{propertyType}}),
typeof(MyObject<T1, T2, T3, T4, T5>),
new PropertyMetadata(null));
public {{declaredType}} [|Name|]
{
get => ({{declaredType}})GetValue(NameProperty);
set => SetValue(NameProperty, value);
}
}
""";

string @fixed = $$"""
using System;
using CommunityToolkit.WinUI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
#nullable enable
namespace MyApp;
public partial class MyObject<T1, T2, T3, T4, T5> : DependencyObject
where T1 : class
where T3 : T2, new()
where T4 : unmanaged
where T5 : IDisposable
{
[GeneratedDependencyProperty{{attributeArguments}}]
public partial {{declaredType}} {|CS9248:Name|} { get; set; }
}
""";

CSharpCodeFixTest test = new(LanguageVersion.Preview)
{
TestCode = original,
FixedCode = @fixed
};

await test.RunAsync();
}
}

0 comments on commit 8782e14

Please sign in to comment.