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 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 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()); }
private Expression GetIdPartOrThrow(Expression idPart) { if (idPart.Type == typeof(object)) { if (idPart.NodeType == ExpressionType.Convert) { idPart = ((UnaryExpression)idPart).Operand; } return(GetStringIdPart(idPart)); } if (idPart.Type.IsSimple()) { return(GetStringIdPart(idPart)); } var typeIdentifier = _configInfo .MapperContext .GetIdentifierOrNull(idPart); if (typeIdentifier != null) { return(GetStringIdPart(typeIdentifier)); } // ReSharper disable once NotResolvedInText throw new MappingConfigurationException( "Unable to determine identifier for composite identifier part " + $"{idPart.ToReadableString()} of Type '{idPart.Type.GetFriendlyName()}'", new ArgumentNullException("idExpressions")); }
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 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 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 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 ShouldLeaveABlankLineAfterAMultipleLineExpression() { var longCallChain = CreateLambda((List <int> list) => list .Select(i => i * 2) .Select(i => i * 3) .Select(i => i * 4) .ToArray()); var longChainblock = Expression.Block(longCallChain.Body, longCallChain.Body); 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();"; var translated = ToReadableString(longChainblock); translated.ShouldBe(EXPECTED.TrimStart()); }
public void ShouldSplitMultipleArgumentListsOntoMultipleLines() { var intsMethod = typeof(HelperClass) .GetPublicInstanceMethod("GiveMeFourInts"); var helperVariable = Expression.Variable(typeof(HelperClass), "helper"); var intVariable = Expression.Variable(typeof(int), "intVariable"); var intsMethodCall = Expression.Call( helperVariable, intsMethod, intVariable, intVariable, intVariable, intVariable); var translated = ToReadableString(intsMethodCall); const string EXPECTED = @" helper.GiveMeFourInts( intVariable, intVariable, intVariable, intVariable)"; translated.ShouldBe(EXPECTED.TrimStart()); }
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 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 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 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 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 string Translate(Expression expression, TranslationContext context) { var conditional = (ConditionalExpression)expression; var hasNoElseCondition = HasNoElseCondition(conditional); var ifTrueBlock = context.TranslateCodeBlock(conditional.IfTrue); if (hasNoElseCondition) { return(IfStatement(GetTest(conditional, context), ifTrueBlock.WithCurlyBraces())); } var ifFalseBlock = context.TranslateCodeBlock(conditional.IfFalse); if (IsTernary(conditional)) { return(new FormattedTernary(conditional.Test, ifTrueBlock, ifFalseBlock, context)); } var test = GetTest(conditional, context); if (conditional.IfTrue.IsReturnable()) { return(ShortCircuitingIf(test, ifTrueBlock, ifFalseBlock)); } return(IfElse(test, ifTrueBlock, ifFalseBlock, IsElseIf(conditional))); }
private static bool CanBeConvertedToMethodGroup(Expression argument) { if (argument.NodeType != ExpressionType.Lambda) { return(false); } var argumentLambda = (LambdaExpression)argument; if (argumentLambda.Body.NodeType != ExpressionType.Call) { return(false); } var lambdaBodyMethodCall = (MethodCallExpression)argumentLambda.Body; var lambdaBodyMethodCallArguments = lambdaBodyMethodCall.Arguments.ToArray(); if (lambdaBodyMethodCall.Method.IsExtensionMethod()) { lambdaBodyMethodCallArguments = lambdaBodyMethodCallArguments.Skip(1).ToArray(); } if (lambdaBodyMethodCallArguments.Length != argumentLambda.Parameters.Count) { return(false); } var i = 0; var allArgumentTypesMatch = argumentLambda .Parameters .All(lambdaParameter => lambdaBodyMethodCallArguments[i++] == lambdaParameter); return(allArgumentTypesMatch); }
public string Translate(Expression expression, TranslationContext context) { var dynamicExpression = (DynamicExpression)expression; var operationDescription = dynamicExpression.ToString(); // DynamicExpressions are created with CallSiteBinders which are created // via language-specific assemblies (e.g. Microsoft.CSharp) to which this // assembly has no access; translating the descriptions provided by the // ToStrings of these assemblies (with a fallback) seems like the easiest // way to go. foreach (var translator in _translators) { if (translator.TryTranslate( operationDescription, dynamicExpression, context, out var translated)) { return(translated); } } return(operationDescription); }
private string TranslateArgumentAsCodeBlock(Expression argument) { var argumentBlock = _context.TranslateCodeBlock(argument); var translated = argumentBlock.WithCurlyBracesIfMultiStatement(); return(translated); }
public string Translate(Expression expression, TranslationContext context) { var debugInfo = (DebugInfoExpression)expression; string debugInfoText; if (debugInfo.IsClear) { debugInfoText = $"Clear debug info from {debugInfo.Document.FileName}"; } else { debugInfoText = string.Format( CultureInfo.InvariantCulture, "Debug to {0}, {1}, {2} -> {3}, {4}", debugInfo.Document.FileName, debugInfo.StartLine, debugInfo.StartColumn, debugInfo.EndLine, debugInfo.EndColumn); } var debugInfoComment = ReadableExpression.Comment(debugInfoText); return(context.Translate(debugInfoComment)); }
public void ShouldTranslateADefaultExpression() { var defaultInt = Expression.Default(typeof(uint)); var translated = ToReadableString(defaultInt); translated.ShouldBe("default(uint)"); }
private static bool KeepSurroundingParentheses(Expression expression) { switch (expression.NodeType) { case ExpressionType.Conditional: case ExpressionType.Lambda: return(true); case ExpressionType.Call: var parentExpression = expression.GetParentOrNull(); while (parentExpression != null) { expression = parentExpression; parentExpression = expression.GetParentOrNull(); } switch (expression.NodeType) { case ExpressionType.Add: case ExpressionType.Convert: case ExpressionType.Multiply: case ExpressionType.Subtract: return(true); } return(false); case ExpressionType.Invoke: var invocation = (InvocationExpression)expression; return(invocation.Expression.NodeType == ExpressionType.Lambda); } return(false); }
public void ShouldIgnoreADefaultVoidExpression() { var defaultVoid = Expression.Default(typeof(void)); var translated = ToReadableString(defaultVoid); translated.ShouldBeNull(); }
public void ShouldTranslateAVariableBlockLambdaWithAReturnExpression() { var listVariable = Expression.Variable(typeof(List <int>), "list"); var createList = CreateLambda(() => new List <int> { 1, 2, 3 }); var listAssignment = Expression.Assign(listVariable, createList.Body); var toArrayMethod = typeof(Enumerable).GetPublicStaticMethod("ToArray"); var typedToArrayMethod = toArrayMethod.MakeGenericMethod(typeof(int)); var listToArray = Expression.Call(typedToArrayMethod, listVariable); var listBlock = Expression.Block(new[] { listVariable }, listAssignment, listToArray); var listLambda = Expression.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()); }
private static void VerifyIsEscaped(string keyword) { var variable = Expression.Variable(typeof(bool), keyword); var translated = ToReadableString(variable); translated.ShouldBe("@" + keyword); }
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 ShouldTranslateATryWithATopLevelCatchWithExceptionUseAndRethrow() { var writeException = CreateLambda((Exception ex) => Console.Write(ex)); var exception = writeException.Parameters.First(); var writeHello = CreateLambda(() => Console.Write("Hello")); var rethrow = Expression.Throw(exception); var writeExceptionAndRethrow = Expression.Block(writeException.Body, rethrow); var globalCatch = Expression.Catch(exception, writeExceptionAndRethrow); var tryCatch = Expression.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 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()); }
internal static string GetAssignment( string target, ExpressionType assignmentType, Expression value, TranslationContext context) { var symbol = _symbolsByNodeType[assignmentType]; var valueString = (value.NodeType == ExpressionType.Default) ? DefaultExpressionTranslator.Translate((DefaultExpression)value) : GetValueTranslation(value, context); var assignment = target + " " + symbol; if (!valueString.StartsWithNewLine()) { assignment += " "; } assignment += valueString; assignment = AdjustForCheckedAssignmentIfAppropriate(assignmentType, assignment); return(assignment); }