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

Add hint for type test expressions, and support for safe cast expressions #41

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
30 changes: 30 additions & 0 deletions PowerAssert/Hints/TypeTestHint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using PowerAssert.Infrastructure;

namespace PowerAssert.Hints
{
class TypeTestHint : IHint
{
public bool TryGetHint(ExpressionParser parser, Expression expression, out string hint)
{
if (expression is TypeBinaryExpression typeBinaryExp && typeBinaryExp.NodeType == ExpressionType.TypeIs)
{
var expressionOperand = parser.DynamicInvoke(typeBinaryExp.Expression);
var typeOperand = typeBinaryExp.TypeOperand;

if (!typeOperand.IsInstanceOfType(expressionOperand))
{
hint = $", {expressionOperand} is not assignable to {typeOperand}";
return true;
}
}

hint = null;
return false;
}
}
}
11 changes: 10 additions & 1 deletion PowerAssert/Infrastructure/ExpressionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ Node ParseExpression(UnaryExpression e)
return new UnaryNode {Prefix = "-", Operand = Parse(e.Operand), PrefixValue = GetValue(e)};
case ExpressionType.ArrayLength:
return new MemberAccessNode {Container = Parse(e.Operand), MemberName = "Length", MemberValue = GetValue(e)};
case ExpressionType.TypeAs:
return new BinaryNode
{
Left = Parse(e.Operand),
Operator = "as",
Right = new ConstantNode() { Text = NameOfType(e.Type) },
Value = GetValue(e)
};
}
throw new ArgumentOutOfRangeException("e", string.Format("Can't handle UnaryExpression expression of class {0} and type {1}", e.GetType().Name, e.NodeType));
}
Expand Down Expand Up @@ -410,7 +418,8 @@ string GetDisplayText(MemberInfo member)
new FloatEqualityHint(),
new BrokenEqualityHint(),
new TimeSpanTotalMistakesHint(),
new EnumComparisonShowValuesHint()
new EnumComparisonShowValuesHint(),
new TypeTestHint()
);

string GetHints(Expression e, object value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
b is string
. __
. |
| False
| False, System.Object is not assignable to System.String
System.Object

at PowerAssert.PAssert.IsTrue(Expression`1 expression) in ...\PAssert.cs
Expand Down
12 changes: 12 additions & 0 deletions PowerAssertTests/Approvals/EndToEndTest.SafeCasting.approved.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
System.Exception: IsTrue failed, expression was:

a as string != null
. .. __
. __ |
. | |
| | False
| null
System.Object

at PowerAssert.PAssert.IsTrue(Expression`1 expression) in ...\PAssert.cs
at PowerAssertTests.Approvals.EndToEndTest.ApproveException(Expression`1 func) in ...\EndToEndTest.cs
8 changes: 8 additions & 0 deletions PowerAssertTests/Approvals/EndToEndTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,14 @@ public void Casting()
ApproveException(() => (long) x == 10L);
}

[Test]
public void SafeCasting()
{
object a = new object();

ApproveException(() => a as string != null);
}

[Test]
public void ArrayLength()
{
Expand Down
34 changes: 34 additions & 0 deletions PowerAssertTests/Hints/TypeTestHintTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using PowerAssert.Hints;
using PowerAssert.Infrastructure;

namespace PowerAssertTests.Hints
{
[TestFixture]
public class TypeTestHintTests
{
[Test]
public void ShouldPickUpTypeComparisonOperator()
{
var hint = new TypeTestHint();

var a = new TypeA();

Expression<Func<bool>> x = () => a is TypeB;
var p = new ExpressionParser(x.Body);

string description;
Assert.IsTrue(hint.TryGetHint(p, x.Body, out description));
Assert.IsNotNull(description);
}

class TypeA { }
class TypeB { }
}
}
1 change: 1 addition & 0 deletions PowerAssertTests/PowerAssertTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
<Compile Include="Hints\StringEqualsHintTests.cs" />
<Compile Include="Hints\StringOperatorEqualsHint.cs" />
<Compile Include="Hints\TimeSpanTotalMistakesHintTests.cs" />
<Compile Include="Hints\TypeTestHintTests.cs" />
<Compile Include="NodeFormatterTest.cs" />
<Compile Include="ParserTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down