Skip to content

Release 0.6.0 #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 10, 2024
Merged

Release 0.6.0 #7

merged 1 commit into from
Oct 10, 2024

Conversation

CoderGamester
Copy link
Owner

@CoderGamester CoderGamester commented Oct 10, 2024

-Improved the ObservableResolverList and ObservableResolverDictionary data types to properly resolve lists and dictionaries with different data types from the original collection.
-Fixed Unit tests for floatPTests that were failing.

  • Added new unit tests for ObservableResolverList and ObservableResolverDictionary data types

Summary by CodeRabbit

Release Notes:

  • New Feature: Improved data types for resolving lists and dictionaries.
  • Bug Fix: Fixed unit tests for floatPTests and adjusted assertions for floatP values.
  • Test: Added new unit tests for ObservableResolverList and ObservableResolverDictionary.
  • Refactor: Refactored interfaces and classes related to resolving lists with different value types.
  • Test: Updated unit tests for ObservableResolverList and ObservableResolverDictionary to ensure proper functionality and coverage.

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced StructPair and floatP data types for improved memory usage and precision.
    • Added ObservableResolverList and ObservableResolverDictionary classes for enhanced list and dictionary functionalities.
  • Improvements

    • Updated ObservableList and ObservableDictionary to support complex interactions and observability.
    • Enhanced unit tests for ObservableResolverList, ObservableResolverDictionary, and floatP.
  • Bug Fixes

    • Fixed issues with dispose methods to prevent unwanted exceptions.
  • Documentation

    • Updated changelog to reflect all new features and changes across versions.

…ry* data types to properly resolve lists and dictionaries with different data types from the original collection.

Fixed Unit tests for floatPTests that were failing.
Added new unit tests for *ObservableResolverList* and *ObservableResolverDictionary* data types
@CoderGamester CoderGamester self-assigned this Oct 10, 2024
Copy link

coderabbitai bot commented Oct 10, 2024

📝 Walkthrough

Walkthrough

The changes in this pull request include updates to the changelog, which details new features and fixes across multiple versions, specifically highlighting the introduction of new data types and enhancements to existing ones. Notable additions include StructPair, floatP, and improvements to ObservableResolverList and ObservableResolverDictionary. Several classes and interfaces have been added or modified to enhance the functionality of observable collections. Additionally, unit tests have been introduced for ObservableResolverList and ObservableResolverDictionary, and existing tests have been updated for clarity and effectiveness. The package version has also been incremented.

Changes

File Change Summary
CHANGELOG.md Updated to include new versions and their changes, including new data types and fixes.
Runtime/ObservableDictionary.cs Added new interfaces and class ObservableResolverDictionary, modified existing interfaces, and enhanced methods for observing changes in key-value pairs.
Runtime/ObservableList.cs Introduced new interfaces and class ObservableResolverList, modified ObservableList class methods, and updated constructor parameters.
Tests/Editor/ObservableResolverListTest.cs Added unit tests for ObservableResolverList, including setup and multiple test methods for verifying functionality.
Tests/Editor/ObservableResolverListTest.cs.meta New metadata file created with properties for the test class.
Tests/Editor/ObservableDictionaryTest.cs Modified test class to simplify variable names and added multiple new test methods for ObservableDictionary functionality.
Tests/Editor/ObservableListTest.cs Updated test class to focus on ObservableList<int>, replacing previous references and adjusting method names and assertions.
Tests/Editor/ObservableResolverDictionaryTest.cs New file introduced with unit tests for ObservableResolverDictionary, covering core functionalities.
Tests/Editor/ObservableResolverDictionaryTest.cs.meta New metadata file created with properties for the test class.
Tests/Editor/floatPTests.cs Updated assertions in tests for floatP to ensure type consistency by casting float literals to floatP.
package.json Version updated from 0.5.1 to 0.6.0 and Unity version requirement updated from 2021.4 to 2022.4.

Poem

In the garden of code, we hop with glee,
New types and fixes, as bright as can be!
With lists and dictionaries, we dance and play,
Observing the changes, come join the fray!
A sprinkle of tests, to keep bugs at bay,
In the world of data, we leap and sway! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

github-actions bot commented Oct 10, 2024

Image description CodeRabbit

Walkthrough

The changes include improvements to data types for resolving lists and dictionaries, fixes to unit tests, and the addition of new unit tests for ObservableResolverList and ObservableResolverDictionary. The changes also involve refactoring interfaces and classes related to resolving lists with different value types.

Changes

Files Summary
CHANGELOG.md Improved data types for resolving lists and dictionaries, fixed unit tests, and added new unit tests for ObservableResolverList and ObservableResolverDictionary.
Runtime/ObservableDictionary.cs
Runtime/ObservableList.cs
Changes to improve ObservableResolverList and ObservableResolverDictionary data types, fix unit tests for floatPTests, and add new unit tests. Refactored interfaces and classes related to resolving lists with different value types.
Tests/Editor/OberservableResolverListTest.cs
Tests/Editor/ObservableListTest.cs
Tests/Editor/ObservableResolverDictionaryTest.cs
Updated unit tests for ObservableResolverList and ObservableResolverDictionary classes to ensure proper functionality and coverage.
Tests/Editor/floatPTests.cs Adjusted assertions in floatPTests class to cast float values explicitly to floatP. Modifications affect test cases for representations, equality, addition, and multiplication of floatP values.

"Changes have arrived, a code transformation,
Lists and dictionaries, improved resolution.
Unit tests fixed, new ones added with care,
Ensuring functionality, coverage is fair.
With refactoring done, interfaces refined,
Resolving lists with different types, redefined.
Assertions adjusted, float values cast,
Representations, equality, all unsurpassed."


Uplevel your code reviews with CodeRabbit Pro

CodeRabbit Pro

If you like this project, please support us by purchasing the Pro version. The Pro version has advanced context, superior noise reduction and several proprietary improvements compared to the open source version. Moreover, CodeRabbit Pro is free for open source projects.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

Commits Files that changed from the base of the PR and between 3c445ea and f0a6b70 commits.
Files selected (8)
  • CHANGELOG.md (1)
  • Runtime/ObservableDictionary.cs (8)
  • Runtime/ObservableList.cs (8)
  • Tests/Editor/OberservableResolverListTest.cs (1)
  • Tests/Editor/ObservableDictionaryTest.cs (3)
  • Tests/Editor/ObservableListTest.cs (1)
  • Tests/Editor/ObservableResolverDictionaryTest.cs (1)
  • Tests/Editor/floatPTests.cs (2)
Files ignored due to filter (3)
  • Tests/Editor/OberservableResolverListTest.cs.meta
  • Tests/Editor/ObservableResolverDictionaryTest.cs.meta
  • package.json
Files not summarized due to errors (1)
  • Tests/Editor/ObservableDictionaryTest.cs (diff tokens exceeds limit)
Review comments generated (71)
  • Review: 57
  • LGTM: 14

Tips

Chat with Image description CodeRabbit Bot (@coderabbitai)

  • Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
  • Invite the bot into a review comment chain by tagging @coderabbitai in a reply.

Code suggestions

  • The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
  • You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.

Pausing incremental reviews

  • Add @coderabbitai: ignore anywhere in the PR description to pause further reviews from the bot.

Comment on lines +24 to +25
- Added utility methods and extensions for Unity's Object and GameObject types, enhancing the codebase's functionality.
- Introduced a SerializableType struct for viewing, modifying, and saving types from the inspector, with serialization support and compatibility with filter attributes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The description states that the assertions in the floatPTests class have been adjusted to cast float values explicitly to floatP. However, the code changes in this hunk are missing, so it's difficult to provide a thorough review. Please include the actual code changes for a more accurate review.

Changelog:

Comment on lines 34 to +35
- Added new *ObservableResolverList*, *ObservableResolverDictionary* & *ObservableResolverField* to allow to create observable types without referencing the collection directly
- Added Unit tests to all types
- Added Unit tests to all data types in the project

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The changelog entry for version 0.6.0 mentions improvements to the ObservableResolverList and ObservableResolverDictionary data types. However, the actual changes made to these data types are not mentioned in the changelog. It would be helpful to provide more details about the specific improvements made to these data types.

Overall, please provide the missing code changes for a more accurate review of the logic, performance, and other aspects of the code.

Comment on lines +14 to +19
[TestFixture]
public class ObservableResolverListTest
{
private int _index = 0;
private IObservableResolverList<int, string> _list;
private IList<string> _mockList;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The ObservableResolverListTest class is missing a namespace declaration. Please add the appropriate namespace declaration for the test class.

+ using GameLoversEditor.DataExtensions.Tests;

Comment on lines +31 to +38
public void AddOrigin_AddsValueToOriginList()
{
var value = "1";

_list.AddOrigin(value);

_mockList.Received().Add(value);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The AddOrigin_AddsValueToOriginList test method looks good. It verifies that calling the AddOrigin method adds the value to the origin list. The assertion is made using the Received method of the _mockList object. This ensures that the Add method of the _mockList object is called with the expected value. Well done!

Comment on lines +40 to +49
[Test]
public void UpdateOrigin_UpdatesOriginList()
{
var value = "1";

_list.AddOrigin(value);
_list.UpdateOrigin(value, _index);

_mockList.Received()[_index] = value;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The UpdateOrigin_UpdatesOriginList test method also looks good. It tests that calling the UpdateOrigin method updates the value at the specified index in the origin list. The assertion is made using the Received indexer of the _mockList object. This ensures that the value at the specified index is set to the expected value. Great job!

Comment on lines +372 to +377
public bool RemoveOrigin(TOrigin value)
{
_originList.Remove(value);

return base.Remove(_fromOrignResolver(value));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The implementation of the RemoveOrigin method in the ObservableResolverList<T, TOrigin> class is incorrect. It should remove the value from the _originList before calling the base Remove method. Please update the implementation as follows:

+ public bool RemoveOrigin(TOrigin value)
+ {
+     _originList.Remove(value);
+     return base.Remove(_fromOrignResolver(value));
+ }

Comment on lines +380 to 384
public void ClearOrigin()
{
_listResolver = listResolver;
_originList.Clear();
base.Clear();
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The implementation of the ClearOrigin method in the ObservableResolverList<T, TOrigin> class is incorrect. It should clear the _originList before calling the base Clear method. Please update the implementation as follows:

+ public void ClearOrigin()
+ {
+     _originList.Clear();
+     base.Clear();
+ }

Comment on lines +14 to +23
Assert.AreEqual(floatP.Zero, (floatP)0f);
Assert.AreEqual(-floatP.Zero, (floatP) (-0f));
Assert.AreEqual(floatP.Zero, -floatP.Zero);
Assert.AreEqual(floatP.NaN, float.NaN);
Assert.AreEqual(floatP.One, 1f);
Assert.AreEqual(floatP.MinusOne, -1f);
Assert.AreEqual(floatP.PositiveInfinity, float.PositiveInfinity);
Assert.AreEqual(floatP.NegativeInfinity, float.NegativeInfinity);
Assert.AreEqual(floatP.Epsilon, float.Epsilon);
Assert.AreEqual(floatP.MaxValue, float.MaxValue);
Assert.AreEqual(floatP.MinValue, float.MinValue);
Assert.AreEqual(floatP.NaN, (floatP) float.NaN);
Assert.AreEqual(floatP.MinusOne, (floatP) (- 1f));
Assert.AreEqual(floatP.PositiveInfinity, (floatP)float.PositiveInfinity);
Assert.AreEqual(floatP.NegativeInfinity, (floatP)float.NegativeInfinity);
Assert.AreEqual(floatP.Epsilon, (floatP)float.Epsilon);
Assert.AreEqual(floatP.MaxValue, (floatP)float.MaxValue);
Assert.AreEqual(floatP.MinValue, (floatP)float.MinValue);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The unit test Representation in the floatPTests class is comparing floatP values with float values, which will always fail. The floatP values need to be explicitly cast to float before comparison. Here's the fix:

- Assert.AreEqual(floatP.Zero, (floatP)0f);
+ Assert.AreEqual((float)floatP.Zero, 0f);

- Assert.AreEqual(-floatP.Zero, (floatP)(-0f));
+ Assert.AreEqual((float)-floatP.Zero, -0f);

- Assert.AreEqual(floatP.NaN, (floatP)float.NaN);
+ Assert.AreEqual((float)floatP.NaN, float.NaN);

- Assert.AreEqual(floatP.MinusOne, (floatP)(-1f));
+ Assert.AreEqual((float)floatP.MinusOne, -1f);

- Assert.AreEqual(floatP.PositiveInfinity, (floatP)float.PositiveInfinity);
+ Assert.AreEqual((float)floatP.PositiveInfinity, float.PositiveInfinity);

- Assert.AreEqual(floatP.NegativeInfinity, (floatP)float.NegativeInfinity);
+ Assert.AreEqual((float)floatP.NegativeInfinity, float.NegativeInfinity);

- Assert.AreEqual(floatP.Epsilon, (floatP)float.Epsilon);
+ Assert.AreEqual((float)floatP.Epsilon, float.Epsilon);

- Assert.AreEqual(floatP.MaxValue, (floatP)float.MaxValue);
+ Assert.AreEqual((float)floatP.MaxValue, float.MaxValue);

- Assert.AreEqual(floatP.MinValue, (floatP)float.MinValue);
+ Assert.AreEqual((float)floatP.MinValue, float.MinValue);

Comment on lines +45 to 47
Assert.AreEqual(floatP.One + floatP.One, (floatP)2f);
Assert.AreEqual(floatP.One - floatP.One, (floatP)0f);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The unit test Addition in the floatPTests class is comparing floatP values with float values, which will always fail. The floatP values need to be explicitly cast to float before comparison. Here's the fix:

- Assert.AreEqual(floatP.One + floatP.One, (floatP)2f);
+ Assert.AreEqual((float)floatP.One + (float)floatP.One, 2f);

- Assert.AreEqual(floatP.One - floatP.One, (floatP)0f);
+ Assert.AreEqual((float)floatP.One - (float)floatP.One, 0f);

Comment on lines +52 to +62
Assert.AreEqual(floatP.PositiveInfinity * floatP.Zero, (floatP) (float.PositiveInfinity * 0f));
Assert.AreEqual(floatP.PositiveInfinity * (-floatP.Zero), (floatP)(float.PositiveInfinity * (-0f)));
Assert.AreEqual(floatP.PositiveInfinity * floatP.One, (floatP)(float.PositiveInfinity * 1f));
Assert.AreEqual(floatP.PositiveInfinity * floatP.MinusOne, (floatP)(float.PositiveInfinity * -1f));

Assert.AreEqual(floatP.NegativeInfinity * floatP.Zero, float.NegativeInfinity * 0f);
Assert.AreEqual(floatP.NegativeInfinity * (-floatP.Zero), float.NegativeInfinity * (-0f));
Assert.AreEqual(floatP.NegativeInfinity * floatP.One, float.NegativeInfinity * 1f);
Assert.AreEqual(floatP.NegativeInfinity * floatP.MinusOne, float.NegativeInfinity * -1f);
Assert.AreEqual(floatP.NegativeInfinity * floatP.Zero, (floatP)(float.NegativeInfinity * 0f));
Assert.AreEqual(floatP.NegativeInfinity * (-floatP.Zero), (floatP)(float.NegativeInfinity * (-0f)));
Assert.AreEqual(floatP.NegativeInfinity * floatP.One, (floatP)(float.NegativeInfinity * 1f));
Assert.AreEqual(floatP.NegativeInfinity * floatP.MinusOne, (floatP)(float.NegativeInfinity * -1f));

Assert.AreEqual(floatP.One * floatP.One, 1f);
Assert.AreEqual(floatP.One * floatP.One, (floatP)1f);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description CodeRabbit

The unit test Multiplication in the floatPTests class is comparing floatP values with float values, which will always fail. The floatP values need to be explicitly cast to float before comparison. Here's the fix:

- Assert.AreEqual(floatP.PositiveInfinity * floatP.Zero, (floatP)(float.PositiveInfinity * 0f));
+ Assert.AreEqual((float)floatP.PositiveInfinity * (float)floatP.Zero, float.PositiveInfinity * 0f);

- Assert.AreEqual(floatP.PositiveInfinity * (-floatP.Zero), (floatP)(float.PositiveInfinity * (-0f)));
+ Assert.AreEqual((float)floatP.PositiveInfinity * (float)-floatP.Zero, float.PositiveInfinity * (-0f));

- Assert.AreEqual(floatP.PositiveInfinity * floatP.One, (floatP)(float.PositiveInfinity * 1f));
+ Assert.AreEqual((float)floatP.PositiveInfinity * (float)floatP.One, float.PositiveInfinity * 1f);

- Assert.AreEqual(floatP.PositiveInfinity * floatP.MinusOne, (floatP)(float.PositiveInfinity * -1f));
+ Assert.AreEqual((float)floatP.PositiveInfinity * (float)floatP.MinusOne, float.PositiveInfinity * -1f);

- Assert.AreEqual(floatP.NegativeInfinity * floatP.Zero, (floatP)(float.NegativeInfinity * 0f));
+ Assert.AreEqual((float)floatP.NegativeInfinity * (float)floatP.Zero, float.NegativeInfinity * 0f);

- Assert.AreEqual(floatP.NegativeInfinity * (-floatP.Zero), (floatP)(float.NegativeInfinity * (-0f)));
+ Assert.AreEqual((float)floatP.NegativeInfinity * (float)-floatP.Zero, float.NegativeInfinity * (-0f));

- Assert.AreEqual(floatP.NegativeInfinity * floatP.One, (floatP)(float.NegativeInfinity * 1f));
+ Assert.AreEqual((float)floatP.NegativeInfinity * (float)floatP.One, float.NegativeInfinity * 1f);

- Assert.AreEqual(floatP.NegativeInfinity * floatP.MinusOne, (floatP)(float.NegativeInfinity * -1f));
+ Assert.AreEqual((float)floatP.NegativeInfinity * (float)floatP.MinusOne, float.NegativeInfinity * -1f);

Please review these changes.

@CoderGamester CoderGamester merged commit 7279e03 into master Oct 10, 2024
1 check passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 23

🧹 Outside diff range and nitpick comments (20)
Tests/Editor/OberservableResolverListTest.cs (3)

17-28: LGTM: Proper setup, with a minor suggestion

The setup method and field declarations are well-structured and follow best practices for unit testing. The use of NSubstitute for mocking and the initialization of ObservableResolverList with conversion functions are appropriate.

Consider initializing _index in the SetUp method for consistency and to ensure a fresh state for each test:

 private int _index = 0;
 private IObservableResolverList<int, string> _list;
 private IList<string> _mockList;

 [SetUp]
 public void SetUp()
 {
+    _index = 0;
     _mockList = Substitute.For<IList<string>>();
     _list = new ObservableResolverList<int, string>(_mockList,
         origin => int.Parse(origin),
         value => value.ToString());
 }

40-60: LGTM: Effective tests for UpdateOrigin and RemoveOrigin methods, with a suggestion

Both test methods correctly verify the behavior of their respective ObservableResolverList methods. The assertions are appropriate and check the expected interactions with the mock list.

Consider parameterizing the UpdateOrigin_UpdatesOriginList test to check multiple index values:

[Test]
[TestCase(0)]
[TestCase(1)]
[TestCase(5)]
public void UpdateOrigin_UpdatesOriginList(int index)
{
    var value = "1";

    _list.AddOrigin(value);
    _list.UpdateOrigin(value, index);

    _mockList.Received()[index] = value;
}

This change would test the UpdateOrigin method more thoroughly across different index values.


1-70: Overall: Well-structured and comprehensive test suite

This test file provides good coverage for the ObservableResolverList class, testing all major operations (Add, Update, Remove, Clear) effectively. The use of NSubstitute for mocking is consistent and appropriate throughout the tests.

To further improve the test suite, consider adding the following tests:

  1. Test the behavior when adding multiple items to ensure the list maintains the correct order.
  2. Test edge cases, such as updating or removing items at the boundaries of the list (first and last elements).
  3. Test the conversion functions to ensure they're working correctly, especially with edge cases (e.g., very large numbers, negative numbers).
  4. Test the behavior when the underlying list is initially non-empty.

Example of a test for adding multiple items:

[Test]
public void AddOrigin_MultipleTimes_MaintainsCorrectOrder()
{
    var values = new[] { "1", "2", "3" };

    foreach (var value in values)
    {
        _list.AddOrigin(value);
    }

    for (int i = 0; i < values.Length; i++)
    {
        _mockList.Received().Add(values[i]);
    }
}

These additional tests would provide more comprehensive coverage and help ensure the robustness of the ObservableResolverList implementation.

Tests/Editor/ObservableResolverDictionaryTest.cs (2)

23-38: Consider adding a comment to explain conversion logic

The Init method does a great job setting up the test environment. However, the lambda expressions used in the ObservableResolverDictionary constructor (lines 27-30) are somewhat complex. Consider adding a comment to explain the conversion logic for better readability and maintainability.


40-44: Enhance test assertion for existing key

While the test correctly checks if TryGetOriginValue returns true for an existing key, it doesn't verify the actual value returned. Consider adding an assertion to check the returned value:

 Assert.IsTrue(_dictionary.TryGetOriginValue(_key, out var value));
+Assert.AreEqual(_value, value);

This will ensure that the correct value is being returned along with the boolean result.

CHANGELOG.md (2)

15-16: Minor grammatical improvements needed.

Consider the following changes to improve clarity and grammar:

- Fixed the dispose extension methods for GameObject and Object, removing pragma directives and adding null reference check in GetValid method to avoid unwanted exceptions
+ Fixed the dispose extension methods for GameObject and Object, removing pragma directives and adding a null reference check in the GetValid method to avoid unwanted exceptions
🧰 Tools
🪛 LanguageTool

[uncategorized] ~16-~16: You might be missing the article “a” here.
Context: ..., removing pragma directives and adding null reference check in GetValid method to a...

(AI_EN_LECTOR_MISSING_DETERMINER_A)


[uncategorized] ~16-~16: You might be missing the article “the” here.
Context: ...ives and adding null reference check in GetValid method to avoid unwanted exceptions

...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


34-40: Improve formatting and grammar for version 0.2.0 changelog entry.

Consider the following changes to improve clarity, grammar, and formatting:

- Added new *ObservableResolverList*, *ObservableResolverDictionary* & *ObservableResolverField* to allow to create observable types without referencing the collection directly
- Added Unit tests to all data types in the project

**Changed**:
- Removed *ObservableIdList* because it's behaviour was too confusing and the same result can be obtained with *ObservableList* or *ObservableDictionary*
- Removed all Pair Data and moved them to new *Pair<Key,Value>* serialized type that can now be serializable on Unity 2020.1
- Moved all Vector2, Vector3 & Vector4 extensions to the ValueData file

+ ### Added
+ - New *ObservableResolverList*, *ObservableResolverDictionary*, and *ObservableResolverField* to allow creating observable types without referencing the collection directly
+ - Unit tests for all data types in the project
+
+ ### Changed
+ - Removed *ObservableIdList* due to confusing behavior (same functionality can be achieved with *ObservableList* or *ObservableDictionary*)
+ - Replaced all Pair Data with new serializable *Pair<Key,Value>* type, compatible with Unity 2020.1
+ - Relocated all Vector2, Vector3, and Vector4 extensions to the ValueData file

These changes improve the structure, grammar, and clarity of the changelog entry.

🧰 Tools
🪛 LanguageTool

[grammar] ~34-~34: Did you mean “creating”? Or maybe you should add a pronoun? In active voice, ‘allow’ + ‘to’ takes an object, usually a pronoun.
Context: ...y* & ObservableResolverField to allow to create observable types without referencing th...

(ALLOW_TO)


[grammar] ~38-~38: Did you mean to use the possessive pronoun “its”?
Context: ...:

  • Removed ObservableIdList because it's behaviour was too confusing and the sam...

(IT_S_ITS)


[uncategorized] ~38-~38: Use a comma before “and” if it connects two independent clauses (unless they are closely connected and short).
Context: ...because it's behaviour was too confusing and the same result can be obtained with *O...

(COMMA_COMPOUND_SENTENCE_2)

Tests/Editor/ObservableListTest.cs (5)

33-34: Proper initialization of mock list and observable list

The initialization of _mockList and _list in the Init method is correct and consistent with the earlier field changes. This setup allows for flexible mocking of list behavior.

Consider adding a comment explaining the purpose of using a mock list, e.g.:

// Use a mock list to allow precise control over list behavior in tests
_mockList = Substitute.For<IList<int>>();

38-42: Improved test method name and assertion

The renaming of the test method to AddValue_AddsValueToList is a good improvement, as it clearly describes the behavior being tested. The updated assertion correctly checks the value in the new _list instance.

Consider adding an additional assertion to verify that the Add method was called on the mock list:

_mockList.Received(1).Add(_previousValue);

This would ensure that the ObservableList is correctly delegating the Add operation to the underlying list.


46-57: Improved test method name and assertions

The renaming of the test method to SetValue_UpdatesValue is a good improvement, as it clearly describes the behavior being tested. The updated assertions correctly check the values in the new _list instance for both Add and indexer set operations.

Consider adding assertions to verify that the underlying mock list is being updated:

_mockList.Received(1).Add(valueCheck1);
_mockList.Received(1)[_index] = valueCheck2;

This would ensure that the ObservableList is correctly delegating operations to the underlying list.


63-75: Improved test precision for Observe method

The updates to this test method improve its precision by using the new _list instance and verifying specific method calls on the mock caller. This approach provides a more accurate test of the Observe method's behavior and the subsequent list operations.

Consider adding assertions to verify that the underlying mock list is being updated:

_mockList.Received(1).Add(_previousValue);
_mockList.Received(1)[_index] = _newValue;
_mockList.Received(1).RemoveAt(_index);

This would ensure that the ObservableList is correctly delegating operations to the underlying list.


117-123: Simplified and consistent update for StopObserveCheck test

The changes to use _list and simplify the test structure are good improvements. The test effectively verifies the behavior of the StopObserving method.

Consider adding assertions to verify that the underlying mock list is being updated:

_mockList.Received(1).Add(_previousValue);
_mockList.Received(1)[_index] = _previousValue;
_mockList.Received(1).RemoveAt(_index);

This would ensure that the ObservableList is correctly delegating operations to the underlying list, even when observations are stopped.

Tests/Editor/ObservableDictionaryTest.cs (3)

173-176: Confirm exception type for better specificity

In the test InvokeUpdate_MissingKey_ThrowsException, you're asserting that a KeyNotFoundException is thrown. Ensure that this is the most appropriate exception type for this scenario. If a more specific exception could be used, it might provide clearer insight into the error condition.


79-84: Verify indexer set operation with existing key

In the test Indexer_SetsValue_WhenKeyExists, adding an assertion before changing the value would confirm the initial state and enhance the test's clarity.

Apply this diff to include the assertion:

 _dictionary.Add(1, 100);
+Assert.AreEqual(100, _dictionary[1]);

 _dictionary[1] = 200;

 Assert.AreEqual(200, _dictionary[1]);

34-34: Consider simplifying dictionary initialization

Since _mockDictionary is a standard Dictionary<int, int>, you might initialize _dictionary without explicitly passing it, unless you are testing functionality that depends on the underlying dictionary.

If the underlying dictionary is crucial for certain tests, consider renaming _mockDictionary to _baseDictionary or _innerDictionary for clarity.

Runtime/ObservableList.cs (2)

5-5: Remove unused using directive System.Reflection

It appears that the System.Reflection namespace is not used anywhere in this file. Removing unnecessary using directives can help keep the code clean and improve readability.


169-169: Potential issue with list casting in constructor

In the ObservableList<T> constructor, the list is assigned using:

List = list as List<T> ?? list.ToList();

If list is not a List<T>, this creates a new list via ToList(), which may not reflect changes to the original IList<T> passed in. If the intention is to have List always reflect changes to the original list, consider directly using the provided IList<T> or copying it based on requirements.

Runtime/ObservableDictionary.cs (3)

148-149: Correct grammatical error in documentation comment

The comment has an incorrect apostrophe in "Add's". It should be "Adds to the origin dictionary".

Apply this diff to fix the comment:

	/// <remarks>
-	/// Add's to the origin dictionary
+	/// Adds to the origin dictionary
	/// </remarks>

154-155: Correct grammatical error in documentation comment

The comment incorrectly uses an apostrophe in "Remove's". It should be "Removes from the origin dictionary".

Apply this diff to fix the comment:

	/// <remarks>
-	/// Remove's to the origin dictionary
+	/// Removes from the origin dictionary
	/// </remarks>

160-161: Correct grammatical error in documentation comment

The comment incorrectly uses an apostrophe in "Clear's". It should be "Clears the origin dictionary".

Apply this diff to fix the comment:

	/// <remarks>
-	/// Clear's to the origin dictionary
+	/// Clears the origin dictionary
	/// </remarks>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 3c445ea and f0a6b70.

📒 Files selected for processing (11)
  • CHANGELOG.md (1 hunks)
  • Runtime/ObservableDictionary.cs (8 hunks)
  • Runtime/ObservableList.cs (8 hunks)
  • Tests/Editor/OberservableResolverListTest.cs (1 hunks)
  • Tests/Editor/OberservableResolverListTest.cs.meta (1 hunks)
  • Tests/Editor/ObservableDictionaryTest.cs (2 hunks)
  • Tests/Editor/ObservableListTest.cs (1 hunks)
  • Tests/Editor/ObservableResolverDictionaryTest.cs (1 hunks)
  • Tests/Editor/ObservableResolverDictionaryTest.cs.meta (1 hunks)
  • Tests/Editor/floatPTests.cs (2 hunks)
  • package.json (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • Tests/Editor/OberservableResolverListTest.cs.meta
  • Tests/Editor/ObservableResolverDictionaryTest.cs.meta
  • package.json
🧰 Additional context used
🪛 LanguageTool
CHANGELOG.md

[uncategorized] ~16-~16: You might be missing the article “a” here.
Context: ..., removing pragma directives and adding null reference check in GetValid method to a...

(AI_EN_LECTOR_MISSING_DETERMINER_A)


[uncategorized] ~16-~16: You might be missing the article “the” here.
Context: ...ives and adding null reference check in GetValid method to avoid unwanted exceptions

...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)


[grammar] ~34-~34: Did you mean “creating”? Or maybe you should add a pronoun? In active voice, ‘allow’ + ‘to’ takes an object, usually a pronoun.
Context: ...y* & ObservableResolverField to allow to create observable types without referencing th...

(ALLOW_TO)


[grammar] ~38-~38: Did you mean to use the possessive pronoun “its”?
Context: ...:

  • Removed ObservableIdList because it's behaviour was too confusing and the sam...

(IT_S_ITS)


[uncategorized] ~38-~38: Use a comma before “and” if it connects two independent clauses (unless they are closely connected and short).
Context: ...because it's behaviour was too confusing and the same result can be obtained with *O...

(COMMA_COMPOUND_SENTENCE_2)

🔇 Additional comments (23)
Tests/Editor/OberservableResolverListTest.cs (3)

1-15: LGTM: Proper setup for unit tests

The namespace, imports, and test fixture setup are correctly implemented. The use of NUnit and NSubstitute is appropriate for unit testing in this context.


30-38: LGTM: Effective test for AddOrigin method

This test correctly verifies that the AddOrigin method of ObservableResolverList calls the Add method on the underlying list with the correct value.


62-69: LGTM: Effective test for ClearOrigin method

This test correctly verifies that the ClearOrigin method of ObservableResolverList calls the Clear method on the underlying list.

Tests/Editor/ObservableResolverDictionaryTest.cs (1)

1-22: LGTM: Well-structured test class setup

The file structure and class setup follow good practices for unit testing. The use of appropriate imports, test fixture attribute, and private fields for test data and mocks is commendable.

Tests/Editor/floatPTests.cs (5)

14-15: Improved type consistency in assertions

The changes in the Representation method enhance type safety and consistency. By casting float literals to floatP in assertions (e.g., (floatP)0f instead of 0f), we ensure that comparisons are made between values of the same type. This modification not only makes the tests more accurate but also aligns with best practices for strongly-typed languages.

Also applies to: 17-23


45-46: Consistent type casting in arithmetic operations

The modifications in the Addition method follow the same pattern as in the Representation method. Casting the results of arithmetic operations to floatP (e.g., (floatP)2f, (floatP)0f) ensures type consistency and makes the tests more robust. This change maintains the improved type safety throughout the test class.


52-55: Proper type casting for infinity operations

The changes in the Multiplication method for PositiveInfinity operations are consistent with the previous modifications. By casting the results to floatP, we ensure that these edge cases are tested with the correct type. This is particularly important for operations involving infinity, as it verifies that floatP correctly handles these special cases in the same manner as the standard float type.


57-60: Symmetrical testing for negative infinity operations

The modifications for NegativeInfinity operations mirror those made for PositiveInfinity. This symmetrical approach to testing both positive and negative infinity operations is crucial for ensuring that floatP handles all edge cases correctly. The consistent casting to floatP maintains type safety and provides a comprehensive test suite for infinity-related arithmetic.


62-62: Consistent type casting for all operations

The final modification in the Multiplication method, casting the result of floatP.One * floatP.One to (floatP)1f, maintains consistency with all previous changes. This attention to detail ensures that even simple operations are tested with proper type consistency.

Overall, these modifications throughout the floatPTests class significantly improve the robustness and reliability of the test suite. By consistently casting float literals and operation results to floatP, we ensure that all comparisons and assertions are performed using the correct type. This approach not only enhances type safety but also provides a more accurate validation of the floatP type's behavior across various scenarios, including edge cases and basic arithmetic operations.

CHANGELOG.md (4)

7-10: LGTM: Version 0.6.0 changes are well-documented.

The changelog entry for version 0.6.0 accurately reflects the improvements mentioned in the PR objectives. The description is clear and concise, providing valuable information about the enhancements to ObservableResolverList and ObservableResolverDictionary.


18-20: LGTM: Version 0.5.0 changes are well-documented.

The changelog entry for version 0.5.0 accurately describes the addition of the floatP type, including its purpose and features. The description is clear and informative, providing valuable context for the new functionality.


22-25: LGTM: Version 0.4.0 changes are well-documented.

The changelog entries for version 0.4.0 accurately describe the additions of utility methods, extensions, and the SerializableType struct. The descriptions are clear and concise, providing a good overview of the new functionality.


27-30: LGTM: Version 0.3.0 changes are well-documented.

The changelog entries for version 0.3.0 accurately describe the additions of field update observation support and the UnitySerializedDictionary class. The descriptions are clear and concise, providing a good overview of the new functionality.

Tests/Editor/ObservableListTest.cs (6)

25-26: Improved test setup with mock list

The replacement of separate observable list instances with a single ObservableList<int> backed by a mocked IList<int> is a good improvement. This change simplifies the test setup and allows for better control and verification of list operations.


83-86: Improved test precision for InvokeObserve method

The updates to this test method improve its precision by using the new _list instance and verifying specific method calls on the mock caller. This approach provides a more accurate test of the InvokeObserve method's behavior.


94-101: Improved test precision for InvokeUpdate method

The updates to this test method improve its precision by using the new _list instance and verifying specific method calls on the mock caller. This approach provides a more accurate test of the InvokeUpdate method's behavior.


109-111: Consistent update for InvokeUpdate_NotObserving_DoesNothing test

The change to use _list instead of _observableList is consistent with the earlier refactoring. The test correctly verifies that InvokeUpdate does nothing when not observing.


131-146: Simplified and consistent updates for StopObservingAll tests

The changes to use _list and simplify the test structure in both StopObservingAllCheck and StopObservingAll_MultipleCalls_Check are good improvements. These tests effectively verify the behavior of the StopObservingAll method in different scenarios.


154-171: Consistent updates for remaining StopObservingAll tests

The changes to use _list in the StopObservingAll_Everything_Check and StopObservingAll_NotObserving_DoesNothing tests are consistent with the earlier refactoring. These tests effectively verify the behavior of the StopObservingAll method when called with no arguments and when not observing.

Tests/Editor/ObservableDictionaryTest.cs (3)

199-203: Test method correctly named and implemented

The test method InvokeUpdate_NotObserving_DoesNothing follows the naming convention and accurately tests the expected behavior when no observers are registered.


276-281: Test method correctly named and implemented

The test method StopObservingAll_NotObserving_DoesNothing adheres to the naming convention and accurately tests the behavior when no observers are registered.


147-148: Clarify observer registration in tests

In the ObserveCheck test, both key-specific and global observers are registered. Ensure the test separately verifies the notifications received by each observer to confirm that both are functioning correctly.

You can enhance the test by distinguishing between calls received by key-specific and global observers.

Runtime/ObservableList.cs (1)

250-252: Optimize nested loop in Clear method

In the Clear method of ObservableList<T>, there's a nested loop that could be optimized:

for (var i = 0; i < _updateActions.Count; i++)
{
    for (var j = 0; j < list.Count; j++)
    {
        _updateActions[i](j, list[j], default, ObservableUpdateType.Removed);
    }
}

Consider combining the loops or reducing the number of iterations to improve performance, especially for large lists.

[performance]

Comment on lines +55 to +87
[Test]
public void AddOrigin_AddsValueToOriginDictionary()
{
_dictionary.AddOrigin(_key, _value);

_mockDictionary.Received().Add(_key, _value);
}

[Test]
public void UpdateOrigin_UpdatesValueInOriginDictionary()
{
_dictionary.AddOrigin(_key, _value);
_dictionary.UpdateOrigin(_key, _value);

_mockDictionary.Received()[_key] = _value;
}

[Test]
public void RemoveOrigin_RemovesValueFromOriginDictionary()
{
_dictionary.AddOrigin(_key, _value);

Assert.IsTrue(_dictionary.RemoveOrigin(_key));
_mockDictionary.Received().Remove(_key);
}

[Test]
public void ClearOrigin_ClearsOriginDictionary()
{
_dictionary.ClearOrigin();

_mockDictionary.Received().Clear();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance test coverage for dictionary operations

The tests for AddOrigin, UpdateOrigin, RemoveOrigin, and ClearOrigin cover basic functionality, but could be more comprehensive:

  1. For AddOrigin, consider verifying that the value can be retrieved after adding:

    _dictionary.AddOrigin(_key, _value);
    Assert.IsTrue(_dictionary.TryGetOriginValue(_key, out var retrievedValue));
    Assert.AreEqual(_value, retrievedValue);
  2. For UpdateOrigin, verify that the value was actually updated:

    _dictionary.UpdateOrigin(_key, "new_value");
    Assert.IsTrue(_dictionary.TryGetOriginValue(_key, out var updatedValue));
    Assert.AreEqual("new_value", updatedValue);
  3. For RemoveOrigin, check that the key no longer exists after removal:

    Assert.IsTrue(_dictionary.RemoveOrigin(_key));
    Assert.IsFalse(_dictionary.TryGetOriginValue(_key, out _));
  4. For ClearOrigin, verify that the dictionary is empty after clearing:

    _dictionary.ClearOrigin();
    Assert.AreEqual(0, _dictionary.Count);

These additions will provide more robust verification of the ObservableResolverDictionary behavior.

Comment on lines +1 to +89
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
using GameLovers;
using NSubstitute;
using NUnit.Framework;
using UnityEngine;

// ReSharper disable once CheckNamespace

namespace GameLoversEditor.DataExtensions.Tests
{
[TestFixture]
public class ObservableResolverDictionaryTest
{
private int _key = 0;
private string _value = "1";
private ObservableResolverDictionary<int, int, int, string> _dictionary;
private IDictionary<int, string> _mockDictionary;

[SetUp]
public void Init()
{
_mockDictionary = Substitute.For<IDictionary<int, string>>();
_dictionary = new ObservableResolverDictionary<int, int, int, string>(
_mockDictionary,
origin => new KeyValuePair<int, int>(origin.Key, int.Parse(origin.Value)),
(key, value) => new KeyValuePair<int, string>(key, key.ToString()));

_mockDictionary[_key].Returns(_value);
_mockDictionary.TryGetValue(_key, out _).Returns(callInfo =>
{
callInfo[1] = _mockDictionary[_key];
return true;
});
}

[Test]
public void TryGetOriginValue_KeyExists_ReturnsTrueAndOutValue()
{
Assert.IsTrue(_dictionary.TryGetOriginValue(_key, out var value));
}

[Test]
public void TryGetOriginValue_KeyDoesNotExist_ReturnsFalseAndOutDefault()
{
var result = _dictionary.TryGetOriginValue(999, out var value);

Assert.IsFalse(result);
Assert.IsNull(value);
}

[Test]
public void AddOrigin_AddsValueToOriginDictionary()
{
_dictionary.AddOrigin(_key, _value);

_mockDictionary.Received().Add(_key, _value);
}

[Test]
public void UpdateOrigin_UpdatesValueInOriginDictionary()
{
_dictionary.AddOrigin(_key, _value);
_dictionary.UpdateOrigin(_key, _value);

_mockDictionary.Received()[_key] = _value;
}

[Test]
public void RemoveOrigin_RemovesValueFromOriginDictionary()
{
_dictionary.AddOrigin(_key, _value);

Assert.IsTrue(_dictionary.RemoveOrigin(_key));
_mockDictionary.Received().Remove(_key);
}

[Test]
public void ClearOrigin_ClearsOriginDictionary()
{
_dictionary.ClearOrigin();

_mockDictionary.Received().Clear();
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider additional test scenarios for comprehensive coverage

The current test suite provides good coverage of basic operations for ObservableResolverDictionary. To further enhance the robustness of your tests, consider adding the following scenarios:

  1. Test the behavior when adding a duplicate key.
  2. Verify that the Count property is updated correctly after add, remove, and clear operations.
  3. Test the ContainsKey method for both existing and non-existing keys.
  4. Verify the behavior of the Keys and Values properties.
  5. Test the GetEnumerator method to ensure proper iteration over the dictionary.
  6. Add tests for any custom events or notifications that ObservableResolverDictionary might implement.

These additional tests will help ensure that all aspects of the ObservableResolverDictionary class are thoroughly verified.


- Improved the *ObservableResolverList* and *ObservableResolverDictionary* data types to properly resolve lists and dictionaries with different data types from the original collection.

## [0.5.1] - 2023-09-04
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Inconsistent version date.

The date for version 0.5.1 (2023-09-04) is later than the date for version 0.6.0 (2023-08-05). This appears to be an inconsistency in the changelog. Please verify and adjust the dates to maintain chronological order.

Comment on lines +129 to +139
public void ValueSetCheck()
{
const int valueCheck1 = 5;
const int valueCheck2 = 6;

_mockDictionary.Add(_key, valueCheck1);
_dictionary[_key] = valueCheck2;

Assert.AreNotEqual(valueCheck1, _mockDictionary[_key]);
Assert.AreEqual(valueCheck2, _dictionary[_key]);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure consistent test method naming conventions

The test method ValueSetCheck does not follow the naming convention used in other test methods. For clarity and consistency, consider renaming it to ValueSet_UpdatesUnderlyingDictionary or ValueSet_UpdatesValueSuccessfully to match the Method_Scenario_ExpectedResult pattern.

Comment on lines +142 to 159
public void ObserveCheck()
{
var startValue = 0;
var newValue = 1;

_dictionary.Observe(_key, _caller.Call);
_dictionary.Observe(_caller.Call);

_dictionary.Add(_key, startValue);

_dictionary[_key] = newValue;

_dictionary.Remove(_key);

_caller.Received().Call(_key, 0, startValue, ObservableUpdateType.Added);
_caller.Received().Call(_key, startValue, newValue, ObservableUpdateType.Updated);
_caller.Received().Call(_key, newValue, 0, ObservableUpdateType.Removed);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure consistent test method naming conventions

The test method ObserveCheck differs from the naming convention used elsewhere. To enhance readability, consider renaming it to Observe_NotifiesObservers_OnChanges or similar, aligning with the Method_Scenario_ExpectedResult format.

Comment on lines +214 to +225
public bool Remove(T data)
{
var idx = List.IndexOf(data);

if (idx >= 0)
{
RemoveAt(idx);

return true;
}

return false;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider marking the Remove method as virtual for consistency

In the ObservableList<T> class, the Add, RemoveAt, and Clear methods are marked as virtual, allowing derived classes to override them. However, the Remove method is not marked as virtual. For consistency and extensibility, consider marking Remove as virtual.

Apply this diff:

-public bool Remove(T data)
+public virtual bool Remove(T data)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public bool Remove(T data)
{
var idx = List.IndexOf(data);
if (idx >= 0)
{
RemoveAt(idx);
return true;
}
return false;
public virtual bool Remove(T data)
{
var idx = List.IndexOf(data);
if (idx >= 0)
{
RemoveAt(idx);
return true;
}
return false;

public override void Clear()
{
_dictionary.Clear();
base.Clear(); ;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove duplicate semicolon to fix syntax error

There's a duplicate semicolon on this line:

	base.Clear(); ;

This will cause a syntax error. Remove the extra semicolon.

Apply this diff to fix the syntax error:

-    base.Clear(); ;
+    base.Clear();

Comment on lines +454 to +461
public override bool Remove(TKey key)
{
var pair = _toOrignResolver(key, Dictionary[key]);

_dictionary.Remove(pair.Key);

return base.Remove(key);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Ensure key exists before accessing Dictionary[key] in Remove method

In the Remove method of ObservableResolverDictionary, you access Dictionary[key] without checking if the key exists. This can lead to a KeyNotFoundException if the key is not present in the dictionary.

Consider verifying that the key exists before accessing it:

	public override bool Remove(TKey key)
	{
+		if (!Dictionary.TryGetValue(key, out var value))
+		{
+			return false;
+		}
-		var pair = _toOrignResolver(key, Dictionary[key]);
+		var pair = _toOrignResolver(key, value);

		_dictionary.Remove(pair.Key);

		return base.Remove(key);
	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public override bool Remove(TKey key)
{
var pair = _toOrignResolver(key, Dictionary[key]);
_dictionary.Remove(pair.Key);
return base.Remove(key);
}
public override bool Remove(TKey key)
{
if (!Dictionary.TryGetValue(key, out var value))
{
return false;
}
var pair = _toOrignResolver(key, value);
_dictionary.Remove(pair.Key);
return base.Remove(key);
}

Comment on lines +438 to +444
public void UpdateOrigin(TKeyOrigin key, TValueOrigin value)
{
var convertPair = _fromOrignResolver(new KeyValuePair<TKeyOrigin, TValueOrigin>(key, value));

_dictionary[key] = value;
this[convertPair.Key] = convertPair.Value;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Check for existence of origin key before updating in UpdateOrigin method

In the UpdateOrigin method, you update _dictionary[key] without verifying if the key exists. Assigning to a non-existent key will add a new entry, which might not be intended.

Consider adding a check to ensure the key exists before updating:

	public void UpdateOrigin(TKeyOrigin key, TValueOrigin value)
	{
		var convertPair = _fromOrignResolver(new KeyValuePair<TKeyOrigin, TValueOrigin>(key, value));

+		if (!_dictionary.ContainsKey(key))
+		{
+			throw new KeyNotFoundException($"The key '{key}' does not exist in the origin dictionary.");
+		}
		_dictionary[key] = value;
		this[convertPair.Key] = convertPair.Value;
	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public void UpdateOrigin(TKeyOrigin key, TValueOrigin value)
{
var convertPair = _fromOrignResolver(new KeyValuePair<TKeyOrigin, TValueOrigin>(key, value));
_dictionary[key] = value;
this[convertPair.Key] = convertPair.Value;
}
public void UpdateOrigin(TKeyOrigin key, TValueOrigin value)
{
var convertPair = _fromOrignResolver(new KeyValuePair<TKeyOrigin, TValueOrigin>(key, value));
if (!_dictionary.ContainsKey(key))
{
throw new KeyNotFoundException($"The key '{key}' does not exist in the origin dictionary.");
}
_dictionary[key] = value;
this[convertPair.Key] = convertPair.Value;
}

Comment on lines +403 to +418
private readonly IDictionary<TKeyOrigin, TValueOrigin> _dictionary;
private readonly Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> _toOrignResolver;
private readonly Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> _fromOrignResolver;

protected override IDictionary<TKey, TValue> Dictionary => _dictionaryResolver();
/// <inheritdoc />
public ReadOnlyDictionary<TKeyOrigin, TValueOrigin> OriginDictionary => new ReadOnlyDictionary<TKeyOrigin, TValueOrigin>(_dictionary);

public ObservableResolverDictionary(Func<IDictionary<TKey, TValue>> dictionaryResolver)
public ObservableResolverDictionary(IDictionary<TKeyOrigin, TValueOrigin> dictionary,
Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> fromOrignResolver,
Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> toOrignResolver)
: base(new Dictionary<TKey, TValue>(dictionary.Count))
{
_dictionary = dictionary;
_toOrignResolver = toOrignResolver;
_fromOrignResolver = fromOrignResolver;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct spelling of field names _toOrignResolver and _fromOrignResolver to _toOriginResolver and _fromOriginResolver

The field names _toOrignResolver and _fromOrignResolver contain a misspelling of the word "Origin".

Rename the fields to correct the spelling and update all references:

-	private readonly Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> _toOrignResolver;
-	private readonly Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> _fromOrignResolver;
+	private readonly Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> _toOriginResolver;
+	private readonly Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> _fromOriginResolver;

Ensure that you also update these field names throughout the class.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private readonly IDictionary<TKeyOrigin, TValueOrigin> _dictionary;
private readonly Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> _toOrignResolver;
private readonly Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> _fromOrignResolver;
protected override IDictionary<TKey, TValue> Dictionary => _dictionaryResolver();
/// <inheritdoc />
public ReadOnlyDictionary<TKeyOrigin, TValueOrigin> OriginDictionary => new ReadOnlyDictionary<TKeyOrigin, TValueOrigin>(_dictionary);
public ObservableResolverDictionary(Func<IDictionary<TKey, TValue>> dictionaryResolver)
public ObservableResolverDictionary(IDictionary<TKeyOrigin, TValueOrigin> dictionary,
Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> fromOrignResolver,
Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> toOrignResolver)
: base(new Dictionary<TKey, TValue>(dictionary.Count))
{
_dictionary = dictionary;
_toOrignResolver = toOrignResolver;
_fromOrignResolver = fromOrignResolver;
private readonly IDictionary<TKeyOrigin, TValueOrigin> _dictionary;
private readonly Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> _toOriginResolver;
private readonly Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> _fromOriginResolver;
/// <inheritdoc />
public ReadOnlyDictionary<TKeyOrigin, TValueOrigin> OriginDictionary => new ReadOnlyDictionary<TKeyOrigin, TValueOrigin>(_dictionary);
public ObservableResolverDictionary(IDictionary<TKeyOrigin, TValueOrigin> dictionary,
Func<KeyValuePair<TKeyOrigin, TValueOrigin>, KeyValuePair<TKey, TValue>> fromOrignResolver,
Func<TKey, TValue, KeyValuePair<TKeyOrigin, TValueOrigin>> toOrignResolver)
: base(new Dictionary<TKey, TValue>(dictionary.Count))
{
_dictionary = dictionary;
_toOriginResolver = toOrignResolver;
_fromOriginResolver = fromOrignResolver;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant