From dff2ab53aa9d106399666791d7690565358f2daf Mon Sep 17 00:00:00 2001 From: sveinungf Date: Fri, 21 Jun 2024 16:48:32 +0200 Subject: [PATCH 1/2] Architecture test for there not being default constructor on structs on .NET Standard 2.0 --- Directory.Packages.props | 1 + ...NoDefaultConstructorForStructsCondition.cs | 42 +++++++++++++++++++ SpreadCheetah.Test/SpreadCheetah.Test.csproj | 2 +- SpreadCheetah.Test/Tests/ArchitectureTests.cs | 27 ++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 SpreadCheetah.Test/Helpers/NoDefaultConstructorForStructsCondition.cs create mode 100644 SpreadCheetah.Test/Tests/ArchitectureTests.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 07317381..c06ecbb0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -31,6 +31,7 @@ + diff --git a/SpreadCheetah.Test/Helpers/NoDefaultConstructorForStructsCondition.cs b/SpreadCheetah.Test/Helpers/NoDefaultConstructorForStructsCondition.cs new file mode 100644 index 00000000..92130ad8 --- /dev/null +++ b/SpreadCheetah.Test/Helpers/NoDefaultConstructorForStructsCondition.cs @@ -0,0 +1,42 @@ +using ArchUnitNET.Domain; +using ArchUnitNET.Domain.Extensions; +using ArchUnitNET.Fluent.Conditions; + +namespace SpreadCheetah.Test.Helpers; + +internal sealed class NoDefaultConstructorForStructsCondition : ICondition +{ + public string Description => "not have a default constructor"; + + public IEnumerable Check(IEnumerable objects, Architecture architecture) + { + foreach (var obj in objects) + { + yield return Check(obj); + } + } + + private static ConditionResult Check(IType type) + { + var pass = true; + + if (type is Struct structType) + { + foreach (var constructor in structType.GetConstructors()) + { + if (constructor.IsStatic is true) + continue; + + if (!constructor.Parameters.Any()) + { + pass = false; + break; + } + } + } + + return new ConditionResult(type, pass: pass, failDescription: pass ? null : "has a default constructor"); + } + + public bool CheckEmpty() => true; +} diff --git a/SpreadCheetah.Test/SpreadCheetah.Test.csproj b/SpreadCheetah.Test/SpreadCheetah.Test.csproj index 8ba70d67..199a84cf 100644 --- a/SpreadCheetah.Test/SpreadCheetah.Test.csproj +++ b/SpreadCheetah.Test/SpreadCheetah.Test.csproj @@ -24,6 +24,7 @@ + @@ -50,7 +51,6 @@ - diff --git a/SpreadCheetah.Test/Tests/ArchitectureTests.cs b/SpreadCheetah.Test/Tests/ArchitectureTests.cs new file mode 100644 index 00000000..ae0d3ca8 --- /dev/null +++ b/SpreadCheetah.Test/Tests/ArchitectureTests.cs @@ -0,0 +1,27 @@ +#if !NET5_0_OR_GREATER +using ArchUnitNET.Domain; +using ArchUnitNET.Loader; +using ArchUnitNET.xUnit; +using SpreadCheetah.Test.Helpers; +using static ArchUnitNET.Fluent.ArchRuleDefinition; + +namespace SpreadCheetah.Test.Tests; + +public class ArchitectureTests +{ + private static readonly Architecture Architecture = new ArchLoader().LoadAssemblies(typeof(Spreadsheet).Assembly).Build(); + + /// + /// Structs with a default constructor leads to a compilation error on UWP: https://github.com/sveinungf/spreadcheetah/issues/58 + /// + [Fact] + public void Architecture_NoDefaultConstructorForStructs() + { + // Arrange + var rule = Types().Should().FollowCustomCondition(new NoDefaultConstructorForStructsCondition()); + + // Act & Assert + rule.Check(Architecture); + } +} +#endif \ No newline at end of file From 53c359460ddf7225c38ac8d4d0c46d64a90c0671 Mon Sep 17 00:00:00 2001 From: sveinungf Date: Fri, 21 Jun 2024 17:15:16 +0200 Subject: [PATCH 2/2] Remove default constructors on structs on .NET Standard 2.0 --- SpreadCheetah/CellValues/CellValue.cs | 4 ++-- SpreadCheetah/CellValues/PrimitiveCellValue.cs | 4 ++-- SpreadCheetah/CellValues/StringOrPrimitiveCellValue.cs | 4 ++-- SpreadCheetah/Helpers/PooledArray.cs | 8 +------- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/SpreadCheetah/CellValues/CellValue.cs b/SpreadCheetah/CellValues/CellValue.cs index 718462ff..6b63e5b5 100644 --- a/SpreadCheetah/CellValues/CellValue.cs +++ b/SpreadCheetah/CellValues/CellValue.cs @@ -8,12 +8,12 @@ internal readonly struct CellValue [FieldOffset(0)] public readonly StringOrPrimitiveCellValue StringOrPrimitive; [FieldOffset(0)] public readonly ReadOnlyMemory Memory; +#if NET5_0_OR_GREATER public CellValue() { -#if NET5_0_OR_GREATER System.Runtime.CompilerServices.Unsafe.SkipInit(out this); -#endif } +#endif public CellValue(StringOrPrimitiveCellValue value) : this() => StringOrPrimitive = value; public CellValue(ReadOnlyMemory value) : this() => Memory = value; diff --git a/SpreadCheetah/CellValues/PrimitiveCellValue.cs b/SpreadCheetah/CellValues/PrimitiveCellValue.cs index 72fab1ac..41c604f2 100644 --- a/SpreadCheetah/CellValues/PrimitiveCellValue.cs +++ b/SpreadCheetah/CellValues/PrimitiveCellValue.cs @@ -9,12 +9,12 @@ internal readonly struct PrimitiveCellValue [FieldOffset(0)] public readonly float FloatValue; [FieldOffset(0)] public readonly double DoubleValue; +#if NET5_0_OR_GREATER public PrimitiveCellValue() { -#if NET5_0_OR_GREATER System.Runtime.CompilerServices.Unsafe.SkipInit(out this); -#endif } +#endif public PrimitiveCellValue(int value) : this() => IntValue = value; public PrimitiveCellValue(float value) : this() => FloatValue = value; diff --git a/SpreadCheetah/CellValues/StringOrPrimitiveCellValue.cs b/SpreadCheetah/CellValues/StringOrPrimitiveCellValue.cs index 1938414f..ed306552 100644 --- a/SpreadCheetah/CellValues/StringOrPrimitiveCellValue.cs +++ b/SpreadCheetah/CellValues/StringOrPrimitiveCellValue.cs @@ -5,12 +5,12 @@ internal readonly struct StringOrPrimitiveCellValue public readonly string? StringValue; public readonly PrimitiveCellValue PrimitiveValue; +#if NET5_0_OR_GREATER public StringOrPrimitiveCellValue() { -#if NET5_0_OR_GREATER System.Runtime.CompilerServices.Unsafe.SkipInit(out this); -#endif } +#endif public StringOrPrimitiveCellValue(string? value) : this() => StringValue = value; public StringOrPrimitiveCellValue(PrimitiveCellValue value) : this() => PrimitiveValue = value; diff --git a/SpreadCheetah/Helpers/PooledArray.cs b/SpreadCheetah/Helpers/PooledArray.cs index bb5348cd..022d3883 100644 --- a/SpreadCheetah/Helpers/PooledArray.cs +++ b/SpreadCheetah/Helpers/PooledArray.cs @@ -9,12 +9,6 @@ namespace SpreadCheetah.Helpers; public ReadOnlyMemory Memory => _array.AsMemory(0, _count); - public PooledArray() - { - _array = []; - _count = 0; - } - private PooledArray(T[] array, int count) { _array = array; @@ -24,7 +18,7 @@ private PooledArray(T[] array, int count) public static PooledArray Create(ICollection collection) { if (collection.Count == 0) - return new PooledArray(); + return new PooledArray([], 0); var array = ArrayPool.Shared.Rent(collection.Count);