-
Notifications
You must be signed in to change notification settings - Fork 227
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b0d5c07
commit c0ca608
Showing
2 changed files
with
197 additions
and
60 deletions.
There are no files selected for viewing
148 changes: 144 additions & 4 deletions
148
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/CastShouldNotBeDuplicated.CSharp12.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,150 @@ | ||
using System.Collections.Generic; | ||
using System; | ||
using System.Collections.Generic; | ||
using Person = (string name, string surname); | ||
|
||
class MyClass | ||
class WithAliasAnyType | ||
{ | ||
void AliasType(Person person) | ||
void ValidCases(Person person) | ||
{ | ||
var a = (Person)person; // FN | ||
_ = (Person)person; // Compliant: not a duplicated cast | ||
} | ||
|
||
void InvalidCases(object obj) | ||
{ | ||
if (obj is Person) // FN: Person is alias for a struct | ||
{ | ||
_ = (Person)obj; | ||
} | ||
|
||
if (obj is (string, string)) // FN: (string, string) and Person are equivalent | ||
{ | ||
_ = (Person)obj; | ||
} | ||
|
||
if (obj is Person) // FN: Person and (string, string) are equivalent | ||
{ | ||
_ = ((string, string))obj; | ||
} | ||
|
||
if (obj is Person) // FN: Person and (string ..., string) are equivalent | ||
{ | ||
_ = ((string differentName1, string))obj; | ||
} | ||
|
||
if (obj is Person) // FN: Person and (string, string ...) are equivalent | ||
{ | ||
_ = ((string, string differentName2))obj; | ||
} | ||
|
||
if (obj is (string differentName1, string)) // FN: (string ..., string) and Person are equivalent | ||
{ | ||
_ = (Person)obj; | ||
} | ||
|
||
if (obj is (string, string differentName2)) // FN: (string, string ...) and Person are equivalent | ||
{ | ||
_ = (Person)obj; | ||
} | ||
} | ||
} | ||
|
||
// https://github.com/SonarSource/sonar-dotnet/issues/223 | ||
class Repro_223 | ||
{ | ||
void NumericTypes(object obj) | ||
{ | ||
if (obj is int) // FN | ||
{ | ||
_ = (int)obj; | ||
} | ||
|
||
if (obj is double) // FN | ||
{ | ||
_ = (double)obj; | ||
} | ||
|
||
if (obj is ushort) // FN | ||
{ | ||
_ = (ushort)obj; | ||
} | ||
} | ||
|
||
void NullableValueTypes(object obj) | ||
{ | ||
if (obj is int?) // FN | ||
{ | ||
_ = (int?)obj; | ||
} | ||
|
||
if (obj is byte?) // FN | ||
{ | ||
_ = (byte?)obj; | ||
} | ||
} | ||
|
||
void UsingLanguageKeywordAndFrameworkName(object obj) | ||
{ | ||
if (obj is Nullable<int>) // FN | ||
{ | ||
_ = (int?)obj; | ||
} | ||
|
||
if (obj is int?) // FN | ||
{ | ||
_ = (Nullable<int>)obj; | ||
} | ||
|
||
if (obj is IntPtr) // FN | ||
{ | ||
_ = (nint)obj; | ||
} | ||
|
||
if (obj is nint) // FN | ||
{ | ||
_ = (IntPtr)obj; | ||
} | ||
|
||
if (obj is System.UIntPtr) // FN | ||
{ | ||
_ = (nuint)obj; | ||
} | ||
} | ||
|
||
void Enums(object obj) | ||
{ | ||
if (obj is AnEnum) // Noncompliant | ||
{ | ||
_ = (AnEnum)obj; // Secondary | ||
} | ||
|
||
if (obj is AnEnum?) // FN | ||
{ | ||
_ = (AnEnum?)obj; | ||
} | ||
} | ||
|
||
void UserDefinedStructs(object obj) | ||
{ | ||
if (obj is AStruct) // FN | ||
{ | ||
_ = (AStruct)obj; | ||
} | ||
|
||
if (obj is ARecordStruct) // FN | ||
{ | ||
_ = (ARecordStruct)obj; | ||
} | ||
|
||
if (obj is AReadonlyRefStruct) // FN | ||
{ | ||
_ = (AStruct)obj; | ||
} | ||
} | ||
|
||
enum AnEnum { Value1, Value2 } | ||
struct AStruct { } | ||
record struct ARecordStruct { } | ||
readonly ref struct AReadonlyRefStruct { } | ||
} | ||
|
||
|
109 changes: 53 additions & 56 deletions
109
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/CastShouldNotBeDuplicated.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,84 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace Tests.Diagnostics | ||
class Fruit { } | ||
|
||
class Program | ||
{ | ||
class Fruit { } | ||
private object someField; | ||
|
||
class Program | ||
public void Foo(Object x) | ||
{ | ||
private object someField; | ||
|
||
public void Foo(Object x) | ||
if (x is Fruit) // Noncompliant | ||
{ | ||
if (x is Fruit) // Noncompliant | ||
{ | ||
var f1 = (Fruit)x; | ||
// ^^^^^^^^ Secondary | ||
var f2 = (Fruit)x; | ||
// ^^^^^^^^ Secondary | ||
} | ||
var f1 = (Fruit)x; | ||
// ^^^^^^^^ Secondary | ||
var f2 = (Fruit)x; | ||
// ^^^^^^^^ Secondary | ||
} | ||
|
||
var f = x as Fruit; | ||
if (x != null) // Compliant | ||
{ | ||
var f = x as Fruit; | ||
if (x != null) // Compliant | ||
{ | ||
|
||
} | ||
} | ||
} | ||
|
||
public void Bar(object x) | ||
public void Bar(object x) | ||
{ | ||
if (!(x is Fruit)) | ||
{ | ||
if (!(x is Fruit)) | ||
{ | ||
var f1 = (Fruit)x; // Compliant - but will throw | ||
} | ||
else | ||
{ | ||
var f2 = (Fruit)x; // Compliant - should be non compliant | ||
} | ||
|
||
var f1 = (Fruit)x; // Compliant - but will throw | ||
} | ||
else | ||
{ | ||
var f2 = (Fruit)x; // Compliant - should be non compliant | ||
} | ||
|
||
} | ||
|
||
public void FooBar(object x) | ||
public void FooBar(object x) | ||
{ | ||
if (x is int) | ||
{ | ||
if (x is int) | ||
{ | ||
var res = (int)x; // Compliant because we are casting to a ValueType | ||
} | ||
var res = (int)x; // Compliant because we are casting to a ValueType | ||
} | ||
} | ||
|
||
// See https://github.com/SonarSource/sonar-dotnet/issues/2314 | ||
public void TakeIdentifierIntoAccount(object x) | ||
// See https://github.com/SonarSource/sonar-dotnet/issues/2314 | ||
public void TakeIdentifierIntoAccount(object x) | ||
{ | ||
if (x is Fruit) | ||
{ | ||
if (x is Fruit) | ||
{ | ||
var f = new Fruit(); | ||
var c = (Fruit)f; | ||
} | ||
var f = new Fruit(); | ||
var c = (Fruit)f; | ||
} | ||
|
||
if (someField is Fruit) // Noncompliant | ||
{ | ||
var fruit = (Fruit)this.someField; | ||
// ^^^^^^^^^^^^^^^^^^^^^ Secondary | ||
} | ||
if (someField is Fruit) // Noncompliant | ||
{ | ||
var fruit = (Fruit)this.someField; | ||
// ^^^^^^^^^^^^^^^^^^^^^ Secondary | ||
} | ||
} | ||
|
||
public void UnknownFoo(object x) | ||
public void UnknownFoo(object x) | ||
{ | ||
if (x is Car) // Compliant because we ignore what the type is // Error [CS0246] | ||
{ | ||
if (x is Car) // Compliant because we ignore what the type is // Error [CS0246] | ||
{ | ||
var c = (Car)x; // Error [CS0246] | ||
} | ||
var c = (Car)x; // Error [CS0246] | ||
} | ||
} | ||
} | ||
|
||
public class Bar<T> { } | ||
public class Bar<T> { } | ||
|
||
public class Foo<T> | ||
public class Foo<T> | ||
{ | ||
public void Process(object message) | ||
{ | ||
public void Process(object message) | ||
if (message is Bar<T>/*comment*/) // Noncompliant | ||
{ | ||
if (message is Bar<T>/*comment*/) // Noncompliant | ||
{ | ||
var sub = (Bar<T>/**/) message; // Secondary | ||
} | ||
var sub = (Bar<T>/**/) message; // Secondary | ||
} | ||
} | ||
} |