public void ShouldIncludeReturnKeywordsForConstantsAndCasts() { var nullLong = Expression.Constant(null, typeof(long?)); var writeOne = CreateLambda(() => Console.WriteLine("One!")); var oneCastToLong = Expression.Convert(Expression.Constant(1), typeof(long?)); var elseBlock = Expression.Block(writeOne.Body, writeOne.Body, oneCastToLong); var nullOrOne = Expression.IfThenElse(Expression.Constant(true), nullLong, elseBlock); var translated = ToReadableString(nullOrOne); const string EXPECTED = @" if (true) { return null; } Console.WriteLine(""One!""); Console.WriteLine(""One!""); return ((long?)1);"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateASwitchStatementWithMultiLineCases() { 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 writeOneTwo = Expression.Block(writeOne.Body, writeTwo.Body); var writeTwoThree = Expression.Block(writeTwo.Body, writeThree.Body); var switchStatement = Expression.Switch( intVariable, Expression.SwitchCase(writeOneTwo, Expression.Constant(12)), Expression.SwitchCase(writeTwoThree, Expression.Constant(23))); var translated = ToReadableString(switchStatement); const string EXPECTED = @" switch (i) { case 12: Console.WriteLine(""One""); Console.WriteLine(""Two""); break; case 23: Console.WriteLine(""Two""); Console.WriteLine(""Three""); break; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldDeclareAVariableIfUsedBeforeInitialisation() { var nameVariable = Expression.Variable(typeof(string), "name"); var getNameVariable = Expression.Variable(typeof(Func <string>), "getName"); var getNameLambda = Expression.Lambda(nameVariable); var getNameAssignment = Expression.Assign(getNameVariable, getNameLambda); var nameAssignment = Expression.Assign(nameVariable, Expression.Constant("Fred")); var getNameCall = Expression.Invoke(getNameVariable); var block = Expression.Block( new[] { nameVariable, getNameVariable }, getNameAssignment, nameAssignment, getNameCall); var translated = ToReadableString(block); const string EXPECTED = @" string name; Func<string> getName = () => name; name = ""Fred""; return getName.Invoke();"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldIncludeAReturnKeywordForANewArrayInitStatement() { var exception = Expression.Variable(typeof(Exception), "ex"); var zero = Expression.Constant(0, typeof(int)); var newArray = Expression.NewArrayInit(typeof(int), zero); var rethrow = Expression.Rethrow(newArray.Type); var globalCatchAndRethrow = Expression.Catch(exception, rethrow); var tryCatch = Expression.TryCatch(newArray, globalCatchAndRethrow); var tryCatchBlock = Expression.Block(tryCatch); var translated = ToReadableString(tryCatchBlock); const string EXPECTED = @" try { return new[] { 0 }; } catch { throw; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldVarAssignVariablesInSiblingBlocks() { var intVariable1 = Expression.Variable(typeof(int), "i"); var assignVariable1 = Expression.Assign(intVariable1, Expression.Constant(1)); var variable1Block = Expression.Block(new[] { intVariable1 }, assignVariable1); var intVariable2 = Expression.Variable(typeof(int), "j"); var assignVariable2 = Expression.Assign(intVariable2, Expression.Constant(2)); var variable2Block = Expression.Block(new[] { intVariable2 }, assignVariable2); var assign1Or2 = Expression.IfThenElse( Expression.Constant(true), variable1Block, variable2Block); var translated = ToReadableString(assign1Or2); const string EXPECTED = @" if (true) { var i = 1; } else { var j = 2; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateAMultipleLineIfStatementTest() { var intVariable = Expression.Variable(typeof(int), "i"); var one = Expression.Constant(1); var intVariableLessThanOne = Expression.LessThan(intVariable, one); var returnLabel = Expression.Label(typeof(bool), "Return"); var returnTrue = Expression.Return(returnLabel, Expression.Constant(true)); var ifLessThanOneReturnTrue = Expression.IfThen(intVariableLessThanOne, returnTrue); var five = Expression.Constant(5); var intVariableMoreThanFive = Expression.GreaterThan(intVariable, five); var returnMoreThanFive = Expression.Label(returnLabel, intVariableMoreThanFive); var testBlock = Expression.Block(ifLessThanOneReturnTrue, returnMoreThanFive); var writeHello = CreateLambda(() => Console.WriteLine("Hello")); var writeVariable = Expression.Variable(writeHello.Type, "write"); var assignWrite = Expression.Assign(writeVariable, writeHello); var ifTestPassesThenWrite = Expression.IfThen(testBlock, assignWrite); var translated = ToReadableString(ifTestPassesThenWrite); const string EXPECTED = @" if ({ if (i < 1) { return true; } return i > 5; }) { write = () => Console.WriteLine(""Hello""); }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldIncludeAReturnKeywordForAnObjectInitStatement() { var exception = Expression.Variable(typeof(Exception), "ex"); var newAddress = Expression.New(typeof(Address).GetConstructors().First()); var line1Property = newAddress.Type.GetMember("Line1").First(); var line1Value = Expression.Constant("Over here"); var line1Init = Expression.Bind(line1Property, line1Value); var addressInit = Expression.MemberInit(newAddress, line1Init); var rethrow = Expression.Rethrow(newAddress.Type); var globalCatchAndRethrow = Expression.Catch(exception, rethrow); var tryCatch = Expression.TryCatch(addressInit, globalCatchAndRethrow); var tryCatchBlock = Expression.Block(tryCatch); var translated = ToReadableString(tryCatchBlock); const string EXPECTED = @" try { return new WhenTranslatingBlocks.Address { Line1 = ""Over here"" }; } catch { throw; }"; 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 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()); }
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()); }
public void ShouldTranslateAMultipleVariableBlockWithNoReturnValue() { var countOneVariable = Expression.Variable(typeof(int), "countOne"); var countTwoVariable = Expression.Variable(typeof(int), "countTwo"); var countThreeVariable = Expression.Variable(typeof(byte), "countThree"); var assignOneToCountOne = Expression.Assign(countOneVariable, Expression.Constant(1)); var assignTwoToCountTwo = Expression.Assign(countTwoVariable, Expression.Constant(2)); var sumCounts = Expression.Add(countOneVariable, countTwoVariable); var castSumToBye = Expression.Convert(sumCounts, typeof(byte)); var assignSumToCountThree = Expression.Assign(countThreeVariable, castSumToBye); var countBlock = Expression.Block( new[] { countOneVariable, countTwoVariable, countThreeVariable }, assignOneToCountOne, assignTwoToCountTwo, assignSumToCountThree); var translated = ToReadableString(countBlock); const string EXPECTED = @" var countOne = 1; var countTwo = 2; var countThree = (byte)(countOne + countTwo);"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateAGotoReturnStatement() { var returnTarget = Expression.Label(typeof(int), "Return"); var numberParameter = Expression.Parameter(typeof(string), "i"); var numberEqualsOne = Expression.Equal(numberParameter, Expression.Constant("One")); var returnOne = Expression.Goto(returnTarget, Expression.Constant(1)); var ifOneReturnOne = Expression.IfThen(numberEqualsOne, returnOne); var returnLabel = Expression.Label(returnTarget, Expression.Constant(0)); var gotoBlock = Expression.Block(ifOneReturnOne, 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; } return 0; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateAMultipleLineNonVoidIfElseStatements() { var intVariable = Expression.Variable(typeof(int), "i"); var zero = Expression.Constant(0); var intVariableEqualsZero = Expression.Equal(intVariable, zero); var writeHello = CreateLambda(() => Console.WriteLine("Hello")); var writeGoodbye = CreateLambda(() => Console.WriteLine("Goodbye")); var helloThenGoodbye = Expression.Block(writeHello.Body, writeGoodbye.Body, intVariable); var goodbyeThenHello = Expression.Block(writeGoodbye.Body, writeHello.Body, intVariable); var writeHelloAndGoodbye = Expression.IfThenElse(intVariableEqualsZero, helloThenGoodbye, goodbyeThenHello); var translated = ToReadableString(writeHelloAndGoodbye); const string EXPECTED = @" if (i == 0) { Console.WriteLine(""Hello""); Console.WriteLine(""Goodbye""); return i; } Console.WriteLine(""Goodbye""); Console.WriteLine(""Hello""); return i; "; translated.ShouldBe(EXPECTED.Trim()); }
public void ShouldNotVarAssignAnOuterBlockDeclaredVariable() { var nameVariable = Expression.Variable(typeof(string), "name"); var writeNameTwiceVariable = Expression.Variable(typeof(Action), "writeNameTwice"); var writeLine = CreateLambda(() => Console.WriteLine(default(string))); var writeLineMethod = ((MethodCallExpression)writeLine.Body).Method; var writeLineCall = Expression.Call(writeLineMethod, nameVariable); var writeNameTwice = Expression.Block(writeLineCall, writeLineCall); var writeNameTwiceLambda = Expression.Lambda(writeNameTwice); var writeNameTwiceAssignment = Expression.Assign(writeNameTwiceVariable, writeNameTwiceLambda); var nameAssignment = Expression.Assign(nameVariable, Expression.Constant("Alice")); var writeNameTwiceCall = Expression.Invoke(writeNameTwiceVariable); var block = Expression.Block( new[] { nameVariable, writeNameTwiceVariable }, Expression.Block(writeNameTwiceAssignment), Expression.Block(nameAssignment, writeNameTwiceCall)); var translated = ToReadableString(block); const string EXPECTED = @" string name; Action writeNameTwice = () => { Console.WriteLine(name); Console.WriteLine(name); }; name = ""Alice""; writeNameTwice.Invoke();"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateALoopWithABreakStatement() { var intVariable = Expression.Variable(typeof(int), "i"); var intGreaterThanTwo = Expression.GreaterThan(intVariable, Expression.Constant(2)); var breakLoop = Expression.Break(Expression.Label()); var ifGreaterThanTwoBreak = Expression.IfThen(intGreaterThanTwo, breakLoop); var writeLine = CreateLambda(() => Console.WriteLine()); var incrementVariable = Expression.Increment(intVariable); var loopBody = Expression.Block(ifGreaterThanTwoBreak, writeLine.Body, incrementVariable); var loop = Expression.Loop(loopBody, breakLoop.Target); var translated = ToReadableString(loop); const string EXPECTED = @" while (true) { if (i > 2) { break; } Console.WriteLine(); ++i; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateALoopWithAContinueStatement() { var intVariable = Expression.Variable(typeof(int), "i"); var intLessThanThree = Expression.LessThan(intVariable, Expression.Constant(3)); var incrementVariable = Expression.Increment(intVariable); var continueLoop = Expression.Continue(Expression.Label()); var incrementAndContinue = Expression.Block(incrementVariable, continueLoop); var ifLessThanThreeContinue = Expression.IfThen(intLessThanThree, incrementAndContinue); var writeFinished = CreateLambda(() => Console.Write("Finished!")); var returnFromLoop = Expression.Return(Expression.Label()); var loopBody = Expression.Block(ifLessThanThreeContinue, writeFinished.Body, returnFromLoop); var loop = Expression.Loop(loopBody, returnFromLoop.Target, continueLoop.Target); var translated = ToReadableString(loop); const string EXPECTED = @" while (true) { if (i < 3) { ++i; continue; } Console.Write(""Finished!""); return; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldUnindentGotoTargetLabels() { var labelTargetOne = Expression.Label(typeof(void), "One"); var labelOne = Expression.Label(labelTargetOne); var gotoOne = Expression.Goto(labelTargetOne); var labelTargetTwo = Expression.Label(typeof(void), "Two"); var labelTwo = Expression.Label(labelTargetTwo); var gotoTwo = Expression.Goto(labelTargetTwo); var gotoBlock = Expression.Block(labelOne, gotoTwo, labelTwo, gotoOne); var ifTrueGoto = Expression.IfThen(Expression.Constant(true), gotoBlock); var translated = ToReadableString(ifTrueGoto); const string EXPECTED = @" if (true) { One: goto Two; Two: goto One; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateALabelWithABlockDefaultValue() { var returnLabelTarget = Expression.Label(typeof(int), "Return"); 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(variableAdditionTwo, intVariable); var returnVariableBlock = Expression.Label(returnLabelTarget, variableBlock); var returnBlock = Expression.Block( new[] { intVariable }, variableInit, variableAdditionOne, returnVariableBlock); const string EXPECTED = @" var i = 0; i = i + 1; return { i = i + 2; return i; };"; var translated = ToReadableString(returnBlock); translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldNotIncludeLabelNamesWithoutAGoto() { var returnLabelTarget = Expression.Label(typeof(bool), "ReturnTarget"); var intVariable = Expression.Variable(typeof(int), "i"); var variableLessThanOne = Expression.LessThan(intVariable, Expression.Constant(1)); var returnTrue = Expression.Return(returnLabelTarget, Expression.Constant(true)); var ifLessThanOneReturnTrue = Expression.IfThen(variableLessThanOne, returnTrue); var testBlock = Expression.Block( ifLessThanOneReturnTrue, Expression.Label(returnLabelTarget, Expression.Constant(false))); var translated = ToReadableString(testBlock); const string EXPECTED = @" if (i < 1) { return true; } return false;"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateATryWithATopLevelCatchWithAWrappedExceptionThrow() { var exception = Expression.Variable(typeof(Exception), "ex"); var writeBoom = CreateLambda(() => Console.Write("BOOM?")); var wrappedException = Expression.New( // ReSharper disable once AssignNullToNotNullAttribute typeof(InvalidOperationException).GetConstructor(new[] { typeof(string), typeof(Exception) }), Expression.Constant("Wrapped!"), exception); var throwWrapped = Expression.Throw(wrappedException); var globalCatch = Expression.Catch(exception, throwWrapped); var tryCatch = Expression.TryCatch(writeBoom.Body, globalCatch); var translated = ToReadableString(tryCatch); const string EXPECTED = @" try { Console.Write(""BOOM?""); } catch (Exception ex) { throw new InvalidOperationException(""Wrapped!"", ex); }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldIncludeAReturnKeywordForANewListInitStatement() { var exception = Expression.Variable(typeof(Exception), "ex"); var listConstructor = typeof(List <int>).GetConstructor(new[] { typeof(int) }); var one = Expression.Constant(1); // ReSharper disable once AssignNullToNotNullAttribute var newList = Expression.New(listConstructor, one); var newListInit = Expression.ListInit(newList, one); var rethrow = Expression.Rethrow(newListInit.Type); var globalCatchAndRethrow = Expression.Catch(exception, rethrow); var tryCatch = Expression.TryCatch(newListInit, globalCatchAndRethrow); var tryCatchBlock = Expression.Block(tryCatch); var translated = ToReadableString(tryCatchBlock); const string EXPECTED = @" try { return new List<int>(1) { 1 }; } catch { throw; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateAVariableBlockLambdaWithAReturnValue() { var countVariable = Expression.Variable(typeof(ushort), "count"); var countEqualsZero = Expression.Assign(countVariable, Expression.Constant((ushort)0)); var incrementCount = Expression.Increment(countVariable); var returnCount = countVariable; var countBlock = Expression.Block( new[] { countVariable }, countEqualsZero, incrementCount, returnCount); var countLambda = Expression.Lambda <Func <ushort> >(countBlock); var translated = ToReadableString(countLambda); const string EXPECTED = @"() => { var count = 0; ++count; return count; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateANonWholeNumberDecimal() { var decimalConstant = Expression.Constant(6373282.64738m, typeof(decimal)); var translated = ToReadableString(decimalConstant); translated.ShouldBe("6373282.64738m"); }
public void ShouldUseFriendlyNamesForGenericNestedTypes() { var genericListEnumeratorType = Expression.Constant(typeof(List <string> .Enumerator), typeof(Type)); var translated = ToReadableString(genericListEnumeratorType); translated.ShouldBe("typeof(List<string>.Enumerator)"); }
public void ShouldUseFriendlyNamesForNestedGenericTypes() { var genericListEnumeratorType = Expression.Constant(typeof(GenericTestHelper <int>), typeof(Type)); var translated = ToReadableString(genericListEnumeratorType); translated.ShouldBe("typeof(WhenGettingFriendlyNames.GenericTestHelper<int>)"); }
public void ShouldUseFriendlyNamesForMultiplyNestedTypes() { var nestedType = Expression.Constant(typeof(OuterClass.InnerClass.Nested), typeof(Type)); var translated = ToReadableString(nestedType); translated.ShouldBe("typeof(OuterClass.InnerClass.Nested)"); }
public void ShouldTranslateANonWholeNumberNullableFloat() { var floatConstant = Expression.Constant(12.34f, typeof(float?)); var translated = ToReadableString(floatConstant); translated.ShouldBe("12.34f"); }
public void ShouldTranslateAWholeNumberDouble() { var doubleConstant = Expression.Constant(999.0, typeof(double)); var translated = ToReadableString(doubleConstant); translated.ShouldBe("999d"); }
public void ShouldTranslateAWholeNumberFloat() { var floatConstant = Expression.Constant(890.0f, typeof(float)); var translated = ToReadableString(floatConstant); translated.ShouldBe("890f"); }
public void ShouldTranslateAWholeNumberNullableDecimal() { var decimalConstant = Expression.Constant(456.00m, typeof(decimal?)); var translated = ToReadableString(decimalConstant); translated.ShouldBe("456m"); }