diff --git a/.github/workflows/CodeCoverage.yml b/.github/workflows/CodeCoverage.yml index 52155b3..3bd4aa0 100644 --- a/.github/workflows/CodeCoverage.yml +++ b/.github/workflows/CodeCoverage.yml @@ -19,13 +19,13 @@ jobs: - name: Set up dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.0.x' + dotnet-version: '8.0.x' - - name: Collect coverage for net6.0 - run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net6.0 -p:CollectCoverage=true -p:CoverletOutputFormat=lcov -p:CoverletOutput=..\..\build\lcov.info -p:Exclude="[*]DefaultEcs.Technical.Debug*" /p:TEST=true + - name: Collect coverage for net8.0 + run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net8.0 -p:CollectCoverage=true -p:CoverletOutputFormat=lcov -p:CoverletOutput=..\..\build\lcov.info -p:Exclude="[*]DefaultEcs.Technical.Debug*" /p:TEST=true - name: Upload to coverall uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: 'build\lcov.net6.0.info' + path-to-lcov: 'build\lcov.net8.0.info' diff --git a/.github/workflows/ContinuousIntegration.yml b/.github/workflows/ContinuousIntegration.yml index ab448e9..da7b912 100644 --- a/.github/workflows/ContinuousIntegration.yml +++ b/.github/workflows/ContinuousIntegration.yml @@ -18,19 +18,19 @@ jobs: - name: Set up dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.0.x' + dotnet-version: '8.0.x' source-url: https://nuget.pkg.github.com/Doraku/index.json env: NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} - - name: Run tests net452 - run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net452 /p:TEST=true + - name: Run tests net462 + run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net462 /p:TEST=true - name: Run tests net48 run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net48 /p:TEST=true - - name: Run tests net6.0 - run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net6.0 /p:TEST=true + - name: Run tests net8.0 + run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net8.0 /p:TEST=true - name: Decrypte snk file env: diff --git a/.github/workflows/PullRequest.yml b/.github/workflows/PullRequest.yml index cab4542..afb8d67 100644 --- a/.github/workflows/PullRequest.yml +++ b/.github/workflows/PullRequest.yml @@ -16,13 +16,13 @@ jobs: - name: Set up dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.0.x' + dotnet-version: '8.0.x' - - name: Run tests net452 - run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net452 /p:TEST=true + - name: Run tests net462 + run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net462 /p:TEST=true - name: Run tests net48 run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net48 /p:TEST=true - - name: Run tests net6.0 - run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net6.0 /p:TEST=true \ No newline at end of file + - name: Run tests net8.0 + run: dotnet test source\DefaultUnDo.Test\DefaultUnDo.Test.csproj -c Release -f net8.0 /p:TEST=true \ No newline at end of file diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index 001c4ce..8f703ce 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -16,7 +16,7 @@ jobs: - name: Set up dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: '6.0.x' + dotnet-version: '8.0.x' source-url: https://api.nuget.org/v3/index.json env: NUGET_AUTH_TOKEN: ${{ secrets.NUGET_API_KEY }} diff --git a/documentation/NEXT_RELEASENOTES.txt b/documentation/NEXT_RELEASENOTES.txt index 9883e1b..4774c0b 100644 --- a/documentation/NEXT_RELEASENOTES.txt +++ b/documentation/NEXT_RELEASENOTES.txt @@ -1 +1 @@ -added null reference type decorations \ No newline at end of file +- added null reference type decorations \ No newline at end of file diff --git a/source/.editorconfig b/source/.editorconfig index 878c10d..ab9cebe 100644 --- a/source/.editorconfig +++ b/source/.editorconfig @@ -1,5 +1,245 @@ [*.cs] +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = true + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = true +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false:suggestion +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_property = false:suggestion + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true + +# Parameter preferences +dotnet_code_quality_unused_parameters = all + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = false:suggestion +dotnet_style_allow_statement_immediately_after_block_experimental = false:suggestion + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = false:suggestion +csharp_style_var_for_built_in_types = false:suggestion +csharp_style_var_when_type_is_apparent = false:suggestion + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = true:silent +csharp_style_expression_bodied_methods = true:none +csharp_style_expression_bodied_operators = true:silent +csharp_style_expression_bodied_properties = true:silent + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null-checking preferences +csharp_style_conditional_delegate_call = true + +# Modifier preferences +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true + +# Code-block preferences +csharp_prefer_braces = true:suggestion +csharp_prefer_simple_using_statement = true:suggestion +csharp_style_namespace_declarations = block_scoped:suggestion +csharp_style_prefer_method_group_conversion = true:suggestion +csharp_style_prefer_top_level_statements = false:suggestion + +# Expression-level preferences +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable:none + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:silent + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false:suggestion +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false:suggestion +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false:suggestion +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:suggestion +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = false +csharp_indent_labels = flush_left +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = false + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.private_fields_should_be_private_field.severity = suggestion +dotnet_naming_rule.private_fields_should_be_private_field.symbols = private_fields +dotnet_naming_rule.private_fields_should_be_private_field.style = private_field + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +dotnet_naming_symbols.private_fields.applicable_kinds = field +dotnet_naming_symbols.private_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_fields.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.private_field.required_prefix = _ +dotnet_naming_style.private_field.required_suffix = +dotnet_naming_style.private_field.word_separator = +dotnet_naming_style.private_field.capitalization = camel_case + +# Analyzers configuration + +dotnet_analyzer_diagnostic.severity = none + # CA1000: Do not declare static members on generic types dotnet_diagnostic.CA1000.severity = none @@ -12,16 +252,36 @@ dotnet_diagnostic.CA1200.severity = none # CA1716: Identifiers should not match keywords dotnet_diagnostic.CA1716.severity = none -# CA1815: Override equals and operator equals on value types -dotnet_diagnostic.CA1815.severity = none - # CA1819: Properties should not return arrays dotnet_diagnostic.CA1819.severity = none +# IDE0058: Expression value is never used +dotnet_diagnostic.IDE0058.severity = none + +# IDE0290: Use primary constructor +dotnet_diagnostic.IDE0290.severity = none + +# RCS1189: Add or remove region name +dotnet_diagnostic.RCS1189.severity = none + +[{**/CSharpFeatures/**.cs,**/Extensions/**.cs}] + +# IDE0130: Namespace does not match folder structure +dotnet_diagnostic.IDE0130.severity = none + [**{.Test}/**.cs] # CA1062: Validate arguments of public methods dotnet_diagnostic.CA1062.severity = none # CA1707: Identifiers should not contain underscores -dotnet_diagnostic.CA1707.severity = none \ No newline at end of file +dotnet_diagnostic.CA1707.severity = none + +# CA1859: Use concrete types when possible for improved performance +dotnet_diagnostic.CA1859.severity = none + +# CA1861: Avoid constant arrays as arguments +dotnet_diagnostic.CA1861.severity = none + +# IDE0022: Use expression body for method +dotnet_diagnostic.IDE0022.severity = none diff --git a/source/DefaultUnDo.Test/CollectionUndoTest.cs b/source/DefaultUnDo.Test/CollectionUndoTest.cs index 1e65d9e..4ac5c67 100644 --- a/source/DefaultUnDo.Test/CollectionUndoTest.cs +++ b/source/DefaultUnDo.Test/CollectionUndoTest.cs @@ -8,8 +8,6 @@ namespace DefaultUnDo.Test { public sealed class CollectionUndoTest { - #region Tests - [Fact] public void CollectionUnDo_Should_throw_ArgumentNullException_When_source_is_null() { @@ -90,7 +88,5 @@ public void Description_Should_return_description() Check.That(undo.Description).IsEqualTo("test"); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/DefaultUnDo.Test.csproj b/source/DefaultUnDo.Test/DefaultUnDo.Test.csproj index c7ad712..328bfbe 100644 --- a/source/DefaultUnDo.Test/DefaultUnDo.Test.csproj +++ b/source/DefaultUnDo.Test/DefaultUnDo.Test.csproj @@ -1,19 +1,19 @@  - net452; + net462; net48; - net6.0; + net8.0; - - - - - - + + + + + + diff --git a/source/DefaultUnDo.Test/DictionaryUnDoTest.cs b/source/DefaultUnDo.Test/DictionaryUnDoTest.cs index c48dc0e..fb5688d 100644 --- a/source/DefaultUnDo.Test/DictionaryUnDoTest.cs +++ b/source/DefaultUnDo.Test/DictionaryUnDoTest.cs @@ -8,8 +8,6 @@ namespace DefaultUnDo.Test { public sealed class DictionaryUnDoTest { - #region Tests - [Fact] public void DictionaryUnDo_Should_throw_ArgumentNullException_When_source_is_null() { @@ -106,7 +104,5 @@ public void Description_Should_return_description() Check.That(undo.Description).IsEqualTo("test"); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/GroupUnDoTest.cs b/source/DefaultUnDo.Test/GroupUnDoTest.cs index 0b93917..4175b7a 100644 --- a/source/DefaultUnDo.Test/GroupUnDoTest.cs +++ b/source/DefaultUnDo.Test/GroupUnDoTest.cs @@ -8,8 +8,6 @@ namespace DefaultUnDo.Test { public sealed class GroupUnDoTest { - #region Tests - [Fact] public void GroupUnDo_Should_throw_ArgumentNullException_When_commands_is_null() { @@ -40,7 +38,7 @@ public void GroupUnDo_Should_throw_ArgumentNullException_When_commands_contains_ [Fact] public void Do_Should_execute_children_Do() { - List done = new(); + List done = []; IUnDo undo1 = Substitute.For(); undo1.When(u => u.Do()).Do(_ => done.Add(undo1)); @@ -60,7 +58,7 @@ public void Do_Should_execute_children_Do() [Fact] public void Undo_Should_execute_children_Undo_in_reverse() { - List done = new(); + List done = []; IUnDo undo1 = Substitute.For(); undo1.When(u => u.Undo()).Do(_ => done.Add(undo1)); @@ -190,7 +188,5 @@ public void TryMerge_Should_use_MergeDescriptionAction_When_set() GroupUnDo.MergeDescriptionAction = null; } - - #endregion } } diff --git a/source/DefaultUnDo.Test/ICollectionExtensionTest.cs b/source/DefaultUnDo.Test/ICollectionExtensionTest.cs index 7e45196..20c2f5c 100644 --- a/source/DefaultUnDo.Test/ICollectionExtensionTest.cs +++ b/source/DefaultUnDo.Test/ICollectionExtensionTest.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; using NFluent; using NSubstitute; using Xunit; @@ -12,8 +11,6 @@ namespace DefaultUnDo.Test { public sealed class ICollectionExtensionTest { - #region Methods - [Fact] public void AsUnDo_Should_throw_ArgumentNullException_When_source_is_null() { @@ -140,14 +137,11 @@ public void UnDoCollection_Contains_Should_return_Contains() } [Fact] -#if !NET452 - [SuppressMessage("Performance", "CA1825")] -#endif public void UnDoCollection_CopyTo_Should_CopyTo() { ICollection source = Substitute.For>(); IUnDoManager manager = Substitute.For(); - object[] values = new object[0]; + object[] values = []; const int index = 42; bool done = false; @@ -328,7 +322,5 @@ public void UnDoCollection_PropertyChanged_remove_Should_remove_PropertyChanged( Check.That(done).IsTrue(); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/IDictionaryExtensionTest.cs b/source/DefaultUnDo.Test/IDictionaryExtensionTest.cs index 4e25a86..fd5e0ad 100644 --- a/source/DefaultUnDo.Test/IDictionaryExtensionTest.cs +++ b/source/DefaultUnDo.Test/IDictionaryExtensionTest.cs @@ -8,8 +8,6 @@ namespace DefaultUnDo.Test { public sealed class IDictionaryExtensionTest { - #region Methods - [Fact] public void AsUnDo_Should_throw_ArgumentNullException_When_source_is_null() { @@ -263,7 +261,5 @@ public void UnDoDictionary_Values_Should_return_Values() Check.That(unDoDictionary.Values).IsEqualTo(source.Values); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/IListExtensionTest.cs b/source/DefaultUnDo.Test/IListExtensionTest.cs index 0322c2f..55789c9 100644 --- a/source/DefaultUnDo.Test/IListExtensionTest.cs +++ b/source/DefaultUnDo.Test/IListExtensionTest.cs @@ -9,8 +9,6 @@ namespace DefaultUnDo.Test { public sealed class IListExtensionTest { - #region Tests - [Fact] public void AsUnDo_Should_throw_ArgumentNullException_When_source_is_null() { @@ -202,7 +200,7 @@ public void Move_Should_throw_When_source_is_null() [Fact] public void Move_Should_move_item() { - List items = new() { 1, 2 }; + List items = [1, 2]; items.Move(0, 1); @@ -265,7 +263,5 @@ public void Move_Should_set_description_as_Move() Check.That(description.Value.Parameters[0]).IsEqualTo(42); Check.That(description.Value.Parameters[1]).IsEqualTo(43); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/ISetExtensionTest.cs b/source/DefaultUnDo.Test/ISetExtensionTest.cs index c5e0f1e..e968b52 100644 --- a/source/DefaultUnDo.Test/ISetExtensionTest.cs +++ b/source/DefaultUnDo.Test/ISetExtensionTest.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; using NFluent; using NSubstitute; @@ -10,8 +9,6 @@ namespace DefaultUnDo.Test { public sealed class ISetExtensionTest { - #region Tests - [Fact] public void AsUnDo_Should_throw_ArgumentNullException_When_source_is_null() { @@ -83,7 +80,7 @@ public void UnDoSet_ExceptWith_Should_work() IUnDoManager manager = new UnDoManager(); ISet unDoSet = new HashSet { 1, 2, 3 }.AsUnDo(manager); - unDoSet.ExceptWith(new[] { 2 }); + unDoSet.ExceptWith([2]); Check.That(unDoSet.OrderBy(i => i)).ContainsExactly(1, 3); @@ -93,9 +90,6 @@ public void UnDoSet_ExceptWith_Should_work() } [Fact] -#if !NET452 - [SuppressMessage("Performance", "CA1825")] -#endif public void UnDoSet_ExceptWith_Should_generate_ExceptWith_description() { ISet source = Substitute.For>(); @@ -108,7 +102,7 @@ public void UnDoSet_ExceptWith_Should_generate_ExceptWith_description() ISet unDoCollection = source.AsUnDo(manager, d => description = d); - IEnumerable other = new object[0]; + IEnumerable other = []; unDoCollection.ExceptWith(other); Check.That(description.HasValue).IsTrue(); @@ -124,7 +118,7 @@ public void UnDoSet_IntersectWith_Should_work() IUnDoManager manager = new UnDoManager(); ISet unDoSet = new HashSet { 1, 2, 3 }.AsUnDo(manager); - unDoSet.IntersectWith(new[] { 2 }); + unDoSet.IntersectWith([2]); Check.That(unDoSet.OrderBy(i => i)).ContainsExactly(2); @@ -134,9 +128,6 @@ public void UnDoSet_IntersectWith_Should_work() } [Fact] -#if !NET452 - [SuppressMessage("Performance", "CA1825")] -#endif public void UnDoSet_IntersectWith_Should_generate_IntersectWith_description() { ISet source = Substitute.For>(); @@ -149,7 +140,7 @@ public void UnDoSet_IntersectWith_Should_generate_IntersectWith_description() ISet unDoCollection = source.AsUnDo(manager, d => description = d); - IEnumerable other = new object[0]; + IEnumerable other = []; unDoCollection.IntersectWith(Enumerable.Empty()); Check.That(description.HasValue).IsTrue(); @@ -267,7 +258,7 @@ public void UnDoSet_SymmetricExceptWith_Should_work() IUnDoManager manager = new UnDoManager(); ISet unDoSet = new HashSet { 1, 2, 3 }.AsUnDo(manager); - unDoSet.SymmetricExceptWith(new[] { 2, 3, 4 }); + unDoSet.SymmetricExceptWith([2, 3, 4]); Check.That(unDoSet.OrderBy(i => i)).ContainsExactly(1, 4); @@ -277,9 +268,6 @@ public void UnDoSet_SymmetricExceptWith_Should_work() } [Fact] -#if !NET452 - [SuppressMessage("Performance", "CA1825")] -#endif public void UnDoSet_SymmetricExceptWith_Should_generate_SymmetricExceptWith_description() { ISet source = Substitute.For>(); @@ -291,7 +279,7 @@ public void UnDoSet_SymmetricExceptWith_Should_generate_SymmetricExceptWith_desc ISet unDoCollection = source.AsUnDo(manager, d => description = d); - IEnumerable other = new object[0]; + IEnumerable other = []; unDoCollection.SymmetricExceptWith(other); Check.That(description.HasValue).IsTrue(); @@ -307,7 +295,7 @@ public void UnDoSet_UnionWith_Should_work() IUnDoManager manager = new UnDoManager(); ISet unDoSet = new HashSet { 1, 2, 3 }.AsUnDo(manager); - unDoSet.UnionWith(new[] { 2, 3, 4 }); + unDoSet.UnionWith([2, 3, 4]); Check.That(unDoSet.OrderBy(i => i)).ContainsExactly(1, 2, 3, 4); @@ -317,9 +305,6 @@ public void UnDoSet_UnionWith_Should_work() } [Fact] -#if !NET452 - [SuppressMessage("Performance", "CA1825")] -#endif public void UnDoSet_UnionWith_Should_generate_UnionWith_description() { ISet source = Substitute.For>(); @@ -331,7 +316,7 @@ public void UnDoSet_UnionWith_Should_generate_UnionWith_description() ISet unDoCollection = source.AsUnDo(manager, d => description = d); - IEnumerable other = new object[0]; + IEnumerable other = []; unDoCollection.UnionWith(other); Check.That(description.HasValue).IsTrue(); @@ -340,7 +325,5 @@ public void UnDoSet_UnionWith_Should_generate_UnionWith_description() Check.That(description.Value.Parameters.Length).IsEqualTo(1); Check.That(description.Value.Parameters[0]).IsEqualTo(other); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/IUnDoManagerExtensionTest.cs b/source/DefaultUnDo.Test/IUnDoManagerExtensionTest.cs index 63e687e..6f95ed7 100644 --- a/source/DefaultUnDo.Test/IUnDoManagerExtensionTest.cs +++ b/source/DefaultUnDo.Test/IUnDoManagerExtensionTest.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using NFluent; using NSubstitute; using NSubstitute.ExceptionExtensions; @@ -10,8 +9,6 @@ namespace DefaultUnDo.Test { public sealed class IUnDoManagerExtensionTest { - #region Tests - [Fact] public void DoAdd_ISet_Should_throw_ArgumentNullException_When_manager_is_null() { @@ -64,7 +61,7 @@ public void DoAdd_ICollection_Should_throw_ArgumentNullException_When_source_is_ public void DoAdd_ICollection_Should_keep_index_When_source_is_IList() { IUnDoManager manager = new UnDoManager(); - ICollection source = new List { 0, 1 }; + ICollection source = [0, 1]; manager.DoAdd(source, 2); @@ -106,15 +103,14 @@ public void DoClear_Should_throw_ArgumentNullException_When_source_is_null() [Fact] public void DoClear_Should_add_old_elements_When_undone() { - ICollection source = new List - { - new object(), - new object(), - new object() - }; + ICollection source = [ + new(), + new(), + new() + ]; IUnDoManager manager = Substitute.For(); IUnDo undo = null; - List sourceCopy = source.ToList(); + List sourceCopy = [.. source]; manager.Do(Arg.Do(i => undo = i)); @@ -159,7 +155,7 @@ public void DoRemove_ICollection_Should_throw_ArgumentNullException_When_source_ public void DoRemove_ICollection_Should_keep_index_When_source_is_IList() { IUnDoManager manager = new UnDoManager(); - ICollection source = new List { 0, 1 }; + ICollection source = [0, 1]; manager.DoRemove(source, 0); @@ -460,7 +456,5 @@ public void Do_ValueUnDo_Should_throw_ArgumentNullException_When_setter_is_null( .Throws() .WithProperty("ParamName", "setter"); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/ListUnDoTest.cs b/source/DefaultUnDo.Test/ListUnDoTest.cs index 1978852..fd09808 100644 --- a/source/DefaultUnDo.Test/ListUnDoTest.cs +++ b/source/DefaultUnDo.Test/ListUnDoTest.cs @@ -8,8 +8,6 @@ namespace DefaultUnDo.Test { public sealed class ListUnDoTest { - #region Tests - [Fact] public void ListUnDo_Should_throw_ArgumentNullException_When_source_is_null() { @@ -94,7 +92,5 @@ public void Description_Should_return_description() Check.That(undo.Description).IsEqualTo("test"); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/UnDoFieldTest.cs b/source/DefaultUnDo.Test/UnDoFieldTest.cs index c4a226b..96d2c4d 100644 --- a/source/DefaultUnDo.Test/UnDoFieldTest.cs +++ b/source/DefaultUnDo.Test/UnDoFieldTest.cs @@ -7,8 +7,6 @@ namespace DefaultUnDo.Test { public sealed class UnDoFieldTest { - #region Tests - [Fact] public void UnDoField_Should_throw_ArgumentNullException_When_manager_is_null() { @@ -68,9 +66,7 @@ public void Implicit_Should_return_value() [Fact] public void Implicit_Should_return_default_When_null() { - Check.That(default(int)).IsEqualTo(default(UnDoField)); + Check.That(default).IsEqualTo((int)default(UnDoField)); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/UnDoManagerTest.cs b/source/DefaultUnDo.Test/UnDoManagerTest.cs index 1e0d06b..b14e09a 100644 --- a/source/DefaultUnDo.Test/UnDoManagerTest.cs +++ b/source/DefaultUnDo.Test/UnDoManagerTest.cs @@ -8,16 +8,7 @@ namespace DefaultUnDo.Test { public sealed class UnDoManagerTest { - #region Methods - - public static IEnumerable UnDoManagers - { - get - { - yield return new object[] { new UnDoManager() }; - yield return new object[] { new UnDoManager(10) }; - } - } + public static TheoryData UnDoManagers => new(new UnDoManager(), new UnDoManager(10)); [Fact] public void UnDoManager_maxCapacity_Should_throw_ArgumentException_When_maxCapacity_is_inferior_or_equal_to_zero() @@ -255,7 +246,7 @@ public void Do_Should_clear_undone_history(IUnDoManager manager) public void Undo_Should_throw_InvalidOperationException_When_CanUndo_is_false(IUnDoManager manager) { Check - .ThatCode(() => manager.Undo()) + .ThatCode(manager.Undo) .Throws(); } @@ -266,7 +257,7 @@ public void Undo_Should_throw_InvalidOperationException_When_a_transaction_is_go using (manager.BeginTransaction()) { Check - .ThatCode(() => manager.Undo()) + .ThatCode(manager.Undo) .Throws() .WithMessage("Cannot perform Undo while a transaction is going on."); } @@ -292,7 +283,7 @@ public void Undo_Should_Undo(IUnDoManager manager) public void Redo_Should_throw_InvalidOperationException_When_CanRedo_is_false(IUnDoManager manager) { Check - .ThatCode(() => manager.Redo()) + .ThatCode(manager.Redo) .Throws(); } @@ -303,7 +294,7 @@ public void Redo_Should_throw_InvalidOperationException_When_a_transaction_is_go using (manager.BeginTransaction()) { Check - .ThatCode(() => manager.Redo()) + .ThatCode(manager.Redo) .Throws() .WithMessage("Cannot perform Redo while a transaction is going on."); } @@ -330,7 +321,7 @@ public void Redo_Should_Redo(IUnDoManager manager) [MemberData(nameof(UnDoManagers))] public void PropertyChanged_Should_be_called(IUnDoManager manager) { - List properties = new(); + List properties = []; manager.PropertyChanged += (_, e) => properties.Add(e.PropertyName); manager.Do(() => { }, () => { }); @@ -522,7 +513,5 @@ public void IUnDoTransactionDispose_Should_undo_When_not_committed() Check.That(unDone).IsTrue(); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/UnDoTest.cs b/source/DefaultUnDo.Test/UnDoTest.cs index 212e322..1b94bae 100644 --- a/source/DefaultUnDo.Test/UnDoTest.cs +++ b/source/DefaultUnDo.Test/UnDoTest.cs @@ -5,8 +5,6 @@ namespace DefaultUnDo.Test { public sealed class UnDoTest { - #region Tests - [Fact] public void Do_Should_not_throw_When_doAction_is_null() { @@ -56,7 +54,5 @@ public void Description_Should_return_description() Check.That(undo.Description).IsEqualTo("test"); } - - #endregion } } diff --git a/source/DefaultUnDo.Test/ValueUnDoTest.cs b/source/DefaultUnDo.Test/ValueUnDoTest.cs index 58ff87c..0befe98 100644 --- a/source/DefaultUnDo.Test/ValueUnDoTest.cs +++ b/source/DefaultUnDo.Test/ValueUnDoTest.cs @@ -7,8 +7,6 @@ namespace DefaultUnDo.Test { public sealed class ValueUnDoTest { - #region Tests - [Fact] public void ValueUnDo_Should_throw_ArgumentNullException_When_setter_is_null() { @@ -171,7 +169,5 @@ public void TryMerge_Should_return_true_When_merged_with_GroupUnDo() merged.Undo(); Check.That(item).IsEqualTo(0); } - - #endregion } } diff --git a/source/DefaultUnDo/CollectionUnDo.cs b/source/DefaultUnDo/CollectionUnDo.cs index f07e486..510c742 100644 --- a/source/DefaultUnDo/CollectionUnDo.cs +++ b/source/DefaultUnDo/CollectionUnDo.cs @@ -10,18 +10,12 @@ namespace DefaultUnDo /// The type of element in the . public sealed class CollectionUnDo : IUnDo { - #region Fields - private readonly object? _description; private readonly ICollection _source; [AllowNull] private readonly T _item; private readonly bool _isAdd; - #endregion - - #region Initialisation - /// /// Initialise an instance of . /// @@ -32,8 +26,10 @@ public sealed class CollectionUnDo : IUnDo /// is null. public CollectionUnDo(object? description, ICollection source, [AllowNull] T item, bool isAdd) { + ArgumentNullException.ThrowIfNull(source); + _description = description; - _source = source ?? throw new ArgumentNullException(nameof(source)); + _source = source; _item = item; _isAdd = isAdd; } @@ -49,10 +45,6 @@ public CollectionUnDo(ICollection source, [AllowNull] T item, bool isAdd) : this(null, source, item, isAdd) { } - #endregion - - #region Methods - private void Action(bool isAdd) { if (isAdd) @@ -65,8 +57,6 @@ private void Action(bool isAdd) } } - #endregion - #region IUnDo /// diff --git a/source/DefaultUnDo/DefaultUnDo.csproj b/source/DefaultUnDo/DefaultUnDo.csproj index 4632c83..545f985 100644 --- a/source/DefaultUnDo/DefaultUnDo.csproj +++ b/source/DefaultUnDo/DefaultUnDo.csproj @@ -2,8 +2,8 @@ netstandard1.0; - netstandard2.0; netstandard2.1; + net8.0; enable true @@ -15,7 +15,7 @@ - + diff --git a/source/DefaultUnDo/DictionaryUnDo.cs b/source/DefaultUnDo/DictionaryUnDo.cs index 674df4c..4190c63 100644 --- a/source/DefaultUnDo/DictionaryUnDo.cs +++ b/source/DefaultUnDo/DictionaryUnDo.cs @@ -11,8 +11,6 @@ namespace DefaultUnDo /// Type of the values. public sealed class DictionaryUnDo : IUnDo { - #region Fields - private readonly object? _description; private readonly IDictionary _source; private readonly TKey _key; @@ -20,10 +18,6 @@ public sealed class DictionaryUnDo : IUnDo private readonly TValue _element; private readonly bool _isAdd; - #endregion - - #region Initialisation - /// /// Initialise an instance of . /// @@ -35,9 +29,12 @@ public sealed class DictionaryUnDo : IUnDo /// or is null. public DictionaryUnDo(object? description, IDictionary source, TKey key, [AllowNull] TValue value, bool isAdd) { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(key); + _description = description; - _source = source ?? throw new ArgumentNullException(nameof(source)); - _key = key ?? throw new ArgumentNullException(nameof(key)); + _source = source; + _key = key; _element = value; _isAdd = isAdd; } @@ -54,10 +51,6 @@ public DictionaryUnDo(IDictionary source, TKey key, [AllowNull] TV : this(null, source, key, value, isAdd) { } - #endregion - - #region Methods - private void Action(bool isAdd) { if (isAdd) @@ -70,8 +63,6 @@ private void Action(bool isAdd) } } - #endregion - #region IUnDo /// diff --git a/source/DefaultUnDo/Documentations.cs b/source/DefaultUnDo/Documentations.cs index d229957..8c34be0 100644 --- a/source/DefaultUnDo/Documentations.cs +++ b/source/DefaultUnDo/Documentations.cs @@ -3,5 +3,6 @@ /// /// This is the full API documentation of DefaultUnDo. /// - internal static class AssemblyDoc { } + internal static class AssemblyDoc + { } } diff --git a/source/DefaultUnDo/GroupUnDo.cs b/source/DefaultUnDo/GroupUnDo.cs index b324e78..5c8a666 100644 --- a/source/DefaultUnDo/GroupUnDo.cs +++ b/source/DefaultUnDo/GroupUnDo.cs @@ -1,6 +1,6 @@ using System; -using System.Linq; using System.Diagnostics.CodeAnalysis; +using System.Linq; namespace DefaultUnDo { @@ -18,24 +18,14 @@ public sealed class GroupUnDo : IMergeableUnDo /// The final description to use. public delegate object MergeDescriptionHandler(object? oldDescription, object? newDescription, object? mergedDescription); - #region Fields - private readonly object? _description; private readonly IUnDo[] _commands; - #endregion - - #region Properties - /// /// The used to merge description between a and a instances. /// public static MergeDescriptionHandler? MergeDescriptionAction { get; set; } - #endregion - - #region Initialisation - /// /// Initialise an instance of . /// @@ -45,13 +35,16 @@ public sealed class GroupUnDo : IMergeableUnDo /// contains null elements. public GroupUnDo(object? description, params IUnDo[] commands) { + ArgumentNullException.ThrowIfNull(commands); + _description = description; - _commands = commands ?? throw new ArgumentNullException(nameof(commands)); + _commands = commands; if (_commands.Length is 0) { throw new ArgumentException("IUnDo sequence contains no elements.", nameof(commands)); } + if (_commands.Any(i => i is null)) { throw new ArgumentException("IUnDo sequence contains null elements.", nameof(commands)); @@ -68,10 +61,6 @@ public GroupUnDo(params IUnDo[] commands) : this(null, commands) { } - #endregion - - #region Method - /// /// Gets the single of this instance. /// @@ -89,8 +78,6 @@ public bool TryGetSingle([NotNullWhen(true)] out T command) return command != null; } - #endregion - #region IMergeableUnDo /// diff --git a/source/DefaultUnDo/ICollectionExtension.cs b/source/DefaultUnDo/ICollectionExtension.cs index 91ed9aa..ecb7480 100644 --- a/source/DefaultUnDo/ICollectionExtension.cs +++ b/source/DefaultUnDo/ICollectionExtension.cs @@ -9,8 +9,6 @@ namespace DefaultUnDo /// public static class ICollectionExtension { - #region Methods - /// /// Wraps an to an UnDo collection linked to an to automatically generate operations. /// @@ -20,11 +18,15 @@ public static class ICollectionExtension /// Factory used to create the description of the generated . /// A wrapped . /// or is null. - public static ICollection AsUnDo(this ICollection source, IUnDoManager manager, Func? descriptionFactory = null) => new UnDoICollection( - manager ?? throw new ArgumentNullException(nameof(manager)), - source ?? throw new ArgumentNullException(nameof(source)), - descriptionFactory); + public static ICollection AsUnDo(this ICollection source, IUnDoManager manager, Func? descriptionFactory = null) + { + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); - #endregion + return new UnDoICollection( + manager, + source, + descriptionFactory); + } } } diff --git a/source/DefaultUnDo/IDictionaryExtension.cs b/source/DefaultUnDo/IDictionaryExtension.cs index cf84af0..da02711 100644 --- a/source/DefaultUnDo/IDictionaryExtension.cs +++ b/source/DefaultUnDo/IDictionaryExtension.cs @@ -9,8 +9,6 @@ namespace DefaultUnDo /// public static class IDictionaryExtension { - #region Methods - /// /// Wraps an to an UnDo dictionary linked to an to automatically generate operations. /// @@ -21,11 +19,15 @@ public static class IDictionaryExtension /// Factory used to create the description of the generated . /// A wrapped . /// or is null. - public static IDictionary AsUnDo(this IDictionary source, IUnDoManager manager, Func? descriptionFactory = null) => new UnDoIDictionary( - manager ?? throw new ArgumentNullException(nameof(manager)), - source ?? throw new ArgumentNullException(nameof(source)), - descriptionFactory); + public static IDictionary AsUnDo(this IDictionary source, IUnDoManager manager, Func? descriptionFactory = null) + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(manager); - #endregion + return new UnDoIDictionary( + manager, + source, + descriptionFactory); + } } } diff --git a/source/DefaultUnDo/IListExtension.cs b/source/DefaultUnDo/IListExtension.cs index 71f4815..5d346b8 100644 --- a/source/DefaultUnDo/IListExtension.cs +++ b/source/DefaultUnDo/IListExtension.cs @@ -10,8 +10,6 @@ namespace DefaultUnDo /// public static class IListExtension { - #region Methods - /// /// Wraps an to an UnDo list linked to an to automatically generate operations. /// @@ -21,10 +19,16 @@ public static class IListExtension /// Factory used to create the description of the generated . /// A wrapped . /// or is null. - public static IList AsUnDo(this IList source, IUnDoManager manager, Func? descriptionFactory = null) => new UnDoIList( - manager ?? throw new ArgumentNullException(nameof(manager)), - source ?? throw new ArgumentNullException(nameof(source)), - descriptionFactory); + public static IList AsUnDo(this IList source, IUnDoManager manager, Func? descriptionFactory = null) + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(manager); + + return new UnDoIList( + manager, + source, + descriptionFactory); + } /// /// Moves the item at the specified index to a new location in the collection. @@ -35,12 +39,10 @@ public static class IListExtension /// The on which to perform the move. /// The zero-based index specifying the location of the item to be moved. /// The zero-based index specifying the new location of the item. + /// is null. public static void Move(this IList source, int oldIndex, int newIndex) { - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); if (source is UnDoIList undo) { @@ -53,7 +55,5 @@ public static void Move(this IList source, int oldIndex, int newIndex) source.Insert(newIndex, item); } } - - #endregion } } diff --git a/source/DefaultUnDo/ISetExtension.cs b/source/DefaultUnDo/ISetExtension.cs index 79d7de2..5e68ddc 100644 --- a/source/DefaultUnDo/ISetExtension.cs +++ b/source/DefaultUnDo/ISetExtension.cs @@ -9,8 +9,6 @@ namespace DefaultUnDo /// public static class ISetExtension { - #region Methods - /// /// Wraps an to an UnDo set linked to an to automatically generate operations. /// @@ -20,11 +18,15 @@ public static class ISetExtension /// Factory used to create the description of the generated . /// A wrapped . /// or is null. - public static ISet AsUnDo(this ISet source, IUnDoManager manager, Func? descriptionFactory = null) => new UnDoISet( - manager ?? throw new ArgumentNullException(nameof(manager)), - source ?? throw new ArgumentNullException(nameof(source)), - descriptionFactory); + public static ISet AsUnDo(this ISet source, IUnDoManager manager, Func? descriptionFactory = null) + { + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(manager); - #endregion + return new UnDoISet( + manager, + source, + descriptionFactory); + } } } diff --git a/source/DefaultUnDo/IUnDoManagerExtension.cs b/source/DefaultUnDo/IUnDoManagerExtension.cs index ed7feb6..e1029a9 100644 --- a/source/DefaultUnDo/IUnDoManagerExtension.cs +++ b/source/DefaultUnDo/IUnDoManagerExtension.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; namespace DefaultUnDo { @@ -10,8 +9,6 @@ namespace DefaultUnDo /// public static class IUnDoManagerExtension { - #region Methods - /// /// Adds an item from a as a operation. /// @@ -24,14 +21,8 @@ public static class IUnDoManagerExtension /// or is null. public static bool DoAdd(this IUnDoManager manager, ISet source, [AllowNull] T item, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); bool result = !source.Contains(item!); @@ -54,14 +45,8 @@ public static bool DoAdd(this IUnDoManager manager, ISet source, [AllowNul /// or is null. public static void DoAdd(this IUnDoManager manager, ICollection source, [AllowNull] T item, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); if (source is IList list) { @@ -83,18 +68,12 @@ public static void DoAdd(this IUnDoManager manager, ICollection source, [A /// or is null. public static void DoClear(this IUnDoManager manager, ICollection source, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); if (source.Count > 0) { - T[] oldValues = source.ToArray(); + T[] oldValues = [.. source]; manager.Do(source.Clear, () => { foreach (T oldValue in oldValues) { source.Add(oldValue); } }, description); } @@ -112,14 +91,8 @@ public static void DoClear(this IUnDoManager manager, ICollection source, /// or is null. public static bool DoRemove(this IUnDoManager manager, ICollection source, [AllowNull] T item, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); bool result = false; @@ -154,18 +127,9 @@ public static bool DoRemove(this IUnDoManager manager, ICollection source, /// , or is null. public static void DoAdd(this IUnDoManager manager, IDictionary source, TKey key, [AllowNull] TValue value, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } - if (key is null) - { - throw new ArgumentNullException(nameof(key)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(key); manager.Do(new DictionaryUnDo(description, source, key, value, true)); } @@ -183,21 +147,12 @@ public static void DoAdd(this IUnDoManager manager, IDictionary, or is null. public static bool DoRemove(this IUnDoManager manager, IDictionary source, TKey key, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } - if (key is null) - { - throw new ArgumentNullException(nameof(key)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(key); bool result = false; - if (source.TryGetValue(key, out TValue value)) + if (source.TryGetValue(key, out TValue? value)) { manager.Do(new DictionaryUnDo(description, source, key, value, false)); result = true; @@ -219,20 +174,11 @@ public static bool DoRemove(this IUnDoManager manager, IDictionary /// , or is null. public static void Do(this IUnDoManager manager, IDictionary source, TKey key, [AllowNull] TValue value, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } - if (key is null) - { - throw new ArgumentNullException(nameof(key)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); + ArgumentNullException.ThrowIfNull(key); - if (source.TryGetValue(key, out TValue oldValue)) + if (source.TryGetValue(key, out TValue? oldValue)) { manager.Do(v => source[key] = v!, value, oldValue, description); } @@ -254,14 +200,8 @@ public static void Do(this IUnDoManager manager, IDictionary or is null. public static void DoInsert(this IUnDoManager manager, IList source, int index, [AllowNull] T item, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); manager.Do(new ListUnDo(description, source, index, item, true)); } @@ -277,14 +217,8 @@ public static void DoInsert(this IUnDoManager manager, IList source, int i /// or is null. public static void DoRemoveAt(this IUnDoManager manager, IList source, int index, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); manager.Do(new ListUnDo(description, source, index, source[index], false)); } @@ -301,14 +235,8 @@ public static void DoRemoveAt(this IUnDoManager manager, IList source, int /// or is null. public static void Do(this IUnDoManager manager, IList source, int index, [AllowNull] T item, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (source is null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(source); manager.Do(v => source[index] = v!, item, source[index], description); } @@ -323,10 +251,7 @@ public static void Do(this IUnDoManager manager, IList source, int index, /// is null. public static void Do(this IUnDoManager manager, Action? doAction, Action? undoAction, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } + ArgumentNullException.ThrowIfNull(manager); if (doAction != null || undoAction != null) { @@ -364,18 +289,10 @@ public static void Do(this IUnDoManager manager, Action? doAction, Action? undoA /// or is null. public static void Do(this IUnDoManager manager, Action setter, [AllowNull] T newValue, [AllowNull] T oldValue, object? description = null) { - if (manager is null) - { - throw new ArgumentNullException(nameof(manager)); - } - if (setter is null) - { - throw new ArgumentNullException(nameof(setter)); - } + ArgumentNullException.ThrowIfNull(manager); + ArgumentNullException.ThrowIfNull(setter); manager.Do(new ValueUnDo(description, setter, newValue, oldValue)); } - - #endregion } } diff --git a/source/DefaultUnDo/Internal/CSharpFeatures/ArgumentNullException.cs b/source/DefaultUnDo/Internal/CSharpFeatures/ArgumentNullException.cs new file mode 100644 index 0000000..e26b435 --- /dev/null +++ b/source/DefaultUnDo/Internal/CSharpFeatures/ArgumentNullException.cs @@ -0,0 +1,25 @@ +#if !NET5_0_OR_GREATER + +global using ArgumentNullException = DefaultUnDo.ArgumentNullException; + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Text; + +namespace DefaultUnDo +{ + internal static class ArgumentNullException + { + public static void ThrowIfNull([NotNull] object? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) + { + if (argument is null) + { + throw new System.ArgumentNullException(paramName); + } + } + } +} + +#endif diff --git a/source/DefaultUnDo/Internal/CSharpFeatures/CallerArgumentExpressionAttribute.cs b/source/DefaultUnDo/Internal/CSharpFeatures/CallerArgumentExpressionAttribute.cs new file mode 100644 index 0000000..6f0acef --- /dev/null +++ b/source/DefaultUnDo/Internal/CSharpFeatures/CallerArgumentExpressionAttribute.cs @@ -0,0 +1,17 @@ +#if !NET5_0_OR_GREATER + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] + internal sealed class CallerArgumentExpressionAttribute : Attribute + { + public string ParameterName { get; } + + public CallerArgumentExpressionAttribute(string parameterName) + { + ParameterName = parameterName; + } + } +} + +#endif diff --git a/source/DefaultUnDo/Internal/CSharpFeatures/IsExternalInit.cs b/source/DefaultUnDo/Internal/CSharpFeatures/IsExternalInit.cs new file mode 100644 index 0000000..c3e6021 --- /dev/null +++ b/source/DefaultUnDo/Internal/CSharpFeatures/IsExternalInit.cs @@ -0,0 +1,11 @@ +#if !NET5_0_OR_GREATER + +using System.ComponentModel; + +namespace System.Runtime.CompilerServices +{ + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit; +} + +#endif diff --git a/source/DefaultUnDo/Internal/CSharpFeatures/NullableAttributes.cs b/source/DefaultUnDo/Internal/CSharpFeatures/NullableAttributes.cs new file mode 100644 index 0000000..d4820ac --- /dev/null +++ b/source/DefaultUnDo/Internal/CSharpFeatures/NullableAttributes.cs @@ -0,0 +1,48 @@ +#if !NETSTANDARD2_1_OR_GREATER && !NET5_0_OR_GREATER + +namespace System.Diagnostics.CodeAnalysis +{ + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] + internal sealed class AllowNullAttribute : Attribute; + + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] + internal sealed class MaybeNullAttribute : Attribute; + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class NotNullAttribute : Attribute; + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class NotNullWhenAttribute : Attribute + { + public bool ReturnValue { get; } + + public NotNullWhenAttribute(bool returnValue) + { + ReturnValue = returnValue; + } + } + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class MaybeNullWhenAttribute : Attribute + { + public bool ReturnValue { get; } + + public MaybeNullWhenAttribute(bool returnValue) + { + ReturnValue = returnValue; + } + } + + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + internal sealed class DoesNotReturnIfAttribute : Attribute + { + public bool ParameterValue { get; } + + public DoesNotReturnIfAttribute(bool parameterValue) + { + ParameterValue = parameterValue; + } + } +} + +#endif diff --git a/source/DefaultUnDo/Internal/CSharpFeatures/ObjectDisposedException.cs b/source/DefaultUnDo/Internal/CSharpFeatures/ObjectDisposedException.cs new file mode 100644 index 0000000..97624af --- /dev/null +++ b/source/DefaultUnDo/Internal/CSharpFeatures/ObjectDisposedException.cs @@ -0,0 +1,35 @@ +#if !NET5_0_OR_GREATER + +global using ObjectDisposedException = DefaultUnDo.ObjectDisposedException; + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace DefaultUnDo +{ + internal static class ObjectDisposedException + { + [StackTraceHidden] + public static void ThrowIf([DoesNotReturnIf(true)] bool condition, object instance) + { + if (condition) + { + throw new System.ObjectDisposedException(instance?.GetType().FullName); + } + } + + [StackTraceHidden] + public static void ThrowIf([DoesNotReturnIf(true)] bool condition, Type type) + { + if (condition) + { + throw new System.ObjectDisposedException(type?.FullName); + } + } + } +} + +#endif diff --git a/source/DefaultUnDo/Internal/CSharpFeatures/StackTraceHiddenAttribute.cs b/source/DefaultUnDo/Internal/CSharpFeatures/StackTraceHiddenAttribute.cs new file mode 100644 index 0000000..bc72ee8 --- /dev/null +++ b/source/DefaultUnDo/Internal/CSharpFeatures/StackTraceHiddenAttribute.cs @@ -0,0 +1,13 @@ +#if !NET5_0_OR_GREATER + +namespace System.Diagnostics +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Struct, Inherited = false)] + internal sealed class StackTraceHiddenAttribute : Attribute + { + public StackTraceHiddenAttribute() + { } + } +} + +#endif diff --git a/source/DefaultUnDo/Internal/NullableAttributes.cs b/source/DefaultUnDo/Internal/NullableAttributes.cs deleted file mode 100644 index fda056f..0000000 --- a/source/DefaultUnDo/Internal/NullableAttributes.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace System.Diagnostics.CodeAnalysis -{ -#if !NETSTANDARD2_1 - /// Specifies that null is allowed as an input even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property, Inherited = false)] - internal sealed class AllowNullAttribute : Attribute - { } - - /// Specifies that an output may be null even if the corresponding type disallows it. - [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)] - internal sealed class MaybeNullAttribute : Attribute - { } - - /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] - internal sealed class NotNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - - /// Gets the return value condition. - public bool ReturnValue { get; } - } -#endif -} \ No newline at end of file diff --git a/source/DefaultUnDo/Internal/UnDoBuffer.cs b/source/DefaultUnDo/Internal/UnDoBuffer.cs index 29af072..71e4216 100644 --- a/source/DefaultUnDo/Internal/UnDoBuffer.cs +++ b/source/DefaultUnDo/Internal/UnDoBuffer.cs @@ -37,6 +37,7 @@ public IEnumerable UndoDescriptions { i += _buffer.Length; } + if (i == _tail) { if (_currentState is true) @@ -64,6 +65,7 @@ public IEnumerable RedoDescription { i = 0; } + if (i == _head) { if (_currentState is false) diff --git a/source/DefaultUnDo/Internal/UnDoICollection.cs b/source/DefaultUnDo/Internal/UnDoICollection.cs index cb16e68..c078be9 100644 --- a/source/DefaultUnDo/Internal/UnDoICollection.cs +++ b/source/DefaultUnDo/Internal/UnDoICollection.cs @@ -8,17 +8,11 @@ namespace DefaultUnDo.Internal { internal class UnDoICollection : ICollection, INotifyCollectionChanged, INotifyPropertyChanged { - #region Fields - private readonly ICollection _source; protected readonly IUnDoManager _manager; protected readonly Func? _descriptionFactory; - #endregion - - #region Initialisation - public UnDoICollection(IUnDoManager manager, ICollection source, Func? descriptionFactory) { _source = source; @@ -26,8 +20,6 @@ public UnDoICollection(IUnDoManager manager, ICollection source, Func.Add(T item) => _manager.DoAdd(_source, item, _descriptionFactory?.Invoke(new UnDoCollectionOperation(this, UnDoCollectionAction.ICollectionAdd, item))); @@ -56,7 +48,7 @@ public UnDoICollection(IUnDoManager manager, ICollection source, Func : UnDoICollection>, IDictionary + internal sealed class UnDoIDictionary : UnDoICollection>, IDictionary { - #region Fields - private readonly IDictionary _source; - #endregion - - #region Initialisation - public UnDoIDictionary(IUnDoManager manager, IDictionary source, Func? descriptionFactory) : base(manager, source, descriptionFactory) { _source = source; } - #endregion - #region IDictionary void IDictionary.Add(TKey key, TValue value) => _manager.DoAdd(_source, key, value, _descriptionFactory?.Invoke(new UnDoCollectionOperation(this, UnDoCollectionAction.IDictionaryAdd, key, value))); @@ -29,7 +22,13 @@ public UnDoIDictionary(IUnDoManager manager, IDictionary source, F bool IDictionary.Remove(TKey key) => _manager.DoRemove(_source, key, _descriptionFactory?.Invoke(new UnDoCollectionOperation(this, UnDoCollectionAction.IDictionaryRemove, key))); - bool IDictionary.TryGetValue(TKey key, out TValue value) => _source.TryGetValue(key, out value); + bool IDictionary.TryGetValue( + TKey key, +#if NET5_0_OR_GREATER + [MaybeNullWhen(false)] +#endif + out TValue value) + => _source.TryGetValue(key, out value); TValue IDictionary.this[TKey key] { diff --git a/source/DefaultUnDo/Internal/UnDoIList.cs b/source/DefaultUnDo/Internal/UnDoIList.cs index 7bb9526..4760151 100644 --- a/source/DefaultUnDo/Internal/UnDoIList.cs +++ b/source/DefaultUnDo/Internal/UnDoIList.cs @@ -4,26 +4,16 @@ namespace DefaultUnDo.Internal { - internal class UnDoIList : UnDoICollection, IList + internal sealed class UnDoIList : UnDoICollection, IList { - #region Fields - private readonly IList _source; - #endregion - - #region Initialisation - public UnDoIList(IUnDoManager manager, IList source, Func? descriptionFactory) : base(manager, source, descriptionFactory) { _source = source; } - #endregion - - #region Methods - public void Move(int oldIndex, int newIndex) { if (_source is ObservableCollection collection) @@ -46,8 +36,6 @@ public void Move(int oldIndex, int newIndex) } } - #endregion - #region IList int IList.IndexOf(T item) => _source.IndexOf(item); diff --git a/source/DefaultUnDo/Internal/UnDoISet.cs b/source/DefaultUnDo/Internal/UnDoISet.cs index dfbcd16..feb759d 100644 --- a/source/DefaultUnDo/Internal/UnDoISet.cs +++ b/source/DefaultUnDo/Internal/UnDoISet.cs @@ -4,24 +4,16 @@ namespace DefaultUnDo.Internal { - internal class UnDoISet : UnDoICollection, ISet + internal sealed class UnDoISet : UnDoICollection, ISet { - #region Fields - private readonly ISet _source; - #endregion - - #region Initialisation - public UnDoISet(IUnDoManager manager, ISet source, Func? descriptionFactory) : base(manager, source, descriptionFactory) { _source = source; } - #endregion - #region ISet bool ISet.Add(T item) => _manager.DoAdd(_source, item, _descriptionFactory?.Invoke(new UnDoCollectionOperation(this, UnDoCollectionAction.ISetAdd, item))); diff --git a/source/DefaultUnDo/ListUnDo.cs b/source/DefaultUnDo/ListUnDo.cs index 47c9960..7fa534a 100644 --- a/source/DefaultUnDo/ListUnDo.cs +++ b/source/DefaultUnDo/ListUnDo.cs @@ -10,8 +10,6 @@ namespace DefaultUnDo /// The type of element in the . public sealed class ListUnDo : IUnDo { - #region Fields - private readonly object? _description; private readonly IList _source; private readonly int _index; @@ -19,10 +17,6 @@ public sealed class ListUnDo : IUnDo private readonly T _item; private readonly bool _isAdd; - #endregion - - #region Initialisation - /// /// Initialises an instance of . /// @@ -34,8 +28,10 @@ public sealed class ListUnDo : IUnDo /// is null. public ListUnDo(object? description, IList source, int index, [AllowNull] T item, bool isAdd) { + ArgumentNullException.ThrowIfNull(source); + _description = description; - _source = source ?? throw new ArgumentNullException(nameof(source)); + _source = source; _index = index; _item = item; _isAdd = isAdd; @@ -53,10 +49,6 @@ public ListUnDo(IList source, int index, [AllowNull] T item, bool isAdd) : this(null, source, index, item, isAdd) { } - #endregion - - #region Methods - private void Action(bool isAdd) { if (isAdd) @@ -69,8 +61,6 @@ private void Action(bool isAdd) } } - #endregion - #region IUnDo /// diff --git a/source/DefaultUnDo/UnDo.cs b/source/DefaultUnDo/UnDo.cs index c16a5e6..bfc712e 100644 --- a/source/DefaultUnDo/UnDo.cs +++ b/source/DefaultUnDo/UnDo.cs @@ -7,16 +7,10 @@ namespace DefaultUnDo /// public sealed class UnDo : IUnDo { - #region Fields - private readonly object? _description; private readonly Action? _doAction; private readonly Action? _undoAction; - #endregion - - #region Initialisation - /// /// Initialises an instance of . /// @@ -39,8 +33,6 @@ public UnDo(Action? doAction, Action? undoAction) : this(null, doAction, undoAction) { } - #endregion - #region IUnDo /// diff --git a/source/DefaultUnDo/UnDoCollectionOperation.cs b/source/DefaultUnDo/UnDoCollectionOperation.cs index 58a9cbc..0e3db9f 100644 --- a/source/DefaultUnDo/UnDoCollectionOperation.cs +++ b/source/DefaultUnDo/UnDoCollectionOperation.cs @@ -1,37 +1,13 @@ -using System; - -namespace DefaultUnDo +namespace DefaultUnDo { /// /// Provides data for the operation about to be performed on an undo collection. /// - public readonly struct UnDoCollectionOperation - { - /// - /// Gets the collection on which the action is performed. - /// - public object Collection { get; } - /// - /// Gets the action performed. - /// - public UnDoCollectionAction Action { get; } - - /// - /// Gets the parameters of the action performed. - /// - public object?[] Parameters { get; } - - /// - /// Initializes a new instance of the struct. - /// - /// The collection on which the action is performed. - /// The action performed. - /// The parameters of the action performed. - public UnDoCollectionOperation(object collection, UnDoCollectionAction action, params object?[] parameters) - { - Collection = collection ?? throw new ArgumentNullException(nameof(collection)); - Action = action; - Parameters = parameters; - } - } + /// The collection on which the action is performed. + /// The action performed. + /// The parameters of the action performed. + public readonly record struct UnDoCollectionOperation( + object Collection, + UnDoCollectionAction Action, + params object?[] Parameters); } diff --git a/source/DefaultUnDo/UnDoField.cs b/source/DefaultUnDo/UnDoField.cs index 59b72ac..7401ab0 100644 --- a/source/DefaultUnDo/UnDoField.cs +++ b/source/DefaultUnDo/UnDoField.cs @@ -6,7 +6,7 @@ namespace DefaultUnDo /// /// Provides a simple wrapper for a field to automatically generate operations. /// - /// + /// The type of the filed. public class UnDoField where T : notnull { @@ -35,7 +35,9 @@ public T Value /// is null. public UnDoField(IUnDoManager manager, [AllowNull] T value, Func, object?>? descriptionFactory = null) { - _manager = manager ?? throw new ArgumentNullException(nameof(manager)); + ArgumentNullException.ThrowIfNull(manager); + + _manager = manager; _descriptionFactory = descriptionFactory; _value = value; @@ -78,15 +80,9 @@ protected virtual void PostSet([AllowNull] T oldValue) /// ///Defines an implicit conversion of a to a . /// - /// - [return: MaybeNull] - public static implicit operator T(UnDoField field) => field is null ? default : field.ToT(); - - /// - /// Returns the underlying . - /// - /// The underlying . + /// The field to implicitely convert. [return: MaybeNull] - public T ToT() => Value; + [SuppressMessage("Usage", "CA2225:Operator overloads have named alternates", Justification = "Value property")] + public static implicit operator T(UnDoField field) => field is null ? default : field.Value; } } diff --git a/source/DefaultUnDo/UnDoFieldChange.cs b/source/DefaultUnDo/UnDoFieldChange.cs index 70bb4c9..362083e 100644 --- a/source/DefaultUnDo/UnDoFieldChange.cs +++ b/source/DefaultUnDo/UnDoFieldChange.cs @@ -1,34 +1,12 @@ -using System.Diagnostics.CodeAnalysis; - -namespace DefaultUnDo +namespace DefaultUnDo { /// /// Describes a value change operation done on a . /// - /// - public readonly struct UnDoFieldChange - { - /// - /// Gets the field old value. - /// - [AllowNull] - public T OldValue { get; } - - /// - /// Gets the field new value. - /// - [AllowNull] - public T NewValue { get; } - - /// - /// Initializes a new instance of the struct. - /// - /// The old value of the field. - /// The new value of the field. - public UnDoFieldChange([AllowNull] T oldValue, [AllowNull] T newValue) - { - OldValue = oldValue; - NewValue = newValue; - } - } + /// The type of the field. + /// The field old value. + /// The field new value. + public readonly record struct UnDoFieldChange( + T? OldValue, + T? NewValue); } diff --git a/source/DefaultUnDo/UnDoManager.cs b/source/DefaultUnDo/UnDoManager.cs index 85aef3e..e80f8ca 100644 --- a/source/DefaultUnDo/UnDoManager.cs +++ b/source/DefaultUnDo/UnDoManager.cs @@ -10,12 +10,8 @@ namespace DefaultUnDo /// public sealed class UnDoManager : IUnDoManager { - #region Types - private sealed class Transaction : IUnDoTransaction { - #region Fields - private readonly UnDoManager _manager; private readonly object? _description; private readonly List _commands; @@ -23,15 +19,11 @@ private sealed class Transaction : IUnDoTransaction private bool _isCommitted; private bool _isDisposed; - #endregion - - #region Initialisation - public Transaction(UnDoManager manager, object? description) { _manager = manager; _description = description; - _commands = new List(); + _commands = []; _isCommitted = false; _isDisposed = false; @@ -39,26 +31,19 @@ public Transaction(UnDoManager manager, object? description) _manager._transactions.Push(this); } - #endregion - - #region Methods - public void Add(IUnDo command) => _commands.Add(command); - #endregion - #region IUnDoTransaction public void Commit() { - if (_isDisposed) - { - throw new ObjectDisposedException(nameof(IUnDoTransaction)); - } + ObjectDisposedException.ThrowIf(_isDisposed, this); + if (_isCommitted) { throw new InvalidOperationException("Current transaction has already been committed"); } + if (_manager._transactions.Peek() != this) { throw new InvalidOperationException("Current transaction is not the highest one on the stack"); @@ -67,7 +52,7 @@ public void Commit() _manager._transactions.Pop(); if (_commands.Count > 0) { - IUnDo group = new GroupUnDo(_description, _commands.ToArray()); + IUnDo group = new GroupUnDo(_description, [.. _commands]); if (_manager._transactions.Count > 0) { _manager._transactions.Peek().Add(group); @@ -112,10 +97,6 @@ void IDisposable.Dispose() #endregion } - #endregion - - #region Fields - private readonly IUnDoStack _stack; private readonly Stack _transactions; @@ -123,10 +104,6 @@ void IDisposable.Dispose() private int _version; private int _lastVersion; - #endregion - - #region Initialisation - /// /// Initialises an instance of . /// @@ -153,14 +130,8 @@ public UnDoManager() : this(int.MaxValue) { } - #endregion - - #region Methods - private void Push(IUnDo command) => Version = _stack.Push(command, ++_lastVersion, Version); - #endregion - #region IUnDoManager /// @@ -213,6 +184,7 @@ private set /// /// Clears the history of operations. /// + /// Cannot perform Clear while a transaction is going on. public void Clear() { if (_transactions.Count > 0) @@ -235,10 +207,7 @@ public void Clear() /// is null. public void Do(IUnDo command) { - if (command is null) - { - throw new ArgumentNullException(nameof(command)); - } + ArgumentNullException.ThrowIfNull(command); try { @@ -274,6 +243,7 @@ public void Undo() { throw new InvalidOperationException("Cannot perform Undo while a transaction is going on."); } + if (!CanUndo) { throw new InvalidOperationException("No operation to undo."); @@ -301,6 +271,7 @@ public void Redo() { throw new InvalidOperationException("Cannot perform Redo while a transaction is going on."); } + if (!CanRedo) { throw new InvalidOperationException("No operation to redo."); diff --git a/source/DefaultUnDo/ValueUnDo.cs b/source/DefaultUnDo/ValueUnDo.cs index 133d106..727ddfe 100644 --- a/source/DefaultUnDo/ValueUnDo.cs +++ b/source/DefaultUnDo/ValueUnDo.cs @@ -44,8 +44,6 @@ public sealed class ValueUnDo : IMergeableUnDo /// The new description that will be using for the resulting merged . public delegate object MergeDescriptionHandler(object? oldDescription, T oldValue, object? newDescription, T newValue); - #region Fields - private readonly DateTime _timeStamp; private readonly object? _description; private readonly Action _setter; @@ -54,27 +52,17 @@ public sealed class ValueUnDo : IMergeableUnDo [AllowNull] private readonly T _oldValue; - #endregion - - #region Properties - /// /// The interval equivalent instances should respect to be mergeable. /// If not set, will be used. /// - [SuppressMessage("Design", "RCS1158:Static member in generic type should use a type parameter.")] public static TimeSpan? MergeInterval { get; set; } /// /// The used to merge description between two instance. /// - [SuppressMessage("Design", "RCS1158:Static member in generic type should use a type parameter.")] public static MergeDescriptionHandler? MergeDescriptionAction { get; set; } - #endregion - - #region Initialisation - /// /// Initialises an instance of . /// @@ -85,9 +73,11 @@ public sealed class ValueUnDo : IMergeableUnDo /// is null. public ValueUnDo(object? description, Action setter, [AllowNull] T newValue, [AllowNull] T oldValue) { + ArgumentNullException.ThrowIfNull(setter); + _timeStamp = DateTime.Now; _description = description; - _setter = setter ?? throw new ArgumentNullException(nameof(setter)); + _setter = setter; _newValue = newValue; _oldValue = oldValue; } @@ -103,8 +93,6 @@ public ValueUnDo(Action setter, T newValue, T oldValue) : this(null, setter, newValue, oldValue) { } - #endregion - #region IMergeableUnDo /// diff --git a/source/Directory.Build.props b/source/Directory.Build.props index 7337513..33a871e 100644 --- a/source/Directory.Build.props +++ b/source/Directory.Build.props @@ -1,17 +1,20 @@ + latest - true - true - AllEnabledByDefault - latest - true - true + true + true + AllEnabledByDefault + latest + true + true - - - + + + + +