-
-
Notifications
You must be signed in to change notification settings - Fork 45
Duplicate Code: Qualified DU Case Name Resolution in LensesGenerator and DUCasesGenerator #251
Description
Analysis of commit 165a7e5
Assignee: @copilot
Summary
The logic for resolving a DU case's fully-qualified SynLongIdent (based on whether RequireQualifiedAccess is in effect) is duplicated between LensesGenerator.fs and DUCasesGenerator.fs. DUCasesGenerator correctly extracted this into a named helper (resolveCaseIdent), but LensesGenerator contains an identical inline copy.
Duplication Details
Pattern: Qualified DU case identifier construction
-
Severity: Medium
-
Occurrences: 2
-
Locations:
src/Myriad.Plugins/DUCasesGenerator.fs(lines 18–24) — extracted helperresolveCaseIdentsrc/Myriad.Plugins/LensesGenerator.fs(lines 68–72) — identical inline logic
-
Code Sample (DUCasesGenerator.fs, lines 18–24):
let resolveCaseIdent (requiresQualifiedAccess: bool) (parent: LongIdent) (id: Ident) : SynLongIdent = let parts = if requiresQualifiedAccess then (parent |> List.map (fun i -> i.idText)) @ [id.idText] else [id.idText] SynLongIdent.Create parts
-
Code Sample (LensesGenerator.fs, lines 68–72 — duplicate inline):
let matchCaseIdentParts = if requiresQualifiedAccess then (parent |> List.map (fun i -> i.idText)) @ [id.idText] else [id.idText] let fullCaseName = SynLongIdent.Create matchCaseIdentParts
Impact Analysis
- Maintainability: Any change to how DU case names are qualified (e.g., supporting nested modules) must be applied in both files separately.
- Bug Risk: A future fix to one copy is likely to be missed in the other, leading to inconsistent behaviour between lenses on DUs and DU case utilities.
- Code Bloat: Minor — 6 duplicate lines — but the semantic impact is higher than the line count suggests.
Refactoring Recommendations
-
Move
resolveCaseIdenttoGeneratorHelpers- Target file:
src/Myriad.Plugins/GeneratorHelpers.fs - Make it
internal(it already fits the module's helper scope). - Replace the inline logic in
LensesGenerator.fswith a call toGeneratorHelpers.resolveCaseIdent. - Estimated effort: <1 hour
- Benefits: single source of truth for qualified DU case name resolution; prevents divergence
- Target file:
-
Alternative: keep
resolveCaseIdentinCreateDUModuleandopenit inLensesGenerator- Less ideal (cross-module coupling within the plugin), but avoids moving the function if preferred.
Implementation Checklist
- Move (or re-expose)
resolveCaseIdentinGeneratorHelpers.fs - Replace the inline duplication in
LensesGenerator.fscreateLensForDUwith a call to the shared helper - Run integration tests:
dotnet run --framework net9.0 --fail-on-focused-tests --summary --project ./test/Myriad.IntegrationPluginTests/Myriad.IntegrationPluginTests.fsproj - Verify generated output is unchanged
Analysis Metadata
- Analyzed Files: 3 (
FieldsGenerator.fs,LensesGenerator.fs,DUCasesGenerator.fs) - Detection Method: Semantic code analysis
- Commit: 165a7e5
- Analysis Date: 2026-03-11
Generated by Duplicate Code Detector
To install this workflow, run
gh aw add githubnext/agentics/workflows/duplicate-code-detector.md@ee49512da7887942965ac0a0e48357106313c9dd. View source at https://github.com/githubnext/agentics/tree/ee49512da7887942965ac0a0e48357106313c9dd/workflows/duplicate-code-detector.md.