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

S3655: Static properties and fields called Value #7000

Merged
merged 5 commits into from
Mar 31, 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
Expand Up @@ -32,10 +32,11 @@ protected override ProgramState PreProcessSimple(SymbolicContext context)
if (operationInstance.Kind == OperationKindEx.PropertyReference
&& operationInstance.ToPropertyReference() is var reference
&& reference.Property.Name == nameof(Nullable<int>.Value)
&& reference.Instance.Type.IsNullableValueType()
&& context.HasConstraint(reference.Instance, ObjectConstraint.Null))
&& reference.Instance is { } instance
&& instance.Type.IsNullableValueType()
&& context.HasConstraint(instance, ObjectConstraint.Null))
{
ReportIssue(reference.Instance, reference.Instance.Syntax.ToString());
ReportIssue(instance, instance.Syntax.ToString());
}
else if (operationInstance.Kind == OperationKindEx.Conversion
&& operationInstance.ToConversion() is var conversion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -949,46 +949,99 @@ void Basics(MaybeInt i)
}
}

namespace TypeWithValueProperty
namespace TypeWithInstancePropertyCalledValue
{
class Test
{
void Basics1()
{
ClassWithValueProperty i = null;
_ = i.Value; // Compliant, ClassWithValueProperty not a nullable type
ClassWithPropertyCalledValue i = null;
_ = i.Value; // Compliant, not a nullable type
}

void Basics2()
{
ClassWithValueProperty i = null;
_ = i.APropertyNotCalledValue; // Compliant, ClassWithValuePropertyAndImplicitCast not a nullable type
ClassWithPropertyCalledValue i = null;
_ = i.APropertyNotCalledValue; // Compliant, not a nullable type
}

void ImplicitCast()
{
StructWithValuePropertyAndCastOperators i = null as int?; // Noncompliant, FP
_ = i.Value; // Compliant, ClassWithValuePropertyAndImplicitCast not a nullable type
StructWithPropertyCalledValueAndCastOperators i = null as int?; // Noncompliant, FP
_ = i.Value; // Compliant, not a nullable type
}

int ExplicitCast1 => ((StructWithValuePropertyAndCastOperators)(null as long?)).Value; // Noncompliant, FP, just gives 42
StructWithValuePropertyAndCastOperators ExplicitCast2 => (null as StructWithValuePropertyAndCastOperators?).Value; // Noncompliant, FP, just gives a struct
int ExplicitCast3 => (null as StructWithValuePropertyAndCastOperators?).Value.Value; // Noncompliant, FP, just gives 42
int ExplicitCast1 => ((StructWithPropertyCalledValueAndCastOperators)(null as long?)).Value; // Noncompliant, FP, just gives 42
StructWithPropertyCalledValueAndCastOperators ExplicitCast2 => (null as StructWithPropertyCalledValueAndCastOperators?).Value; // Noncompliant, FP, just gives a struct
int ExplicitCast3 => (null as StructWithPropertyCalledValueAndCastOperators?).Value.Value; // Noncompliant, FP, just gives 42
}

class ClassWithValueProperty
class ClassWithPropertyCalledValue
{
public int Value => 42;
public int APropertyNotCalledValue => 42;
}

struct StructWithValuePropertyAndCastOperators
struct StructWithPropertyCalledValueAndCastOperators
{
public int Value => 42;
public int APropertyNotCalledValue => 42;

public static implicit operator StructWithValuePropertyAndCastOperators(int? value) => new StructWithValuePropertyAndCastOperators();
public static explicit operator StructWithValuePropertyAndCastOperators(long? value) => new StructWithValuePropertyAndCastOperators();
public static implicit operator StructWithPropertyCalledValueAndCastOperators(int? value) => new StructWithPropertyCalledValueAndCastOperators();
public static explicit operator StructWithPropertyCalledValueAndCastOperators(long? value) => new StructWithPropertyCalledValueAndCastOperators();
}
}

namespace TypeWithStaticPropertyCalledValue
{
class Test
{
void Basics()
{
_ = ClassWithStaticPropertyCalledValue.Value; // Compliant, not on nullable value type
_ = ClassWithStaticPropertyCalledValue.Value.Value; // Compliant
_ = ClassWithStaticPropertyCalledValue.Value.Value.InstanceProperty; // Compliant
_ = ClassWithStaticPropertyCalledValue.Value.Value.InstanceProperty.Value; // Compliant
_ = new ClassWithInstancePropertyCalledValue().Value; // Compliant
}
}

class ClassWithStaticPropertyCalledValue
{
public ClassWithInstancePropertyCalledValue InstanceProperty => null;

public static ClassWithInstancePropertyCalledValue Value => null;
}

class ClassWithInstancePropertyCalledValue
{
public ClassWithStaticPropertyCalledValue Value => null;
}
}

namespace TypeWithStaticFieldCalledValue
{
class Test
{
void Basics()
{
_ = ClassWithStaticFieldCalledValue.Value; // Compliant, not on nullable value type
_ = ClassWithStaticFieldCalledValue.Value.Value; // Compliant
_ = ClassWithStaticFieldCalledValue.Value.Value.InstanceField; // Compliant
_ = ClassWithStaticFieldCalledValue.Value.Value.InstanceField.Value; // Compliant
_ = new ClassWithInstanceFieldCalledValue().Value; // Compliant
}
}

class ClassWithStaticFieldCalledValue
{
public ClassWithInstanceFieldCalledValue InstanceField = null;

public static ClassWithInstanceFieldCalledValue Value = null;
}

class ClassWithInstanceFieldCalledValue
{
public ClassWithStaticFieldCalledValue Value = null;
}
}