As far as I know, none of the values from CSharpFormattingOptions will be helpful there. One could expect NewLineForMembersInObjectInit to be suited for your case but it purposely doesn't format when it's on a single line.
However, we can still use a CSharpSyntaxRewriter to put your object initializer on multiple lines first, then let Formatter.Format indent it properly.
Here's an example implementation of such a CSharpSyntaxRewriter :
public class Rewriter : CSharpSyntaxRewriter
{
public override SyntaxNode VisitObjectCreationExpression(ObjectCreationExpressionSyntax node)
{
if (node.Initializer != null)
{
node = node.ReplaceNode(node.Initializer, MakeMultiLine(node.Initializer));
}
return base.VisitObjectCreationExpression(node);
}
private InitializerExpressionSyntax MakeMultiLine(InitializerExpressionSyntax initializer)
{
var initializerLineSpan = initializer.GetLocation().GetLineSpan();
// Add new lines only if the whole initializer is on a single line
if (initializerLineSpan.StartLinePosition.Line == initializerLineSpan.EndLinePosition.Line)
{
SyntaxTrivia newLineTrivia = SyntaxFactory.EndOfLine(Environment.NewLine);
initializer = initializer.ReplaceToken(initializer.OpenBraceToken, initializer.OpenBraceToken.WithLeadingTrivia(newLineTrivia));
initializer = initializer.ReplaceNodes(initializer.Expressions, (x, y) => y.WithLeadingTrivia(newLineTrivia));
initializer = initializer.ReplaceToken(initializer.CloseBraceToken, initializer.CloseBraceToken.WithLeadingTrivia(newLineTrivia));
}
return initializer;
}
}
To use it before the code gets formatted, we can change your GetFormatedNode to the following :
public static SyntaxNode GetFormatedNode(SyntaxNode node)
{
node = new Rewriter().Visit(node);
var workspace = new AdhocWorkspace();
OptionSet options = workspace.Options;
// From what I know, object initializers are always indented no matter the options
return Formatter.Format(node, workspace, options);
}
Note that, while MakeMultiLine could also be used to rewrite collection initializers in the same way, the above implementation only affects object initializers. Here are two variations :
- If you want to rewrite collection and object initializers, override
VisitInitializerExpression instead of VisitObjectCreationExpression in Rewriter as follows :
public override SyntaxNode VisitInitializerExpression(InitializerExpressionSyntax node)
{
return base.VisitInitializerExpression(MakeMultiLine(node));
}
- If you want to rewrite collection initializers only, override
VisitArrayCreationExpression instead of VisitObjectCreationExpression with this (pretty similar) implementation :
public override SyntaxNode VisitArrayCreationExpression(ArrayCreationExpressionSyntax node)
{
if (node.Initializer != null)
{
node = node.ReplaceNode(node.Initializer, MakeMultiLine(node.Initializer));
}
return base.VisitArrayCreationExpression(node);
}
Sadly, at the time of writing, unlike for object initializers, Formatter.Format(...) will not indent collection initializers meaning you'd have to do all the work "manually" there (possibly with an other CSharpSyntaxRewriter)