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 ShouldNotWrapSingleExpressionTernaryConditionsInParentheses() { var ternary = Expression.Condition( Expression.Constant(false), Expression.Constant(1), Expression.Constant(2)); var translated = ToReadableString(ternary); translated.ShouldBe("false ? 1 : 2"); }
public void ShouldTranslateEnumComparisonTests() { var flagParameter = Expression.Parameter(typeof(bool), "flag"); var one = Expression.Constant(Test.One); var two = Expression.Constant(Test.Two); var oneOrTwo = Expression.Condition(flagParameter, one, two); var oneOrTwoEqualsTwo = Expression.Equal(oneOrTwo, two); var testLambda = Expression.Lambda <Func <bool, bool> >(oneOrTwoEqualsTwo, flagParameter); var translated = ToReadableString(testLambda); translated.ShouldBe("flag => (flag ? Test.One : Test.Two) == Test.Two"); }
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)"); }
public void ShouldNotWrapMethodCallTernaryConditionsInParentheses() { var method = typeof(MethodCallHelper).GetPublicInstanceMethod("MultipleParameterMethod"); var methodCall = Expression.Call( Expression.Variable(typeof(MethodCallHelper), "helper"), method, Expression.Constant("hello"), Expression.Constant(123)); var ternary = Expression.Condition( methodCall, Expression.Constant(1), Expression.Constant(2)); var translated = ToReadableString(ternary); translated.ShouldBe("helper.MultipleParameterMethod(\"hello\", 123) ? 1 : 2"); }
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 ShouldOnlyRemoveParenthesesIfNecessary() { var intVariable = Expression.Variable(typeof(int), "i"); var intVariableIsOne = Expression.Equal(intVariable, Expression.Constant(1)); var objectVariable = Expression.Variable(typeof(object), "o"); var objectCastToInt = Expression.Convert(objectVariable, typeof(int)); var intToStringMethod = typeof(object).GetPublicInstanceMethod("ToString"); var intToStringCall = Expression.Call(objectCastToInt, intToStringMethod); var emptyString = CreateLambda(() => string.Empty); var toStringOrEmptyString = Expression.Condition( intVariableIsOne, emptyString.Body, intToStringCall); var translated = ToReadableString(toStringOrEmptyString); translated.ShouldBe("(i == 1) ? string.Empty : ((int)o).ToString()"); }
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 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 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 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()); }