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

Support BinaryOperation for Boolean expressions in SE #5479

Merged
merged 6 commits into from
Mar 17, 2022
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
138 changes: 138 additions & 0 deletions analyzers/src/SonarAnalyzer.CFG/ShimLayer/BinaryOperatorKind.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

namespace StyleCop.Analyzers.Lightup
{
/// <summary>
/// Kind of binary operator.
/// </summary>
public enum BinaryOperatorKind
{
/// <summary>
/// Represents unknown or error operator kind.
/// </summary>
None = 0x0,

/// <summary>
/// Represents the '+' operator.
/// </summary>
Add = 0x1,

/// <summary>
/// Represents the '-' operator.
/// </summary>
Subtract = 0x2,

/// <summary>
/// Represents the '*' operator.
/// </summary>
Multiply = 0x3,

/// <summary>
/// Represents the '/' operator.
/// </summary>
Divide = 0x4,

/// <summary>
/// Represents the VB '\' integer divide operator.
/// </summary>
IntegerDivide = 0x5,

/// <summary>
/// Represents the C# '%' operator and VB 'Mod' operator.
/// </summary>
Remainder = 0x6,

/// <summary>
/// Represents the VB '^' exponentiation operator.
/// </summary>
Power = 0x7,

/// <summary>
/// Represents the <![CDATA['<<']]> operator.
/// </summary>
LeftShift = 0x8,

/// <summary>
/// Represents the <![CDATA['>>']]> operator.
/// </summary>
RightShift = 0x9,

/// <summary>
/// Represents the C# <![CDATA['&']]> operator and VB 'And' operator.
/// </summary>
And = 0xa,

/// <summary>
/// Represents the C# <![CDATA['|']]> operator and VB 'Or' operator.
/// </summary>
Or = 0xb,

/// <summary>
/// Represents the C# '^' operator and VB 'Xor' operator.
/// </summary>
ExclusiveOr = 0xc,

/// <summary>
/// Represents the C# <![CDATA['&&']]> operator and VB 'AndAlso' operator.
/// </summary>
ConditionalAnd = 0xd,

/// <summary>
/// Represents the C# <![CDATA['||']]> operator and VB 'OrElse' operator.
/// </summary>
ConditionalOr = 0xe,

/// <summary>
/// Represents the VB <![CDATA['&']]> operator for string concatenation.
/// </summary>
Concatenate = 0xf,

// Relational operations.

/// <summary>
/// Represents the C# '==' operator and VB 'Is' operator and '=' operator for non-object typed operands.
/// </summary>
Equals = 0x10,

/// <summary>
/// Represents the VB '=' operator for object typed operands.
/// </summary>
ObjectValueEquals = 0x11,

/// <summary>
/// Represents the C# '!=' operator and VB 'IsNot' operator and <![CDATA['<>']]> operator for non-object typed operands.
/// </summary>
NotEquals = 0x12,

/// <summary>
/// Represents the VB <![CDATA['<>']]> operator for object typed operands.
/// </summary>
ObjectValueNotEquals = 0x13,

/// <summary>
/// Represents the <![CDATA['<']]> operator.
/// </summary>
LessThan = 0x14,

/// <summary>
/// Represents the <![CDATA['<=']]> operator.
/// </summary>
LessThanOrEqual = 0x15,

/// <summary>
/// Represents the <![CDATA['>=']]> operator.
/// </summary>
GreaterThanOrEqual = 0x16,

/// <summary>
/// Represents the <![CDATA['>']]> operator.
/// </summary>
GreaterThan = 0x17,

/// <summary>
/// Represents the VB 'Like' operator.
/// </summary>
Like = 0x18
}
}
9 changes: 8 additions & 1 deletion analyzers/src/SonarAnalyzer.CFG/ShimLayer/LightupHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,14 @@ TProperty FallbackAccessor(TOperation syntax)
Expression.New(constructor, Expression.Convert(Expression.Call(instance, property.GetMethod), typeof(object))),
operationParameter);
return expression.Compile();

}
else if (typeof(TProperty).IsEnum && property.PropertyType.IsEnum)
{
Expression<Func<TOperation, TProperty>> expression =
Expression.Lambda<Func<TOperation, TProperty>>(
Expression.Convert(Expression.Call(instance, property.GetMethod), typeof(TProperty)),
operationParameter);
return expression.Compile();
}
else if (!typeof(TProperty).GetTypeInfo().IsAssignableFrom(property.PropertyType.GetTypeInfo()))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,8 @@ public sealed class BoolConstraint : SymbolicConstraint
this == True ? nameof(True) : nameof(False);

private BoolConstraint() { }

public static BoolConstraint From(bool value) =>
value ? True : False;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* SonarAnalyzer for .NET
* Copyright (C) 2015-2022 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.
*/

using SonarAnalyzer.SymbolicExecution.Constraints;
using StyleCop.Analyzers.Lightup;

namespace SonarAnalyzer.SymbolicExecution.Roslyn.OperationProcessors
{
internal static class Binary
{
public static ProgramState Process(SymbolicContext context, IBinaryOperationWrapper binary) =>
context.State[binary.LeftOperand] is { } left
&& context.State[binary.RightOperand] is { } right
&& left.HasConstraint<BoolConstraint>()
&& right.HasConstraint<BoolConstraint>()
&& BinaryBoolConstraint(binary.OperatorKind, left.HasConstraint(BoolConstraint.True), right.HasConstraint(BoolConstraint.True)) is { } newConstraint
? context.SetOperationConstraint(newConstraint)
: context.State;

private static SymbolicConstraint BinaryBoolConstraint(BinaryOperatorKind kind, bool left, bool right) =>
kind switch
{
BinaryOperatorKind.Equals or BinaryOperatorKind.ObjectValueEquals => BoolConstraint.From(left == right),
BinaryOperatorKind.NotEquals or BinaryOperatorKind.ObjectValueNotEquals => BoolConstraint.From(left != right),
BinaryOperatorKind.And or BinaryOperatorKind.ConditionalAnd => BoolConstraint.From(left && right),
BinaryOperatorKind.Or or BinaryOperatorKind.ConditionalOr => BoolConstraint.From(left || right),
BinaryOperatorKind.ExclusiveOr => BoolConstraint.From(left ^ right),
_ => null
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ private static ProgramState ProcessOperation(SymbolicContext context) =>
context.Operation.Instance.Kind switch
{
OperationKindEx.Argument => Invocation.Process(context, IArgumentOperationWrapper.FromOperation(context.Operation.Instance)),
OperationKindEx.Binary => Binary.Process(context, IBinaryOperationWrapper.FromOperation(context.Operation.Instance)),
OperationKindEx.Conversion => Conversion.Process(context, IConversionOperationWrapper.FromOperation(context.Operation.Instance)),
OperationKindEx.FieldReference => References.Process(context, IFieldReferenceOperationWrapper.FromOperation(context.Operation.Instance)),
OperationKindEx.LocalReference => References.Process(context, ILocalReferenceOperationWrapper.FromOperation(context.Operation.Instance)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,6 @@ public PropertyData(XElement node)
this.IsSkipped = this.Type switch
{
"ArgumentKind" => true,
"BinaryOperatorKind" => true,
"BranchKind" => true,
"CaseKind" => true,
"CommonConversion" => true,
Expand Down
Loading