Skip to content

Commit

Permalink
IsNullable (#110)
Browse files Browse the repository at this point in the history
* enhanced IsNullable methods
* XML doc updates and some cleanup
* updated editorconfig
  • Loading branch information
jeremyknight-me authored Apr 12, 2024
1 parent e177602 commit 7c541a9
Show file tree
Hide file tree
Showing 24 changed files with 255 additions and 75 deletions.
55 changes: 50 additions & 5 deletions src/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ indent_style = space
charset = utf-8-bom
end_of_line = crlf
indent_size = 4
tab_width = 4
insert_final_newline = true
trim_trailing_whitespace = true

Expand Down Expand Up @@ -51,6 +52,17 @@ dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_readonly_field = true:warning
dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_prefer_collection_expression = when_types_loosely_match:suggestion
dotnet_style_namespace_match_folder = true:suggestion
dotnet_code_quality_unused_parameters = all:error

# Experimental
dotnet_style_allow_multiple_blank_lines_experimental = false:error
dotnet_style_allow_statement_immediately_after_block_experimental = false:error

# -- .NET Naming Conventions ---------------------------- #

Expand All @@ -72,26 +84,26 @@ dotnet_naming_symbols.parameter_symbol.applicable_kinds = parameter
dotnet_naming_style.parameter_style.capitalization = camel_case
dotnet_naming_rule.parameters_are_camel_case.severity = warning
dotnet_naming_rule.parameters_are_camel_case.symbols = parameter_symbol
dotnet_naming_rule.parameters_are_camel_case.style = parameter_style
dotnet_naming_rule.parameters_are_camel_case.style = private_field_style

dotnet_naming_symbols.non_interface_type_symbol.applicable_kinds = class,struct,enum,delegate
dotnet_naming_style.non_interface_type_style.capitalization = pascal_case
dotnet_naming_rule.non_interface_types_are_pascal_case.severity = warning
dotnet_naming_rule.non_interface_types_are_pascal_case.symbols = non_interface_type_symbol
dotnet_naming_rule.non_interface_types_are_pascal_case.style = non_interface_type_style
dotnet_naming_rule.non_interface_types_are_pascal_case.style = non_private_field_style

dotnet_naming_symbols.interface_type_symbol.applicable_kinds = interface
dotnet_naming_style.interface_type_style.capitalization = pascal_case
dotnet_naming_style.interface_type_style.required_prefix = I
dotnet_naming_rule.interface_types_must_be_prefixed_with_I.severity = warning
dotnet_naming_rule.interface_types_must_be_prefixed_with_i.severity = warning
dotnet_naming_rule.interface_types_must_be_prefixed_with_I.symbols = interface_type_symbol
dotnet_naming_rule.interface_types_must_be_prefixed_with_I.style = interface_type_style
dotnet_naming_rule.interface_types_must_be_prefixed_with_i.style = interface_type_style

dotnet_naming_symbols.member_symbol.applicable_kinds = method,property,event
dotnet_naming_style.member_style.capitalization = pascal_case
dotnet_naming_rule.members_are_pascal_case.severity = warning
dotnet_naming_rule.members_are_pascal_case.symbols = member_symbol
dotnet_naming_rule.members_are_pascal_case.style = member_style
dotnet_naming_rule.members_are_pascal_case.style = non_private_field_style

# -- C# Files ------------------------------------------- #

Expand Down Expand Up @@ -167,3 +179,36 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = none
csharp_space_between_square_brackets = false

# General Styling
csharp_using_directive_placement = outside_namespace:error
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_static_local_function = true:suggestion
csharp_style_prefer_switch_expression = true:suggestion
csharp_style_prefer_pattern_matching = true:suggestion
csharp_style_prefer_not_pattern = true:error
csharp_style_prefer_extended_property_pattern = true:suggestion
csharp_style_namespace_declarations = file_scoped:suggestion
csharp_style_prefer_method_group_conversion = true:suggestion
csharp_style_prefer_top_level_statements = false:silent
csharp_style_prefer_primary_constructors = false:silent
csharp_style_expression_bodied_lambdas = true:suggestion
csharp_style_expression_bodied_local_functions = true:suggestion
csharp_style_prefer_null_check_over_type_check = true:suggestion
csharp_style_prefer_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
csharp_style_prefer_tuple_swap = true:suggestion
csharp_style_prefer_utf8_string_literals = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
csharp_style_prefer_readonly_struct = true:suggestion
csharp_style_prefer_readonly_struct_member = true:suggestion

# Experimental
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@

namespace JK.Common.DateTimeProviders;

/// <summary>
/// Abstraction to disconnect <see cref="DateTimeOffset"/> from the system clock.
/// </summary>
public interface IDateTimeOffsetProvider
{
/// <summary>
/// Returns a <see cref="DateTimeOffset"/> representing the current date and time.
/// </summary>
DateTimeOffset Now { get; }

/// <summary>
/// Returns a <see cref="DateTimeOffset"/> representing the current UTC date and time.
/// </summary>
DateTimeOffset UtcNow { get; }
}
16 changes: 16 additions & 0 deletions src/JK.Common.Abstractions/DateTimeProviders/IDateTimeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,25 @@

namespace JK.Common.DateTimeProviders;

/// <summary>
/// Abstraction to disconnect <see cref="DateTime"/> from the system clock.
/// </summary>
public interface IDateTimeProvider
{
/// <summary>
/// Returns a <see cref="DateTime"/> representing the current date and time.
/// </summary>
DateTime Now { get; }

/// <summary>
/// Returns a Dat<see cref="DateTime"/>eTime representing the current date. The date part
/// of the returned value is the current date, and the time-of-day part of
/// the returned value is zero (midnight).
/// </summary>
DateTime Today { get; }

/// <summary>
/// Returns a <see cref="DateTime"/> representing the current UTC date and time.
/// </summary>
DateTime UtcNow { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace JK.Common.FluentValidation.Validators;

/// <summary>
/// Validator to determine whether or not a string property contains only alphabetical characters.
/// </summary>
public class AlphabeticalValidator<T> : StringValidatorBase<T>
{
///<inheritdoc/>
Expand Down
4 changes: 4 additions & 0 deletions src/JK.Common.FluentValidation/Validators/NullValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace JK.Common.FluentValidation.Validators;

/// <summary>
/// Null object pattern AbstractValidator implementation.
/// </summary>
/// <typeparam name="T"></typeparam>
public class NullValidator<T> : AbstractValidator<T>
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace JK.Common.FluentValidation.Validators;

/// <summary>
/// Validator to determine whether or not a string property is a valid United States social security number.
/// </summary>
public class SocialSecurityNumberValidator<T> : StringValidatorBase<T>
{
///<inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

namespace JK.Common.FluentValidation.Validators;

/// <summary>
/// String property abstract validator.
/// </summary>
public abstract class StringValidatorBase<T> : PropertyValidator<T, string>
{
/// <summary>Determine if the given string is valid.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace JK.Common.FluentValidation.Validators;

/// <summary>
/// Validator to determine whether or not a string property is a valid United States phone number.
/// </summary>
public class UnitedStatesPhoneNumberValidator<T> : StringValidatorBase<T>
{
///<inheritdoc/>
Expand Down
42 changes: 21 additions & 21 deletions src/JK.Common.Tests/Extensions/TypeExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,6 @@ public void DoesImplement_WithoutInterface_False()
Assert.False(actual);
}

#endregion

#region IsNullable

[Theory]
[MemberData(nameof(IsNullable_Data))]
public void IsNullable_Tests(Type type, bool expected)
{
var actual = type.IsNullable();
Assert.Equal(expected, actual);
}

public static IEnumerable<object[]> IsNullable_Data()
=> new List<object[]>
{
new object[] { typeof(int), false },
new object[] { typeof(int?), true }
};

#endregion

private interface IInterface
{
}
Expand All @@ -60,4 +39,25 @@ private class TestWithoutInterface
private class NotAnInterface
{
}

#endregion

#region IsNullableT

[Theory]
[MemberData(nameof(IsNullableT_Data))]
public void IsNullable_Tests(Type type, bool expected)
{
var actual = type.IsNullableT();
Assert.Equal(expected, actual);
}

public static IEnumerable<object[]> IsNullableT_Data()
=>
[
[typeof(int), false],
[typeof(int?), true]
];

#endregion
}
43 changes: 23 additions & 20 deletions src/JK.Common.Tests/TypeHelpers/TypeHelperTests.cs
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
using System.Collections.Generic;
using JK.Common.TypeHelpers;
using JK.Common.TypeHelpers;

namespace JK.Common.Tests.TypeHelpers;

public class TypeHelperTests
{
[Theory]
[MemberData(nameof(IsNullable_Data))]
public void IsNullable_Tests(Type type, bool expected)
[MemberData(nameof(IsNullableT_Data))]
public void IsNullableT_Theories(Type type, bool expected)
{
var actual = TypeHelper.IsNullable(type);
var actual = TypeHelper.IsNullableT(type);
Assert.Equal(expected, actual);
}

[Fact]
public void IsNullableT_False()
{
var actual = TypeHelper.IsNullable<int>();
Assert.False(actual);
}
public static TheoryData<Type, bool> IsNullableT_Data()
=> new()
{
{ typeof(int), false },
{ typeof(int?), true },
{ typeof(string), false },
{ typeof(ComplexObject), false },
};

[Fact]
public void IsNullableT_True()
[Theory]
[MemberData(nameof(IsNullable_Data))]
public void IsNullable_Theories(Type type, bool expected)
{
var actual = TypeHelper.IsNullable<int?>();
Assert.True(actual);
var actual = TypeHelper.IsNullable(type);
Assert.Equal(expected, actual);
}

public static IEnumerable<object[]> IsNullable_Data()
=> new List<object[]>
public static TheoryData<Type, bool> IsNullable_Data()
=> new()
{
new object[] { typeof(int), false },
new object[] { typeof(int?), true },
new object[] { typeof(ComplexObject), false }
{ typeof(int), false },
{ typeof(int?), true },
{ typeof(string), true },
{ typeof(ComplexObject), true }
};
}
10 changes: 10 additions & 0 deletions src/JK.Common/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

Unless otherwise noted, all changes made by [@jeremyknight-me](https://github.com/jeremyknight-me).

## Unreleased

## Added

- `IsNullable` helper method in `TypeHelper`

## Changed

- `IsNullable` to `IsNullableT` int `TypeHelper`.

## 5.2.0

### Added
Expand Down
6 changes: 3 additions & 3 deletions src/JK.Common/Converters/BooleanConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ public sealed class BooleanConverter

public BooleanConverter()

Check warning on line 15 in src/JK.Common/Converters/BooleanConverter.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'BooleanConverter.BooleanConverter()'
{
this.trueItems = new object[] { "TRUE", "True", "true", "Y", "y", "YES", "Yes", "yes", 1, "1" };
this.falseItems = new object[] { "FALSE", "False", "false", "N", "n", "NO", "No", "no", 0, "0" };
this.nullItems = new object[] { null, "", string.Empty };
this.trueItems = ["TRUE", "True", "true", "Y", "y", "YES", "Yes", "yes", 1, "1"];
this.falseItems = ["FALSE", "False", "false", "N", "n", "NO", "No", "no", 0, "0"];
this.nullItems = [null, "", string.Empty];
}

public bool Convert(object value)

Check warning on line 22 in src/JK.Common/Converters/BooleanConverter.cs

View workflow job for this annotation

GitHub Actions / build

Missing XML comment for publicly visible type or member 'BooleanConverter.Convert(object)'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

namespace JK.Common.DateTimeProviders;

/// <inheritdoc/>
public sealed class DefaultDateTimeOffsetProvider : IDateTimeOffsetProvider
{
/// <inheritdoc/>
public DateTimeOffset Now => DateTimeOffset.Now;

/// <inheritdoc/>
public DateTimeOffset UtcNow => DateTimeOffset.UtcNow;
}
6 changes: 6 additions & 0 deletions src/JK.Common/DateTimeProviders/DefaultDateTimeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

namespace JK.Common.DateTimeProviders;

/// <inheritdoc/>
public sealed class DefaultDateTimeProvider : IDateTimeProvider
{
/// <inheritdoc/>
public DateTime Now => DateTime.Now;

/// <inheritdoc/>
public DateTime Today => DateTime.Today;

/// <inheritdoc/>
public DateTime UtcNow => DateTime.UtcNow;
}
3 changes: 3 additions & 0 deletions src/JK.Common/Extensions/BooleanExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace JK.Common.Extensions;

/// <summary>
/// Helper and utility extension methods for <see cref="bool"/>.
/// </summary>
public static class BooleanExtensions
{
public static string ConvertToText(this bool value, in string trueText = "Yes", in string falseText = "No")
Expand Down
3 changes: 3 additions & 0 deletions src/JK.Common/Extensions/ConcurrentBagExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

namespace JK.Common.Extensions;

/// <summary>
/// Helper and utility extension methods for <see cref="ConcurrentBag{T}"/>.
/// </summary>
public static class ConcurrentBagExtensions
{
public static void AddRange<T>(this ConcurrentBag<T> bag, in IEnumerable<T> list)
Expand Down
5 changes: 4 additions & 1 deletion src/JK.Common/Extensions/DateOnlyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

namespace JK.Common.Extensions;

#if (NET6_0_OR_GREATER)
#if NET6_0_OR_GREATER

/// <summary>
/// Helper and utility extension methods for <see cref="DateOnly"/>.
/// </summary>
public static class DateOnlyExtensions
{
/// <summary>Adds given number of business days to a date.</summary>
Expand Down
Loading

0 comments on commit 7c541a9

Please sign in to comment.