Skip to content

Commit

Permalink
Merge pull request #72 from sveinungf/dev/src-gen-cellvalueconverter
Browse files Browse the repository at this point in the history
Source generator - CellValueConverter
  • Loading branch information
sveinungf authored Sep 7, 2024
2 parents 4e8ef39 + 115ce1b commit 0447c23
Show file tree
Hide file tree
Showing 53 changed files with 1,103 additions and 474 deletions.
6 changes: 5 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ dotnet_diagnostic.IDE0301.severity = warning
# IDE0305: Use collection expression for fluent
dotnet_diagnostic.IDE0305.severity = warning

[{CellValueTruncateAttribute.cs,ColumnHeaderAttribute.cs,ColumnOrderAttribute.cs,CellStyleAttribute.cs,ColumnWidthAttribute.cs,WorksheetRowAttribute.cs}]
[{CellStyleAttribute.cs,CellValueConverterAttribute.cs,CellValueTruncateAttribute.cs,ColumnHeaderAttribute.cs,ColumnOrderAttribute.cs,ColumnWidthAttribute.cs,WorksheetRowAttribute.cs}]
# CA1019: Define accessors for attribute arguments
dotnet_diagnostic.CA1019.severity = none
# CS9113: Parameter is unread
Expand Down Expand Up @@ -266,6 +266,10 @@ dotnet_diagnostic.S3925.severity = none
# S4136: Method overloads should be grouped together
dotnet_diagnostic.S4136.severity = warning

[{CellValueConverter.cs}]
# S1694: An abstract class should have both abstract and concrete methods
dotnet_diagnostic.S1694.severity = none

[{*Test,*.Benchmark}/**.cs]
# S927: Parameter names should match base declaration
dotnet_diagnostic.S927.severity = none
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace SpreadCheetah.SourceGenerator.CSharp8Test.Models
public class BaseClass
{
[CellStyle("Id style")]
[CellValueConverter(typeof(RemoveDashesValueConverter))]
public string Id { get; }

protected BaseClass(string id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class ClassWithMultipleProperties : BaseClass
public string LastName { get; }

[ColumnOrder(1)]
[CellValueConverter(typeof(UpperCaseValueConverter))]
public string FirstName { get; }

[ColumnWidth(5)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using SpreadCheetah.SourceGeneration;

namespace SpreadCheetah.SourceGenerator.CSharp8Test.Models
{
internal class RemoveDashesValueConverter : CellValueConverter<string>
{
public override DataCell ConvertToDataCell(string value)
{
return new DataCell(value.Replace("-", ""));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using SpreadCheetah.SourceGeneration;

namespace SpreadCheetah.SourceGenerator.CSharp8Test.Models
{
public class UpperCaseValueConverter : CellValueConverter<string>
{
public override DataCell ConvertToDataCell(string value)
{
return new DataCell(value.ToUpperInvariant());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ public class WorksheetRowGeneratorTests
public async Task Spreadsheet_AddAsRow_ClassWithMultipleProperties()
{
// Arrange
const string id = "2cc56ae0-32b2-46c2-b6d2-27c6ce8568ec";
var obj = new ClassWithMultipleProperties(
id: Guid.NewGuid().ToString(),
id: id,
firstName: "Ola",
lastName: "Nordmann",
age: 30);
Expand All @@ -36,8 +37,8 @@ public async Task Spreadsheet_AddAsRow_ClassWithMultipleProperties()

// Assert
using var sheet = SpreadsheetAssert.SingleSheet(stream);
Assert.Equal(obj.FirstName, sheet["A1"].StringValue);
Assert.Equal(obj.Id, sheet["B1"].StringValue);
Assert.Equal(obj.FirstName.ToUpperInvariant(), sheet["A1"].StringValue);
Assert.Equal(obj.Id.Replace("-", ""), sheet["B1"].StringValue);
Assert.Equal(obj.LastName, sheet["C1"].StringValue);
Assert.Equal(obj.Age, sheet["D1"].IntValue);
Assert.Equal(4, sheet.CellCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
Severity: Error,
WarningLevel: 0,
Location: : (6,5)-(6,18),
MessageFormat: '{0}' is an invalid argument for attribute '{1}',
Message: '' is an invalid argument for attribute 'SpreadCheetah.SourceGeneration.CellStyleAttribute',
MessageFormat: '{0}' is an invalid argument for {1},
Message: '' is an invalid argument for CellStyleAttribute,
Category: SpreadCheetah.SourceGenerator
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,28 @@ public partial class MyGenRowContext
public MyGenRowContext()
{
}
private static readonly MyNamespace.StringValueConverter _valueConverter0 = new MyNamespace.StringValueConverter();

private WorksheetRowTypeInfo<MyNamespace.ClassWithDuplicateColumnOrdering>? _ClassWithDuplicateColumnOrdering;
public WorksheetRowTypeInfo<MyNamespace.ClassWithDuplicateColumnOrdering> ClassWithDuplicateColumnOrdering => _ClassWithDuplicateColumnOrdering
??= WorksheetRowMetadataServices.CreateObjectInfo<MyNamespace.ClassWithDuplicateColumnOrdering>(
AddHeaderRow0Async, AddAsRowAsync, AddRangeAsRowsAsync, null);
private WorksheetRowTypeInfo<MyNamespace.ClassPropertyWithConverterAndCellStyle>? _ClassPropertyWithConverterAndCellStyle;
public WorksheetRowTypeInfo<MyNamespace.ClassPropertyWithConverterAndCellStyle> ClassPropertyWithConverterAndCellStyle => _ClassPropertyWithConverterAndCellStyle
??= WorksheetRowMetadataServices.CreateObjectInfo<MyNamespace.ClassPropertyWithConverterAndCellStyle>(
AddHeaderRow0Async, AddAsRowAsync, AddRangeAsRowsAsync, null, CreateWorksheetRowDependencyInfo0);

private static WorksheetRowDependencyInfo CreateWorksheetRowDependencyInfo0(Spreadsheet spreadsheet)
{
var styleIds = new[]
{
spreadsheet.GetStyleId("My style"),
};
return new WorksheetRowDependencyInfo(styleIds);
}

private static async ValueTask AddHeaderRow0Async(SpreadCheetah.Spreadsheet spreadsheet, SpreadCheetah.Styling.StyleId? styleId, CancellationToken token)
{
var cells = ArrayPool<StyledCell>.Shared.Rent(1);
try
{
cells[0] = new StyledCell("PropertyA", styleId);
cells[0] = new StyledCell("Property", styleId);
await spreadsheet.AddRowAsync(cells.AsMemory(0, 1), token).ConfigureAwait(false);
}
finally
Expand All @@ -40,17 +50,17 @@ private static async ValueTask AddHeaderRow0Async(SpreadCheetah.Spreadsheet spre
}
}

private static ValueTask AddAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet, MyNamespace.ClassWithDuplicateColumnOrdering? obj, CancellationToken token)
private static ValueTask AddAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet, MyNamespace.ClassPropertyWithConverterAndCellStyle? obj, CancellationToken token)
{
if (spreadsheet is null)
throw new ArgumentNullException(nameof(spreadsheet));
if (obj is null)
return spreadsheet.AddRowAsync(ReadOnlyMemory<DataCell>.Empty, token);
return spreadsheet.AddRowAsync(ReadOnlyMemory<StyledCell>.Empty, token);
return AddAsRowInternalAsync(spreadsheet, obj, token);
}

private static ValueTask AddRangeAsRowsAsync(SpreadCheetah.Spreadsheet spreadsheet,
IEnumerable<MyNamespace.ClassWithDuplicateColumnOrdering?> objs,
IEnumerable<MyNamespace.ClassPropertyWithConverterAndCellStyle?> objs,
CancellationToken token)
{
if (spreadsheet is null)
Expand All @@ -61,48 +71,50 @@ private static ValueTask AddRangeAsRowsAsync(SpreadCheetah.Spreadsheet spreadshe
}

private static async ValueTask AddAsRowInternalAsync(SpreadCheetah.Spreadsheet spreadsheet,
MyNamespace.ClassWithDuplicateColumnOrdering obj,
MyNamespace.ClassPropertyWithConverterAndCellStyle obj,
CancellationToken token)
{
var cells = ArrayPool<DataCell>.Shared.Rent(1);
var cells = ArrayPool<StyledCell>.Shared.Rent(1);
try
{
var styleIds = Array.Empty<StyleId>();
var worksheetRowDependencyInfo = spreadsheet.GetOrCreateWorksheetRowDependencyInfo(Default.ClassPropertyWithConverterAndCellStyle);
var styleIds = worksheetRowDependencyInfo.StyleIds;
await AddCellsAsRowAsync(spreadsheet, obj, cells, styleIds, token).ConfigureAwait(false);
}
finally
{
ArrayPool<DataCell>.Shared.Return(cells, true);
ArrayPool<StyledCell>.Shared.Return(cells, true);
}
}

private static async ValueTask AddRangeAsRowsInternalAsync(SpreadCheetah.Spreadsheet spreadsheet,
IEnumerable<MyNamespace.ClassWithDuplicateColumnOrdering?> objs,
IEnumerable<MyNamespace.ClassPropertyWithConverterAndCellStyle?> objs,
CancellationToken token)
{
var cells = ArrayPool<DataCell>.Shared.Rent(1);
var cells = ArrayPool<StyledCell>.Shared.Rent(1);
try
{
var styleIds = Array.Empty<StyleId>();
var worksheetRowDependencyInfo = spreadsheet.GetOrCreateWorksheetRowDependencyInfo(Default.ClassPropertyWithConverterAndCellStyle);
var styleIds = worksheetRowDependencyInfo.StyleIds;
foreach (var obj in objs)
{
await AddCellsAsRowAsync(spreadsheet, obj, cells, styleIds, token).ConfigureAwait(false);
}
}
finally
{
ArrayPool<DataCell>.Shared.Return(cells, true);
ArrayPool<StyledCell>.Shared.Return(cells, true);
}
}

private static ValueTask AddCellsAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet,
MyNamespace.ClassWithDuplicateColumnOrdering? obj,
DataCell[] cells, IReadOnlyList<StyleId> styleIds, CancellationToken token)
MyNamespace.ClassPropertyWithConverterAndCellStyle? obj,
StyledCell[] cells, IReadOnlyList<StyleId> styleIds, CancellationToken token)
{
if (obj is null)
return spreadsheet.AddRowAsync(ReadOnlyMemory<DataCell>.Empty, token);
return spreadsheet.AddRowAsync(ReadOnlyMemory<StyledCell>.Empty, token);

cells[0] = new DataCell(obj.PropertyA);
cells[0] = new StyledCell(_valueConverter0.ConvertToDataCell(obj.Property), styleIds[0]);
return spreadsheet.AddRowAsync(cells.AsMemory(0, 1), token);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
Diagnostics: [
{
Id: SPCH1008,
Title: Attribute combination not supported,
Severity: Error,
WarningLevel: 0,
Location: : (7,19)-(7,27),
MessageFormat: Having both the {0} and the {1} attributes on a property is not supported,
Message: Having both the CellValueConverter and the CellValueTruncate attributes on a property is not supported,
Category: SpreadCheetah.SourceGenerator
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
Diagnostics: [
{
Id: SPCH1007,
Title: Invalid attribute type argument,
Severity: Error,
WarningLevel: 0,
Location: : (5,5)-(5,54),
MessageFormat: Type '{0}' is an invalid argument for {1} because it does not inherit {2},
Message: Type 'MyNamespace.DecimalValueConverter' is an invalid argument for CellValueConverterAttribute because it does not inherit CellValueConverter<decimal>,
Category: SpreadCheetah.SourceGenerator
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
Diagnostics: [
{
Id: SPCH1007,
Title: Invalid attribute type argument,
Severity: Error,
WarningLevel: 0,
Location: : (5,5)-(5,54),
MessageFormat: Type '{0}' is an invalid argument for {1} because it does not inherit {2},
Message: Type 'MyNamespace.DecimalValueConverter' is an invalid argument for CellValueConverterAttribute because it does not inherit CellValueConverter<string>,
Category: SpreadCheetah.SourceGenerator
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,32 @@ public partial class MyGenRowContext
public MyGenRowContext()
{
}
private static readonly MyNamespace.StringValueConverter _valueConverter0 = new MyNamespace.StringValueConverter();
private static readonly MyNamespace.NullableIntValueConverter _valueConverter1 = new MyNamespace.NullableIntValueConverter();
private static readonly MyNamespace.DecimalValueConverter _valueConverter2 = new MyNamespace.DecimalValueConverter();

private WorksheetRowTypeInfo<MyNamespace.ClassWithDuplicateColumnOrdering>? _ClassWithDuplicateColumnOrdering;
public WorksheetRowTypeInfo<MyNamespace.ClassWithDuplicateColumnOrdering> ClassWithDuplicateColumnOrdering => _ClassWithDuplicateColumnOrdering
??= WorksheetRowMetadataServices.CreateObjectInfo<MyNamespace.ClassWithDuplicateColumnOrdering>(
private WorksheetRowTypeInfo<MyNamespace.ClassWithMultipleConverters>? _ClassWithMultipleConverters;
public WorksheetRowTypeInfo<MyNamespace.ClassWithMultipleConverters> ClassWithMultipleConverters => _ClassWithMultipleConverters
??= WorksheetRowMetadataServices.CreateObjectInfo<MyNamespace.ClassWithMultipleConverters>(
AddHeaderRow0Async, AddAsRowAsync, AddRangeAsRowsAsync, null);

private static async ValueTask AddHeaderRow0Async(SpreadCheetah.Spreadsheet spreadsheet, SpreadCheetah.Styling.StyleId? styleId, CancellationToken token)
{
var cells = ArrayPool<StyledCell>.Shared.Rent(1);
var cells = ArrayPool<StyledCell>.Shared.Rent(3);
try
{
cells[0] = new StyledCell("PropertyB", styleId);
await spreadsheet.AddRowAsync(cells.AsMemory(0, 1), token).ConfigureAwait(false);
cells[0] = new StyledCell("Property", styleId);
cells[1] = new StyledCell("Property1", styleId);
cells[2] = new StyledCell("Property2", styleId);
await spreadsheet.AddRowAsync(cells.AsMemory(0, 3), token).ConfigureAwait(false);
}
finally
{
ArrayPool<StyledCell>.Shared.Return(cells, true);
}
}

private static ValueTask AddAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet, MyNamespace.ClassWithDuplicateColumnOrdering? obj, CancellationToken token)
private static ValueTask AddAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet, MyNamespace.ClassWithMultipleConverters? obj, CancellationToken token)
{
if (spreadsheet is null)
throw new ArgumentNullException(nameof(spreadsheet));
Expand All @@ -50,7 +55,7 @@ private static ValueTask AddAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet, My
}

private static ValueTask AddRangeAsRowsAsync(SpreadCheetah.Spreadsheet spreadsheet,
IEnumerable<MyNamespace.ClassWithDuplicateColumnOrdering?> objs,
IEnumerable<MyNamespace.ClassWithMultipleConverters?> objs,
CancellationToken token)
{
if (spreadsheet is null)
Expand All @@ -61,10 +66,10 @@ private static ValueTask AddRangeAsRowsAsync(SpreadCheetah.Spreadsheet spreadshe
}

private static async ValueTask AddAsRowInternalAsync(SpreadCheetah.Spreadsheet spreadsheet,
MyNamespace.ClassWithDuplicateColumnOrdering obj,
MyNamespace.ClassWithMultipleConverters obj,
CancellationToken token)
{
var cells = ArrayPool<DataCell>.Shared.Rent(1);
var cells = ArrayPool<DataCell>.Shared.Rent(3);
try
{
var styleIds = Array.Empty<StyleId>();
Expand All @@ -77,10 +82,10 @@ private static async ValueTask AddAsRowInternalAsync(SpreadCheetah.Spreadsheet s
}

private static async ValueTask AddRangeAsRowsInternalAsync(SpreadCheetah.Spreadsheet spreadsheet,
IEnumerable<MyNamespace.ClassWithDuplicateColumnOrdering?> objs,
IEnumerable<MyNamespace.ClassWithMultipleConverters?> objs,
CancellationToken token)
{
var cells = ArrayPool<DataCell>.Shared.Rent(1);
var cells = ArrayPool<DataCell>.Shared.Rent(3);
try
{
var styleIds = Array.Empty<StyleId>();
Expand All @@ -96,14 +101,16 @@ private static async ValueTask AddRangeAsRowsInternalAsync(SpreadCheetah.Spreads
}

private static ValueTask AddCellsAsRowAsync(SpreadCheetah.Spreadsheet spreadsheet,
MyNamespace.ClassWithDuplicateColumnOrdering? obj,
MyNamespace.ClassWithMultipleConverters? obj,
DataCell[] cells, IReadOnlyList<StyleId> styleIds, CancellationToken token)
{
if (obj is null)
return spreadsheet.AddRowAsync(ReadOnlyMemory<DataCell>.Empty, token);

cells[0] = new DataCell(obj.PropertyB);
return spreadsheet.AddRowAsync(cells.AsMemory(0, 1), token);
cells[0] = _valueConverter0.ConvertToDataCell(obj.Property);
cells[1] = _valueConverter1.ConvertToDataCell(obj.Property1);
cells[2] = _valueConverter2.ConvertToDataCell(obj.Property2);
return spreadsheet.AddRowAsync(cells.AsMemory(0, 3), token);
}

private static DataCell ConstructTruncatedDataCell(string? value, int truncateLength)
Expand Down
Loading

0 comments on commit 0447c23

Please sign in to comment.