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

S3247: Add repro for #223 #8259

Merged
merged 1 commit into from
Oct 27, 2023
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
@@ -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 { }
}


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
}
}
}