I have the following partial code which I use to generate datacontracts based on an excel-file we use for customer facing workshops and such.
private PropertyDeclarationSyntax[] GenerateProperties()
{
var props = new List<PropertyDeclarationSyntax>();
props.Add(SF.PropertyDeclaration(SF.ParseTypeName("IMigrationInformation"), "MigrationInformation")
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.OverrideKeyword))
.AddAccessorListAccessors(
SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithBody(SF.Block(SF.ReturnStatement(SF.ObjectCreationExpression(SF.ParseTypeName($"{Form.RegistryName}MigrationInformation")))))
));
foreach (var field in Form.AllDataFields().Where(f => f.FieldTypeInfo != null))
{
props.Add(SF.PropertyDeclaration(SF.ParseTypeName(field.FieldTypeInfo.BackingType.Name), field.SafeName)
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)),
SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
));
}
return props.ToArray();
}
The code works surprisingly well with one small snag. The code generated looks like this:
public string VariableName
{
get;
set;
}
And I really want it to look like this:
public string VariableName { get; set; }
Does anyone know how to do this, if possible?
I got the exact same problem. In my case, I was saving the code to file after converting it to a string something like this:
private void WriteCodeToFile(NamespaceDeclarationSyntax ns)
{
var codeAsString = ns.NormalizeWhitespace()
.ToFullString();
File.WriteAllText(destFileName, codeAsString);
}
So, in that case, I just solved it byrunning a regex replace on the string, in an extension method:
private static readonly Regex AutoPropRegex = new Regex(@"\s*\{\s*get;\s*set;\s*}\s");
public static string FormatAutoPropertiesOnOneLine(this string str)
{
return AutoPropRegex.Replace(str, " { get; set; }");
}
And then call it after converting it to string:
var codeAsString = ns.NormalizeWhitespace()
.ToFullString()
.FormatAutoPropertiesOnOneLine();
You are not speficying how you do your file-writing step (if any), so if this is not relevant at all in your case, I apologize for not targeting your question 100%. In any case, someone else might benefit from it.
You could implement a CSharpSyntaxRewriter and than apply it to a parent SyntaxNode:
public static class WhitespaceFormatter
{
public static SyntaxNode NormalizeWhitespacesSingleLineProperties(this SyntaxNode node) =>
node.NormalizeWhitespace().SingleLineProperties();
public static SyntaxNode SingleLineProperties(this SyntaxNode node) => new SingleLinePropertyRewriter().Visit(node);
class SingleLinePropertyRewriter : CSharpSyntaxRewriter
{
public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) =>
node.NormalizeWhitespace(indentation: "", eol: " ")
.WithLeadingTrivia(node.GetLeadingTrivia())
.WithTrailingTrivia(node.GetTrailingTrivia());
}
}
Use NormalizeWhitespacesSingleLineProperties
to apply default whitespaces to everything but property declarations which will be written to a single line. Make sure not to call Format
or NormalizeWhitespace()
on your node afterwards, because it will again clutter your property declarations.
As one of simple solution (another way create a nodes and tokens with correct trivias) just use SyntaxNodeExtensions.NormalizeWhitespace(...)
for nodes that you want to represent at the one line:
...
foreach (var field in Form.AllDataFields().Where(f => f.FieldTypeInfo != null))
{
props.Add(SF.PropertyDeclaration(SF.ParseTypeName(field.FieldTypeInfo.BackingType.Name), field.SafeName)
.AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)),
SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
).NormalizeWhitespace(indentation: "", eol: " "));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With