Skip to content

Commit

Permalink
Add Processor for deconstruction operations
Browse files Browse the repository at this point in the history
  • Loading branch information
zsolt-kolbay-sonarsource committed Dec 11, 2023
1 parent b36349a commit c2a0b7c
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ OperationKindEx.PropertyReference when operation.ToPropertyReference() is { Prop
internal static IConversionOperationWrapper? AsConversion(this IOperation operation) =>
operation.As(OperationKindEx.Conversion, IConversionOperationWrapper.FromOperation);

internal static IDeclarationExpressionOperationWrapper? AsDeclarationExpression(this IOperation operation) =>
operation.As(OperationKindEx.DeclarationExpression, IDeclarationExpressionOperationWrapper.FromOperation);

internal static IInvocationOperationWrapper? AsInvocation(this IOperation operation) =>
operation.As(OperationKindEx.Invocation, IInvocationOperationWrapper.FromOperation);

Expand All @@ -66,6 +69,9 @@ OperationKindEx.PropertyReference when operation.ToPropertyReference() is { Prop
internal static IPropertyReferenceOperationWrapper? AsPropertyReference(this IOperation operation) =>
operation.As(OperationKindEx.PropertyReference, IPropertyReferenceOperationWrapper.FromOperation);

internal static ITupleOperationWrapper? AsTuple(this IOperation operation) =>
operation.As(OperationKindEx.Tuple, ITupleOperationWrapper.FromOperation);

internal static IAwaitOperationWrapper ToAwait(this IOperation operation) =>
IAwaitOperationWrapper.FromOperation(operation);

Expand Down Expand Up @@ -120,6 +126,9 @@ internal static IParameterReferenceOperationWrapper ToParameterReference(this IO
internal static IEventReferenceOperationWrapper ToEventReference(this IOperation operation) =>
IEventReferenceOperationWrapper.FromOperation(operation);

internal static ITupleOperationWrapper ToTuple(this IOperation operation) =>
ITupleOperationWrapper.FromOperation(operation);

internal static IUnaryOperationWrapper ToUnary(this IOperation operation) =>
IUnaryOperationWrapper.FromOperation(operation);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ internal static class OperationDispatcher
{ OperationKindEx.CompoundAssignment, new CompoundAssignment() },
{ OperationKindEx.Conversion, new Conversion() },
{ OperationKindEx.DeclarationPattern, new DeclarationPattern() },
{ OperationKindEx.DeconstructionAssignment, new DeconstructionAssignment() },
{ OperationKindEx.Decrement, new IncrementOrDecrement() },
{ OperationKindEx.DefaultValue, new DefaultValue() },
{ OperationKindEx.DelegateCreation, new NotNullOperation() },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* SonarAnalyzer for .NET
* Copyright (C) 2015-2023 SonarSource SA
* mailto: contact AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

namespace SonarAnalyzer.SymbolicExecution.Roslyn.OperationProcessors;

internal sealed class DeconstructionAssignment : SimpleProcessor<IDeconstructionAssignmentOperationWrapper>
{
protected override IDeconstructionAssignmentOperationWrapper Convert(IOperation operation) =>
IDeconstructionAssignmentOperationWrapper.FromOperation(operation);

protected override ProgramState Process(SymbolicContext context, IDeconstructionAssignmentOperationWrapper assignment) =>
Process(context.State, assignment.Target, assignment.Value);

private static ProgramState Process(ProgramState state, IOperation target, IOperation value)
{
var leftTupleElements = UnwrapDeclaration(target).ToTuple().Elements;

// If the right side is a tuple, then every symbol/constraint is copied to the left side.
if (value.AsTuple() is { } rightSideTuple)
{
for (var i = 0; i < leftTupleElements.Length; i++)
{
var leftTupleMember = UnwrapDeclaration(leftTupleElements[i]);
var rightTupleMember = rightSideTuple.Elements[i];
if (leftTupleMember.Kind == OperationKindEx.Discard)
{
continue;
}
if (leftTupleMember.AsTuple() is { } nestedTuple)
{
var rightSideMember = rightTupleMember.AsTuple()?.WrappedOperation ?? rightTupleMember;
state = Process(state, nestedTuple.WrappedOperation, rightSideMember);
}
else
{
state = state.SetOperationAndSymbolValue(leftTupleMember, state[rightTupleMember]);
}
}
}
// If the right side is not a tuple, then every member of the left side tuple is set to empty.
else
{
foreach (var tupleMember in leftTupleElements.Where(x => x.Kind != OperationKindEx.Discard))
{
state = state.SetOperationAndSymbolValue(tupleMember, SymbolicValue.Empty);
}
}
return state;
}

private static IOperation UnwrapDeclaration(IOperation operation) =>
operation.AsDeclarationExpression()?.Expression ?? operation;
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ protected ProgramState(ProgramState original) // Custom record override constr
Exceptions = original.Exceptions;
}

public ProgramState SetOperationAndSymbolValue(IOperation operation, SymbolicValue value)
{
var newState = SetOperationValue(operation, value);
if (operation.TrackedSymbol(this) is { } symbol)
{
newState = newState.SetSymbolValue(symbol, value);
}
return newState;
}

public ProgramState SetOperationValue(IOperationWrapper operation, SymbolicValue value) =>
operation is null
? throw new ArgumentNullException(nameof(operation))
Expand Down

0 comments on commit c2a0b7c

Please sign in to comment.