diff --git a/Src/FluentAssertions/Types/TypeSelector.cs b/Src/FluentAssertions/Types/TypeSelector.cs index b22f059d79..613b554112 100644 --- a/Src/FluentAssertions/Types/TypeSelector.cs +++ b/Src/FluentAssertions/Types/TypeSelector.cs @@ -219,6 +219,30 @@ public TypeSelector ThatAreNotSealed() return this; } + /// + /// Filters and returns the types that are structs (a value type but not an Enum) + /// + public TypeSelector ThatAreStructs() + { + // A Type is a struct when it is a valueType, but Enums and primitives are also + // valueTypes so they must be excluded + types = types.Where(t => t.IsValueType && !t.IsEnum + && !t.IsPrimitive && !t.IsEquivalentTo(typeof(decimal))) + .ToList(); + return this; + } + + /// + /// Filters and returns the types that are not structs + /// + public TypeSelector ThatAreNotStructs() + { + types = types.Where(t => !t.IsValueType || t.IsEnum + || t.IsPrimitive || t.IsEquivalentTo(typeof(decimal))) + .ToList(); + return this; + } + /// /// Determines whether the type is static /// diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net47.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net47.verified.txt index e4791ac991..41cf188702 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net47.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net47.verified.txt @@ -2665,9 +2665,11 @@ namespace FluentAssertions.Types public FluentAssertions.Types.TypeSelector ThatAreNotInNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreNotSealed() { } public FluentAssertions.Types.TypeSelector ThatAreNotStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreNotStructs() { } public FluentAssertions.Types.TypeSelector ThatAreNotUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreSealed() { } public FluentAssertions.Types.TypeSelector ThatAreStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreStructs() { } public FluentAssertions.Types.TypeSelector ThatAreUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatDeriveFrom() { } public FluentAssertions.Types.TypeSelector ThatDoNotDeriveFrom() { } diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net6.0.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net6.0.verified.txt index 029ff8811d..8ed92097bc 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net6.0.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/net6.0.verified.txt @@ -2795,9 +2795,11 @@ namespace FluentAssertions.Types public FluentAssertions.Types.TypeSelector ThatAreNotInNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreNotSealed() { } public FluentAssertions.Types.TypeSelector ThatAreNotStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreNotStructs() { } public FluentAssertions.Types.TypeSelector ThatAreNotUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreSealed() { } public FluentAssertions.Types.TypeSelector ThatAreStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreStructs() { } public FluentAssertions.Types.TypeSelector ThatAreUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatDeriveFrom() { } public FluentAssertions.Types.TypeSelector ThatDoNotDeriveFrom() { } diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netcoreapp2.1.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netcoreapp2.1.verified.txt index 8c05e9795d..cb0c2445bc 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netcoreapp2.1.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netcoreapp2.1.verified.txt @@ -2667,9 +2667,11 @@ namespace FluentAssertions.Types public FluentAssertions.Types.TypeSelector ThatAreNotInNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreNotSealed() { } public FluentAssertions.Types.TypeSelector ThatAreNotStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreNotStructs() { } public FluentAssertions.Types.TypeSelector ThatAreNotUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreSealed() { } public FluentAssertions.Types.TypeSelector ThatAreStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreStructs() { } public FluentAssertions.Types.TypeSelector ThatAreUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatDeriveFrom() { } public FluentAssertions.Types.TypeSelector ThatDoNotDeriveFrom() { } diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netcoreapp3.0.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netcoreapp3.0.verified.txt index 8c05e9795d..cb0c2445bc 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netcoreapp3.0.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netcoreapp3.0.verified.txt @@ -2667,9 +2667,11 @@ namespace FluentAssertions.Types public FluentAssertions.Types.TypeSelector ThatAreNotInNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreNotSealed() { } public FluentAssertions.Types.TypeSelector ThatAreNotStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreNotStructs() { } public FluentAssertions.Types.TypeSelector ThatAreNotUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreSealed() { } public FluentAssertions.Types.TypeSelector ThatAreStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreStructs() { } public FluentAssertions.Types.TypeSelector ThatAreUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatDeriveFrom() { } public FluentAssertions.Types.TypeSelector ThatDoNotDeriveFrom() { } diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.0.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.0.verified.txt index 6af101d69f..9e26fab580 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.0.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.0.verified.txt @@ -2616,9 +2616,11 @@ namespace FluentAssertions.Types public FluentAssertions.Types.TypeSelector ThatAreNotInNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreNotSealed() { } public FluentAssertions.Types.TypeSelector ThatAreNotStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreNotStructs() { } public FluentAssertions.Types.TypeSelector ThatAreNotUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreSealed() { } public FluentAssertions.Types.TypeSelector ThatAreStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreStructs() { } public FluentAssertions.Types.TypeSelector ThatAreUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatDeriveFrom() { } public FluentAssertions.Types.TypeSelector ThatDoNotDeriveFrom() { } diff --git a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.1.verified.txt b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.1.verified.txt index 8c05e9795d..cb0c2445bc 100644 --- a/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.1.verified.txt +++ b/Tests/Approval.Tests/ApprovedApi/FluentAssertions/netstandard2.1.verified.txt @@ -2667,9 +2667,11 @@ namespace FluentAssertions.Types public FluentAssertions.Types.TypeSelector ThatAreNotInNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreNotSealed() { } public FluentAssertions.Types.TypeSelector ThatAreNotStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreNotStructs() { } public FluentAssertions.Types.TypeSelector ThatAreNotUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatAreSealed() { } public FluentAssertions.Types.TypeSelector ThatAreStatic() { } + public FluentAssertions.Types.TypeSelector ThatAreStructs() { } public FluentAssertions.Types.TypeSelector ThatAreUnderNamespace(string @namespace) { } public FluentAssertions.Types.TypeSelector ThatDeriveFrom() { } public FluentAssertions.Types.TypeSelector ThatDoNotDeriveFrom() { } diff --git a/Tests/FluentAssertions.Specs/Types/TypeSelectorSpecs.cs b/Tests/FluentAssertions.Specs/Types/TypeSelectorSpecs.cs index ec0872031f..2c4ac0833f 100644 --- a/Tests/FluentAssertions.Specs/Types/TypeSelectorSpecs.cs +++ b/Tests/FluentAssertions.Specs/Types/TypeSelectorSpecs.cs @@ -11,6 +11,7 @@ using Internal.Other.Test.Common; using Internal.SealedAndNotSealedClasses.Test; using Internal.StaticAndNonStaticClasses.Test; +using Internal.StructsAndNotStructs.Test; using Internal.UnwrapSelectorTestTypes.Test; using Xunit; using ISomeInterface = Internal.Main.Test.ISomeInterface; @@ -564,6 +565,44 @@ public void When_selecting_types_that_are_not_sealed_classes_it_should_return_th .Which.Should().Be(typeof(NotSealedClass)); } + [Fact] + public void When_selecting_types_that_are_structs_it_should_return_the_correct_types() + { + // Arrange + Assembly assembly = typeof(InternalStructType).GetTypeInfo().Assembly; + + // Act + IEnumerable types = AllTypes.From(assembly) + .ThatAreInNamespace("Internal.StructsAndNotStructs.Test") + .ThatAreStructs(); + + // Assert + types.Should() + .HaveCount(2) + .And.Contain(typeof(InternalRecordStructType)) + .And.Contain(typeof(InternalStructType)); + } + + [Fact] + public void When_selecting_types_that_are_not_structs_it_should_return_the_correct_types() + { + // Arrange + Assembly assembly = typeof(InternalClassAndNotStruct).GetTypeInfo().Assembly; + + // Act + IEnumerable types = AllTypes.From(assembly) + .ThatAreInNamespace("Internal.StructsAndNotStructs.Test") + .ThatAreNotStructs(); + + // Assert + types.Should() + .HaveCount(4) + .And.Contain(typeof(InternalClassAndNotStruct)) + .And.Contain(typeof(InternalEnumAndNotStruct)) + .And.Contain(typeof(InternalInterfaceAndNotStruct)) + .And.Contain(typeof(InternalRecordClass)); + } + [Fact] public void When_selecting_types_that_are_static_classes_it_should_return_the_correct_types() { @@ -779,6 +818,33 @@ internal static class NotAbstractStaticClass } } +namespace Internal.StructsAndNotStructs.Test +{ + internal struct InternalStructType + { + } + + internal record struct InternalRecordStructType + { + } + + internal record class InternalRecordClass + { + } + + internal enum InternalEnumAndNotStruct + { + } + + internal interface InternalInterfaceAndNotStruct + { + } + + internal class InternalClassAndNotStruct + { + } +} + namespace Internal.UnwrapSelectorTestTypes.Test { internal class ClassToExploreUnwrappedTaskTypes diff --git a/docs/_pages/releases.md b/docs/_pages/releases.md index 0c5c3a0afb..206fe4b0e7 100644 --- a/docs/_pages/releases.md +++ b/docs/_pages/releases.md @@ -13,7 +13,9 @@ sidebar: * Added `ThatAre[Not]Abstract` method for filtering the types - [#2058](https://github.com/fluentassertions/fluentassertions/pull/2058) * Added `ThatAre[Not]Sealed` method for filtering the types - [#2059](https://github.com/fluentassertions/fluentassertions/pull/2059) * Added `ThatAre[Not]Abstract` methods to `MethodInfoSelector.cs` for filtering the methods - [#2060](https://github.com/fluentassertions/fluentassertions/pull/2060) +* Added `ThatAre[Not]Structs` method for Types Filter - [#2056](https://github.com/fluentassertions/fluentassertions/pull/2056) * Added `ThatAre[Not]Abstract`, `ThatAre[Not]Static` and `ThatAre[Not]Virtual` properties for filtering in `PropertyInfoSelector.cs` - [#2054](https://github.com/fluentassertions/fluentassertions/pull/2054) +* Added `ThatAre[Not]Struct` method for Types Filter - [#2056](https://github.com/fluentassertions/fluentassertions/pull/2056) * Added `BeOneOf` methods for object comparisons and `IComparable`s - [#2028](https://github.com/fluentassertions/fluentassertions/pull/2028) * Added `BeCloseTo` and `NotBeCloseTo` to `TimeOnly` - [#2030](https://github.com/fluentassertions/fluentassertions/pull/2030)