public void ShouldNotLeaveDoubleBlankLinesBetweenIfStatements()
        {
            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(
                new[] { intVariable },
                ifIntEqualsOneDoNothing,
                ifIntEqualsOneDoNothing);

            const string EXPECTED = @"
int i;

if (i == 1)
{
}

if (i == 1)
{
}";

            var translated = ToReadableString(block);

            translated.ShouldBe(EXPECTED.TrimStart());
        }
示例#2
0
        public void ShouldIgnoreADefaultVoidExpression()
        {
            var defaultVoid = Expression.Default(typeof(void));
            var translated  = ToReadableString(defaultVoid);

            translated.ShouldBeNull();
        }
        public void ShouldAssignTheResultOfATryCatch()
        {
            var intVariable = Expression.Variable(typeof(int), "i");

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

            var returnDefault = Expression.Catch(typeof(IOException), Expression.Default(typeof(int)));
            var readOrDefault = Expression.TryCatch(read.Body, returnDefault);

            var assignReadOrDefault = Expression.Assign(intVariable, readOrDefault);

            var translated = ToReadableString(assignReadOrDefault);

            const string EXPECTED = @"
i =
{
    try
    {
        return Console.Read();
    }
    catch (IOException)
    {
        return default(int);
    }
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateAComplexMethodArgument()
        {
            var intVariable        = Expression.Variable(typeof(int), "intValue");
            var dictionaryVariable = Expression.Variable(typeof(Dictionary <string, int>), "dictionary_String_IntValues");
            var tryGetValueMethod  = dictionaryVariable.Type.GetPublicInstanceMethod("TryGetValue", 2);
            var key             = Expression.Constant("NumberThatIWantToGet");
            var tryGetValueCall = Expression.Call(dictionaryVariable, tryGetValueMethod, key, intVariable);

            var defaultInt          = Expression.Default(typeof(int));
            var valueOrDefault      = Expression.Condition(tryGetValueCall, intVariable, defaultInt);
            var valueOrDefaultBlock = Expression.Block(new[] { intVariable }, valueOrDefault);

            var helperCtor = typeof(HelperClass).GetPublicInstanceConstructors().First();
            var helper     = Expression.New(helperCtor, defaultInt, defaultInt, defaultInt);
            var intsMethod = helper.Type.GetPublicInstanceMethod(nameof(HelperClass.GiveMeSomeInts));
            var methodCall = Expression.Call(helper, intsMethod, defaultInt, valueOrDefaultBlock, defaultInt);

            var translated = ToReadableString(methodCall);

            const string EXPECTED = @"
new HelperClass(default(int), default(int), default(int)).GiveMeSomeInts(
    default(int),
    {
        int intValue;
        return dictionary_String_IntValues.TryGetValue(""NumberThatIWantToGet"", out intValue)
            ? intValue
            : default(int);
    },
    default(int))";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
示例#5
0
        public void ShouldTranslateADefaultExpression()
        {
            var defaultInt = Expression.Default(typeof(uint));
            var translated = ToReadableString(defaultInt);

            translated.ShouldBe("default(uint)");
        }
        public void ShouldIndentParamsArrayArgumentsInAnIfTest()
        {
            var stringTest = CreateLambda(() =>
                                          JoinStrings(",", "[", "i", "]", "[", "j", "]", "[", "k", "]") != string.Empty);

            var doNothing       = Expression.Default(typeof(void));
            var ifTestDoNothing = Expression.IfThen(stringTest.Body, doNothing);

            const string EXPECTED   = @"
if (WhenFormattingCode.JoinStrings(
    "","",
    ""["",
    ""i"",
    ""]"",
    ""["",
    ""j"",
    ""]"",
    ""["",
    ""k"",
    ""]"") != string.Empty)
{
}";
            var          translated = ToReadableString(ifTestDoNothing);

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldNotVarAssignAVariableAssignedInATryButUsedInACatch()
        {
            var exceptionFactory = CreateLambda((int number) => new Exception(number.ToString()));
            var intVariable      = exceptionFactory.Parameters.First();
            var newException     = exceptionFactory.Body;

            var assignment      = Expression.Assign(intVariable, Expression.Constant(10));
            var assignmentBlock = Expression.Block(assignment, Expression.Default(typeof(void)));

            var catchBlock    = Expression.Catch(typeof(Exception), Expression.Throw(newException));
            var tryCatch      = Expression.TryCatch(assignmentBlock, catchBlock);
            var tryCatchBlock = Expression.Block(new[] { intVariable }, tryCatch);

            var translated = ToReadableString(tryCatchBlock);

            const string EXPECTED = @"
int number;
try
{
    number = 10;
}
catch
{
    throw new Exception(number.ToString());
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldTranslateADefaultString()
        {
            var nullStringConstant = Expression.Default(typeof(string));

            var translated = ToReadableString(nullStringConstant);

            translated.ShouldBe("null");
        }
        public void ShouldNameAnUnnamedVariable()
        {
            var intVariable        = Expression.Variable(typeof(int));
            var assignDefaultToInt = Expression.Assign(intVariable, Expression.Default(typeof(int)));

            var translated = ToReadableString(assignDefaultToInt);

            translated.ShouldBe("@int = default(int)");
        }
        public void ShouldAbbreviateDefaultBooleanComparisons()
        {
            var boolVariable = Expression.Variable(typeof(bool), "couldBe");
            var boolIsFalse  = Expression.Equal(Expression.Default(typeof(bool)), boolVariable);

            var translated = ToReadableString(boolIsFalse);

            translated.ShouldBe("!couldBe");
        }
        public void ShouldTranslateAnAssignment()
        {
            var intVariable        = Expression.Variable(typeof(int), "i");
            var assignDefaultToInt = Expression.Assign(intVariable, Expression.Default(typeof(int)));

            var translated = ToReadableString(assignDefaultToInt);

            translated.ShouldBe("i = default(int)");
        }
示例#12
0
        public void ShouldUseFriendlyNamesForArrays()
        {
            var intArrayVariable = Expression.Variable(typeof(int[]), "ints");
            var assignNull       = Expression.Assign(intArrayVariable, Expression.Default(intArrayVariable.Type));
            var assignNullBlock  = Expression.Block(new[] { intArrayVariable }, assignNull);

            var translated = ToReadableString(assignNullBlock);

            translated.ShouldBe("var ints = default(int[]);");
        }
        private static Expression GetReturnStatementBlock(out ParameterExpression existingInts)
        {
            existingInts = Expression.Variable(typeof(List <int>), "ints");

            var existingIntsEnumerator = Expression.Variable(typeof(List <int> .Enumerator), "enumerator");
            var getEnumeratorMethod    = existingInts.Type.GetPublicInstanceMethod("GetEnumerator");
            var getEnumeratorCall      = Expression.Call(existingInts, getEnumeratorMethod);
            var enumeratorAssignment   = Expression.Assign(existingIntsEnumerator, getEnumeratorCall);

            var enumeratorMoveNextMethod = existingIntsEnumerator.Type.GetPublicInstanceMethod("MoveNext");
            var enumeratorMoveNextCall   = Expression.Call(existingIntsEnumerator, enumeratorMoveNextMethod);

            var enumeratorItem    = Expression.Variable(typeof(int), "item");
            var enumeratorCurrent = Expression.Property(existingIntsEnumerator, "Current");
            var itemAssignment    = Expression.Assign(enumeratorItem, enumeratorCurrent);

            var intsAddMethod = existingInts.Type.GetPublicInstanceMethod("Add");
            var intsAddCall   = Expression.Call(existingInts, intsAddMethod, enumeratorItem);

            var addItemBlock = Expression.Block(
                new[] { enumeratorItem },
                itemAssignment,
                intsAddCall);

            var loopBreakTarget = Expression.Label(typeof(void), "LoopBreak");

            var conditionallyAddItems = Expression.Condition(
                Expression.IsTrue(enumeratorMoveNextCall),
                addItemBlock,
                Expression.Break(loopBreakTarget));

            var addItemsLoop = Expression.Loop(conditionallyAddItems, loopBreakTarget);

            var populateExistingInts = Expression.Block(
                new[] { existingIntsEnumerator },
                enumeratorAssignment,
                addItemsLoop);

            var conditionFalseBlock = Expression.Block(
                populateExistingInts,
                existingInts);

            var valueConditional = Expression.Condition(
                Expression.Equal(existingInts, Expression.Default(existingInts.Type)),
                Expression.New(conditionFalseBlock.Type),
                conditionFalseBlock);

            return(valueConditional);
        }
        public void ShouldTranslateAssignmentsOfNestedVariableBlocksWithANestedTernaryReturnValue()
        {
            var objectVariable = Expression.Variable(typeof(object), "id");
            var objectValue    = Expression.Variable(typeof(object), "value");
            var longVariable   = Expression.Variable(typeof(long), "number");
            var longValue      = Expression.Variable(typeof(long), "numberValue");

            var longTryParse = Expression.Call(
                null,
                typeof(long).GetPublicStaticMethod("TryParse", parameterCount: 2),
                Expression.Call(objectVariable, typeof(object).GetPublicInstanceMethod("ToString")),
                longValue);

            var objectNotNull = Expression.NotEqual(objectVariable, Expression.Default(typeof(object)));
            var defaultlong   = Expression.Default(typeof(long));

            var objectAslongOrDefault = Expression.Condition(
                objectNotNull,
                Expression.Condition(longTryParse, longValue, defaultlong),
                defaultlong);

            var longParseInnerBlock = Expression.Block(new[] { longValue }, objectAslongOrDefault);

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

            var longAssignment = Expression.Assign(longVariable, longParseOuterBlock);

            var translated = ToReadableString(longAssignment);

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

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

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldWrapAnAssignmentTernaryTestInParentheses()
        {
            var intVariable1 = Expression.Variable(typeof(int), "i");
            var intVariable2 = Expression.Variable(typeof(int), "j");

            var intVariable2GreaterThanOne = Expression.GreaterThan(intVariable2, Expression.Constant(1));

            var threeOrDefault = Expression.Condition(
                intVariable2GreaterThanOne,
                Expression.Constant(3),
                Expression.Default(typeof(int)));

            var assignment = Expression.Assign(intVariable1, threeOrDefault);

            var translated = ToReadableString(assignment);

            translated.ShouldBe("i = (j > 1) ? 3 : default(int)");
        }
示例#16
0
        public void ShouldTranslateAssignmentOutcomeTests()
        {
            var intVariable   = Expression.Variable(typeof(int), "i");
            var intValue      = Expression.Constant(123);
            var intAssignment = Expression.Assign(intVariable, intValue);
            var intDefault    = Expression.Default(typeof(int));
            var assignmentResultNotDefault = Expression.NotEqual(intAssignment, intDefault);
            var doNothing             = Expression.Default(typeof(void));
            var ifNotdefaultDoNothing = Expression.IfThen(assignmentResultNotDefault, doNothing);

            var translated = ToReadableString(ifNotdefaultDoNothing);

            const string EXPECTED = @"
if ((i = 123) != default(int))
{
}";

            translated.ShouldBe(EXPECTED.TrimStart());
        }
        public void ShouldAssignAVariableInAMethodCallArgument()
        {
            var stringVariable          = Expression.Variable(typeof(string), "value");
            var setStringVariableToNull = Expression.Assign(stringVariable, Expression.Default(typeof(string)));

            var intVariable = Expression.Variable(typeof(int), "i");

            var intToStringMethod = typeof(int)
                                    .GetMethods()
                                    .First(m =>
                                           (m.Name == "ToString") &&
                                           (m.GetParameters().FirstOrDefault()?.ParameterType == typeof(string)));

            var intToString = Expression.Call(intVariable, intToStringMethod, setStringVariableToNull);

            var translated = ToReadableString(intToString);

            translated.ShouldBe("i.ToString(value = null)");
        }
        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 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());
        }
        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 ShouldTranslateMultilineConstructorParameters()
        {
            var consoleRead = CreateLambda(() => Console.Read());

            var catchAll   = Expression.Catch(typeof(Exception), Expression.Default(typeof(int)));
            var tryReadInt = Expression.TryCatch(consoleRead.Body, catchAll);

            var createStringBuilder = Expression.New(
                typeof(StringBuilder).GetPublicInstanceConstructor(typeof(int), typeof(int)),
                tryReadInt,
                tryReadInt);

            const string EXPECTED = @"
new StringBuilder(
    {
        try
        {
            return Console.Read();
        }
        catch
        {
            return default(int);
        }
    },
    {
        try
        {
            return Console.Read();
        }
        catch
        {
            return default(int);
        }
    })";

            var translated = ToReadableString(createStringBuilder);

            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());
        }
示例#23
0
        public void ShouldTranslateAnIfStatementWithAConditional()
        {
            var guidVariable        = Expression.Variable(typeof(Guid), "guid");
            var defaultGuid         = Expression.Default(typeof(Guid));
            var guidNotDefault      = Expression.NotEqual(guidVariable, defaultGuid);
            var guidEmpty           = Expression.Field(null, typeof(Guid), "Empty");
            var guidNotEmpty        = Expression.NotEqual(guidVariable, guidEmpty);
            var falseConstant       = Expression.Constant(false);
            var guidNotEmptyOrFalse = Expression.Condition(guidNotDefault, guidNotEmpty, falseConstant);
            var writeGuidFun        = CreateLambda(() => Console.Write("GUID FUN!"));
            var ifNotEmptyThenWrite = Expression.IfThen(guidNotEmptyOrFalse, writeGuidFun.Body);

            var translated = ToReadableString(ifNotEmptyThenWrite);

            const string EXPECTED = @"
if ((guid != default(Guid)) ? guid != Guid.Empty : false)
{
    Console.Write(""GUID FUN!"");
}";

            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 ShouldSplitLongTernaryOptionsOntoMultipleLines()
        {
            var oneEqualsTwo = Expression.Equal(Expression.Constant(1), Expression.Constant(2));

            var defaultInt = Expression.Default(typeof(int));

            var threeIntsFunc = Expression.Variable(typeof(Func <int, int, int, int>), "threeIntsFunc");
            var longVariable  = Expression.Variable(typeof(int), "thisVariableReallyHasAVeryLongNameIndeed");
            var threeIntsCall = Expression.Invoke(threeIntsFunc, longVariable, longVariable, longVariable);

            var ternary = Expression.Condition(oneEqualsTwo, defaultInt, threeIntsCall);

            var translated = ToReadableString(ternary);

            const string EXPECTED = @"
(1 == 2)
    ? default(int)
    : threeIntsFunc.Invoke(
        thisVariableReallyHasAVeryLongNameIndeed,
        thisVariableReallyHasAVeryLongNameIndeed,
        thisVariableReallyHasAVeryLongNameIndeed)";

            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 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());
        }