Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix DateOnly / TimeOnly parameters is TestCaseUsage #821

Merged
merged 6 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ private static IEnumerable<TestCaseData> GetTestData()
SetName("CanAssignToWhenParameterIsVersionAndArgumentIsValidString");
yield return new TestCaseData("\"a.b.c.d\"", "Version", "object", Is.True).
SetName("CanAssignToWhenParameterIsVersionAndArgumentIsInValidString");
#if NET6_0_OR_GREATER
yield return new TestCaseData("\"00:03:00\"", "TimeOnly", "string", Is.True).
SetName("CanAssignToWhenParameterIsTimeSpanAndArgumentIsValidString");
yield return new TestCaseData("\"2020-05-08\"", "DateOnly", "string", Is.True).
SetName("CanAssignToWhenParameterIsDateTimeAndArgumentIsValidString");
#endif
}

private static async Task<(TypedConstant argumentConstant, ITypeSymbol typeSymbol, Compilation compilation)>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ private static IEnumerable<TestCaseData> SpecialConversions
}
}

#if NET6_0_OR_GREATER
private static IEnumerable<TestCaseData> SpecialConversions_NET6
{
get
{
yield return new TestCaseData("2019-10-10", typeof(DateOnly));
yield return new TestCaseData("23:59:59", typeof(TimeOnly));
}
}
#endif

[Test]
public void VerifySupportedDiagnostics()
{
Expand Down Expand Up @@ -756,6 +767,20 @@ public void TestWithGenericParameter<T>(T arg1) { }
RoslynAssert.Valid(this.analyzer, testCode);
}

#if NET6_0_OR_GREATER
[TestCaseSource(nameof(SpecialConversions_NET6))]
public void AnalyzeWhenArgumentIsSpecialConversionNET6(string value, Type targetType)
{
var testCode = TestUtility.WrapClassInNamespaceAndAddUsing($@"
public sealed class AnalyzeWhenArgumentIsSpecialConversion
{{
[TestCase(""{value}"")]
public void Test({targetType.Name} a) {{ }}
}}");
RoslynAssert.Valid(this.analyzer, testCode);
}
#endif

#if NUNIT4
#if NET6_0_OR_GREATER
[Test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,37 @@ internal static class AttributeArgumentTypedConstantExtensions

// Intrinsic type converters for types
// https://github.com/dotnet/runtime/blob/master/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs
// For converters that exist in .NET Standard 1.6 we use the converter.
// For converters that exist in .NET Standard 2.0 we use the converter.
// Otherwise, we assume that the converter exists and it can convert the value.
private static readonly List<(Type type, Lazy<TypeConverter>? typeConverter)> IntrinsicTypeConverters =
private static readonly List<(string fullName, Lazy<TypeConverter>? typeConverter)> IntrinsicTypeConverters =
new()
{
(typeof(bool), new Lazy<TypeConverter>(() => new BooleanConverter())),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated mapping per TypeConverter updates:
https://github.com/dotnet/runtime/blob/main/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/ReflectTypeDescriptionProvider.cs#L154

Had to update it to string from Type, as netstandard2.0 does not have DateTime/DateOnly/etc types.

(typeof(byte), new Lazy<TypeConverter>(() => new ByteConverter())),
(typeof(sbyte), new Lazy<TypeConverter>(() => new SByteConverter())),
(typeof(char), new Lazy<TypeConverter>(() => new CharConverter())),
(typeof(double), new Lazy<TypeConverter>(() => new DoubleConverter())),
(typeof(string), new Lazy<TypeConverter>(() => new StringConverter())),
(typeof(int), new Lazy<TypeConverter>(() => new Int32Converter())),
(typeof(short), new Lazy<TypeConverter>(() => new Int16Converter())),
(typeof(long), new Lazy<TypeConverter>(() => new Int64Converter())),
(typeof(float), new Lazy<TypeConverter>(() => new SingleConverter())),
(typeof(ushort), new Lazy<TypeConverter>(() => new UInt16Converter())),
(typeof(uint), new Lazy<TypeConverter>(() => new UInt32Converter())),
(typeof(ulong), new Lazy<TypeConverter>(() => new UInt64Converter())),
(typeof(CultureInfo), null),
(typeof(DateTime), new Lazy<TypeConverter>(() => new DateTimeConverter())),
(typeof(DateTimeOffset), new Lazy<TypeConverter>(() => new DateTimeOffsetConverter())),
(typeof(decimal), new Lazy<TypeConverter>(() => new DecimalConverter())),
(typeof(TimeSpan), new Lazy<TypeConverter>(() => new TimeSpanConverter())),
(typeof(Guid), new Lazy<TypeConverter>(() => new GuidConverter())),
(typeof(Uri), new Lazy<TypeConverter>(() => new UriTypeConverter())),
(typeof(Version), null),
("System.Boolean", new Lazy<TypeConverter>(() => new BooleanConverter())),
("System.Byte", new Lazy<TypeConverter>(() => new ByteConverter())),
("System.SByte", new Lazy<TypeConverter>(() => new SByteConverter())),
("System.Char", new Lazy<TypeConverter>(() => new CharConverter())),
("System.Double", new Lazy<TypeConverter>(() => new DoubleConverter())),
("System.String", new Lazy<TypeConverter>(() => new StringConverter())),
("System.Int32", new Lazy<TypeConverter>(() => new Int32Converter())),
("System.Int16", new Lazy<TypeConverter>(() => new Int16Converter())),
("System.Int64", new Lazy<TypeConverter>(() => new Int64Converter())),
("System.Int128", null),
("System.Half", null),
("System.Single", new Lazy<TypeConverter>(() => new SingleConverter())),
("System.UInt16", new Lazy<TypeConverter>(() => new UInt16Converter())),
("System.UInt32", new Lazy<TypeConverter>(() => new UInt32Converter())),
("System.UInt64", new Lazy<TypeConverter>(() => new UInt64Converter())),
("System.UInt128", null),
("System.Globalization.CultureInfo", null),
("System.DateTime", new Lazy<TypeConverter>(() => new DateTimeConverter())),
("System.DateTimeOffset", new Lazy<TypeConverter>(() => new DateTimeOffsetConverter())),
("System.DateOnly", null),
("System.Decimal", new Lazy<TypeConverter>(() => new DecimalConverter())),
("System.TimeOnly", null),
("System.TimeSpan", new Lazy<TypeConverter>(() => new TimeSpanConverter())),
("System.Guid", new Lazy<TypeConverter>(() => new GuidConverter())),
("System.Uri", new Lazy<TypeConverter>(() => new UriTypeConverter())),
("System.Version", null)
};

internal static bool CanAssignTo(this TypedConstant @this, ITypeSymbol target, Compilation compilation,
Expand Down Expand Up @@ -214,7 +219,7 @@ private static bool CanBeTranslatedByTypeConverter(
Compilation compilation)
{
var typeName = targetTypeSymbol.GetFullMetadataName();
var targetType = IntrinsicTypeConverters.FirstOrDefault(t => t.type.FullName == typeName);
var targetType = IntrinsicTypeConverters.FirstOrDefault(t => t.fullName == typeName);

if (targetType != default)
{
Expand Down Expand Up @@ -254,7 +259,7 @@ private static bool CanBeTranslatedByTypeConverter(
return false;
}

#endregion
#endregion

#pragma warning disable SA1202 // Elements should be ordered by access. Prefer grouping
internal static ImmutableArray<TypedConstant> AdjustArguments(this ImmutableArray<TypedConstant> attributePositionalArguments)
Expand Down
1 change: 0 additions & 1 deletion src/nunit.analyzers/nunit.analyzers.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
<PackageReference Include="Nullable" Version="1.3.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.11.0" />
<PackageReference Include="System.ComponentModel.TypeConverter" Version="4.3.0" />
</ItemGroup>

</Project>
Loading