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 ShouldTranslateANewExpressionWithAMultiLineInitialisationValue() { var writeWat = CreateLambda(() => Console.WriteLine("Wat")); var read = CreateLambda <long>(() => Console.Read()); var newMemoryStream = Expression.New(typeof(MemoryStream)); var positionProperty = newMemoryStream.Type.GetPublicInstanceProperty(nameof(MemoryStream.Position)); var valueBlock = Expression.Block(writeWat.Body, writeWat.Body, read.Body); var positionInit = Expression.Bind(positionProperty, valueBlock); var memoryStreamInit = Expression.MemberInit(newMemoryStream, positionInit); var translated = ToReadableString(memoryStreamInit); const string EXPECTED = @" new MemoryStream { Position = { Console.WriteLine(""Wat""); Console.WriteLine(""Wat""); return (long)Console.Read(); } }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateAGotoReturnStatement() { var returnTarget = Label(typeof(int), "Return"); var numberParameter = Parameter(typeof(string), "i"); var numberEqualsOne = Equal(numberParameter, Constant("One")); var returnOne = Goto(returnTarget, Constant(1)); var ifOneReturnOne = IfThen(numberEqualsOne, returnOne); var returnLabel = Label(returnTarget, Constant(0)); var gotoBlock = Block(ifOneReturnOne, returnLabel); var gotoLambda = Lambda <Func <string, int> >(gotoBlock, numberParameter); gotoLambda.Compile(); var translated = gotoLambda.ToReadableString(); const string EXPECTED = @" i => { if (i == ""One"") { return 1; } return 0; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateAMultipleVariableBlockWithNoReturnValue() { var countOneVariable = Variable(typeof(int), "countOne"); var countTwoVariable = Variable(typeof(int), "countTwo"); var countThreeVariable = Variable(typeof(byte), "countThree"); var assignOneToCountOne = Assign(countOneVariable, Constant(1)); var assignTwoToCountTwo = Assign(countTwoVariable, Constant(2)); var sumCounts = Add(countOneVariable, countTwoVariable); var castSumToBye = Convert(sumCounts, typeof(byte)); var assignSumToCountThree = Assign(countThreeVariable, castSumToBye); var countBlock = 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 ShouldIncludeAReturnKeywordForANewListInitStatement() { var exception = Variable(typeof(Exception), "ex"); var listConstructor = typeof(List <int>).GetConstructor(new[] { typeof(int) }); var one = Constant(1); // ReSharper disable once AssignNullToNotNullAttribute var newList = New(listConstructor, one); var newListInit = ListInit(newList, one); var rethrow = Rethrow(newListInit.Type); var globalCatchAndRethrow = Catch(exception, rethrow); var tryCatch = TryCatch(newListInit, globalCatchAndRethrow); var tryCatchBlock = Block(tryCatch); var translated = ToReadableString(tryCatchBlock); const string EXPECTED = @" try { return new List<int>(1) { 1 }; } catch { throw; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldLeaveABlankLineAfterAMultipleLineExpression() { var longCallChain = CreateLambda((List <int> list) => list .Select(i => i * 2) .Select(i => i * 3) .Select(i => i * 4) .ToArray()); var longChainblock = Block(longCallChain.Body, longCallChain.Body); var translated = longChainblock.ToReadableString(); const string EXPECTED = @" list .Select(i => i * 2) .Select(i => i * 3) .Select(i => i * 4) .ToArray(); return list .Select(i => i * 2) .Select(i => i * 3) .Select(i => i * 4) .ToArray();"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateAVariableBlockLambdaWithAReturnValue() { var countVariable = Variable(typeof(ushort), "count"); var countEqualsZero = Assign(countVariable, Constant((ushort)0)); var incrementCount = Increment(countVariable); var returnCount = countVariable; var countBlock = Block( new[] { countVariable }, countEqualsZero, incrementCount, returnCount); var countLambda = Lambda <Func <ushort> >(countBlock); var translated = ToReadableString(countLambda); const string EXPECTED = @"() => { var count = 0; ++count; return count; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateATryWithATopLevelCatchWithExceptionUseAndRethrow() { var writeException = CreateLambda((Exception ex) => Console.Write(ex)); var exception = writeException.Parameters.First(); var writeHello = CreateLambda(() => Console.Write("Hello")); var rethrow = Throw(exception); var writeExceptionAndRethrow = Block(writeException.Body, rethrow); var globalCatch = Catch(exception, writeExceptionAndRethrow); var tryCatch = TryCatch(writeHello.Body, globalCatch); var translated = ToReadableString(tryCatch); const string EXPECTED = @" try { Console.Write(""Hello""); } catch (Exception ex) { Console.Write(ex); throw; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateATryWithATopLevelCatchWithAWrappedExceptionThrow() { var exception = Variable(typeof(Exception), "ex"); var writeBoom = CreateLambda(() => Console.Write("BOOM?")); var wrappedException = New( // ReSharper disable once AssignNullToNotNullAttribute typeof(InvalidOperationException).GetConstructor(new[] { typeof(string), typeof(Exception) }), Constant("Wrapped!"), exception); var throwWrapped = Throw(wrappedException); var globalCatch = Catch(exception, throwWrapped); var tryCatch = 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 ShouldTranslateAPropertyAssignment() { var arg1 = Parameter(typeof(PublicInt), "myClass"); var arg2 = Parameter(typeof(PublicInt), "myclass"); var arg1Value = Property(arg1, "Value"); var arg2Value = Property(arg2, "Value"); var assignArg1ValueToArg2 = Assign(arg1Value, arg2Value); var assignmentBlock = Block(assignArg1ValueToArg2, assignArg1ValueToArg2); var assignAndReturn = Block(assignmentBlock, arg1); var assignmentLambda = Lambda <Func <PublicInt, PublicInt, PublicInt> >( assignAndReturn, arg1, arg2); var translated = ToReadableString(assignmentLambda); const string EXPECTED = @" (myClass, myclass) => { myClass.Value = myclass.Value; myClass.Value = myclass.Value; return myClass; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldAssignTheResultOfATryCatch() { var intVariable = Variable(typeof(int), "i"); var assignIntToZero = Assign(intVariable, Constant(0)); var read = CreateLambda(() => Console.Read()); var returnDefault = Catch(typeof(IOException), Default(typeof(int))); var readOrDefault = TryCatch(read.Body, returnDefault); var assignReadOrDefault = Assign(intVariable, readOrDefault); var assignmentBlock = Block(new[] { intVariable }, assignIntToZero, assignReadOrDefault); var translated = ToReadableString(assignmentBlock); const string EXPECTED = @" var i = 0; i = { try { return Console.Read(); } catch (IOException) { return default(int); } };"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateMultiParameterCallParamsArrayArgument() { var stringJoinMethod = typeof(string) .GetPublicStaticMethods("Join") .First(m => (m.GetParameters().Length == 2) && (m.GetParameters()[0].ParameterType == typeof(string)) && (m.GetParameters()[1].ParameterType == typeof(string[]))); var stringEmpty = Expression.Field(null, typeof(string).GetPublicStaticField("Empty")); var expressions = new Expression[] { Expression.Constant("Value["), Expression.Constant("0"), Expression.Constant("]") }; var newStringArray = Expression.NewArrayInit(typeof(string), expressions); var stringJoinCall = Expression.Call(stringJoinMethod, stringEmpty, newStringArray); var translated = stringJoinCall.ToReadableString(); // string.Join(string, string[]) in .NET 3.5 doesn't take a params array: #if NET35 const string EXPECTED = @" string.Join(string.Empty, new[] { ""Value["", ""0"", ""]"" })"; #else const string EXPECTED = @" string.Join( string.Empty, ""Value["", ""0"", ""]"")"; #endif translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateANewAonymousTypeExpressionWithAMultiLineCtorValue() { var writeBlah = CreateLambda(() => Console.WriteLine("Blah")); var read = CreateLambda <long>(() => Console.Read()); var anonType = new { LongValue = default(long) }.GetType(); var constructor = anonType.GetPublicInstanceConstructor(typeof(long)); var valueBlock = Block(writeBlah.Body, writeBlah.Body, read.Body); var newAnonType = New(constructor, valueBlock); var translated = newAnonType.ToReadableString(); const string EXPECTED = @" new { LongValue = { Console.WriteLine(""Blah""); Console.WriteLine(""Blah""); return (long)Console.Read(); } }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldFormatGotoTargetLabels() { 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 ShouldPlaceSingleArgumentLambdaParametersOnMethodNameLine() { var stringParam1 = Parameter(typeof(string), "string1"); var stringParam2 = Parameter(typeof(string), "string2"); var writeString = CreateLambda(() => Console.WriteLine("String!")).Body; var writeStringsBlock = Block(writeString, writeString, writeString); var stringLambda = Lambda <Action <string, string> >( writeStringsBlock, stringParam1, stringParam2); var lambdaMethod = typeof(HelperClass).GetPublicStaticMethod("GiveMeALambda"); var lambdaMethodCall = Call(lambdaMethod, stringLambda); var translated = lambdaMethodCall.ToReadableString(); const string EXPECTED = @" HelperClass.GiveMeALambda((string1, string2) => { Console.WriteLine(""String!""); Console.WriteLine(""String!""); Console.WriteLine(""String!""); })"; translated.ShouldBe(EXPECTED.TrimStart()); }
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 = Variable(typeof(int), "intValue"); var dictionaryVariable = Variable(typeof(Dictionary <string, int>), "dictionary_String_IntValues"); var tryGetValueMethod = dictionaryVariable.Type.GetPublicInstanceMethod("TryGetValue", 2); var key = Constant("NumberThatIWantToGet"); var tryGetValueCall = Call(dictionaryVariable, tryGetValueMethod, key, intVariable); var defaultInt = Default(typeof(int)); var valueOrDefault = Condition(tryGetValueCall, intVariable, defaultInt); var valueOrDefaultBlock = Block(new[] { intVariable }, valueOrDefault); var helperCtor = typeof(HelperClass).GetPublicInstanceConstructors().First(); var helper = New(helperCtor, defaultInt, defaultInt, defaultInt); var intsMethod = helper.Type.GetPublicInstanceMethod(nameof(HelperClass.GiveMeSomeInts)); var methodCall = Call(helper, intsMethod, defaultInt, valueOrDefaultBlock, defaultInt); var translated = methodCall.ToReadableString(); 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 ShouldDeclareAVariableIfUsedBeforeInitialisation() { var nameVariable = Variable(typeof(string), "name"); var getNameVariable = Variable(typeof(Func <string>), "getName"); var getNameLambda = Lambda(nameVariable); var getNameAssignment = Assign(getNameVariable, getNameLambda); var nameAssignment = Assign(nameVariable, Constant("Fred")); var getNameCall = Invoke(getNameVariable); var block = Block( new[] { nameVariable, getNameVariable }, getNameAssignment, nameAssignment, getNameCall); var translated = block.ToReadableString(); const string EXPECTED = @" string name; Func<string> getName = () => name; name = ""Fred""; return getName.Invoke();"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldNotLeaveDoubleBlankLinesBetweenIfStatements() { var intVariable = Variable(typeof(int), "i"); var one = Constant(1); var intVariableEqualsOne = Equal(intVariable, one); var doNothing = Default(typeof(void)); var ifIntEqualsOneDoNothing = IfThen(intVariableEqualsOne, doNothing); var block = Block( new[] { intVariable }, ifIntEqualsOneDoNothing, ifIntEqualsOneDoNothing); var translated = block.ToReadableString(); const string EXPECTED = @" int i; if (i == 1) { } if (i == 1) { }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldNotVarAssignAnOuterBlockDeclaredVariable() { var nameVariable = Variable(typeof(string), "name"); var writeNameTwiceVariable = Variable(typeof(Action), "writeNameTwice"); var writeLine = CreateLambda(() => Console.WriteLine(default(string))); var writeLineMethod = ((MethodCallExpression)writeLine.Body).Method; var writeLineCall = Call(writeLineMethod, nameVariable); var writeNameTwice = Block(writeLineCall, writeLineCall); var writeNameTwiceLambda = Lambda(writeNameTwice); var writeNameTwiceAssignment = Assign(writeNameTwiceVariable, writeNameTwiceLambda); var nameAssignment = Assign(nameVariable, Constant("Alice")); var writeNameTwiceCall = Invoke(writeNameTwiceVariable); var block = Block( new[] { nameVariable, writeNameTwiceVariable }, Block(writeNameTwiceAssignment), Block(nameAssignment, writeNameTwiceCall)); var translated = block.ToReadableString(); const string EXPECTED = @" string name; Action writeNameTwice = () => { Console.WriteLine(name); Console.WriteLine(name); }; name = ""Alice""; writeNameTwice.Invoke();"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateAVariableBlockLambdaWithAReturnExpression() { var listVariable = Variable(typeof(List <int>), "list"); var createList = CreateLambda(() => new List <int> { 1, 2, 3 }); var listAssignment = Assign(listVariable, createList.Body); var toArrayMethod = typeof(Enumerable).GetPublicStaticMethod("ToArray"); var typedToArrayMethod = toArrayMethod.MakeGenericMethod(typeof(int)); var listToArray = Call(typedToArrayMethod, listVariable); var listBlock = Block(new[] { listVariable }, listAssignment, listToArray); var listLambda = Lambda <Func <int[]> >(listBlock); var translated = ToReadableString(listLambda); const string EXPECTED = @"() => { var list = new List<int> { 1, 2, 3 }; return list.ToArray(); }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldVarAssignVariablesInSiblingBlocks() { var intVariable1 = Variable(typeof(int), "i"); var assignVariable1 = Assign(intVariable1, Constant(1)); var variable1Block = Block(new[] { intVariable1 }, assignVariable1); var intVariable2 = Variable(typeof(int), "j"); var assignVariable2 = Assign(intVariable2, Constant(2)); var variable2Block = Block(new[] { intVariable2 }, assignVariable2); var assign1Or2 = IfThenElse( Constant(true), variable1Block, variable2Block); var translated = assign1Or2.ToReadableString(); const string EXPECTED = @" if (true) { var i = 1; } else { var j = 2; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldIncludeAReturnKeywordForAnObjectInitStatement() { var exception = Variable(typeof(Exception), "ex"); var newAddress = New(typeof(Address).GetConstructors().First()); var line1Property = newAddress.Type.GetMember("Line1").First(); var line1Value = Constant("Over here"); var line1Init = Bind(line1Property, line1Value); var addressInit = MemberInit(newAddress, line1Init); var rethrow = Rethrow(newAddress.Type); var globalCatchAndRethrow = Catch(exception, rethrow); var tryCatch = TryCatch(addressInit, globalCatchAndRethrow); var tryCatchBlock = 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 = Assign(intVariable, Constant(10)); var assignmentBlock = Block(assignment, Default(typeof(void))); var catchBlock = Catch(typeof(Exception), Throw(newException)); var tryCatch = TryCatch(assignmentBlock, catchBlock); var tryCatchBlock = Block(new[] { intVariable }, tryCatch); var translated = tryCatchBlock.ToReadableString(); const string EXPECTED = @" int number; try { number = 10; } catch { throw new Exception(number.ToString()); }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldIncludeAReturnKeywordForANewArrayInitStatement() { var exception = Variable(typeof(Exception), "ex"); var zero = Constant(0, typeof(int)); var newArray = NewArrayInit(typeof(int), zero); var rethrow = Rethrow(newArray.Type); var globalCatchAndRethrow = Catch(exception, rethrow); var tryCatch = TryCatch(newArray, globalCatchAndRethrow); var tryCatchBlock = Block(tryCatch); var translated = ToReadableString(tryCatchBlock); const string EXPECTED = @" try { return new[] { 0 }; } catch { throw; }"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldSplitMultipleArgumentListsOntoMultipleLines() { var intsMethod = typeof(HelperClass) .GetPublicInstanceMethod("GiveMeFourInts"); var helperVariable = Variable(typeof(HelperClass), "helper"); var intVariable = Variable(typeof(int), "intVariable"); var intsMethodCall = Call( helperVariable, intsMethod, intVariable, intVariable, intVariable, intVariable); var translated = intsMethodCall.ToReadableString(); const string EXPECTED = @" helper.GiveMeFourInts( intVariable, intVariable, intVariable, intVariable)"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateADbSetQueryExpression() { var productQuery = new TestDbContext() .Products .AsNoTracking() .Where(p => p.Id > 10) .Select(p => new Product { Id = p.Id, Name = p.Name }); var translated = productQuery.Expression.ToReadableString(); const string EXPECTED = @" ObjectQuery<WhenTranslatingLambdas.Product> .MergeAs(MergeOption.NoTracking) .Where(p => p.Id > 10) .Select(p => new WhenTranslatingLambdas.Product { Id = p.Id, Name = p.Name })"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldIndentParamsArrayArgumentsInAnIfTest() { var stringTest = CreateLambda(() => JoinStrings(",", "[", "i", "]", "[", "j", "]", "[", "k", "]") != string.Empty); var doNothing = Default(typeof(void)); var ifTestDoNothing = IfThen(stringTest.Body, doNothing); const string EXPECTED = @" if (WhenFormattingCode.JoinStrings( "","", ""["", ""i"", ""]"", ""["", ""j"", ""]"", ""["", ""k"", ""]"") != string.Empty) { }"; var translated = ifTestDoNothing.ToReadableString(); translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldNotIncludeLabelNamesWithoutAGoto() { var returnLabelTarget = Label(typeof(bool), "ReturnTarget"); var intVariable = Variable(typeof(int), "i"); var variableLessThanOne = LessThan(intVariable, Constant(1)); var returnTrue = Return(returnLabelTarget, Constant(true)); var ifLessThanOneReturnTrue = IfThen(variableLessThanOne, returnTrue); var testBlock = Block( ifLessThanOneReturnTrue, Label(returnLabelTarget, Constant(false))); var translated = testBlock.ToReadableString(); const string EXPECTED = @" if (i < 1) { return true; } return false;"; translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldTranslateALoopWithAContinueStatement() { var intVariable = Variable(typeof(int), "i"); var intLessThanThree = LessThan(intVariable, Constant(3)); var incrementVariable = Increment(intVariable); var continueLoop = Continue(Label()); var incrementAndContinue = Block(incrementVariable, continueLoop); var ifLessThanThreeContinue = IfThen(intLessThanThree, incrementAndContinue); var writeFinished = CreateLambda(() => Console.Write("Finished!")); var returnFromLoop = Return(Label()); var loopBody = Block(ifLessThanThreeContinue, writeFinished.Body, returnFromLoop); var loop = Loop(loopBody, returnFromLoop.Target, continueLoop.Target); var translated = loop.ToReadableString(); const string EXPECTED = @" while (true) { if (i < 3) { ++i; continue; } Console.Write(""Finished!""); return; }"; translated.ShouldBe(EXPECTED.TrimStart()); }