mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
6.7 KiB
195 lines
6.7 KiB
// |
|
// CSharpUtil.cs |
|
// |
|
// Author: |
|
// Mike Krüger <mkrueger@novell.com> |
|
// |
|
// Copyright (c) 2011 Novell, Inc (http://www.novell.com) |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy |
|
// of this software and associated documentation files (the "Software"), to deal |
|
// in the Software without restriction, including without limitation the rights |
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
// copies of the Software, and to permit persons to whom the Software is |
|
// furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included in |
|
// all copies or substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
// THE SOFTWARE. |
|
|
|
|
|
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; |
|
|
|
namespace ICSharpCode.Decompiler.CSharp.Syntax |
|
{ |
|
public static class CSharpUtil |
|
{ |
|
/// <summary> |
|
/// Inverts a boolean condition. Note: The condition object can be frozen (from AST) it's cloned internally. |
|
/// </summary> |
|
/// <param name="condition">The condition to invert.</param> |
|
public static Expression InvertCondition(Expression condition) |
|
{ |
|
return InvertConditionInternal(condition); |
|
} |
|
|
|
static Expression InvertConditionInternal(Expression condition) |
|
{ |
|
if (condition is ParenthesizedExpression) |
|
{ |
|
return new ParenthesizedExpression(InvertCondition(((ParenthesizedExpression)condition).Expression)); |
|
} |
|
|
|
if (condition is UnaryOperatorExpression) |
|
{ |
|
var uOp = (UnaryOperatorExpression)condition; |
|
if (uOp.Operator == UnaryOperatorType.Not) |
|
{ |
|
if (!(uOp.Parent is Expression)) |
|
return GetInnerMostExpression(uOp.Expression).Clone(); |
|
return uOp.Expression.Clone(); |
|
} |
|
return new UnaryOperatorExpression(UnaryOperatorType.Not, uOp.Clone()); |
|
} |
|
|
|
if (condition is BinaryOperatorExpression) |
|
{ |
|
var bOp = (BinaryOperatorExpression)condition; |
|
|
|
if ((bOp.Operator == BinaryOperatorType.ConditionalAnd) || (bOp.Operator == BinaryOperatorType.ConditionalOr)) |
|
{ |
|
return new BinaryOperatorExpression(InvertCondition(bOp.Left), NegateConditionOperator(bOp.Operator), InvertCondition(bOp.Right)); |
|
} |
|
else if ((bOp.Operator == BinaryOperatorType.Equality) || (bOp.Operator == BinaryOperatorType.InEquality) || (bOp.Operator == BinaryOperatorType.GreaterThan) |
|
|| (bOp.Operator == BinaryOperatorType.GreaterThanOrEqual) || (bOp.Operator == BinaryOperatorType.LessThan) || |
|
(bOp.Operator == BinaryOperatorType.LessThanOrEqual)) |
|
{ |
|
return new BinaryOperatorExpression(bOp.Left.Clone(), NegateRelationalOperator(bOp.Operator), bOp.Right.Clone()); |
|
} |
|
else |
|
{ |
|
var negatedOp = NegateRelationalOperator(bOp.Operator); |
|
if (negatedOp == BinaryOperatorType.Any) |
|
return new UnaryOperatorExpression(UnaryOperatorType.Not, new ParenthesizedExpression(condition.Clone())); |
|
bOp = (BinaryOperatorExpression)bOp.Clone(); |
|
bOp.Operator = negatedOp; |
|
return bOp; |
|
} |
|
} |
|
if (condition is ConditionalExpression) |
|
{ |
|
var cEx = condition.Clone() as ConditionalExpression; |
|
cEx.Condition = InvertCondition(cEx.Condition); |
|
return cEx; |
|
} |
|
if (condition is PrimitiveExpression) |
|
{ |
|
var pex = condition as PrimitiveExpression; |
|
if (pex.Value is bool) |
|
{ |
|
return new PrimitiveExpression(!((bool)pex.Value)); |
|
} |
|
} |
|
|
|
return new UnaryOperatorExpression(UnaryOperatorType.Not, AddParensForUnaryExpressionIfRequired(condition.Clone())); |
|
} |
|
|
|
/// <summary> |
|
/// When negating an expression this is required, otherwise you would end up with |
|
/// a or b -> !a or b |
|
/// </summary> |
|
internal static Expression AddParensForUnaryExpressionIfRequired(Expression expression) |
|
{ |
|
if ((expression is BinaryOperatorExpression) || |
|
(expression is AssignmentExpression) || |
|
(expression is CastExpression) || |
|
(expression is AsExpression) || |
|
(expression is IsExpression) || |
|
(expression is LambdaExpression) || |
|
(expression is ConditionalExpression)) |
|
{ |
|
return new ParenthesizedExpression(expression); |
|
} |
|
|
|
return expression; |
|
} |
|
|
|
/// <summary> |
|
/// Get negation of the specified relational operator |
|
/// </summary> |
|
/// <returns> |
|
/// negation of the specified relational operator, or BinaryOperatorType.Any if it's not a relational operator |
|
/// </returns> |
|
public static BinaryOperatorType NegateRelationalOperator(BinaryOperatorType op) |
|
{ |
|
switch (op) |
|
{ |
|
case BinaryOperatorType.GreaterThan: |
|
return BinaryOperatorType.LessThanOrEqual; |
|
case BinaryOperatorType.GreaterThanOrEqual: |
|
return BinaryOperatorType.LessThan; |
|
case BinaryOperatorType.Equality: |
|
return BinaryOperatorType.InEquality; |
|
case BinaryOperatorType.InEquality: |
|
return BinaryOperatorType.Equality; |
|
case BinaryOperatorType.LessThan: |
|
return BinaryOperatorType.GreaterThanOrEqual; |
|
case BinaryOperatorType.LessThanOrEqual: |
|
return BinaryOperatorType.GreaterThan; |
|
case BinaryOperatorType.ConditionalOr: |
|
return BinaryOperatorType.ConditionalAnd; |
|
case BinaryOperatorType.ConditionalAnd: |
|
return BinaryOperatorType.ConditionalOr; |
|
} |
|
return BinaryOperatorType.Any; |
|
} |
|
|
|
/// <summary> |
|
/// Returns true, if the specified operator is a relational operator |
|
/// </summary> |
|
public static bool IsRelationalOperator(BinaryOperatorType op) |
|
{ |
|
return NegateRelationalOperator(op) != BinaryOperatorType.Any; |
|
} |
|
|
|
/// <summary> |
|
/// Get negation of the condition operator |
|
/// </summary> |
|
/// <returns> |
|
/// negation of the specified condition operator, or BinaryOperatorType.Any if it's not a condition operator |
|
/// </returns> |
|
public static BinaryOperatorType NegateConditionOperator(BinaryOperatorType op) |
|
{ |
|
switch (op) |
|
{ |
|
case BinaryOperatorType.ConditionalOr: |
|
return BinaryOperatorType.ConditionalAnd; |
|
case BinaryOperatorType.ConditionalAnd: |
|
return BinaryOperatorType.ConditionalOr; |
|
} |
|
return BinaryOperatorType.Any; |
|
} |
|
|
|
public static bool AreConditionsEqual(Expression cond1, Expression cond2) |
|
{ |
|
if (cond1 == null || cond2 == null) |
|
return false; |
|
return GetInnerMostExpression(cond1).IsMatch(GetInnerMostExpression(cond2)); |
|
} |
|
|
|
public static Expression GetInnerMostExpression(Expression target) |
|
{ |
|
while (target is ParenthesizedExpression) |
|
target = ((ParenthesizedExpression)target).Expression; |
|
return target; |
|
} |
|
} |
|
} |
|
|
|
|