2

I am trying to build a SeparatedList using a dynamically-generated IEnumerable sequence (which is constructed by an Enumerable.Select() function call). The API function to create a SeparatedList takes two parameters, an IEnumerable<T> and an IEnumerable<SyntaxToken>. I have provided a simple function, Repeat, that is an infinite sequence generator which yields as many commas, in this case, as are requested.

The SeparatedList function appears to consume as many of the first sequence (parameter types here) as there are entries in the second sequence, which messes me up. Have I misunderstood how the function is supposed to work and has anyone else done this? Thanks

Syntax.SeparatedList<ParameterSyntax>(
    functionParameterTypes,Repeat(i=>Syntax.Token(SyntaxKind.CommaToken)))

(Edit: I should add that converting the functionParameterTypes to a List<> and passing another List<> with one fewer token than elements in functionParameterTypes does work but I am trying to do this without having to explicitly build the list ahead of time.)

svick
  • 236,525
  • 50
  • 385
  • 514
Richard Polton
  • 101
  • 1
  • 5

2 Answers2

0

The XML documentation for the separators parameter says:

The number of tokens must be one less than the number of nodes.

You're right that this is not what the method actually requires: The number of tokens must be one less than the number of nodes or same as the number of tokens. I wouldn't be surprised if this was intentional, code like f(foo, bar, ) makes sense if you're trying to handle code that's just being written.

I think that calling ToList() on the sequence of parameters is the best choice here. And you don't have to use another List for separators, you can use Enumerable.Repeat() for that. For example like this (taken from a library I wrote where I faced the same issue):

public static SeparatedSyntaxList<T> ToSeparatedList<T>(
    this IEnumerable<T> nodes, SyntaxKind separator = SyntaxKind.CommaToken)
    where T : SyntaxNode
{
    var nodesList = nodes == null ? new List<T>() : nodes.ToList();
    return Syntax.SeparatedList(
        nodesList,
        Enumerable.Repeat(
            Syntax.Token(separator), Math.Max(nodesList .Count - 1, 0)));
}
svick
  • 236,525
  • 50
  • 385
  • 514
0

I also had the same need to create a SeparatedList using a dynamically generated list of parameters. My solution was to use SelectMany() and Take() to add separators (i.e. "comma") to the parameters but then remove the last trailing comma.

        SyntaxFactory.SeparatedList<ParameterSyntax>(
            functionParameterTypes
                .SelectMany(param =>
                    new SyntaxNodeOrToken[]
                    {
                        param,
                        SyntaxFactory.Token(SyntaxKind.CommaToken)
                    })
                .Take(functionParameterTypes.Count() * 2 - 1)
        );
Ray
  • 187,153
  • 97
  • 222
  • 204