diff --git a/SpreadCheetah.SourceGenerator/Helpers/StringBuilderExtensions.cs b/SpreadCheetah.SourceGenerator/Helpers/StringBuilderExtensions.cs deleted file mode 100644 index 4b8a135d..00000000 --- a/SpreadCheetah.SourceGenerator/Helpers/StringBuilderExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Text; - -namespace SpreadCheetah.SourceGenerator.Helpers; - -internal static class StringBuilderExtensions -{ - public static StringBuilder AppendIndentation(this StringBuilder sb, int indentationLevel) => indentationLevel switch - { - <= 0 => sb, - 1 => sb.Append(" "), - 2 => sb.Append(" "), - 3 => sb.Append(" "), - 4 => sb.Append(" "), - 5 => sb.Append(" "), - 6 => sb.Append(" "), - _ => sb.Append(new string(' ', 4 * indentationLevel)) - }; - - public static StringBuilder AppendLine(this StringBuilder sb, int indentationLevel, string value) - { - return sb.AppendIndentation(indentationLevel).AppendLine(value); - } -} diff --git a/SpreadCheetah.SourceGenerator/WorksheetRowGenerator.cs b/SpreadCheetah.SourceGenerator/WorksheetRowGenerator.cs index 2e905922..1d05d95f 100644 --- a/SpreadCheetah.SourceGenerator/WorksheetRowGenerator.cs +++ b/SpreadCheetah.SourceGenerator/WorksheetRowGenerator.cs @@ -149,16 +149,18 @@ private static void Execute(ContextClass? contextClass, SourceProductionContext private static void GenerateHeader(StringBuilder sb) { - sb.AppendLine("// "); - sb.AppendLine("#nullable enable"); - sb.AppendLine("using SpreadCheetah;"); - sb.AppendLine("using SpreadCheetah.SourceGeneration;"); - sb.AppendLine("using System;"); - sb.AppendLine("using System.Buffers;"); - sb.AppendLine("using System.Collections.Generic;"); - sb.AppendLine("using System.Threading;"); - sb.AppendLine("using System.Threading.Tasks;"); - sb.AppendLine(); + sb.AppendLine(""" + // + #nullable enable + using SpreadCheetah; + using SpreadCheetah.SourceGeneration; + using System; + using System.Buffers; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + + """); } private static void GenerateCode(StringBuilder sb, ContextClass contextClass, SourceProductionContext context) @@ -166,19 +168,21 @@ private static void GenerateCode(StringBuilder sb, ContextClass contextClass, So GenerateHeader(sb); if (contextClass.Namespace is { } ns) - sb.AppendLine($"namespace {ns}"); + sb.Append("namespace ").AppendLine(ns); var accessibility = SyntaxFacts.GetText(contextClass.DeclaredAccessibility); - sb.AppendLine("{"); - sb.AppendLine($" {accessibility} partial class {contextClass.Name}"); - sb.AppendLine(" {"); - sb.AppendLine($" private static {contextClass.Name}? _default;"); - sb.AppendLine($" public static {contextClass.Name} Default => _default ??= new {contextClass.Name}();"); - sb.AppendLine(); - sb.AppendLine($" public {contextClass.Name}()"); - sb.AppendLine(" {"); - sb.AppendLine(" }"); + sb.AppendLine($$""" + { + {{accessibility}} partial class {{contextClass.Name}} + { + private static {{contextClass.Name}}? _default; + public static {{contextClass.Name}} Default => _default ??= new {{contextClass.Name}}(); + + public {{contextClass.Name}}() + { + } + """); var rowTypeNames = new HashSet(StringComparer.Ordinal); @@ -193,8 +197,10 @@ private static void GenerateCode(StringBuilder sb, ContextClass contextClass, So ++typeIndex; } - sb.AppendLine(" }"); - sb.AppendLine("}"); + sb.AppendLine(""" + } + } + """); } private static void GenerateCodeForType(StringBuilder sb, int typeIndex, RowType rowType, @@ -202,10 +208,10 @@ private static void GenerateCodeForType(StringBuilder sb, int typeIndex, RowType { ReportDiagnostics(rowType, rowType.WorksheetRowAttributeLocation, contextClass.Options, context); - sb.AppendLine().AppendLine(FormattableString.Invariant($$""" - private WorksheetRowTypeInfo<{{rowType.FullName}}>? _{{rowType.Name}}; - public WorksheetRowTypeInfo<{{rowType.FullName}}> {{rowType.Name}} => _{{rowType.Name}} - """)); + sb.AppendLine().AppendLine($$""" + private WorksheetRowTypeInfo<{{rowType.FullName}}>? _{{rowType.Name}}; + public WorksheetRowTypeInfo<{{rowType.FullName}}> {{rowType.Name}} => _{{rowType.Name}} + """); if (rowType.Properties.Count == 0) { @@ -221,12 +227,12 @@ private static void GenerateCodeForType(StringBuilder sb, int typeIndex, RowType """)); GenerateAddHeaderRow(sb, typeIndex, rowType.Properties); - GenerateAddAsRow(sb, 2, rowType); - GenerateAddRangeAsRows(sb, 2, rowType); - GenerateAddAsRowInternal(sb, 2, rowType.FullName, rowType.Properties); - GenerateAddRangeAsRowsInternal(sb, rowType, rowType.Properties); - GenerateAddEnumerableAsRows(sb, 2, rowType); - GenerateAddCellsAsRow(sb, 2, rowType, rowType.Properties); + GenerateAddAsRow(sb, rowType); + GenerateAddRangeAsRows(sb, rowType); + GenerateAddAsRowInternal(sb, rowType); + GenerateAddRangeAsRowsInternal(sb, rowType); + GenerateAddEnumerableAsRows(sb, rowType); + GenerateAddCellsAsRow(sb, rowType); } private static void ReportDiagnostics(RowType rowType, LocationInfo? locationInfo, GeneratorOptions? options, SourceProductionContext context) @@ -258,12 +264,12 @@ private static void GenerateAddHeaderRow(StringBuilder sb, int typeIndex, IReadO Debug.Assert(properties.Count > 0); sb.AppendLine().AppendLine(FormattableString.Invariant($$""" - private static async ValueTask AddHeaderRow{{typeIndex}}Async(SpreadCheetah.Spreadsheet spreadsheet, SpreadCheetah.Styling.StyleId? styleId, CancellationToken token) - { - var cells = ArrayPool.Shared.Rent({{properties.Count}}); - try + private static async ValueTask AddHeaderRow{{typeIndex}}Async(SpreadCheetah.Spreadsheet spreadsheet, SpreadCheetah.Styling.StyleId? styleId, CancellationToken token) { - """)); + var cells = ArrayPool.Shared.Rent({{properties.Count}}); + try + { + """)); foreach (var (i, property) in properties.Index()) { @@ -273,82 +279,85 @@ private static void GenerateAddHeaderRow(StringBuilder sb, int typeIndex, IReadO } sb.AppendLine($$""" - await spreadsheet.AddRowAsync(cells.AsMemory(0, {{properties.Count}}), token).ConfigureAwait(false); - } - finally - { - ArrayPool.Shared.Return(cells, true); + await spreadsheet.AddRowAsync(cells.AsMemory(0, {{properties.Count}}), token).ConfigureAwait(false); + } + finally + { + ArrayPool.Shared.Return(cells, true); + } } - } - """); + """); } - private static void GenerateAddAsRow(StringBuilder sb, int indent, RowType rowType) + private static void GenerateAddAsRow(StringBuilder sb, RowType rowType) { - sb.AppendLine() - .AppendIndentation(indent) - .Append("private static ValueTask AddAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet, ") - .Append(rowType.FullNameWithNullableAnnotation) - .AppendLine(" obj, CancellationToken token)"); + sb.AppendLine($$""" - sb.AppendLine(indent, "{"); - sb.AppendLine(indent, " if (spreadsheet is null)"); - sb.AppendLine(indent, " throw new ArgumentNullException(nameof(spreadsheet));"); + private static ValueTask AddAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet, {{rowType.FullNameWithNullableAnnotation}} obj, CancellationToken token) + { + if (spreadsheet is null) + throw new ArgumentNullException(nameof(spreadsheet)); + """); if (rowType.IsReferenceType) { - sb.AppendLine(indent + 1, "if (obj is null)"); - sb.AppendLine(indent + 1, " return spreadsheet.AddRowAsync(ReadOnlyMemory.Empty, token);"); + sb.AppendLine(""" + if (obj is null) + return spreadsheet.AddRowAsync(ReadOnlyMemory.Empty, token); + """); } - sb.AppendLine(indent, " return AddAsRowInternalAsync(spreadsheet, obj, token);"); - sb.AppendLine(indent, "}"); + sb.AppendLine(""" + return AddAsRowInternalAsync(spreadsheet, obj, token); + } + """); } - private static void GenerateAddAsRowInternal(StringBuilder sb, int indent, string rowTypeFullname, IReadOnlyCollection properties) + private static void GenerateAddAsRowInternal(StringBuilder sb, RowType rowType) { + var properties = rowType.Properties; Debug.Assert(properties.Count > 0); - sb.AppendLine(); - sb.AppendLine(indent, $"private static async ValueTask AddAsRowInternalAsync(SpreadCheetah.Spreadsheet spreadsheet, {rowTypeFullname} obj, CancellationToken token)"); - sb.AppendLine(indent, "{"); - sb.AppendLine(indent, $" var cells = ArrayPool.Shared.Rent({properties.Count});"); - sb.AppendLine(indent, " try"); - sb.AppendLine(indent, " {"); - sb.AppendLine(indent, " await AddCellsAsRowAsync(spreadsheet, obj, cells, token).ConfigureAwait(false);"); - sb.AppendLine(indent, " }"); - sb.AppendLine(indent, " finally"); - sb.AppendLine(indent, " {"); - sb.AppendLine(indent, " ArrayPool.Shared.Return(cells, true);"); - sb.AppendLine(indent, " }"); - sb.AppendLine(indent, "}"); + sb.AppendLine($$""" + + private static async ValueTask AddAsRowInternalAsync(SpreadCheetah.Spreadsheet spreadsheet, {{rowType.FullName}} obj, CancellationToken token) + { + var cells = ArrayPool.Shared.Rent({{properties.Count}}); + try + { + await AddCellsAsRowAsync(spreadsheet, obj, cells, token).ConfigureAwait(false); + } + finally + { + ArrayPool.Shared.Return(cells, true); + } + } + """); } - private static void GenerateAddRangeAsRows(StringBuilder sb, int indent, RowType rowType) + private static void GenerateAddRangeAsRows(StringBuilder sb, RowType rowType) { - sb.AppendLine() - .AppendIndentation(indent) - .Append("private static ValueTask AddRangeAsRowsAsync(SpreadCheetah.Spreadsheet spreadsheet, IEnumerable<") - .Append(rowType.FullNameWithNullableAnnotation) - .AppendLine("> objs, CancellationToken token)"); - - sb.AppendLine(indent, "{"); - sb.AppendLine(indent, " if (spreadsheet is null)"); - sb.AppendLine(indent, " throw new ArgumentNullException(nameof(spreadsheet));"); - sb.AppendLine(indent, " if (objs is null)"); - sb.AppendLine(indent, " throw new ArgumentNullException(nameof(objs));"); - sb.AppendLine(indent, " return AddRangeAsRowsInternalAsync(spreadsheet, objs, token);"); - sb.AppendLine(indent, "}"); + sb.AppendLine($$""" + + private static ValueTask AddRangeAsRowsAsync(SpreadCheetah.Spreadsheet spreadsheet, IEnumerable<{{rowType.FullNameWithNullableAnnotation}}> objs, CancellationToken token) + { + if (spreadsheet is null) + throw new ArgumentNullException(nameof(spreadsheet)); + if (objs is null) + throw new ArgumentNullException(nameof(objs)); + return AddRangeAsRowsInternalAsync(spreadsheet, objs, token); + } + """); } - private static void GenerateAddRangeAsRowsInternal(StringBuilder sb, RowType rowType, IReadOnlyCollection properties) + private static void GenerateAddRangeAsRowsInternal(StringBuilder sb, RowType rowType) { + var properties = rowType.Properties; Debug.Assert(properties.Count > 0); - var typeString = rowType.FullNameWithNullableAnnotation; sb.Append($$""" - private static async ValueTask AddRangeAsRowsInternalAsync(SpreadCheetah.Spreadsheet spreadsheet, IEnumerable<{{typeString}}> objs, CancellationToken token) + private static async ValueTask AddRangeAsRowsInternalAsync(SpreadCheetah.Spreadsheet spreadsheet, IEnumerable<{{rowType.FullNameWithNullableAnnotation}}> objs, CancellationToken token) { var cells = ArrayPool.Shared.Rent({{properties.Count}}); try @@ -364,52 +373,50 @@ private static async ValueTask AddRangeAsRowsInternalAsync(SpreadCheetah.Spreads """); } - private static void GenerateAddEnumerableAsRows(StringBuilder sb, int indent, RowType rowType) + private static void GenerateAddEnumerableAsRows(StringBuilder sb, RowType rowType) { - sb.AppendLine() - .AppendIndentation(indent) - .Append("private static async ValueTask AddEnumerableAsRowsAsync(SpreadCheetah.Spreadsheet spreadsheet, IEnumerable<") - .Append(rowType.FullNameWithNullableAnnotation) - .AppendLine("> objs, DataCell[] cells, CancellationToken token)"); - - sb.AppendLine(indent, "{"); - sb.AppendLine(indent, " foreach (var obj in objs)"); - sb.AppendLine(indent, " {"); - sb.AppendLine(indent, " await AddCellsAsRowAsync(spreadsheet, obj, cells, token).ConfigureAwait(false);"); - sb.AppendLine(indent, " }"); - sb.AppendLine(indent, "}"); + sb.AppendLine($$""" + + private static async ValueTask AddEnumerableAsRowsAsync(SpreadCheetah.Spreadsheet spreadsheet, IEnumerable<{{rowType.FullNameWithNullableAnnotation}}> objs, DataCell[] cells, CancellationToken token) + { + foreach (var obj in objs) + { + await AddCellsAsRowAsync(spreadsheet, obj, cells, token).ConfigureAwait(false); + } + } + """); } - private static void GenerateAddCellsAsRow(StringBuilder sb, int indent, RowType rowType, IReadOnlyCollection properties) + private static void GenerateAddCellsAsRow(StringBuilder sb, RowType rowType) { + var properties = rowType.Properties; Debug.Assert(properties.Count > 0); - sb.AppendLine() - .AppendIndentation(indent) - .Append("private static ValueTask AddCellsAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet, ") - .Append(rowType.FullNameWithNullableAnnotation) - .AppendLine(" obj, DataCell[] cells, CancellationToken token)"); + sb.AppendLine($$""" - sb.AppendLine(indent, "{"); + private static ValueTask AddCellsAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet, {{rowType.FullNameWithNullableAnnotation}} obj, DataCell[] cells, CancellationToken token) + { + """); if (rowType.IsReferenceType) { - sb.AppendLine(indent, " if (obj is null)"); - sb.AppendLine(indent, " return spreadsheet.AddRowAsync(ReadOnlyMemory.Empty, token);"); - sb.AppendLine(); + sb.AppendLine(""" + if (obj is null) + return spreadsheet.AddRowAsync(ReadOnlyMemory.Empty, token); + + """); } foreach (var (i, property) in properties.Index()) { - sb.AppendIndentation(indent + 1) - .Append("cells[") - .Append(i) - .Append("] = new DataCell(obj.") - .Append(property.Name) - .AppendLine(");"); + sb.AppendLine(FormattableString.Invariant($$""" + cells[{{i}}] = new DataCell(obj.{{property.Name}}); + """)); } - sb.AppendLine(indent, $" return spreadsheet.AddRowAsync(cells.AsMemory(0, {properties.Count}), token);"); - sb.AppendLine(indent, "}"); + sb.AppendLine($$""" + return spreadsheet.AddRowAsync(cells.AsMemory(0, {{properties.Count}}), token); + } + """); } }