Question

I am trying to convert a IEnumerable<object[]> property

public IEnumerable<object[]> BeforeConversion
{
    get
    {
        yield return new object[] { new DateTime(2013, 8, 23), new DateTime(2013, 09, 15) };
        yield return new object[] { new DateTime(2013, 9, 20), new DateTime(2013, 10, 15) };
    }
}

to a object[] field

static object[] AfterConversion =
{
    new object[] { new DateTime(2013, 8, 23), new DateTime(2013, 09, 15) },
    new object[] { new DateTime(2013, 9, 20), new DateTime(2013, 10, 15) },
};

Here is my attempt:

var testCases = node.DescendantNodes((_) => true).OfType<ArrayCreationExpressionSyntax>()
                    .Select(i => ((ExpressionSyntax)i))
                    .ToArray();                    

var arrayType = node.DescendantNodes((_) => true).OfType<ArrayTypeSyntax>().First();

var seperators = Enumerable.Repeat(SyntaxFactory
    .Token(SyntaxKind.CommaToken)
    .WithTrailingTrivia(LineFeed), testCases.Length);
var initializerNode = SyntaxFactory       
    .ArrayCreationExpression(arrayType)
    .WithInitializer(SyntaxFactory
        .InitializerExpression(SyntaxKind.ArrayInitializerExpression)
        .WithExpressions(SyntaxFactory.SeparatedList(testCases, seperators)));

return SyntaxFactory.FieldDeclaration(
    new SyntaxList<AttributeListSyntax>(),
    SyntaxFactory.TokenList().Add(
        SyntaxFactory.Token(SyntaxKind.StaticKeyword).WithTrailingTrivia(Space)),
    SyntaxFactory.VariableDeclaration(arrayType.WithTrailingTrivia(Space),
        SyntaxFactory.SeparatedList<VariableDeclaratorSyntax>().Add(
            SyntaxFactory.VariableDeclarator(newName).WithInitializer(
            SyntaxFactory.EqualsValueClause(
                SyntaxFactory.Token(SyntaxKind.EqualsToken).WithLeadingTrivia(Space),
                initializerNode)))))
    .WithLeadingTrivia(node.GetLeadingTrivia())
    .WithTrailingTrivia(node.GetTrailingTrivia());

This implementation produces

static object[] TestGetExpirationDateCases =newobject[]{new object[] { new DateTime(2013, 8, 23), new DateTime(2013, 09, 15) },
 new object[] { new DateTime(2013, 9, 20), new DateTime(2013, 10, 15) },
 };

The formatting is quite off. The newobject[] is one word instead of new object[]. Actually it's not needed at all, but I couldn't figure out how to create the initializer statement without it.

My questions are:
1. Is there any way to do a quick formatting?
2. Is there a better way to do this. Trying to get all the details perfect seems to be time consuming.

Was it helpful?

Solution

  1. To create an array with an implicit type use an ImplicitArrayCreationExpression instead of an ArrayCreationExpression:

    var initializerNode = SyntaxFactory
        .ImplicitArrayCreationExpression(SyntaxFactory
            .InitializerExpression(SyntaxKind.ArrayInitializerExpression)
            .WithExpressions(SyntaxFactory.SeparatedList(testCases, seperators)));
    
  2. You can format your freshly created syntax using the Formatter. Say you've assigned the returned results of your implementation to the variable result, then you can call it like this:

    using Microsoft.CodeAnalysis.Formatting;
    
    var formattedResult = Formatter.Format(result, workspace);
    

    Which produces this nicely formatted output for your example (I've hardcoded the name 'after'):

    static object[] after = new[]
    {
        new object[] { new DateTime(2013, 8, 23), new DateTime(2013, 09, 15) },
        new object[] { new DateTime(2013, 9, 20), new DateTime(2013, 10, 15) },
    };
    
  3. You should try the Roslyn Syntax Visualizer Tool (View > Other Windows > Roslyn Syntax Visualizer). It allows you to look at what syntax nodes Roslyn creates for a given piece of code in your current document. This usually helps a lot when you're trying to figure out how to properly construct your own trees!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top