From b6ff93256fada3aba2ac6dcd616c9b60fb8f6ea7 Mon Sep 17 00:00:00 2001 From: GrahamTheCoder Date: Sun, 18 Nov 2018 22:10:34 +0000 Subject: [PATCH] VB -> C#: Convert date literals - fixes #159 --- .../CSharp/CommonConversions.cs | 6 + .../CSharp/NodesVisitor.cs | 24 +- Tests/CSharp/ExpressionTests.cs | 368 ++---------------- Tests/CSharp/LinqExpressionTests.cs | 350 +++++++++++++++++ Tests/Tests.csproj | 1 + 5 files changed, 401 insertions(+), 348 deletions(-) create mode 100644 Tests/CSharp/LinqExpressionTests.cs diff --git a/ICSharpCode.CodeConverter/CSharp/CommonConversions.cs b/ICSharpCode.CodeConverter/CSharp/CommonConversions.cs index e14fd6ba5..06cd284f3 100644 --- a/ICSharpCode.CodeConverter/CSharp/CommonConversions.cs +++ b/ICSharpCode.CodeConverter/CSharp/CommonConversions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text; using ICSharpCode.CodeConverter.Shared; using ICSharpCode.CodeConverter.Util; using Microsoft.CodeAnalysis; @@ -183,6 +184,11 @@ internal ExpressionSyntax GetLiteralExpression(object value, string fullText = n if (value is char) return SyntaxFactory.LiteralExpression(Microsoft.CodeAnalysis.CSharp.SyntaxKind.CharacterLiteralExpression, SyntaxFactory.Literal((char)value)); + if (value is DateTime dt) { + var valueToOutput = dt.Date.Equals(dt) ? dt.ToString("yyyy-MM-dd") : dt.ToString("yyyy-MM-dd HH:mm:ss"); + return SyntaxFactory.ParseExpression("DateTime.Parse(\"" + valueToOutput + "\")"); + } + throw new ArgumentOutOfRangeException(nameof(value), value, null); } diff --git a/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs b/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs index d1383a488..3dd2755ea 100644 --- a/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs +++ b/ICSharpCode.CodeConverter/CSharp/NodesVisitor.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using SyntaxFactory = Microsoft.CodeAnalysis.CSharp.SyntaxFactory; using VBSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax; using VBasic = Microsoft.CodeAnalysis.VisualBasic; using SyntaxToken = Microsoft.CodeAnalysis.SyntaxToken; @@ -821,10 +822,7 @@ public override CSharpSyntaxNode VisitParameter(VBSyntax.ParameterSyntax node) returnType = arrayType.WithElementType(SyntaxFactory.NullableType(arrayType.ElementType)); } } - EqualsValueClauseSyntax @default = null; - if (node.Default != null) { - @default = SyntaxFactory.EqualsValueClause((ExpressionSyntax)node.Default?.Value.Accept(TriviaConvertingVisitor)); - } + var attributes = node.AttributeLists.SelectMany(ConvertAttribute).ToList(); int outAttributeIndex = attributes.FindIndex(a => a.Attributes.Single().Name.ToString() == "Out"); var modifiers = CommonConversions.ConvertModifiers(node.Modifiers, TokenContext.Local); @@ -832,6 +830,24 @@ public override CSharpSyntaxNode VisitParameter(VBSyntax.ParameterSyntax node) attributes.RemoveAt(outAttributeIndex); modifiers = modifiers.Replace(SyntaxFactory.Token(SyntaxKind.RefKeyword), SyntaxFactory.Token(SyntaxKind.OutKeyword)); } + + EqualsValueClauseSyntax @default = null; + if (node.Default != null) { + if (node.Default.Value is VBSyntax.LiteralExpressionSyntax les && les.Token.Value is DateTime dt) + { + var dateTimeAsLongCsLiteral = CommonConversions.GetLiteralExpression(dt.Ticks, dt.Ticks + "L"); + var dateTimeArg = CommonConversions.CreateAttributeArgumentList(SyntaxFactory.AttributeArgument(dateTimeAsLongCsLiteral)); + var optionalDateTimeAttributes = new[] { + SyntaxFactory.Attribute(SyntaxFactory.ParseName("System.Runtime.InteropServices.Optional")), + SyntaxFactory.Attribute(SyntaxFactory.ParseName("System.Runtime.CompilerServices.DateTimeConstant"), dateTimeArg) + }; + attributes.Insert(0, + SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(optionalDateTimeAttributes))); + } else { + @default = SyntaxFactory.EqualsValueClause( + (ExpressionSyntax)node.Default.Value.Accept(TriviaConvertingVisitor)); + } + } if (node.Parent.Parent is VBSyntax.MethodStatementSyntax mss && mss.AttributeLists.Any(HasExtensionAttribute) && node.Parent.ChildNodes().First() == node) { diff --git a/Tests/CSharp/ExpressionTests.cs b/Tests/CSharp/ExpressionTests.cs index 171403816..4b1b8a4f1 100644 --- a/Tests/CSharp/ExpressionTests.cs +++ b/Tests/CSharp/ExpressionTests.cs @@ -1,4 +1,7 @@ -using Xunit; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Xunit; namespace CodeConverter.Tests.CSharp { @@ -106,6 +109,26 @@ private void TestMethod() }"); } + [Fact] + public void DateLiterals() + { + TestConversionVisualBasicToCSharp(@"Class TestClass + Private Sub TestMethod(ByVal date As Date = #1/1/1900#) + Dim rslt = #1/1/1900# + Dim rslt2 = #8/13/2002 12:14 PM# + End Sub +End Class", @"using System; + +class TestClass +{ + private void TestMethod([System.Runtime.InteropServices.Optional, System.Runtime.CompilerServices.DateTimeConstant(599266080000000000L)] DateTime date) + { + var rslt = DateTime.Parse(""1900-01-01""); + var rslt2 = DateTime.Parse(""2002-08-13 12:14:00""); + } +}"); + } + [Fact] public void ConversionOfCTypeUsesParensIfNeeded() { @@ -808,349 +831,6 @@ private async void TestMethod() }"); } - [Fact] - public void Linq1() - { - TestConversionVisualBasicToCSharp(@"Private Shared Sub SimpleQuery() - Dim numbers As Integer() = {7, 9, 5, 3, 6} - Dim res = From n In numbers Where n > 5 Select n - - For Each n In res - Console.WriteLine(n) - Next -End Sub", - @"private static void SimpleQuery() -{ - int[] numbers = new[] { 7, 9, 5, 3, 6 };"/*TODO Remove need for new[]*/ + @" - var res = from n in numbers - where n > 5 - select n; - - foreach (var n in res) - Console.WriteLine(n); -}"); - } - - [Fact] - public void Linq2() - { - TestConversionVisualBasicToCSharp(@"Public Shared Sub Linq40() - Dim numbers As Integer() = {5, 4, 1, 3, 9, 8, 6, 7, 2, 0} - Dim numberGroups = From n In numbers Group n By __groupByKey1__ = n Mod 5 Into g Select New With {Key .Remainder = g.Key, Key .Numbers = g} - - For Each g In numberGroups - Console.WriteLine($""Numbers with a remainder of {g.Remainder} when divided by 5:"") - - For Each n In g.Numbers - Console.WriteLine(n) - Next - Next -End Sub", - @"public static void Linq40() -{ - int[] numbers = new[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };"/*TODO Remove need for new[]*/ + @" - var numberGroups = from n in numbers - group n by n % 5 into g - select new { Remainder = g.Key, Numbers = g }; - - foreach (var g in numberGroups) - { - Console.WriteLine($""Numbers with a remainder of {g.Remainder} when divided by 5:""); - - foreach (var n in g.Numbers) - Console.WriteLine(n); - } -}"); - } - - [Fact()] - public void Linq3() - { - TestConversionVisualBasicToCSharpWithoutComments(@"Class Product - Public Category As String - Public ProductName As String -End Class - -Class Test - Public Sub Linq102() - Dim categories As String() = New String() {""Beverages"", ""Condiments"", ""Vegetables"", ""Dairy Products"", ""Seafood""} - Dim products As Product() = GetProductList() - Dim q = From c In categories Join p In products On c Equals p.Category Select New With {Key .Category = c, p.ProductName} - - For Each v In q - Console.WriteLine($""{v.ProductName}: {v.Category}"") - Next - End Sub -End Class", - @"using System; -using System.Linq; - -class Product -{ - public string Category; - public string ProductName; -} - -class Test -{ - public void Linq102() - { - string[] categories = new string[] { ""Beverages"", ""Condiments"", ""Vegetables"", ""Dairy Products"", ""Seafood"" }; - Product[] products = GetProductList(); - var q = from c in categories - join p in products on c equals p.Category - select new { Category = c, p.ProductName }; - - foreach (var v in q) - Console.WriteLine($""{v.ProductName}: {v.Category}""); - } -}"); - } - - [Fact] - public void Linq4() - { - TestConversionVisualBasicToCSharp(@"Public Sub Linq103() - Dim categories As String() = New String() {""Beverages"", ""Condiments"", ""Vegetables"", ""Dairy Products"", ""Seafood""} - Dim products = GetProductList() - Dim q = From c In categories Group Join p In products On c Equals p.Category Into ps = Group Select New With {Key .Category = c, Key .Products = ps} - - For Each v In q - Console.WriteLine(v.Category & "":"") - - For Each p In v.Products - Console.WriteLine("" "" & p.ProductName) - Next - Next -End Sub", @"public void Linq103() -{ - string[] categories = new string[] { ""Beverages"", ""Condiments"", ""Vegetables"", ""Dairy Products"", ""Seafood"" }; - var products = GetProductList(); - var q = from c in categories - join p in products on c equals p.Category into ps - select new { Category = c, Products = ps }; - - foreach (var v in q) - { - Console.WriteLine(v.Category + "":""); - - foreach (var p in v.Products) - Console.WriteLine("" "" + p.ProductName); - } -}"); - } - - [Fact] - public void Linq5() - { - TestConversionVisualBasicToCSharp(@"Private Shared Function FindPicFilePath(picId As String) As String - For Each FileInfo As FileInfo In From FileInfo1 In AList Where FileInfo1.Name.Substring(0, 6) = picId - Return FileInfo.FullName - Next - Return String.Empty -End Function", @"private static string FindPicFilePath(string picId) -{ - foreach (FileInfo FileInfo in from FileInfo1 in AList - where FileInfo1.Name.Substring(0, 6) == picId - select FileInfo1) - return FileInfo.FullName; - return string.Empty; -}"); - } - - [Fact] - public void LinqMultipleFroms() - { - TestConversionVisualBasicToCSharp(@"Private Shared Sub LinqSub() - Dim _result = From _claimProgramSummary In New List(Of List(Of List(Of List(Of String))))() - From _claimComponentSummary In _claimProgramSummary.First() - From _lineItemCalculation In _claimComponentSummary.Last() - Select _lineItemCalculation -End Sub", @"private static void LinqSub() -{ - var _result = from _claimProgramSummary in new List>>>() - from _claimComponentSummary in _claimProgramSummary.First() - from _lineItemCalculation in _claimComponentSummary.Last() - select _lineItemCalculation; -}"); - } - - [Fact] - public void LinqPartitionDistinct() - { - TestConversionVisualBasicToCSharp(@"Private Shared Function FindPicFilePath() As IEnumerable(Of String) - Dim words = {""an"", ""apple"", ""a"", ""day"", ""keeps"", ""the"", ""doctor"", ""away""} - - Return From word In words - Skip 1 - Skip While word.Length >= 1 - Take While word.Length < 5 - Take 2 - Distinct -End Function", @"private static IEnumerable FindPicFilePath() -{ - var words = new[] { ""an"", ""apple"", ""a"", ""day"", ""keeps"", ""the"", ""doctor"", ""away"" }; - - return words -.Skip(1) -.SkipWhile(word => word.Length >= 1) -.TakeWhile(word => word.Length < 5) -.Take(2) -.Distinct(); -}"); - } - - [Fact(Skip = "Issue #29 - Aggregate not supported")] - public void LinqAggregateSum() - { - TestConversionVisualBasicToCSharp(@"Private Shared Sub ASub() - Dim expenses() As Double = {560.0, 300.0, 1080.5, 29.95, 64.75, 200.0} - Dim totalExpense = Aggregate expense In expenses Into Sum() -End Sub", @"private static void ASub() -{ - double[] expenses = {560.0, 300.0, 1080.5, 29.95, 64.75, 200.0}; - var totalExpense = expenses.Sum(); -}"); - } - - [Fact(Skip = "Issue #29 - Group join not supported")] - public void LinqGroupJoin() - { - TestConversionVisualBasicToCSharp(@"Private Shared Sub ASub() - Dim customerList = From cust In customers - Group Join ord In orders On - cust.CustomerID Equals ord.CustomerID - Into CustomerOrders = Group, - OrderTotal = Sum(ord.Total) - Select cust.CompanyName, cust.CustomerID, - CustomerOrders, OrderTotal -End Sub", @"private static void ASub() -{ - var customerList = from cust in customers - join ord in orders on cust.CustomerID equals ord.CustomerID into CustomerOrders - let OrderTotal = Sum(ord.Total) //TODO Figure out exact C# syntax for this query - select new { cust.CompanyName, cust.CustomerID, CustomerOrders, OrderTotal }; -}"); - } - - [Fact] - public void LinqGroupByAnonymous() - { - //Very hard to automated test comments on such a complicated query - TestConversionVisualBasicToCSharpWithoutComments(@"Imports System.Runtime.CompilerServices - -Public Class AccountEntry - Public Property LookupAccountEntryTypeId As Object - Public Property LookupAccountEntrySourceId As Object - Public Property SponsorId As Object - Public Property LookupFundTypeId As Object - Public Property StartDate As Object - Public Property SatisfiedDate As Object - Public Property InterestStartDate As Object - Public Property ComputeInterestFlag As Object - Public Property SponsorClaimRevision As Object - Public Property Amount As Decimal - Public Property AccountTransactions As List(Of Object) - Public Property AccountEntryClaimDetails As List(Of AccountEntry) -End Class - -Module Ext - - Public Function Reduce(ByVal accountEntries As IEnumerable(Of AccountEntry)) As IEnumerable(Of AccountEntry) - Return ( - From _accountEntry In accountEntries - Where _accountEntry.Amount > 0D - Group By _keys = New With - { - Key .LookupAccountEntryTypeId = _accountEntry.LookupAccountEntryTypeId, - Key .LookupAccountEntrySourceId = _accountEntry.LookupAccountEntrySourceId, - Key .SponsorId = _accountEntry.SponsorId, - Key .LookupFundTypeId = _accountEntry.LookupFundTypeId, - Key .StartDate = _accountEntry.StartDate, - Key .SatisfiedDate = _accountEntry.SatisfiedDate, - Key .InterestStartDate = _accountEntry.InterestStartDate, - Key .ComputeInterestFlag = _accountEntry.ComputeInterestFlag, - Key .SponsorClaimRevision = _accountEntry.SponsorClaimRevision - } Into Group - Select New AccountEntry() With - { - .LookupAccountEntryTypeId = _keys.LookupAccountEntryTypeId, - .LookupAccountEntrySourceId = _keys.LookupAccountEntrySourceId, - .SponsorId = _keys.SponsorId, - .LookupFundTypeId = _keys.LookupFundTypeId, - .StartDate = _keys.StartDate, - .SatisfiedDate = _keys.SatisfiedDate, - .ComputeInterestFlag = _keys.ComputeInterestFlag, - .InterestStartDate = _keys.InterestStartDate, - .SponsorClaimRevision = _keys.SponsorClaimRevision, - .Amount = Group.Sum(Function(accountEntry) accountEntry.Amount), - .AccountTransactions = New List(Of Object)(), - .AccountEntryClaimDetails = - (From _accountEntry In Group From _claimDetail In _accountEntry.AccountEntryClaimDetails - Select _claimDetail).Reduce().ToList - } - ) - End Function -End Module", @"using System.Collections.Generic; -using System.Linq; - -public class AccountEntry -{ - public object LookupAccountEntryTypeId { get; set; } - public object LookupAccountEntrySourceId { get; set; } - public object SponsorId { get; set; } - public object LookupFundTypeId { get; set; } - public object StartDate { get; set; } - public object SatisfiedDate { get; set; } - public object InterestStartDate { get; set; } - public object ComputeInterestFlag { get; set; } - public object SponsorClaimRevision { get; set; } - public decimal Amount { get; set; } - public List AccountTransactions { get; set; } - public List AccountEntryClaimDetails { get; set; } -} - -static class Ext -{ - public static IEnumerable Reduce(this IEnumerable accountEntries) - { - return (from _accountEntry in accountEntries - where _accountEntry.Amount > 0M - group _accountEntry by new - { - LookupAccountEntryTypeId = _accountEntry.LookupAccountEntryTypeId, - LookupAccountEntrySourceId = _accountEntry.LookupAccountEntrySourceId, - SponsorId = _accountEntry.SponsorId, - LookupFundTypeId = _accountEntry.LookupFundTypeId, - StartDate = _accountEntry.StartDate, - SatisfiedDate = _accountEntry.SatisfiedDate, - InterestStartDate = _accountEntry.InterestStartDate, - ComputeInterestFlag = _accountEntry.ComputeInterestFlag, - SponsorClaimRevision = _accountEntry.SponsorClaimRevision - } into Group - let _keys = Group.Key - select new AccountEntry() - { - LookupAccountEntryTypeId = _keys.LookupAccountEntryTypeId, - LookupAccountEntrySourceId = _keys.LookupAccountEntrySourceId, - SponsorId = _keys.SponsorId, - LookupFundTypeId = _keys.LookupFundTypeId, - StartDate = _keys.StartDate, - SatisfiedDate = _keys.SatisfiedDate, - ComputeInterestFlag = _keys.ComputeInterestFlag, - InterestStartDate = _keys.InterestStartDate, - SponsorClaimRevision = _keys.SponsorClaimRevision, - Amount = Group.Sum(accountEntry => accountEntry.Amount), - AccountTransactions = new List(), - AccountEntryClaimDetails = (from _accountEntry in Group - from _claimDetail in _accountEntry.AccountEntryClaimDetails - select _claimDetail).Reduce().ToList() - } -); - } -}"); - } - [Fact] public void PartiallyQualifiedName() { diff --git a/Tests/CSharp/LinqExpressionTests.cs b/Tests/CSharp/LinqExpressionTests.cs new file mode 100644 index 000000000..6b3764115 --- /dev/null +++ b/Tests/CSharp/LinqExpressionTests.cs @@ -0,0 +1,350 @@ +using Xunit; + +namespace CodeConverter.Tests.CSharp +{ + public class LinqExpressionTests : ConverterTestBase + { + [Fact] + public void Linq1() + { + TestConversionVisualBasicToCSharp(@"Private Shared Sub SimpleQuery() + Dim numbers As Integer() = {7, 9, 5, 3, 6} + Dim res = From n In numbers Where n > 5 Select n + + For Each n In res + Console.WriteLine(n) + Next +End Sub", + @"private static void SimpleQuery() +{ + int[] numbers = new[] { 7, 9, 5, 3, 6 };"/*TODO Remove need for new[]*/ + @" + var res = from n in numbers + where n > 5 + select n; + + foreach (var n in res) + Console.WriteLine(n); +}"); + } + + [Fact] + public void Linq2() + { + TestConversionVisualBasicToCSharp(@"Public Shared Sub Linq40() + Dim numbers As Integer() = {5, 4, 1, 3, 9, 8, 6, 7, 2, 0} + Dim numberGroups = From n In numbers Group n By __groupByKey1__ = n Mod 5 Into g Select New With {Key .Remainder = g.Key, Key .Numbers = g} + + For Each g In numberGroups + Console.WriteLine($""Numbers with a remainder of {g.Remainder} when divided by 5:"") + + For Each n In g.Numbers + Console.WriteLine(n) + Next + Next +End Sub", + @"public static void Linq40() +{ + int[] numbers = new[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };"/*TODO Remove need for new[]*/ + @" + var numberGroups = from n in numbers + group n by n % 5 into g + select new { Remainder = g.Key, Numbers = g }; + + foreach (var g in numberGroups) + { + Console.WriteLine($""Numbers with a remainder of {g.Remainder} when divided by 5:""); + + foreach (var n in g.Numbers) + Console.WriteLine(n); + } +}"); + } + + [Fact()] + public void Linq3() + { + TestConversionVisualBasicToCSharpWithoutComments(@"Class Product + Public Category As String + Public ProductName As String +End Class + +Class Test + Public Sub Linq102() + Dim categories As String() = New String() {""Beverages"", ""Condiments"", ""Vegetables"", ""Dairy Products"", ""Seafood""} + Dim products As Product() = GetProductList() + Dim q = From c In categories Join p In products On c Equals p.Category Select New With {Key .Category = c, p.ProductName} + + For Each v In q + Console.WriteLine($""{v.ProductName}: {v.Category}"") + Next + End Sub +End Class", + @"using System; +using System.Linq; + +class Product +{ + public string Category; + public string ProductName; +} + +class Test +{ + public void Linq102() + { + string[] categories = new string[] { ""Beverages"", ""Condiments"", ""Vegetables"", ""Dairy Products"", ""Seafood"" }; + Product[] products = GetProductList(); + var q = from c in categories + join p in products on c equals p.Category + select new { Category = c, p.ProductName }; + + foreach (var v in q) + Console.WriteLine($""{v.ProductName}: {v.Category}""); + } +}"); + } + + [Fact] + public void Linq4() + { + TestConversionVisualBasicToCSharp(@"Public Sub Linq103() + Dim categories As String() = New String() {""Beverages"", ""Condiments"", ""Vegetables"", ""Dairy Products"", ""Seafood""} + Dim products = GetProductList() + Dim q = From c In categories Group Join p In products On c Equals p.Category Into ps = Group Select New With {Key .Category = c, Key .Products = ps} + + For Each v In q + Console.WriteLine(v.Category & "":"") + + For Each p In v.Products + Console.WriteLine("" "" & p.ProductName) + Next + Next +End Sub", @"public void Linq103() +{ + string[] categories = new string[] { ""Beverages"", ""Condiments"", ""Vegetables"", ""Dairy Products"", ""Seafood"" }; + var products = GetProductList(); + var q = from c in categories + join p in products on c equals p.Category into ps + select new { Category = c, Products = ps }; + + foreach (var v in q) + { + Console.WriteLine(v.Category + "":""); + + foreach (var p in v.Products) + Console.WriteLine("" "" + p.ProductName); + } +}"); + } + + [Fact] + public void Linq5() + { + TestConversionVisualBasicToCSharp(@"Private Shared Function FindPicFilePath(picId As String) As String + For Each FileInfo As FileInfo In From FileInfo1 In AList Where FileInfo1.Name.Substring(0, 6) = picId + Return FileInfo.FullName + Next + Return String.Empty +End Function", @"private static string FindPicFilePath(string picId) +{ + foreach (FileInfo FileInfo in from FileInfo1 in AList + where FileInfo1.Name.Substring(0, 6) == picId + select FileInfo1) + return FileInfo.FullName; + return string.Empty; +}"); + } + + [Fact] + public void LinqMultipleFroms() + { + TestConversionVisualBasicToCSharp(@"Private Shared Sub LinqSub() + Dim _result = From _claimProgramSummary In New List(Of List(Of List(Of List(Of String))))() + From _claimComponentSummary In _claimProgramSummary.First() + From _lineItemCalculation In _claimComponentSummary.Last() + Select _lineItemCalculation +End Sub", @"private static void LinqSub() +{ + var _result = from _claimProgramSummary in new List>>>() + from _claimComponentSummary in _claimProgramSummary.First() + from _lineItemCalculation in _claimComponentSummary.Last() + select _lineItemCalculation; +}"); + } + + [Fact] + public void LinqPartitionDistinct() + { + TestConversionVisualBasicToCSharp(@"Private Shared Function FindPicFilePath() As IEnumerable(Of String) + Dim words = {""an"", ""apple"", ""a"", ""day"", ""keeps"", ""the"", ""doctor"", ""away""} + + Return From word In words + Skip 1 + Skip While word.Length >= 1 + Take While word.Length < 5 + Take 2 + Distinct +End Function", @"private static IEnumerable FindPicFilePath() +{ + var words = new[] { ""an"", ""apple"", ""a"", ""day"", ""keeps"", ""the"", ""doctor"", ""away"" }; + + return words +.Skip(1) +.SkipWhile(word => word.Length >= 1) +.TakeWhile(word => word.Length < 5) +.Take(2) +.Distinct(); +}"); + } + + [Fact(Skip = "Issue #29 - Aggregate not supported")] + public void LinqAggregateSum() + { + TestConversionVisualBasicToCSharp(@"Private Shared Sub ASub() + Dim expenses() As Double = {560.0, 300.0, 1080.5, 29.95, 64.75, 200.0} + Dim totalExpense = Aggregate expense In expenses Into Sum() +End Sub", @"private static void ASub() +{ + double[] expenses = {560.0, 300.0, 1080.5, 29.95, 64.75, 200.0}; + var totalExpense = expenses.Sum(); +}"); + } + + [Fact(Skip = "Issue #29 - Group join not supported")] + public void LinqGroupJoin() + { + TestConversionVisualBasicToCSharp(@"Private Shared Sub ASub() + Dim customerList = From cust In customers + Group Join ord In orders On + cust.CustomerID Equals ord.CustomerID + Into CustomerOrders = Group, + OrderTotal = Sum(ord.Total) + Select cust.CompanyName, cust.CustomerID, + CustomerOrders, OrderTotal +End Sub", @"private static void ASub() +{ + var customerList = from cust in customers + join ord in orders on cust.CustomerID equals ord.CustomerID into CustomerOrders + let OrderTotal = Sum(ord.Total) //TODO Figure out exact C# syntax for this query + select new { cust.CompanyName, cust.CustomerID, CustomerOrders, OrderTotal }; +}"); + } + + [Fact] + public void LinqGroupByAnonymous() + { + //Very hard to automated test comments on such a complicated query + TestConversionVisualBasicToCSharpWithoutComments(@"Imports System.Runtime.CompilerServices + +Public Class AccountEntry + Public Property LookupAccountEntryTypeId As Object + Public Property LookupAccountEntrySourceId As Object + Public Property SponsorId As Object + Public Property LookupFundTypeId As Object + Public Property StartDate As Object + Public Property SatisfiedDate As Object + Public Property InterestStartDate As Object + Public Property ComputeInterestFlag As Object + Public Property SponsorClaimRevision As Object + Public Property Amount As Decimal + Public Property AccountTransactions As List(Of Object) + Public Property AccountEntryClaimDetails As List(Of AccountEntry) +End Class + +Module Ext + + Public Function Reduce(ByVal accountEntries As IEnumerable(Of AccountEntry)) As IEnumerable(Of AccountEntry) + Return ( + From _accountEntry In accountEntries + Where _accountEntry.Amount > 0D + Group By _keys = New With + { + Key .LookupAccountEntryTypeId = _accountEntry.LookupAccountEntryTypeId, + Key .LookupAccountEntrySourceId = _accountEntry.LookupAccountEntrySourceId, + Key .SponsorId = _accountEntry.SponsorId, + Key .LookupFundTypeId = _accountEntry.LookupFundTypeId, + Key .StartDate = _accountEntry.StartDate, + Key .SatisfiedDate = _accountEntry.SatisfiedDate, + Key .InterestStartDate = _accountEntry.InterestStartDate, + Key .ComputeInterestFlag = _accountEntry.ComputeInterestFlag, + Key .SponsorClaimRevision = _accountEntry.SponsorClaimRevision + } Into Group + Select New AccountEntry() With + { + .LookupAccountEntryTypeId = _keys.LookupAccountEntryTypeId, + .LookupAccountEntrySourceId = _keys.LookupAccountEntrySourceId, + .SponsorId = _keys.SponsorId, + .LookupFundTypeId = _keys.LookupFundTypeId, + .StartDate = _keys.StartDate, + .SatisfiedDate = _keys.SatisfiedDate, + .ComputeInterestFlag = _keys.ComputeInterestFlag, + .InterestStartDate = _keys.InterestStartDate, + .SponsorClaimRevision = _keys.SponsorClaimRevision, + .Amount = Group.Sum(Function(accountEntry) accountEntry.Amount), + .AccountTransactions = New List(Of Object)(), + .AccountEntryClaimDetails = + (From _accountEntry In Group From _claimDetail In _accountEntry.AccountEntryClaimDetails + Select _claimDetail).Reduce().ToList + } + ) + End Function +End Module", @"using System.Collections.Generic; +using System.Linq; + +public class AccountEntry +{ + public object LookupAccountEntryTypeId { get; set; } + public object LookupAccountEntrySourceId { get; set; } + public object SponsorId { get; set; } + public object LookupFundTypeId { get; set; } + public object StartDate { get; set; } + public object SatisfiedDate { get; set; } + public object InterestStartDate { get; set; } + public object ComputeInterestFlag { get; set; } + public object SponsorClaimRevision { get; set; } + public decimal Amount { get; set; } + public List AccountTransactions { get; set; } + public List AccountEntryClaimDetails { get; set; } +} + +static class Ext +{ + public static IEnumerable Reduce(this IEnumerable accountEntries) + { + return (from _accountEntry in accountEntries + where _accountEntry.Amount > 0M + group _accountEntry by new + { + LookupAccountEntryTypeId = _accountEntry.LookupAccountEntryTypeId, + LookupAccountEntrySourceId = _accountEntry.LookupAccountEntrySourceId, + SponsorId = _accountEntry.SponsorId, + LookupFundTypeId = _accountEntry.LookupFundTypeId, + StartDate = _accountEntry.StartDate, + SatisfiedDate = _accountEntry.SatisfiedDate, + InterestStartDate = _accountEntry.InterestStartDate, + ComputeInterestFlag = _accountEntry.ComputeInterestFlag, + SponsorClaimRevision = _accountEntry.SponsorClaimRevision + } into Group + let _keys = Group.Key + select new AccountEntry() + { + LookupAccountEntryTypeId = _keys.LookupAccountEntryTypeId, + LookupAccountEntrySourceId = _keys.LookupAccountEntrySourceId, + SponsorId = _keys.SponsorId, + LookupFundTypeId = _keys.LookupFundTypeId, + StartDate = _keys.StartDate, + SatisfiedDate = _keys.SatisfiedDate, + ComputeInterestFlag = _keys.ComputeInterestFlag, + InterestStartDate = _keys.InterestStartDate, + SponsorClaimRevision = _keys.SponsorClaimRevision, + Amount = Group.Sum(accountEntry => accountEntry.Amount), + AccountTransactions = new List(), + AccountEntryClaimDetails = (from _accountEntry in Group + from _claimDetail in _accountEntry.AccountEntryClaimDetails + select _claimDetail).Reduce().ToList() + } +); + } +}"); + } + } +} \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 0a1bae752..7a6dc4835 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -151,6 +151,7 @@ DefaultReferences.cs +