|
// 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();
}
}
}
|