Skip to content

Commit

Permalink
.NET 8 and C# 12: add repros and UTs for rules starting with R in Son…
Browse files Browse the repository at this point in the history
…arWay (#8093)
  • Loading branch information
antonioaversa authored Oct 2, 2023
1 parent d942723 commit 23f21a6
Show file tree
Hide file tree
Showing 10 changed files with 417 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ public void ParameterValidationInYieldShouldBeWrapped_CSharp11() =>
builder.AddPaths("ParameterValidationInYieldShouldBeWrapped.CSharp11.cs")
.WithOptions(ParseOptionsHelper.FromCSharp11)
.Verify();
#endif

#if NET8_0_OR_GREATER

[TestMethod]
public void ParameterValidationInYieldShouldBeWrapped_CSharp12() =>
builder.AddPaths("ParameterValidationInYieldShouldBeWrapped.CSharp12.cs")
.WithOptions(ParseOptionsHelper.FromCSharp12)
.Verify();

#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ public void RedundancyInConstructorDestructorDeclaration_CSharp10() =>
.WithOptions(ParseOptionsHelper.FromCSharp10)
.Verify();

[TestMethod]
public void RedundancyInConstructorDestructorDeclaration_CSharp12() =>
builder.AddPaths("RedundancyInConstructorDestructorDeclaration.CSharp12.cs")
.WithOptions(ParseOptionsHelper.FromCSharp12)
.Verify();

[TestMethod]
public void RedundancyInConstructorDestructorDeclaration_CodeFix_CSharp9() =>
codeFixBuilderRemoveBaseCall.AddPaths("RedundancyInConstructorDestructorDeclaration.CSharp9.cs")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ public void RedundantArgument_CSharp9() =>
.WithTopLevelStatements()
.Verify();

[TestMethod]
public void RedundantArgument_CSharp12() =>
builder.AddPaths("RedundantArgument.CSharp12.cs")
.WithOptions(ParseOptionsHelper.FromCSharp12)
.Verify();

#endif

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,30 @@ public void RedundantDeclaration_CSharp10_CodeFix_ExplicitDelegate() =>
.WithOptions(ParseOptionsHelper.FromCSharp10)
.VerifyCodeFix();

[TestMethod]
public void RedundantDeclaration_CSharp12() =>
builder.AddPaths("RedundantDeclaration.CSharp12.cs")
.WithOptions(ParseOptionsHelper.FromCSharp12)
.Verify();

[TestMethod]
public void RedundantDeclaration_CSharp12_CodeFix_ArraySize() =>
codeFixBuilder.AddPaths("RedundantDeclaration.CSharp12.cs")
.WithCodeFix<RedundantDeclarationCodeFix>()
.WithCodeFixTitle(RedundantDeclarationCodeFix.TitleRedundantArraySize)
.WithCodeFixedPaths("RedundantDeclaration.CSharp12.ArraySize.Fixed.cs")
.WithOptions(ParseOptionsHelper.FromCSharp12)
.VerifyCodeFix();

[TestMethod]
public void RedundantDeclaration_CSharp12_CodeFix_LambdaParameterType() =>
codeFixBuilder.AddPaths("RedundantDeclaration.CSharp12.cs")
.WithCodeFix<RedundantDeclarationCodeFix>()
.WithCodeFixTitle(RedundantDeclarationCodeFix.TitleRedundantLambdaParameterType)
.WithCodeFixedPaths("RedundantDeclaration.CSharp12.LambdaParameterType.Fixed.cs")
.WithOptions(ParseOptionsHelper.FromCSharp12)
.VerifyCodeFix();

#endif

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Collections;
using System.Collections.Generic;

class InlineArrays
{
IEnumerable<int> Invalid(Buffer? buffer) // Noncompliant
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer)); // Secondary

foreach (var item in new Buffer())
yield return item;
}

IEnumerable<int> Valid(Buffer? buffer) // Compliant
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
return Generator(buffer.Value);

IEnumerable<int> Generator(Buffer buffer)
{
foreach (var item in buffer)
yield return item;
}
}

[System.Runtime.CompilerServices.InlineArray(10)]
struct Buffer
{
int arrayItem;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// https://github.com/SonarSource/sonar-dotnet/issues/8092
namespace Repro_8092
{
namespace PrimaryParameterlessConstructor
{
class AClassWithBody() { } // FN
class AClassWithoutBody(); // FN
struct AStructWithBody() { } // FN
struct AStructWithoutBody(); // FN
record ARecordWithBody() { } // FN
record ARecordWithoutBody(); // FN
record struct ARecordStructWithBody() { } // FN
record struct ARecordStructWithoutBody(); // FN

// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/constructor-errors?f1url=%3FappId%3Droslyn%26k%3Dk(CS8983)#constructors-in-struct-types
namespace FieldInitializerInStructRequiresConstructor
{
struct AStructWithFieldInitializer() // Compliant
{
public int aField = 42;
}

struct AStructWithPropertyInitializer() // Compliant
{
public int AProperty { get; } = 42;
}

record struct ARecordStructWithFieldInitializer() // Compliant
{
public int aField = 42;
}
}

namespace FieldInitializerInClassDontRequireConstructor
{
class AClassWithFieldInitializer() // FN
{
public int aField = 42;
}

class AClassWithPropertyInitializer() // FN
{
public int AProperty { get; } = 42;
}

class ARecordWithFieldInitializer() // FN
{
public int aField = 42;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;

class DefaultLambdaParameters
{
void SingleDefaultArgument()
{
var f = (int i = 42) => i;
f(); // Compliant
f(40); // Compliant
f(42); // Noncompliant
f(41 + 1); // Noncompliant, expression results into the default value
}

void MultipleDefaultArguments()
{
var f = (int i = 41, int j = 42) => i + j;
f(); // Compliant
f(42); // Compliant
f(42, 42); // Noncompliant
f(41, 42); // Multiple violations
//^^
// ^^@-1
}

void NamedArguments()
{
var f = (int i = 41, int j = 42, int z = 43) => i;
f(i: 42); // Error CS1746 The delegate '<anonymous delegate>' does not have a parameter named 'i'
}
}

// https://github.com/SonarSource/sonar-dotnet/issues/8096
namespace Repro_8096
{
class PrimaryConstructors
{
void SingleDefaultArgument()
{
_ = new C1(); // Compliant
_ = new C1(41); // Compliant
_ = new C1(42); // FN
_ = new C1(41 + 1); // FN, expression results into the default value
}

void MultipleDefaultArguments()
{
_ = new C1(); // Compliant
_ = new C2(42); // Compliant
_ = new C2(42, 42); // FN
_ = new C2(41, 42); // FN, multiple violations
}

void NamedArguments()
{
_ = new C2(j: 42); // FN
}

class C1(int i = 42);
class C2(int i = 41, int j = 42);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;

namespace AliasAnyType
{
using Int = int;
using IntArray = int[];
using IntNullable = int?;
using Point = (int x, int y);
using ThreeInts = int[3]; // Error [CS0270]: Array size cannot be specified in a variable declaration
using IntToIntFunc = Func<int, int>;

class AClass
{
void AliasWithArraySize()
{
IntArray a1 = new Int[] { 1, 2, 3 }; // Fixed
}

void AliasWithUnnecessaryType()
{
IntToIntFunc f = (Int i) => i; // Fixed
}

void AliasWithInitializer()
{
IntArray a1 = new IntArray { }; // Error [CS8386]: Invalid object creation
var a2 = new IntArray { }; // Error [CS8386]: Invalid object creation
int[] a3 = new IntArray(); // Error [CS8386]: Invalid object creation
}

void AliasWithEmptyParamsList()
{
IntArray a1 = new IntArray(); // Error [CS8386]: Invalid object creation
var a2 = new IntArray(); // Error [CS8386]: Invalid object creation
int[] a3 = new IntArray(); // Error [CS8386]: Invalid object creation
}
}
}

// https://github.com/SonarSource/sonar-dotnet/issues/8115
namespace Repro_8115
{
class CollectionExpressions
{
void ExplicitTypeDeclaration()
{
int[] a1 = [1, 2, 3]; // Compliant
a1 = [1, 2, 3]; // Compliant, reassignment
int[] a2 = new[] { 1, 2, 3 }; // FN, can be written as [1, 2, 3]
a2 = new[] { 1, 2, 3 }; // FN, can be written as [1, 2, 3], reassignment
}

void VarDeclarationWithInlineAssignment()
{
var invalid = [1, 2, 3]; // Error CS9176 There is no target type for the collection expression.
}

void VarDeclarationWithReassignment()
{
var typeInferredAndReassigned = new[] { 1, 2, 3 }; // Compliant, cannot be written as [1, 2, 3]
typeInferredAndReassigned = new[] { 1, 2, 3 }; // FN, can be written as [1, 2, 3], reassignment of a type-inferred variable
typeInferredAndReassigned = new int[] { 1, 2, 3 }; // Fixed
typeInferredAndReassigned = []; // Compliant
typeInferredAndReassigned = new int[] { }; // FN, can be written as []
}

void VarDeclarationWithReassignmentToEmptyCollection()
{
var typeInferredAndReassigned = new[] { 1, 2, 3 };
typeInferredAndReassigned = new[] { }; // Error CS0826 No best type found for implicitly-typed array
// Error@-1 CS0029 Cannot implicitly convert type '?[]' to 'int[]'
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;

namespace AliasAnyType
{
using Int = int;
using IntArray = int[];
using IntNullable = int?;
using Point = (int x, int y);
using ThreeInts = int[3]; // Error [CS0270]: Array size cannot be specified in a variable declaration
using IntToIntFunc = Func<int, int>;

class AClass
{
void AliasWithArraySize()
{
IntArray a1 = new Int[3] { 1, 2, 3 }; // Fixed
}

void AliasWithUnnecessaryType()
{
IntToIntFunc f = (i) => i; // Fixed
}

void AliasWithInitializer()
{
IntArray a1 = new IntArray { }; // Error [CS8386]: Invalid object creation
var a2 = new IntArray { }; // Error [CS8386]: Invalid object creation
int[] a3 = new IntArray(); // Error [CS8386]: Invalid object creation
}

void AliasWithEmptyParamsList()
{
IntArray a1 = new IntArray(); // Error [CS8386]: Invalid object creation
var a2 = new IntArray(); // Error [CS8386]: Invalid object creation
int[] a3 = new IntArray(); // Error [CS8386]: Invalid object creation
}
}
}

// https://github.com/SonarSource/sonar-dotnet/issues/8115
namespace Repro_8115
{
class CollectionExpressions
{
void ExplicitTypeDeclaration()
{
int[] a1 = [1, 2, 3]; // Compliant
a1 = [1, 2, 3]; // Compliant, reassignment
int[] a2 = new[] { 1, 2, 3 }; // FN, can be written as [1, 2, 3]
a2 = new[] { 1, 2, 3 }; // FN, can be written as [1, 2, 3], reassignment
}

void VarDeclarationWithInlineAssignment()
{
var invalid = [1, 2, 3]; // Error CS9176 There is no target type for the collection expression.
}

void VarDeclarationWithReassignment()
{
var typeInferredAndReassigned = new[] { 1, 2, 3 }; // Compliant, cannot be written as [1, 2, 3]
typeInferredAndReassigned = new[] { 1, 2, 3 }; // FN, can be written as [1, 2, 3], reassignment of a type-inferred variable
typeInferredAndReassigned = new int[] { 1, 2, 3 }; // Fixed
typeInferredAndReassigned = []; // Compliant
typeInferredAndReassigned = new int[] { }; // FN, can be written as []
}

void VarDeclarationWithReassignmentToEmptyCollection()
{
var typeInferredAndReassigned = new[] { 1, 2, 3 };
typeInferredAndReassigned = new[] { }; // Error CS0826 No best type found for implicitly-typed array
// Error@-1 CS0029 Cannot implicitly convert type '?[]' to 'int[]'
}
}
}
Loading

0 comments on commit 23f21a6

Please sign in to comment.