Skip to content

Refactor XmlMapStorage enum handling to centralize type-to-string mappings and improve type safety while extending EnumIndexedArray with additional iteration utilities. - #508

Merged
nschimme merged 2 commits into
MUME:masterfrom
nschimme:minor-fix
Apr 8, 2026

Conversation

@nschimme

@nschimme nschimme commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Summary by Sourcery

Refactor XmlMapStorage enum handling to centralize type-to-string mappings and improve type safety while extending EnumIndexedArray with additional iteration utilities.

Enhancements:

  • Introduce shared macros and helper functions to define XmlMapStorage enum types, validate TypeEnum values, and generate type-name strings consistently.
  • Replace raw index-based containers with EnumIndexedArray-based structures for mapping between enum values and strings, including sanity-check static assertions.
  • Add generic iteration helpers to EnumIndexedArray to support element-wise and index-aware callbacks.

nschimme added 2 commits April 7, 2026 18:41
Enumerator TypeEnum::TypeEnum cannot have the same name as its enclosing enum TypeEnum
@sourcery-ai

sourcery-ai Bot commented Apr 7, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors XmlMapStorage enum type handling to be more type-safe and macro-driven, introducing EnumIndexedArray-based storage, compile-time sanity checks, and helper utilities for mapping between enum values, type tags, and strings, plus small enhancements to EnumIndexedArray iteration utilities.

Class diagram for updated XmlMapStorage enum handling

classDiagram
    direction LR

    class TypeEnum {
        <<enum>>
        RoomAlign
        DoorFlag
        ExitFlag
        RoomLight
        RoomLoadFlag
        InfomarkClass
        InfomarkType
        RoomMobFlag
        RoomPortable
        RoomRidable
        RoomSundeath
        RoomTerrain
        Type
    }

    class SanityCheckEnum {
        <<enum>>
        RoomAlign
        DoorFlag
        ExitFlag
        RoomLight
        RoomLoadFlag
        InfomarkClass
        InfomarkType
        RoomMobFlag
        RoomPortable
        RoomRidable
        RoomSundeath
        RoomTerrain
        Type
    }

    class EnumIndexedArray~T,E,SIZE~ {
        - MMapper::Array~T,SIZE~ base
        + EnumIndexedArray()
        + T& at(E index)
        + const T& at(E index) const
        + T& operator[] (E index)
        + const T& operator[] (E index) const
        + size_t size() const
        + iterator begin()
        + iterator end()
        + const_iterator begin() const
        + const_iterator end() const
        + bool operator== (EnumIndexedArray other) const
        + bool operator!= (EnumIndexedArray other) const
        + void for_each(Callback callback)
        + void for_each(Callback callback) const
        + void for_each2(Callback callback)
        + void for_each2(Callback callback) const
    }

    class TypeEnumArray~T~ {
    }

    class Converter {
        - EnumToStrings m_enumToStrings
        - TypeEnumArray~QHash<QStringView,uint32_t>~ m_stringToEnums
        + Converter()
        + ~Converter()
        + void DELETE_CTORS_AND_ASSIGN_OPS()
        + template parseNumber~T~(QStringView str) : std::optional~T~
        + template fromString~ENUM~(QStringView str) : std::optional~ENUM~
        + template toString~ENUM~(ENUM val) : const char*
        - std::optional~uint32_t~ stringToEnum(TypeEnum type, QStringView str) const
        - const QString& enumToString(TypeEnum type, uint32_t val) const
    }

    class XmlMapStorage {
        + class Converter
    }

    TypeEnumArray~T~ --|> EnumIndexedArray~T,TypeEnum,NUM_XMLMAPSTORAGE_TYPE~

    class EnumToStrings {
    }

    EnumToStrings --|> TypeEnumArray~std::vector<QString>~

    Converter --> EnumToStrings : uses
    Converter --> TypeEnumArray~QHash<QStringView,uint32_t>~ : uses
    Converter ..> TypeEnum : indexes
    Converter ..> EnumIndexedArray~T,E,SIZE~ : relies on

    SanityCheckEnum ..> TypeEnum : compile_time_alignment

    class Utilities {
        + bool isValid(TypeEnum type)
        + constexpr TypeEnum enumToType(RoomAlignEnum val)
        + constexpr TypeEnum enumToType(DoorFlagEnum val)
        + constexpr TypeEnum enumToType(ExitFlagEnum val)
        + constexpr TypeEnum enumToType(RoomLightEnum val)
        + constexpr TypeEnum enumToType(RoomLoadFlagEnum val)
        + constexpr TypeEnum enumToType(InfomarkClassEnum val)
        + constexpr TypeEnum enumToType(InfomarkTypeEnum val)
        + constexpr TypeEnum enumToType(RoomMobFlagEnum val)
        + constexpr TypeEnum enumToType(RoomPortableEnum val)
        + constexpr TypeEnum enumToType(RoomRidableEnum val)
        + constexpr TypeEnum enumToType(RoomSundeathEnum val)
        + constexpr TypeEnum enumToType(RoomTerrainEnum val)
        + constexpr TypeEnum enumToType(TypeEnum val)
        + constexpr const char* to_c_string(TypeEnum val)
        + EnumToStrings initEnumToStrings()
    }

    Utilities ..> TypeEnum
    Utilities ..> EnumToStrings
    Utilities ..> EnumIndexedArray~T,E,SIZE~
Loading

File-Level Changes

Change Details Files
Replace hard-coded enum/string mapping tables in XmlMapStorage with macro-generated TypeEnum metadata, type-safe arrays, and helper functions.
  • Redefine XFOREACH_TYPE_ENUM to list base type names (e.g. RoomAlign, DoorFlag) instead of full enum type names, and add XFOREACH_CONVERTER to associate each type with its value lists and declaration styles.
  • Introduce TYPE_NAME_* helper macros and a global isValid(TypeEnum) to centralize validity checks and naming conventions for TypeEnum and related enums.
  • Add SanityCheckEnum and static_asserts to verify that XFOREACH_TYPE_ENUM and XFOREACH_CONVERTER stay in sync and that the number of listed types matches NUM_XMLMAPSTORAGE_TYPE.
  • Generate enumToType overloads and a to_c_string(TypeEnum) function via macros, with static_asserts validating expected mappings and string names.
  • Introduce TypeEnumArray and EnumToStrings aliases using EnumIndexedArray, along with initEnumToStrings() that macro-generates the enum-to-string vectors at construction time.
  • Update Converter to use EnumToStrings and TypeEnumArray-based m_stringToEnums, make the constructor explicit, delete copy/move operations, and build string-to-enum maps via EnumIndexedArray::for_each2 instead of raw index iteration.
  • Refactor Converter::enumToString and stringToEnum to use isValid(type) and EnumIndexedArray indexing by TypeEnum instead of manual size/index checks and to tweak warning messages slightly.
  • Undefine new macro helpers at the end of the file to avoid leakage.
src/mapstorage/XmlMapStorage.cpp
Extend EnumIndexedArray with additional iteration helpers used by XmlMapStorage.
  • Add const for_each method overload to iterate over elements in a const context with a callback.
  • Add for_each2 overloads (const and non-const) that iterate by index, casting each index back to the enum type E and passing (E, reference-to-element) to the callback.
src/global/EnumIndexedArray.h

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • In EnumIndexedArray::for_each2 the loop uses SIZE rather than the template parameter SIZE_ (as used elsewhere in the class), which will either fail to compile or pick up an unintended symbol; this should be changed to SIZE_ for consistency and correctness.
  • EnumIndexedArray now has four similar traversal helpers (for_each/for_each2 const and non-const); consider reducing duplication by having the const overloads call the non-const versions or vice versa, and possibly choosing clearer names that distinguish between element-only and (enum, element) callbacks.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In EnumIndexedArray::for_each2 the loop uses SIZE rather than the template parameter SIZE_ (as used elsewhere in the class), which will either fail to compile or pick up an unintended symbol; this should be changed to SIZE_ for consistency and correctness.
- EnumIndexedArray now has four similar traversal helpers (for_each/for_each2 const and non-const); consider reducing duplication by having the const overloads call the non-const versions or vice versa, and possibly choosing clearer names that distinguish between element-only and (enum, element) callbacks.

## Individual Comments

### Comment 1
<location path="src/mapstorage/XmlMapStorage.cpp" line_range="87-89" />
<code_context>
+
+// clang-format on
+
+#define TYPE_NAME_ENUM_VALUE(_x) (TypeEnum::_x)
+#define TYPE_NAME_ENUM_TYPE(_x) _x##Enum
+#define TYPE_NAME_C_STRING(_x) (#_x "Enum")

 namespace { // anonymous
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The helper TYPE_NAME_* macros are never undefined, which can inadvertently affect later code in this translation unit.

These helper macros are defined here but not undefined later in the file, unlike `XFOREACH_TYPE_ENUM` and `XFOREACH_CONVERTER`. This increases the risk of accidental reuse or name collisions elsewhere in the TU.

Please add `#undef` for `TYPE_NAME_ENUM_VALUE`, `TYPE_NAME_ENUM_TYPE`, and `TYPE_NAME_C_STRING` once they’re no longer needed (e.g., at the end of the file) to keep the macro namespace local.

Suggested implementation:

```cpp
namespace { // anonymous

```

` section.

Here are the edit blocks:

<file_operations>
<file_operation operation="edit" file_path="src/mapstorage/XmlMapStorage.cpp">
<<<<<<< SEARCH
namespace { // anonymous
=======
namespace { // anonymous
>>>>>>> REPLACE
</file_operation>
</file_operations>

<additional_changes>
Please append the following block *after the last use* of the helper macros (typically near the end of `XmlMapStorage.cpp`, e.g., just before the final closing brace or before other unrelated includes/definitions):

```cpp
#undef TYPE_NAME_ENUM_VALUE
#undef TYPE_NAME_ENUM_TYPE
#undef TYPE_NAME_C_STRING
```

This will ensure `TYPE_NAME_ENUM_VALUE`, `TYPE_NAME_ENUM_TYPE`, and `TYPE_NAME_C_STRING` are confined to this file’s local usage and cannot accidentally affect later code in the same translation unit. If the file has a clear “end-of-file” comment or a final function/namespace closing brace, place the `#undef` block immediately before that.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +87 to +89
#define TYPE_NAME_ENUM_VALUE(_x) (TypeEnum::_x)
#define TYPE_NAME_ENUM_TYPE(_x) _x##Enum
#define TYPE_NAME_C_STRING(_x) (#_x "Enum")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): The helper TYPE_NAME_* macros are never undefined, which can inadvertently affect later code in this translation unit.

These helper macros are defined here but not undefined later in the file, unlike XFOREACH_TYPE_ENUM and XFOREACH_CONVERTER. This increases the risk of accidental reuse or name collisions elsewhere in the TU.

Please add #undef for TYPE_NAME_ENUM_VALUE, TYPE_NAME_ENUM_TYPE, and TYPE_NAME_C_STRING once they’re no longer needed (e.g., at the end of the file) to keep the macro namespace local.

Suggested implementation:

namespace { // anonymous

` section.

Here are the edit blocks:

<file_operations>
<file_operation operation="edit" file_path="src/mapstorage/XmlMapStorage.cpp">
<<<<<<< SEARCH
namespace { // anonymous

namespace { // anonymous

REPLACE
</file_operation>
</file_operations>

<additional_changes>
Please append the following block after the last use of the helper macros (typically near the end of XmlMapStorage.cpp, e.g., just before the final closing brace or before other unrelated includes/definitions):

#undef TYPE_NAME_ENUM_VALUE
#undef TYPE_NAME_ENUM_TYPE
#undef TYPE_NAME_C_STRING

This will ensure TYPE_NAME_ENUM_VALUE, TYPE_NAME_ENUM_TYPE, and TYPE_NAME_C_STRING are confined to this file’s local usage and cannot accidentally affect later code in the same translation unit. If the file has a clear “end-of-file” comment or a final function/namespace closing brace, place the #undef block immediately before that.

@nschimme nschimme changed the title Minor fix Refactor XmlMapStorage enum handling to centralize type-to-string mappings and improve type safety while extending EnumIndexedArray with additional iteration utilities. Apr 7, 2026
@nschimme
nschimme merged commit 22c72d2 into MUME:master Apr 8, 2026
18 checks passed
@nschimme
nschimme deleted the minor-fix branch April 8, 2026 00:12
@codecov

codecov Bot commented Apr 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 25.06%. Comparing base (93d43e3) to head (c4b2f25).
⚠️ Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
src/mapstorage/XmlMapStorage.cpp 0.00% 20 Missing ⚠️
src/global/EnumIndexedArray.h 0.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #508      +/-   ##
==========================================
- Coverage   25.06%   25.06%   -0.01%     
==========================================
  Files         510      510              
  Lines       42275    42281       +6     
  Branches     4574     4572       -2     
==========================================
  Hits        10596    10596              
- Misses      31679    31685       +6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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