public string Translate(Expression expression, TranslationContext context)
        {
            var quote = (UnaryExpression)expression;

            if (context.Settings.DoNotCommentQuotedLambdas)
            {
                return(context.TranslateAsCodeBlock(quote.Operand));
            }

            var comment           = ReadableExpression.Comment("Quoted to induce a closure:");
            var quotedLambdaBlock = Expression.Block(comment, quote.Operand);

            var translatedLambda = context
                                   .TranslateCodeBlock(quotedLambdaBlock)
                                   .Indented()
                                   .WithoutCurlyBraces();

            return(Environment.NewLine + translatedLambda);
        }
Exemple #2
0
        public void ShouldTranslateASwitchStatementWithADefault()
        {
            var intVariable = Expression.Variable(typeof(int), "i");
            var writeOne    = CreateLambda(() => Console.WriteLine("One"));
            var writeTwo    = CreateLambda(() => Console.WriteLine("Two"));
            var writeThree  = CreateLambda(() => Console.WriteLine("Three"));

            var writeOneTwoThree = Expression.Block(writeOne.Body, writeTwo.Body, writeThree.Body);

            var switchStatement = Expression.Switch(
                intVariable,
                writeOneTwoThree,
                Expression.SwitchCase(writeOne.Body, Expression.Constant(1)),
                Expression.SwitchCase(writeTwo.Body, Expression.Constant(2)),
                Expression.SwitchCase(writeThree.Body, Expression.Constant(3)));

            var translated = ToReadableString(switchStatement);

            const string EXPECTED = @"
switch (i)
{
    case 1:
        Console.WriteLine(""One"");
        break;

    case 2:
        Console.WriteLine(""Two"");
        break;

    case 3:
        Console.WriteLine(""Three"");
        break;

    default:
        Console.WriteLine(""One"");
        Console.WriteLine(""Two"");
        Console.WriteLine(""Three"");
        break;
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateAssignmentsOfNestedVariableBlocksWithATernaryReturnValue()
        {
            var objectVariable = Expression.Variable(typeof(object), "id");
            var objectValue    = Expression.Variable(typeof(object), "value");
            var intVariable    = Expression.Variable(typeof(int), "num");
            var intValue       = Expression.Variable(typeof(int), "numValue");

            var objectNotNull = Expression.NotEqual(objectVariable, Expression.Default(typeof(object)));
            var defaultInt    = Expression.Default(typeof(int));

            var intTryParse = Expression.Call(
                typeof(int).GetPublicStaticMethod("TryParse", parameterCount: 2),
                Expression.Condition(
                    objectNotNull,
                    Expression.Call(objectVariable, typeof(object).GetPublicInstanceMethod("ToString")),
                    Expression.Default(typeof(string))),
                intValue);

            var objectAsIntOrDefault = Expression.Condition(intTryParse, intValue, defaultInt);

            var intParseInnerBlock = Expression.Block(new[] { intValue }, objectAsIntOrDefault);

            var intParseOuterBlock = Expression.Block(
                new[] { objectVariable },
                Expression.Assign(objectVariable, objectValue),
                intParseInnerBlock);

            var intAssignment = Expression.Assign(intVariable, intParseOuterBlock);

            var translated = ToReadableString(intAssignment);

            const string EXPECTED = @"
num =
{
    var id = value;

    int numValue;
    return int.TryParse((id != null) ? id.ToString() : null, out numValue) ? numValue : default(int);
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldIncludeAReturnKeywordForACoalesce()
        {
            var stringVariable1 = Expression.Variable(typeof(string), "myString");
            var stringVariable2 = Expression.Variable(typeof(string), "yourString");
            var assignStrings   = Expression.Assign(stringVariable1, stringVariable2);

            var stringEmpty    = Expression.Field(null, typeof(string), "Empty");
            var variableOrNull = Expression.Coalesce(stringVariable1, stringEmpty);

            var coalesceBlock = Expression.Block(assignStrings, variableOrNull);

            var translated = ToReadableString(coalesceBlock);

            const string EXPECTED = @"
var myString = yourString;

return (myString ?? string.Empty);";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldSplitLongConstructorArgumentListsOntoMultipleLines()
        {
            var helperVariable    = Expression.Variable(typeof(HelperClass), "helper");
            var helperConstructor = helperVariable.Type.GetConstructors().First();
            var longVariable      = Expression.Variable(typeof(int), "thisVariableReallyHasAVeryLongNameIndeed");
            var newHelper         = Expression.New(helperConstructor, longVariable, longVariable, longVariable);
            var helperAssignment  = Expression.Assign(helperVariable, newHelper);

            var longArgumentListBlock = Expression.Block(new[] { helperVariable }, helperAssignment);

            var translated = ToReadableString(longArgumentListBlock);

            const string EXPECTED = @"
var helper = new HelperClass(
    thisVariableReallyHasAVeryLongNameIndeed,
    thisVariableReallyHasAVeryLongNameIndeed,
    thisVariableReallyHasAVeryLongNameIndeed);";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldSplitLongInvokeArgumentListsOntoMultipleLines()
        {
            var longVariable    = Expression.Variable(typeof(int), "thisVariableReallyHasAVeryLongNameIndeed");
            var threeIntsAction = Expression.Variable(typeof(Action <int, int, int>), "threeIntsAction");
            var threeIntsCall   = Expression.Invoke(threeIntsAction, longVariable, longVariable, longVariable);

            var longArgumentListBlock = Expression.Block(new[] { longVariable, threeIntsAction }, threeIntsCall);

            var translated = ToReadableString(longArgumentListBlock);

            const string EXPECTED = @"
int thisVariableReallyHasAVeryLongNameIndeed;
Action<int, int, int> threeIntsAction;
threeIntsAction.Invoke(
    thisVariableReallyHasAVeryLongNameIndeed,
    thisVariableReallyHasAVeryLongNameIndeed,
    thisVariableReallyHasAVeryLongNameIndeed);";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslatedMultipleLineValueBlockAssignments()
        {
            var linqSelect   = CreateLambda((string[] ints) => ints.Select(int.Parse));
            var selectMethod = ((MethodCallExpression)linqSelect.Body).Method;

            var getStringArray = CreateLambda(() => new[] { "1", "2", "blah" });
            var stringArray    = getStringArray.Body;

            // ReSharper disable once RedundantAssignment
            var intTryParse     = CreateLambda((string str, int value) => int.TryParse(str, out value) ? value : 0);
            var stringParameter = intTryParse.Parameters[0];
            var intVariable     = intTryParse.Parameters[1];
            var tryParseTernary = intTryParse.Body;

            var tryParseBlock  = Expression.Block(new[] { intVariable }, tryParseTernary);
            var tryParseLambda = Expression.Lambda <Func <string, int> >(tryParseBlock, stringParameter);

            var selectCall = Expression.Call(selectMethod, stringArray, tryParseLambda);

            var linqToArray   = CreateLambda((IEnumerable <int> ints) => ints.ToArray());
            var toArrayMethod = ((MethodCallExpression)linqToArray.Body).Method;

            var toArrayCall = Expression.Call(toArrayMethod, selectCall);

            var resultVariable  = Expression.Variable(typeof(IList <int>), "result");
            var assignment      = Expression.Assign(resultVariable, toArrayCall);
            var assignmentBlock = Expression.Block(assignment);

            var translation = ToReadableString(assignmentBlock);

            const string EXPECTED = @"
IList<int> result = new[] { ""1"", ""2"", ""blah"" }
    .Select(str =>
    {
        int value;
        return int.TryParse(str, out value) ? value : 0;
    })
    .ToArray();";

            translation.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldLeaveABlankLineBeforeAnIfStatement()
        {
            var intVariable              = Expression.Variable(typeof(int), "i");
            var zero                     = Expression.Constant(0);
            var intVariableEqualsZero    = Expression.Equal(intVariable, zero);
            var doNothing                = Expression.Default(typeof(void));
            var ifIntEqualsZeroDoNothing = Expression.IfThen(intVariableEqualsZero, doNothing);

            var block = Expression.Block(new[] { intVariable }, ifIntEqualsZeroDoNothing);

            const string EXPECTED = @"
int i;

if (i == 0)
{
}";

            var translated = ToReadableString(block);

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldNotVarAssignATernaryValueWithDifferingTypeBranches()
        {
            var intVariable          = Expression.Variable(typeof(int), "i");
            var intVariableEqualsOne = Expression.Equal(intVariable, Expression.Constant(1));
            var newArray             = Expression.NewArrayBounds(typeof(int?), Expression.Constant(0));
            var newList = Expression.New(typeof(List <int?>));

            var newArrayOrList = Expression.Condition(
                intVariableEqualsOne,
                newArray,
                newList,
                typeof(ICollection <int?>));

            var resultVariable = Expression.Variable(typeof(ICollection <int?>), "result");
            var assignResult   = Expression.Assign(resultVariable, newArrayOrList);
            var assignBlock    = Expression.Block(new[] { resultVariable }, assignResult);

            var translated = ToReadableString(assignBlock);

            translated.ShouldBe("ICollection<int?> result = (i == 1) ? new int?[0] : new List<int?>();");
        }
        public void ShouldTranslateAVariableBlockWithNoReturnValue()
        {
            var countVariable     = Expression.Variable(typeof(int), "count");
            var assignZeroToCount = Expression.Assign(countVariable, Expression.Constant(0));
            var incrementCount    = Expression.Increment(countVariable);
            var returnVoid        = Expression.Default(typeof(void));

            var countBlock = Expression.Block(
                new[] { countVariable },
                assignZeroToCount,
                incrementCount,
                returnVoid);

            var translated = ToReadableString(countBlock);

            const string EXPECTED = @"
var count = 0;
++count;";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
Exemple #11
0
        public void ShouldTranslateAMultipleLineIfStatement()
        {
            var intVariable            = Expression.Variable(typeof(int), "i");
            var one                    = Expression.Constant(1);
            var intVariableLessThanOne = Expression.LessThan(intVariable, one);
            var writeHello             = CreateLambda(() => Console.WriteLine("Hello"));
            var writeThere             = CreateLambda(() => Console.WriteLine("There"));
            var writeBlock             = Expression.Block(writeHello.Body, writeThere.Body);
            var ifLessThanOneThenWrite = Expression.IfThen(intVariableLessThanOne, writeBlock);

            var translated = ToReadableString(ifLessThanOneThenWrite);

            const string EXPECTED = @"
if (i < 1)
{
    Console.WriteLine(""Hello"");
    Console.WriteLine(""There"");
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateABlockAssignmentResultAssignment()
        {
            var longVariable         = Expression.Variable(typeof(long), "i");
            var intVariable          = Expression.Variable(typeof(int), "j");
            var assignInt            = Expression.Assign(intVariable, Expression.Constant(10));
            var castAssignmentResult = Expression.Convert(assignInt, typeof(long));
            var assignIntBlock       = Expression.Block(castAssignmentResult);
            var setLongVariableToAssignmentResult = Expression.Assign(longVariable, assignIntBlock);

            var assignmentBlock = Expression.Block(
                new[] { longVariable, intVariable },
                setLongVariableToAssignmentResult);

            var translated = ToReadableString(assignmentBlock);

            const string EXPECTED = @"
int j;
var i = ((long)(j = 10));";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateSingleStatementValueBlockAssignments()
        {
            var valueConditional = GetReturnStatementBlock(out var existingInts);

            var singleStatementValueBlock = Expression.Block(
                new[] { existingInts },
                valueConditional);

            var resultVariable      = Expression.Variable(singleStatementValueBlock.Type, "result");
            var resultOneAssignment = Expression.Assign(resultVariable, singleStatementValueBlock);

            var translated = ToReadableString(resultOneAssignment);

            const string EXPECTED = @"
result =
{
    List<int> ints;
    return (ints == null)
        ? new List<int>()
        : {
            var enumerator = ints.GetEnumerator();
            while (true)
            {
                if (enumerator.MoveNext())
                {
                    var item = enumerator.Current;
                    ints.Add(item);
                }
                else
                {
                    break;
                }
            }

            return ints;
        };
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldNotLeaveDoubleBlankLinesBetweenInitAndIfStatements()
        {
            var writeWat = CreateLambda(() => Console.WriteLine("Wat"));
            var read     = CreateLambda <long>(() => Console.Read());

            var newMemoryStream  = Expression.New(typeof(MemoryStream));
            var positionProperty = newMemoryStream.Type.GetProperty("Position");
            var valueBlock       = Expression.Block(writeWat.Body, read.Body);
            // ReSharper disable once AssignNullToNotNullAttribute
            var positionInit     = Expression.Bind(positionProperty, valueBlock);
            var memoryStreamInit = Expression.MemberInit(newMemoryStream, positionInit);

            var intVariable             = Expression.Variable(typeof(int), "i");
            var one                     = Expression.Constant(1);
            var intVariableEqualsOne    = Expression.Equal(intVariable, one);
            var doNothing               = Expression.Default(typeof(void));
            var ifIntEqualsOneDoNothing = Expression.IfThen(intVariableEqualsOne, doNothing);

            var block = Expression.Block(memoryStreamInit, ifIntEqualsOneDoNothing);

            const string EXPECTED = @"
new MemoryStream
{
    Position = 
    {
        Console.WriteLine(""Wat"");

        return ((long)Console.Read());
    }
};

if (i == 1)
{
}";

            var translated = ToReadableString(block);

            translated.ShouldBe(EXPECTED.TrimStart());
        }
Exemple #15
0
        public void ShouldTranslateAShortCircuitingIfStatement()
        {
            var oneCastToDouble = Expression.Convert(Expression.Constant(1), typeof(double?));

            var ifTrueOne = Expression.IfThen(Expression.Constant(true), oneCastToDouble);

            var nullDouble = Expression.Constant(null, typeof(double?));

            var block = Expression.Block(ifTrueOne, nullDouble);

            var translated = ToReadableString(block);

            const string EXPECTED = @"
if (true)
{
    return (double?)1;
}

return null;";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateASwitchWithMultipleVariableAssignments()
        {
            var countVariable = Expression.Variable(typeof(int), "count");
            var intVariable   = Expression.Variable(typeof(int), "i");

            var switchStatement = Expression.Switch(
                intVariable,
                Expression.Assign(countVariable, Expression.Constant(0)),
                Enumerable
                .Range(1, 2)
                .Select(i => Expression.SwitchCase(
                            Expression.Assign(countVariable, Expression.Constant(i * 2)),
                            Expression.Constant(i)))
                .ToArray());

            var switchBlock = Expression.Block(new[] { countVariable }, switchStatement);

            var translated = ToReadableString(switchBlock);

            const string EXPECTED = @"
int count;

switch (i)
{
    case 1:
        count = 2;
        break;

    case 2:
        count = 4;
        break;

    default:
        count = 0;
        break;
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateAMemberInitReturnValue()
        {
            var company    = Expression.Variable(typeof(Company), "c");
            var ceo        = Expression.Variable(typeof(Employee), "ceo");
            var ceoAddress = Expression.Property(ceo, "Address");

            var assignCeo = Expression.Assign(ceo, Expression.Property(company, "Ceo"));

            var newAddress = Expression.MemberInit(
                Expression.New(typeof(Address).GetPublicInstanceConstructor()),
                Expression.Bind(
                    typeof(Address).GetPublicInstanceMember("Line1"),
                    Expression.Property(ceoAddress, "Line1")));

            var newEmployee = Expression.MemberInit(
                Expression.New(typeof(Employee).GetPublicInstanceConstructor()),
                Expression.Bind(
                    typeof(Employee).GetPublicInstanceMember("Address"),
                    newAddress)
                );

            var block = Expression.Block(assignCeo, newEmployee);

            var translated = ToReadableString(block);

            const string EXPECTED = @"
var ceo = c.Ceo;

return new WhenTranslatingBlocks.Employee
{
    Address = new WhenTranslatingBlocks.Address
    {
        Line1 = ceo.Address.Line1
    }
};";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateAMultiLineCheckedSubtractionAssignment()
        {
            var intVariable = Expression.Variable(typeof(int), "i");

            var consoleRead = CreateLambda(() => Console.Read());

            var variableOne = Expression.Variable(typeof(int), "one");
            var variableTwo = Expression.Variable(typeof(int), "two");

            var variableOneAssignment = Expression.Assign(variableOne, consoleRead.Body);
            var variableTwoAssignment = Expression.Assign(variableTwo, consoleRead.Body);

            var variableOnePlusTwo = Expression.Add(variableOne, variableTwo);

            var valueBlock = Expression.Block(
                new[] { variableOne, variableTwo },
                variableOneAssignment,
                variableTwoAssignment,
                variableOnePlusTwo);

            var substractOneAndAssign = Expression.SubtractAssignChecked(intVariable, valueBlock);

            var translated = ToReadableString(substractOneAndAssign);

            const string EXPECTED = @"
checked
{
    i -=
    {
        var one = Console.Read();
        var two = Console.Read();

        return (one + two);
    }
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTerminateAMultipleLineMemberInitAssignment()
        {
            var writeWat = CreateLambda(() => Console.WriteLine("Wat"));
            var read     = CreateLambda <long>(() => Console.Read());

            var newMemoryStream  = Expression.New(typeof(MemoryStream));
            var positionProperty = newMemoryStream.Type.GetProperty("Position");
            var valueBlock       = Expression.Block(writeWat.Body, read.Body);
            // ReSharper disable once AssignNullToNotNullAttribute
            var positionInit     = Expression.Bind(positionProperty, valueBlock);
            var memoryStreamInit = Expression.MemberInit(newMemoryStream, positionInit);

            var streamVariable = Expression.Variable(typeof(Stream), "stream");

            var assignStream = Expression.Assign(streamVariable, memoryStreamInit);

            var streamIsNull = Expression.Equal(streamVariable, Expression.Default(typeof(Stream)));

            var ifNullAssign = Expression.IfThen(streamIsNull, assignStream);

            var translated = ToReadableString(ifNullAssign);

            const string EXPECTED = @"
if (stream == null)
{
    stream = new MemoryStream
    {
        Position = 
        {
            Console.WriteLine(""Wat"");

            return ((long)Console.Read());
        }
    };
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateAReturnStatementWithAValue()
        {
            var returnTarget = Expression.Label(typeof(int));

            var returnOne = Expression.Return(returnTarget, Expression.Constant(1));
            var returnTwo = Expression.Return(returnTarget, Expression.Constant(2));

            var numberParameter = Expression.Parameter(typeof(string), "i");
            var numberEqualsOne = Expression.Equal(numberParameter, Expression.Constant("One"));

            var ifOneReturnOneElseTwo = Expression.IfThenElse(numberEqualsOne, returnOne, returnTwo);

            var returnLabel = Expression.Label(returnTarget, Expression.Constant(0));
            var gotoBlock   = Expression.Block(ifOneReturnOneElseTwo, returnLabel);

            var gotoLambda = Expression.Lambda <Func <string, int> >(gotoBlock, numberParameter);

            gotoLambda.Compile();

            var translated = ToReadableString(gotoLambda);

            const string EXPECTED = @"
i =>
{
    if (i == ""One"")
    {
        return 1;
    }
    else
    {
        return 2;
    }

    return 0;
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateAVariableAssignmentWithinACondition()
        {
            var countVariable                  = Expression.Variable(typeof(int), "count");
            var assignFiveToCount              = Expression.Assign(countVariable, Expression.Constant(5));
            var isResultLessThanTen            = Expression.LessThan(assignFiveToCount, Expression.Constant(10));
            var ifResultIsLessThanTenDoNothing = Expression.IfThen(isResultLessThanTen, Expression.Default(typeof(void)));

            var countBlock  = Expression.Block(new[] { countVariable }, ifResultIsLessThanTenDoNothing);
            var countLambda = Expression.Lambda <Action>(countBlock);

            var translated = ToReadableString(countLambda);

            const string EXPECTED = @"() =>
{
    int count;

    if ((count = 5) < 10)
    {
    }
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateAVariableBlockLambdaWithNoReturnValue()
        {
            var countVariable    = Expression.Variable(typeof(short), "count");
            var assignTenToCount = Expression.Assign(countVariable, Expression.Constant((short)10));
            var decrementCount   = Expression.Decrement(countVariable);

            var countBlock = Expression.Block(
                new[] { countVariable },
                assignTenToCount,
                decrementCount);

            var countLambda = Expression.Lambda <Action>(countBlock);

            var translated = ToReadableString(countLambda);

            const string EXPECTED = @"() =>
{
    var count = 10;
    --count;
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateATryCatchFinally()
        {
            var writeHello             = CreateLambda(() => Console.Write("Hello"));
            var writeNotSupported      = CreateLambda((NotSupportedException ex) => Console.Write("NotSupported!"));
            var notSupportedCatchBlock = Expression.Catch(writeNotSupported.Parameters.First(), writeNotSupported.Body);
            var writeException         = CreateLambda((Exception ex) => Console.Write(ex));
            var topLevelCatchBlock     = Expression.Catch(writeException.Parameters.First(), writeException.Body);

            var writeFinished = CreateLambda(() => Console.WriteLine("Finished!"));
            var writeGoodbye  = CreateLambda(() => Console.Write("Goodbye"));
            var finallyBlock  = Expression.Block(writeFinished.Body, writeGoodbye.Body);

            var tryCatchFinally = Expression.TryCatchFinally(writeHello.Body, finallyBlock, notSupportedCatchBlock, topLevelCatchBlock);

            var translated = ToReadableString(tryCatchFinally);

            const string EXPECTED = @"
try
{
    Console.Write(""Hello"");
}
catch (NotSupportedException)
{
    Console.Write(""NotSupported!"");
}
catch (Exception ex)
{
    Console.Write(ex);
}
finally
{
    Console.WriteLine(""Finished!"");
    Console.Write(""Goodbye"");
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateAReturnStatementWithABlock()
        {
            var returnLabelTarget = Expression.Label(typeof(int));

            var intVariable         = Expression.Variable(typeof(int), "i");
            var variableInit        = Expression.Assign(intVariable, Expression.Constant(0));
            var variablePlusOne     = Expression.Add(intVariable, Expression.Constant(1));
            var variableAdditionOne = Expression.Assign(intVariable, variablePlusOne);
            var variablePlusTwo     = Expression.Add(intVariable, Expression.Constant(2));
            var variableAdditionTwo = Expression.Assign(intVariable, variablePlusTwo);

            var variableBlock = Expression.Block(
                new[] { intVariable },
                variableInit,
                variableAdditionOne,
                variableAdditionTwo,
                intVariable);

            var returnVariableBlock = Expression.Return(returnLabelTarget, variableBlock);

            var returnBlock = Expression.Block(returnVariableBlock);

            const string EXPECTED = @"
return 
{
    var i = 0;
    i = i + 1;
    i = i + 2;

    return i;
};";

            var translated = ToReadableString(returnBlock);

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldIncludeAReturnKeywordForANewObjectStatement()
        {
            var exception             = Expression.Variable(typeof(Exception), "ex");
            var newList               = Expression.New(typeof(List <string>).GetConstructors().First());
            var rethrow               = Expression.Rethrow(newList.Type);
            var globalCatchAndRethrow = Expression.Catch(exception, rethrow);
            var tryCatch              = Expression.TryCatch(newList, globalCatchAndRethrow);

            var tryCatchBlock = Expression.Block(tryCatch);

            var translated = ToReadableString(tryCatchBlock);

            const string EXPECTED = @"
try
{
    return new List<string>();
}
catch
{
    throw;
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateACheckedMultiplicationExpression()
        {
            var consoleRead = CreateLambda(() => Console.Read());

            var variableOne = Expression.Variable(typeof(int), "one");
            var variableTwo = Expression.Variable(typeof(int), "two");

            var variableOneAssignment = Expression.Assign(variableOne, consoleRead.Body);
            var variableTwoAssignment = Expression.Assign(variableTwo, consoleRead.Body);

            var variableOnePlusTwo = Expression.Add(variableOne, variableTwo);

            var valueOneBlock = Expression.Block(
                new[] { variableOne, variableTwo },
                variableOneAssignment,
                variableTwoAssignment,
                variableOnePlusTwo);

            var intVariable           = Expression.Parameter(typeof(int), "i");
            var checkedMultiplication = Expression.MultiplyChecked(valueOneBlock, intVariable);

            var translated = ToReadableString(checkedMultiplication);

            const string EXPECTED = @"
checked
{
    {
        var one = Console.Read();
        var two = Console.Read();

        return (one + two);
    } * i
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateANestedBlockAssignment()
        {
            var consoleRead = CreateLambda(() => Console.Read());

            var variableOne = Expression.Variable(typeof(int), "one");
            var variableTwo = Expression.Variable(typeof(int), "two");

            var variableOneAssignment = Expression.Assign(variableOne, consoleRead.Body);
            var variableTwoAssignment = Expression.Assign(variableTwo, consoleRead.Body);

            var variableOneMinusTwo = Expression.Subtract(variableOne, variableTwo);

            var valueBlock = Expression.Block(
                new[] { variableOne, variableTwo },
                variableOneAssignment,
                variableTwoAssignment,
                variableOneMinusTwo);

            var wrappingBlock = Expression.Block(valueBlock);

            var resultVariable      = Expression.Variable(typeof(int), "result");
            var resultOneAssignment = Expression.Assign(resultVariable, wrappingBlock);

            var translated = ToReadableString(resultOneAssignment);

            const string EXPECTED = @"
result =
{
    var one = Console.Read();
    var two = Console.Read();

    return (one - two);
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateAMultipleLineTernaryAssignment()
        {
            var consoleRead = CreateLambda(() => Console.Read());

            var variableOne       = Expression.Variable(typeof(int), "one");
            var variableTwo       = Expression.Variable(typeof(int), "two");
            var resultVariableOne = Expression.Variable(typeof(int), "resultOne");

            var variableOneAssignment = Expression.Assign(variableOne, consoleRead.Body);
            var variableTwoAssignment = Expression.Assign(variableTwo, consoleRead.Body);

            var variableOneTimesTwo = Expression.Multiply(variableOne, variableTwo);
            var resultOneAssignment = Expression.Assign(resultVariableOne, variableOneTimesTwo);

            var ifTrueBlock = Expression.Block(
                new[] { variableOne, variableTwo, resultVariableOne },
                variableOneAssignment,
                variableTwoAssignment,
                resultOneAssignment,
                resultVariableOne);

            var variableThree     = Expression.Variable(typeof(int), "three");
            var variableFour      = Expression.Variable(typeof(int), "four");
            var resultVariableTwo = Expression.Variable(typeof(int), "resultTwo");

            var variableThreeAssignment = Expression.Assign(variableThree, consoleRead.Body);
            var variableFourAssignment  = Expression.Assign(variableFour, consoleRead.Body);

            var variableThreeDivideFour = Expression.Divide(variableThree, variableFour);
            var resultTwoAssignment     = Expression.Assign(resultVariableTwo, variableThreeDivideFour);

            var ifFalseBlock = Expression.Block(
                new[] { variableThree, variableFour, resultVariableTwo },
                variableThreeAssignment,
                variableFourAssignment,
                resultTwoAssignment,
                resultVariableTwo);

            var dateTimeNow      = Expression.Property(null, typeof(DateTime), "Now");
            var nowHour          = Expression.Property(dateTimeNow, "Hour");
            var nowHourModuloTwo = Expression.Modulo(nowHour, Expression.Constant(2));
            var nowHourIsEven    = Expression.Equal(nowHourModuloTwo, Expression.Constant(0));

            var conditional = Expression.Condition(nowHourIsEven, ifTrueBlock, ifFalseBlock);

            var resultVariable   = Expression.Variable(typeof(int), "result");
            var resultAssignment = Expression.Assign(resultVariable, conditional);

            var translated = ToReadableString(resultAssignment);

            const string EXPECTED = @"
result = ((DateTime.Now.Hour % 2) == 0)
    ? {
        var one = Console.Read();
        var two = Console.Read();
        var resultOne = one * two;

        return resultOne;
    }
    : {
        var three = Console.Read();
        var four = Console.Read();
        var resultTwo = three / four;

        return resultTwo;
    }";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldVarAssignAVariableUsedInNestedConstructs()
        {
            var returnLabel    = Expression.Label(typeof(long), "Return");
            var streamVariable = Expression.Variable(typeof(Stream), "stream");

            var memoryStreamVariable   = Expression.Variable(typeof(MemoryStream), "memoryStream");
            var streamAsMemoryStream   = Expression.TypeAs(streamVariable, typeof(MemoryStream));
            var memoryStreamAssignment = Expression.Assign(memoryStreamVariable, streamAsMemoryStream);
            var nullMemoryStream       = Expression.Default(memoryStreamVariable.Type);
            var memoryStreamNotNull    = Expression.NotEqual(memoryStreamVariable, nullMemoryStream);
            var msLengthVariable       = Expression.Variable(typeof(long), "msLength");
            var memoryStreamLength     = Expression.Property(memoryStreamVariable, "Length");
            var msLengthAssignment     = Expression.Assign(msLengthVariable, memoryStreamLength);

            var msTryBlock = Expression.Block(new[] { msLengthVariable }, msLengthAssignment, msLengthVariable);
            var newNotSupportedException = Expression.New(typeof(NotSupportedException));
            var throwMsException         = Expression.Throw(newNotSupportedException, typeof(long));
            var msCatchBlock             = Expression.Catch(typeof(Exception), throwMsException);
            var memoryStreamTryCatch     = Expression.TryCatch(msTryBlock, msCatchBlock);
            var returnMemoryStreamResult = Expression.Return(returnLabel, memoryStreamTryCatch);
            var ifMemoryStreamTryCatch   = Expression.IfThen(memoryStreamNotNull, returnMemoryStreamResult);

            var fileStreamVariable   = Expression.Variable(typeof(FileStream), "fileStream");
            var streamAsFileStream   = Expression.TypeAs(streamVariable, typeof(FileStream));
            var fileStreamAssignment = Expression.Assign(fileStreamVariable, streamAsFileStream);
            var nullFileStream       = Expression.Default(fileStreamVariable.Type);
            var fileStreamNotNull    = Expression.NotEqual(fileStreamVariable, nullFileStream);
            var fsLengthVariable     = Expression.Variable(typeof(long), "fsLength");
            var fileStreamLength     = Expression.Property(fileStreamVariable, "Length");
            var fsLengthAssignment   = Expression.Assign(fsLengthVariable, fileStreamLength);

            var fsTryBlock             = Expression.Block(new[] { fsLengthVariable }, fsLengthAssignment, fsLengthVariable);
            var newIoException         = Expression.New(typeof(IOException));
            var throwIoException       = Expression.Throw(newIoException, typeof(long));
            var fsCatchBlock           = Expression.Catch(typeof(Exception), throwIoException);
            var fileStreamTryCatch     = Expression.TryCatch(fsTryBlock, fsCatchBlock);
            var returnFileStreamResult = Expression.Return(returnLabel, fileStreamTryCatch);
            var ifFileStreamTryCatch   = Expression.IfThen(fileStreamNotNull, returnFileStreamResult);

            var overallBlock = Expression.Block(
                new[] { memoryStreamVariable, fileStreamVariable },
                memoryStreamAssignment,
                ifMemoryStreamTryCatch,
                fileStreamAssignment,
                ifFileStreamTryCatch,
                Expression.Label(returnLabel, Expression.Constant(0L)));

            var overallCatchBlock = Expression.Catch(typeof(Exception), Expression.Constant(-1L));
            var overallTryCatch   = Expression.TryCatch(overallBlock, overallCatchBlock);

            const string EXPECTED = @"
try
{
    var memoryStream = stream as MemoryStream;

    if (memoryStream != null)
    {
        return 
        {
            try
            {
                var msLength = memoryStream.Length;

                return msLength;
            }
            catch
            {
                throw new NotSupportedException();
            }
        };
    }

    var fileStream = stream as FileStream;

    if (fileStream != null)
    {
        return 
        {
            try
            {
                var fsLength = fileStream.Length;

                return fsLength;
            }
            catch
            {
                throw new IOException();
            }
        };
    }

    return 0L;
}
catch
{
    return -1L;
}";

            var translated = ToReadableString(overallTryCatch);

            translated.ShouldBe(EXPECTED.TrimStart());
        }