Skip to content

Commit

Permalink
Refactor parameter dereference method
Browse files Browse the repository at this point in the history
  • Loading branch information
zsolt-kolbay-sonarsource committed Mar 29, 2023
1 parent bbed3eb commit cbd704f
Showing 1 changed file with 16 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,18 @@ static bool MethodDereferencesArguments(BaseMethodDeclarationSyntax method)

protected override ProgramState PreProcessSimple(SymbolicContext context)
{
var operation = context.Operation.Instance;
if (operation.Kind == OperationKindEx.ParameterReference
&& operation.ToParameterReference().Parameter is var parameter
if (NullDereferenceCandidate(context.Operation.Instance) is { } candidate
&& candidate.Kind == OperationKindEx.ParameterReference
&& candidate.ToParameterReference() is var dereferencedParameter
&& dereferencedParameter.Parameter is var parameter
&& !parameter.Type.IsValueType
&& IsParameterDereferenced(context.Operation)
&& NullableStateIsNotKnownForParameter(parameter)
&& !parameter.HasAttribute(KnownType.Microsoft_AspNetCore_Mvc_FromServicesAttribute))
{
var message = SemanticModel.GetDeclaredSymbol(Node).IsConstructor()
? "Refactor this constructor to avoid using members of parameter '{0}' because it could be null."
: "Refactor this method to add validation of parameter '{0}' before using it.";
ReportIssue(operation, string.Format(message, operation.Syntax), context);
ReportIssue(dereferencedParameter.WrappedOperation, string.Format(message, dereferencedParameter.WrappedOperation.Syntax), context);
}

return context.State;
Expand All @@ -91,15 +91,17 @@ bool NullableStateIsNotKnownForParameter(IParameterSymbol symbol) =>
context.State[symbol] is null || !context.State[symbol].HasConstraint<ObjectConstraint>();
}

private static bool IsParameterDereferenced(IOperationWrapperSonar operation) =>
operation.Parent != null
&& operation.Parent.IsAnyKind(
OperationKindEx.Invocation,
OperationKindEx.FieldReference,
OperationKindEx.PropertyReference,
OperationKindEx.EventReference,
OperationKindEx.Await,
OperationKindEx.ArrayElementReference);
private static IOperation NullDereferenceCandidate(IOperation operation) =>
operation.Kind switch
{
OperationKindEx.Invocation => operation.ToInvocation().Instance,
OperationKindEx.FieldReference => operation.ToFieldReference().Instance,
OperationKindEx.PropertyReference => operation.ToPropertyReference().Instance,
OperationKindEx.EventReference => operation.ToEventReference().Instance,
OperationKindEx.Await => operation.ToAwait().Operation,
OperationKindEx.ArrayElementReference => operation.ToArrayElementReference().ArrayReference,
_ => null,
};

private sealed class ArgumentDereferenceWalker : SafeCSharpSyntaxWalker
{
Expand Down

0 comments on commit cbd704f

Please sign in to comment.