|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
Roslyn.Diagnostics.Analyzers.DefaultableTypeShouldHaveDefaultableFieldsAnalyzer,
Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
namespace Roslyn.Diagnostics.Analyzers.UnitTests
{
public class DefaultableTypeShouldHaveDefaultableFieldsTests
{
private const string NonDefaultableAttribute = """
// <auto-generated/>
using System;
namespace Roslyn.Utilities {
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.GenericParameter)]
sealed class NonDefaultableAttribute : Attribute { }
}
""";
public static IEnumerable<object[]> DefaultableTypes
{
get
{
yield return new object[] { "int" };
yield return new object[] { "int?" };
yield return new object[] { "DateTime" };
yield return new object[] { "object?" };
yield return new object[] { "IFormattable?" };
yield return new object[] { "EventHandler?" };
yield return new object[] { "StringComparison" };
}
}
public static IEnumerable<object[]> DefaultableTypesNullableDisableContext
{
get
{
yield return new object[] { "int" };
yield return new object[] { "int?" };
yield return new object[] { "DateTime" };
yield return new object[] { "object" };
yield return new object[] { "IFormattable" };
yield return new object[] { "EventHandler" };
yield return new object[] { "StringComparison" };
}
}
public static IEnumerable<object[]> NonDefaultableTypes
{
get
{
yield return new object[] { "object" };
yield return new object[] { "IFormattable" };
yield return new object[] { "EventHandler" };
yield return new object[] { "NonDefaultableStruct" };
}
}
[Theory]
[MemberData(nameof(NonDefaultableTypes))]
public async Task TestNonDefaultableStructWithNonDefaultableTypeFieldAsync(string nonDefaultableType)
{
var code = $$"""
#nullable enable
using System;
using Roslyn.Utilities;
[NonDefaultable]
struct NonDefaultableStruct { }
[NonDefaultable]
struct NonDefaultableTestStruct {
{{nonDefaultableType}} field;
{{nonDefaultableType}} Property { get; }
static {{nonDefaultableType}} staticField = default!;
static {{nonDefaultableType}} StaticProperty { get; } = default!;
}
""";
await new VerifyCS.Test
{
LanguageVersion = LanguageVersion.CSharp8,
TestState = { Sources = { code, NonDefaultableAttribute } },
}.RunAsync();
}
[Theory]
[MemberData(nameof(NonDefaultableTypes))]
public async Task TestNonDefaultableStructWithNonDefaultableTypeNullableDisableFieldAsync(string nonDefaultableType)
{
var code = $$"""
#nullable disable
using System;
using Roslyn.Utilities;
[NonDefaultable]
struct NonDefaultableStruct { }
[NonDefaultable]
struct NonDefaultableTestStruct {
{{nonDefaultableType}} field;
{{nonDefaultableType}} Property { get; }
static {{nonDefaultableType}} staticField;
static {{nonDefaultableType}} StaticProperty { get; }
}
""";
await new VerifyCS.Test
{
LanguageVersion = LanguageVersion.CSharp8,
TestState = { Sources = { code, NonDefaultableAttribute } },
}.RunAsync();
}
[Theory]
[MemberData(nameof(DefaultableTypes))]
public async Task TestNonDefaultableStructWithDefaultableTypeFieldAsync(string defaultableType)
{
var code = $$"""
#nullable enable
using System;
using Roslyn.Utilities;
[NonDefaultable]
struct NonDefaultableTestStruct {
{{defaultableType}} field;
{{defaultableType}} Property { get; }
static {{defaultableType}} staticField;
static {{defaultableType}} StaticProperty { get; }
}
""";
await new VerifyCS.Test
{
LanguageVersion = LanguageVersion.CSharp8,
TestState = { Sources = { code, NonDefaultableAttribute } },
}.RunAsync();
}
[Theory]
[MemberData(nameof(DefaultableTypesNullableDisableContext))]
public async Task TestNonDefaultableStructWithDefaultableTypeNullableDisableFieldAsync(string defaultableType)
{
var code = $$"""
#nullable disable
using System;
using Roslyn.Utilities;
[NonDefaultable]
struct NonDefaultableTestStruct {
{{defaultableType}} field;
{{defaultableType}} Property { get; }
static {{defaultableType}} staticField;
static {{defaultableType}} StaticProperty { get; }
}
""";
await new VerifyCS.Test
{
LanguageVersion = LanguageVersion.CSharp8,
TestState = { Sources = { code, NonDefaultableAttribute } },
}.RunAsync();
}
[Theory]
[MemberData(nameof(DefaultableTypes))]
public async Task TestDefaultableStructWithDefaultableTypeFieldAsync(string defaultableType)
{
var code = $$"""
#nullable enable
using System;
struct DefaultableStruct {
{{defaultableType}} field;
{{defaultableType}} Property { get; }
static {{defaultableType}} staticField;
static {{defaultableType}} StaticProperty { get; }
}
""";
await new VerifyCS.Test
{
LanguageVersion = LanguageVersion.CSharp8,
TestState = { Sources = { code, NonDefaultableAttribute } },
}.RunAsync();
}
[Theory]
[MemberData(nameof(DefaultableTypes))]
public async Task TestClassWithDefaultableTypeFieldAsync(string defaultableType)
{
var code = $$"""
#nullable enable
using System;
class TestClass {
{{defaultableType}} field;
{{defaultableType}} Property { get; }
static {{defaultableType}} staticField;
static {{defaultableType}} StaticProperty { get; }
}
""";
await new VerifyCS.Test
{
LanguageVersion = LanguageVersion.CSharp8,
TestState = { Sources = { code, NonDefaultableAttribute } },
}.RunAsync();
}
[Theory]
[MemberData(nameof(DefaultableTypesNullableDisableContext))]
public async Task TestClassWithDefaultableTypeNullableDisableFieldAsync(string defaultableType)
{
var code = $$"""
#nullable disable
using System;
class TestClass {
{{defaultableType}} field;
{{defaultableType}} Property { get; }
static {{defaultableType}} staticField;
static {{defaultableType}} StaticProperty { get; }
}
""";
await new VerifyCS.Test
{
LanguageVersion = LanguageVersion.CSharp8,
TestState = { Sources = { code, NonDefaultableAttribute } },
}.RunAsync();
}
[Theory]
[MemberData(nameof(NonDefaultableTypes))]
public async Task TestDefaultableStructWithNonDefaultableTypeFieldAsync(string nonDefaultableType)
{
var code = $$"""
#nullable enable
using System;
using Roslyn.Utilities;
[NonDefaultable]
struct NonDefaultableStruct { }
struct DefaultableStruct {
{{nonDefaultableType}} [|field|];
{{nonDefaultableType}} [|Property|] { get; }
static {{nonDefaultableType}} StaticField = default!;
static {{nonDefaultableType}} StaticProperty { get; } = default!;
}
""";
await new VerifyCS.Test
{
LanguageVersion = LanguageVersion.CSharp8,
TestState = { Sources = { code, NonDefaultableAttribute } },
}.RunAsync();
}
[Theory]
[MemberData(nameof(NonDefaultableTypes))]
public async Task TestDefaultableStructWithNonDefaultableTypeNullableDisableFieldAsync(string nonDefaultableType)
{
var code = $$"""
#nullable disable
using System;
using Roslyn.Utilities;
[NonDefaultable]
struct NonDefaultableStruct { }
struct DefaultableStruct {
{{nonDefaultableType}} field;
{{nonDefaultableType}} Property { get; }
static {{nonDefaultableType}} StaticField;
static {{nonDefaultableType}} StaticProperty { get; }
}
""";
await new VerifyCS.Test
{
LanguageVersion = LanguageVersion.CSharp8,
TestState = { Sources = { code, NonDefaultableAttribute } },
}.RunAsync();
}
}
}
|