Skip to content

Conversation

rmunn
Copy link
Contributor

@rmunn rmunn commented Jul 29, 2025

Fixes #1846.

Implemented:

  • Creating entries with the right morph type.
    • Switching morph types in FW Lite not allowed, so setting it at creation is all that's needed
  • Create, Update, etc. APIs in MiniLcmApi, implemented in FwMiniLcmApi
    • CrdtMiniLcmApi versions throw NotImplemented.
    • Create and Delete not allowed (morph types are fixed and should never be different between projects), so FwData implementations silently ignore the operation rather than throwing

@rmunn rmunn self-assigned this Jul 29, 2025
Copy link

coderabbitai bot commented Jul 29, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

This change introduces the MorphType model and associated CRUD API endpoints, mapping FieldWorks morph types to an enum and data object. It adds conversion logic, updates entry creation and representation to include morph type, and implements diff-based synchronization. The CRDT API stubs morph type operations with NotImplementedException.

Changes

Cohort / File(s) Change Summary
MorphType Model & Enum
backend/FwLite/MiniLcm/Models/MorphType.cs, frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/MorphType.ts
Introduces the MorphType enum and the MorphTypeData class in backend and frontend, modeling morph types with properties and serialization.
API: MorphTypeData CRUD & Mapping
backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs, backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs, backend/FwLite/MiniLcm/IMiniLcmReadApi.cs, backend/FwLite/MiniLcm/IMiniLcmWriteApi.cs
Adds CRUD methods for MorphTypeData to APIs, implements logic in FwDataMiniLcmApi, and stubs in CrdtMiniLcmApi. Extends read/write interfaces.
Conversion & Helper Logic
backend/FwLite/FwDataMiniLcmBridge/Api/LcmHelpers.cs
Adds mapping between Guid and MorphType, updates entry/lexeme creation to be morph-type aware, and introduces helper methods for morph type checks.
Entry Model & Integration
backend/FwLite/MiniLcm/Models/Entry.cs, frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/IEntry.ts, backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateEntryProxy.cs
Adds MorphType property to entry models and integrates morph type into entry creation and update proxies.
Sync & Diff Logic
backend/FwLite/MiniLcm/SyncHelpers/MorphTypeDataSync.cs, backend/FwLite/MiniLcm/SyncHelpers/IntegerDiff.cs
Introduces diff and sync logic for MorphTypeData, enabling patch-based updates and collection synchronization.
Proxy Class for MorphTypeData
backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateMorphTypeDataProxy.cs
Adds a proxy class for update operations on MorphTypeData entities, wrapping underlying FW objects.
Type Generation Config
backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs
Configures type generation for the new MorphType enum as a string enum for frontend consumption.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Model morph type as enum and class, mapping from FW Data (#1846)
Implement CRUD API for MorphTypeData (Create, Delete, Update, List, GetByKind) (#1846)
Map morph type into entries (#1846)
CRDT API can throw for now (#1846)

Possibly related PRs

Poem

In fields of code where morphs reside,
A rabbit hops with enum pride.
New types and tokens now abound,
MorphTypeData’s all around!
Entries know their morphing kin,
Sync and patches neatly spin.
🐇 Hooray for morphs, let changes begin!

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/minilcm-morph-types

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@github-actions github-actions bot added the 💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related label Jul 29, 2025
Copy link

argos-ci bot commented Jul 29, 2025

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Aug 14, 2025, 4:08 AM

Copy link

github-actions bot commented Jul 29, 2025

UI unit Tests

  1 files  ±0   40 suites  ±0   22s ⏱️ -1s
 82 tests ±0   82 ✅ ±0  0 💤 ±0  0 ❌ ±0 
116 runs  ±0  116 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit fc34c25. ± Comparison against base commit 6bd027b.

♻️ This comment has been updated with latest results.

@rmunn rmunn changed the title Add MorphType enum and MorphTypeData class Add morph types to MiniLcm Jul 29, 2025
Copy link

github-actions bot commented Jul 29, 2025

C# Unit Tests

130 tests   130 ✅  19s ⏱️
 20 suites    0 💤
  1 files      0 ❌

Results for commit fc34c25.

♻️ This comment has been updated with latest results.

@rmunn rmunn marked this pull request as ready for review July 29, 2025 09:02
@rmunn
Copy link
Contributor Author

rmunn commented Jul 29, 2025

I think that's everything. @hahn-kev - Want to bikeshed my choice of MorphType for the enum and MorphTypeData for the class with the name, abbreviation, etc? I'd like to nail down the naming before I go much farther, or there will be a lot of code to rename.

@rmunn rmunn requested a review from hahn-kev July 29, 2025 09:03
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: 1

🧹 Nitpick comments (1)
backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateEntryProxy.cs (1)

42-46: Consider consistent behavior for getter and setter.

The MorphType property has inconsistent behavior - the getter throws NotImplementedException while the setter only logs a message. For better consistency and clearer intent, consider either implementing both operations or having both throw NotImplementedException.

If this is temporary (as the comment suggests), consider using the same approach for both:

 public override MorphType MorphType
 {
-    get => throw new NotImplementedException();
-    set => Console.WriteLine("setting MorphType not implemented"); // Not throwing, for now
+    get => throw new NotImplementedException("MorphType getter not implemented");
+    set => throw new NotImplementedException("MorphType setter not implemented");
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b21e444 and e4847c0.

📒 Files selected for processing (14)
  • backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs (3 hunks)
  • backend/FwLite/FwDataMiniLcmBridge/Api/LcmHelpers.cs (2 hunks)
  • backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateEntryProxy.cs (2 hunks)
  • backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateMorphTypeDataProxy.cs (1 hunks)
  • backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs (1 hunks)
  • backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs (1 hunks)
  • backend/FwLite/MiniLcm/IMiniLcmReadApi.cs (1 hunks)
  • backend/FwLite/MiniLcm/IMiniLcmWriteApi.cs (1 hunks)
  • backend/FwLite/MiniLcm/Models/Entry.cs (2 hunks)
  • backend/FwLite/MiniLcm/Models/MorphType.cs (1 hunks)
  • backend/FwLite/MiniLcm/SyncHelpers/IntegerDiff.cs (1 hunks)
  • backend/FwLite/MiniLcm/SyncHelpers/MorphTypeDataSync.cs (1 hunks)
  • frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/IEntry.ts (2 hunks)
  • frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/MorphType.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (13)
backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs (2)

Learnt from: rmunn
PR: #1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:19:37.386Z
Learning: In the sillsdev/languageforge-lexbox project, when file size limits or other constants need to be shared between C# backend and TypeScript frontend code, prefer exposing them through Reinforced.Typings type generation rather than hardcoding the values separately. This ensures consistency and prevents discrepancies when values change.

Learnt from: rmunn
PR: #1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:20:03.040Z
Learning: The user wants to share the 10MB file size limit constant between C# and TypeScript using Reinforced.Typings to ensure consistency and prevent hardcoding discrepancies like the current typo (1034 vs 1024).

frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/IEntry.ts (4)

Learnt from: rmunn
PR: #1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:19:37.386Z
Learning: In the sillsdev/languageforge-lexbox project, when file size limits or other constants need to be shared between C# backend and TypeScript frontend code, prefer exposing them through Reinforced.Typings type generation rather than hardcoding the values separately. This ensures consistency and prevents discrepancies when values change.

Learnt from: rmunn
PR: #1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:20:03.040Z
Learning: The user wants to share the 10MB file size limit constant between C# and TypeScript using Reinforced.Typings to ensure consistency and prevent hardcoding discrepancies like the current typo (1034 vs 1024).

Learnt from: myieye
PR: #1536
File: backend/FwLite/LcmCrdt/Changes/CreateSenseChange.cs:43-44
Timestamp: 2025-03-17T13:16:24.769Z
Learning: In the SIL FieldWorks Language Explorer (FLEx) system, only certain fields support rich text formatting (embedded styles): Definition, Example sentences, Translations, Notes, and Literal meaning fields. Other fields like Gloss, Lexeme form, and Citation form are plain text only. The codebase reflects this distinction by using RichMultiString for rich-text capable fields and MultiString for plain text fields.

Learnt from: myieye
PR: #1536
File: backend/FwLite/LcmCrdt/Changes/CreateSenseChange.cs:43-44
Timestamp: 2025-03-17T13:16:24.769Z
Learning: In the SIL FieldWorks Language Explorer (FLEx) system, only certain fields support rich text formatting (embedded styles): Definition, Example sentence, Translation, Note, and Literal meaning fields. Other fields like Gloss, Lexeme form, and Citation form are plain text only. The codebase reflects this by using RichMultiString for rich-text capable fields and MultiString for plain text fields.

backend/FwLite/MiniLcm/IMiniLcmReadApi.cs (1)

Learnt from: hahn-kev
PR: #1760
File: backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs:274-277
Timestamp: 2025-06-27T09:24:39.507Z
Learning: In the CrdtMiniLcmApi class, the user prefers to keep the current AddChanges method signature (IEnumerable) rather than modifying it to support IAsyncEnumerable for streaming, even when it means materializing collections into memory for bulk operations.

frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/MorphType.ts (2)

Learnt from: rmunn
PR: #1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:19:37.386Z
Learning: In the sillsdev/languageforge-lexbox project, when file size limits or other constants need to be shared between C# backend and TypeScript frontend code, prefer exposing them through Reinforced.Typings type generation rather than hardcoding the values separately. This ensures consistency and prevents discrepancies when values change.

Learnt from: rmunn
PR: #1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:20:03.040Z
Learning: The user wants to share the 10MB file size limit constant between C# and TypeScript using Reinforced.Typings to ensure consistency and prevent hardcoding discrepancies like the current typo (1034 vs 1024).

backend/FwLite/MiniLcm/Models/Entry.cs (2)

Learnt from: myieye
PR: #1536
File: backend/FwLite/LcmCrdt/Changes/CreateSenseChange.cs:43-44
Timestamp: 2025-03-17T13:16:24.769Z
Learning: In the SIL FieldWorks Language Explorer (FLEx) system, only certain fields support rich text formatting (embedded styles): Definition, Example sentences, Translations, Notes, and Literal meaning fields. Other fields like Gloss, Lexeme form, and Citation form are plain text only. The codebase reflects this distinction by using RichMultiString for rich-text capable fields and MultiString for plain text fields.

Learnt from: myieye
PR: #1536
File: backend/FwLite/LcmCrdt/Changes/CreateSenseChange.cs:43-44
Timestamp: 2025-03-17T13:16:24.769Z
Learning: In the SIL FieldWorks Language Explorer (FLEx) system, only certain fields support rich text formatting (embedded styles): Definition, Example sentence, Translation, Note, and Literal meaning fields. Other fields like Gloss, Lexeme form, and Citation form are plain text only. The codebase reflects this by using RichMultiString for rich-text capable fields and MultiString for plain text fields.

backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateEntryProxy.cs (1)

Learnt from: rmunn
PR: #1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:19:37.386Z
Learning: In the sillsdev/languageforge-lexbox project, when file size limits or other constants need to be shared between C# backend and TypeScript frontend code, prefer exposing them through Reinforced.Typings type generation rather than hardcoding the values separately. This ensures consistency and prevents discrepancies when values change.

backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateMorphTypeDataProxy.cs (1)

Learnt from: hahn-kev
PR: #1836
File: backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/MediaTests.cs:28-33
Timestamp: 2025-07-29T07:10:53.376Z
Learning: In test code for FwData-specific functionality (like MediaTests in FwDataMiniLcmBridge.Tests), direct casting to FwDataMiniLcmApi is preferred over safe casting because it serves as an assertion that the test setup is correct. If the cast fails, it indicates a test configuration bug that should be caught immediately rather than silently ignored.

backend/FwLite/FwDataMiniLcmBridge/Api/LcmHelpers.cs (2)

Learnt from: rmunn
PR: #1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:19:37.386Z
Learning: In the sillsdev/languageforge-lexbox project, when file size limits or other constants need to be shared between C# backend and TypeScript frontend code, prefer exposing them through Reinforced.Typings type generation rather than hardcoding the values separately. This ensures consistency and prevents discrepancies when values change.

Learnt from: rmunn
PR: #1795
File: backend/FwLite/MiniLcm/Validators/PublicationValidator.cs:15-23
Timestamp: 2025-07-03T09:52:39.059Z
Learning: In the sillsdev/languageforge-lexbox project, MultiString objects have a custom .ToString() method that joins all strings in the MultiString with ", ". When generating identifiers for publications, the code intentionally uses MultiString.ToString() to show all names from different writing systems, not just the first one.

backend/FwLite/MiniLcm/IMiniLcmWriteApi.cs (1)

Learnt from: hahn-kev
PR: #1760
File: backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs:274-277
Timestamp: 2025-06-27T09:24:39.507Z
Learning: In the CrdtMiniLcmApi class, the user prefers to keep the current AddChanges method signature (IEnumerable) rather than modifying it to support IAsyncEnumerable for streaming, even when it means materializing collections into memory for bulk operations.

backend/FwLite/MiniLcm/Models/MorphType.cs (2)

Learnt from: rmunn
PR: #1836
File: frontend/viewer/src/lib/components/audio/AudioDialog.svelte:25-25
Timestamp: 2025-07-22T09:19:37.386Z
Learning: In the sillsdev/languageforge-lexbox project, when file size limits or other constants need to be shared between C# backend and TypeScript frontend code, prefer exposing them through Reinforced.Typings type generation rather than hardcoding the values separately. This ensures consistency and prevents discrepancies when values change.

Learnt from: hahn-kev
PR: #1609
File: backend/FwLite/LcmCrdt/CompiledModels/ComplexFormComponentEntityType.cs:138-182
Timestamp: 2025-04-17T02:52:44.986Z
Learning: Files in the LcmCrdt.CompiledModels namespace contain auto-generated Entity Framework Core model code that should be ignored during code reviews since they shouldn't be manually modified.

backend/FwLite/MiniLcm/SyncHelpers/MorphTypeDataSync.cs (1)

Learnt from: hahn-kev
PR: #1760
File: backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs:274-277
Timestamp: 2025-06-27T09:24:39.507Z
Learning: In the CrdtMiniLcmApi class, the user prefers to keep the current AddChanges method signature (IEnumerable) rather than modifying it to support IAsyncEnumerable for streaming, even when it means materializing collections into memory for bulk operations.

backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs (2)

Learnt from: hahn-kev
PR: #1760
File: backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs:274-277
Timestamp: 2025-06-27T09:24:39.507Z
Learning: In the CrdtMiniLcmApi class, the user prefers to keep the current AddChanges method signature (IEnumerable) rather than modifying it to support IAsyncEnumerable for streaming, even when it means materializing collections into memory for bulk operations.

Learnt from: hahn-kev
PR: #1609
File: backend/FwLite/LcmCrdt/CompiledModels/ComplexFormComponentEntityType.cs:138-182
Timestamp: 2025-04-17T02:52:44.986Z
Learning: Files in the LcmCrdt.CompiledModels namespace contain auto-generated Entity Framework Core model code that should be ignored during code reviews since they shouldn't be manually modified.

backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs (2)

Learnt from: hahn-kev
PR: #1836
File: backend/FwLite/FwDataMiniLcmBridge.Tests/MiniLcmTests/MediaTests.cs:28-33
Timestamp: 2025-07-29T07:10:53.376Z
Learning: In test code for FwData-specific functionality (like MediaTests in FwDataMiniLcmBridge.Tests), direct casting to FwDataMiniLcmApi is preferred over safe casting because it serves as an assertion that the test setup is correct. If the cast fails, it indicates a test configuration bug that should be caught immediately rather than silently ignored.

Learnt from: hahn-kev
PR: #1760
File: backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs:274-277
Timestamp: 2025-06-27T09:24:39.507Z
Learning: In the CrdtMiniLcmApi class, the user prefers to keep the current AddChanges method signature (IEnumerable) rather than modifying it to support IAsyncEnumerable for streaming, even when it means materializing collections into memory for bulk operations.

🔇 Additional comments (28)
backend/FwLite/FwLiteShared/TypeGen/ReinforcedFwLiteTypingConfig.cs (1)

133-133: LGTM! Proper enum export configuration.

The addition follows the established pattern for exporting enums as string types, ensuring consistent type safety between the C# backend and TypeScript frontend for the new MorphType functionality.

frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/IEntry.ts (2)

9-9: LGTM! Correct import for MorphType.

The import statement properly adds the MorphType type dependency for the new morphType property.


22-22: LGTM! Property addition aligns with backend changes.

The new morphType property correctly reflects the MorphType property added to the Entry model in the backend, maintaining type consistency across the stack.

backend/FwLite/MiniLcm/Models/Entry.cs (2)

53-53: LGTM! Copy method properly updated.

The Copy method correctly includes the new MorphType property, maintaining the integrity of the copy operation.


13-13: Enum default verified: Unknown = 0

The MorphType enum in backend/FwLite/MiniLcm/Models/MorphType.cs correctly declares Unknown as its first member, so any uninitialized MorphType property will default to Unknown. No changes are needed.

• File: backend/FwLite/MiniLcm/Models/MorphType.cs
Lines 6–16:

public enum MorphType
{
    Unknown,
    BoundRoot,
    BoundStem,
    Circumfix,
    Clitic,
    Enclitic,
    Infix,
    Particle,
    Prefix,
}
backend/FwLite/MiniLcm/IMiniLcmReadApi.cs (2)

15-15: LGTM! Method signature follows established patterns.

The GetAllMorphTypeData method correctly uses IAsyncEnumerable for efficient streaming, consistent with other collection retrieval methods in the interface.


17-17: LGTM! Proper single-item retrieval method.

The GetMorphTypeData method follows the established pattern for single-item retrieval with nullable return type and Guid parameter, maintaining consistency with other similar methods.

frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/MorphType.ts (1)

6-28: ✅ MorphType enum matches C# definition

I’ve compared the generated TypeScript enum in
frontend/viewer/src/lib/dotnet-types/generated-types/MiniLcm/Models/MorphType.ts
against the backend C# enum in
backend/FwLite/MiniLcm/Models/MorphType.cs. They are identical and, since this file is auto-generated via Reinforced.Typings, it will stay in sync with the source. No further action required.

backend/FwLite/MiniLcm/IMiniLcmWriteApi.cs (1)

38-50: LGTM! Consistent API design with good organization.

The new MorphType CRUD operations follow the established patterns used for other entities in the API. The addition of region blocks for both ComplexFormType and MorphType improves code organization and readability.

backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateEntryProxy.cs (1)

24-24: LGTM! Proper integration of morph type awareness.

The lexeme form creation now correctly uses the morph type information from the LCM entry, which aligns with the new morph type support throughout the system.

backend/FwLite/MiniLcm/Models/MorphType.cs (3)

5-29: LGTM! Comprehensive morph type enumeration.

The enum provides a thorough set of morphological categories with proper JSON serialization support. The variety of morph types covers standard linguistic analysis needs well.


53-67: LGTM! Proper deep copy implementation.

The Copy() method correctly performs deep copies of all properties, including the multilingual strings and preserving the deletion timestamp.


44-51: No action required: MorphType has no entity references

The empty implementations of GetReferences() and RemoveReference() in MorphType are intentional—this model doesn’t reference any other entities. This is consistent with other “leaf” models (e.g., Publication, WritingSystem, SemanticDomain, Entry, ComplexFormType) that likewise return an empty array and no-op RemoveReference.

backend/FwLite/FwDataMiniLcmBridge/Api/UpdateProxy/UpdateMorphTypeDataProxy.cs (1)

6-53: LGTM! Well-implemented proxy following established patterns.

The proxy correctly wraps IMoMorphType and maps its properties to the MorphTypeData interface. The property mappings are logical (e.g., PrefixLeadingToken, PostfixTrailingToken), and the implementation follows the same pattern as other UpdateProxy classes in the codebase.

backend/FwLite/LcmCrdt/CrdtMiniLcmApi.cs (1)

340-368: LGTM! Consistent stub implementation as intended.

The MorphTypeData method stubs correctly follow the established pattern for unimplemented CRDT operations in this class. All methods appropriately throw NotImplementedException, which aligns with the PR objectives stating that CRDT API implementations are not included in this issue and are planned for future work.

backend/FwLite/FwDataMiniLcmBridge/Api/LcmHelpers.cs (4)

86-113: LGTM! Comprehensive GUID to MorphType conversion.

The pattern matching approach correctly handles all known MorphType values from MoMorphTypeTags. The fallback to MorphType.Other for unrecognized GUIDs and MorphType.Unknown for null values provides proper error handling.


115-142: LGTM! Reverse conversion with appropriate null handling.

The conversion correctly maps MorphType enum values back to their corresponding GUIDs. The comment on line 139 appropriately documents the non-round-trip behavior for MorphType.Other, which is the expected behavior since Other represents unrecognized GUIDs that we cannot map back.


209-235: LGTM! Correct morph type categorization for lexeme form creation.

The IsAffixMorphType method correctly identifies which morphological types should use the affix factory versus the stem factory. The categorization aligns with linguistic principles where circumfixes, infixes, prefixes, suffixes, and their variants are treated as affixes, while everything else uses the stem factory.


237-246: LGTM! Robust entry creation with morph type awareness.

The updated CreateEntry method properly integrates MorphType into the lexeme form creation process. The fallback to MorphType.Stem when conversion returns null (line 243) provides a safe default, and the non-null assertion is justified since ToLcmMorphTypeId(MorphType.Stem) will never return null.

backend/FwLite/MiniLcm/SyncHelpers/MorphTypeDataSync.cs (4)

1-16: LGTM! Standard collection synchronization pattern.

The collection sync method correctly uses the DiffCollection.Diff utility with a custom MorphTypeDataDiffApi to handle bulk synchronization. This follows the established pattern used by other sync helper classes in the codebase.


18-25: LGTM! Efficient individual object synchronization.

The method correctly computes the diff between before and after states, only performing an update if changes are detected. The return value properly reflects whether any changes were made.


27-50: LGTM! Comprehensive property diff generation.

The diff method correctly handles all MorphTypeData properties using appropriate diff utilities:

  • MultiStringDiff for Name, Abbreviation, and Description
  • SimpleStringDiff for LeadingToken and TrailingToken
  • IntegerDiff for SecondaryOrder

The early return when no operations are generated (line 48) optimizes performance by avoiding unnecessary updates.


52-70: LGTM! Proper implementation of collection diff API.

The nested MorphTypeDataDiffApi class correctly implements the required interface methods:

  • Add calls CreateMorphTypeData for new items
  • Remove calls DeleteMorphTypeData for deleted items
  • Replace delegates to the individual sync method for modified items

The implementation follows the established pattern and correctly propagates the API calls.

backend/FwLite/FwDataMiniLcmBridge/Api/FwDataMiniLcmApi.cs (5)

491-505: LGTM! Morph type retrieval methods follow established patterns.

The GetAllMorphTypeData and GetMorphTypeData methods correctly implement the standard repository pattern used throughout the class, with appropriate async enumerable collection handling and nullable single-item retrieval.


507-520: LGTM! Comprehensive morph type conversion implementation.

The FromLcmMorphType conversion method correctly maps all necessary properties from the LCM morph type to the MiniLCM model, following established patterns for multilingual string handling and enum conversion.


522-553: LGTM! CRUD operations correctly implement FwData project constraints.

The implementation correctly handles the constraint that morph types are fixed in FwData projects:

  • Create and Delete operations silently ignore requests (as documented in PR objectives)
  • Update operations properly implement the undoable unit of work pattern
  • The sync-based update method follows established architectural patterns

The design choice to silently ignore rather than throw exceptions aligns with the stated requirements.


600-600: LGTM! Entry morph type integration implemented correctly.

The addition of the MorphType property to entry creation correctly uses the primary morph type and the established conversion helper. The TODO comment appropriately flags the consideration needed for entries with mixed morph types in future iterations.


904-904: LGTM! Entry creation correctly integrates morph type.

The modification to pass entry.MorphType to the Cache.CreateEntry method correctly integrates morph type support into the entry creation process, aligning with the PR objective to enable creation of entries with the correct morph type.

rmunn added 2 commits July 29, 2025 16:38
The "add" operation, if we had ever used it, would have added nothing
because the value to be added wasn't being passed in. Fixed now.
@github-actions github-actions bot added the 📦 Lexbox issues related to any server side code, fw-headless included label Jul 29, 2025
Copy link
Collaborator

@hahn-kev hahn-kev left a comment

Choose a reason for hiding this comment

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

nice job! It looks good. One fix that's actually a pre existing issue, and one that's just incomplete.

@rmunn rmunn requested a review from hahn-kev August 1, 2025 03:30
Copy link
Collaborator

@hahn-kev hahn-kev left a comment

Choose a reason for hiding this comment

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

nice work, feel free to test the mapping functions in a followup testing PR if you want.

@myieye
Copy link
Collaborator

myieye commented Aug 8, 2025

I pushed a bunch of fixes.
The last one (ccd7cf9) I feel somewhat unsure of, but I think we need crdt's to mimic FwData's behaviour of defaulting to the Stem MorphType, so I just added that extremely broadly in crdt and mini-lcm land.

@myieye myieye force-pushed the feat/minilcm-morph-types branch from ccd7cf9 to c95af0c Compare August 8, 2025 16:03
@myieye
Copy link
Collaborator

myieye commented Aug 11, 2025

My commits basically only fixed tests (by fixing/completing functionality).

There's just one failing test left, which is sort of related to the fact that MorphTypeData isn't getting synced at this point. There's a sync method (MorphTypeDataSync), but it's not being called. Perhaps that's intentional:

[xUnit.net 00:00:37.73] LcmCrdt.Tests.ConfigRegistrationTests.AllObjectsAreRegistered [FAIL]

Error: Expected registeredObjectTypes {MiniLcm.Models.Entry, MiniLcm.Models.Sense, MiniLcm.Models.ExampleSentence, MiniLcm.Models.WritingSystem, MiniLcm.Models.PartOfSpeech, MiniLcm.Models.Publication, MiniLcm.Models.SemanticDomain, MiniLcm.Models.ComplexFormType, MiniLcm.Models.ComplexFormComponent, SIL.Harmony.Resource.RemoteResource} to contain MiniLcm.Models.MorphTypeData because All IObjectWithId types should be added in LcmCrdtKernel.ConfigureCrdt, if not exclude it in this test.

I think this PR has covered at least some of #1847.
Looking at the other issues for this feature, we maybe just want to register MorphTypeData as the test requires and then call it good?

@rmunn
Copy link
Contributor Author

rmunn commented Aug 14, 2025

@myieye wrote:

Looking at the other issues for this feature, we maybe just want to register MorphTypeData as the test requires and then call it good?

Discussed it with Kevin today, and he said "Just exclude it from the test for now, register it once CRDT supports it". So I pushed commit 31218de to do just that.

@rmunn rmunn merged commit 13eabbb into develop Aug 14, 2025
30 checks passed
@rmunn rmunn deleted the feat/minilcm-morph-types branch August 14, 2025 04:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FW Lite issues related to the fw lite application, not miniLcm or crdt related 📦 Lexbox issues related to any server side code, fw-headless included

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Model morph type, map from FW Data

3 participants