Analysis of the Myriad plugin generators reveals that the logic for resolving a DU case identifier (optionally fully qualifying it with the parent type name when RequireQualifiedAccess is present) is duplicated between DUCasesGenerator.fs and LensesGenerator.fs.
Assignee: @copilot
Summary
DUCasesGenerator.fs defines a named helper function resolveCaseIdent that computes the full case name. LensesGenerator.fs re-implements the exact same logic inline as matchCaseIdentParts. These should be unified in GeneratorHelpers so both generators share a single implementation.
Duplication Details
Pattern: Qualified DU case name resolution
- Severity: Medium
- Occurrences: 2
- Locations:
src/Myriad.Plugins/DUCasesGenerator.fs (lines 18–24) — named function resolveCaseIdent
src/Myriad.Plugins/LensesGenerator.fs (lines 68–72) — inline matchCaseIdentParts
Code in DUCasesGenerator.fs (lines 18–24):
let resolveCaseIdent (requiresQualifiedAccess: bool) (parent: LongIdent) (id: Fantomas.FCS.Syntax.Ident) : SynLongIdent =
let parts =
if requiresQualifiedAccess then
(parent |> List.map (fun i -> i.idText)) @ [id.idText]
else
[id.idText]
SynLongIdent.Create parts
Equivalent inline logic in LensesGenerator.fs (lines 68–72):
let matchCaseIdentParts =
if requiresQualifiedAccess then
(parent |> List.map (fun i -> i.idText)) @ [id.idText]
else
[id.idText]
// then used as: SynLongIdent.Create matchCaseIdentParts
Impact Analysis
- Maintainability: Any change to qualified-access case resolution (e.g. supporting nested modules) must be applied in two places, risking divergence.
- Bug Risk: A fix for one generator may be missed in the other, causing inconsistent behaviour between
lenses and dus generators.
- Code Bloat: Minor, but obscures the shared contract between the two generators.
Refactoring Recommendations
- Move
resolveCaseIdent to GeneratorHelpers
- Add
resolveCaseIdent (or rename to resolveDuCaseIdent) to src/Myriad.Plugins/GeneratorHelpers.fs
- Remove the local definition from
DUCasesGenerator.fs
- Replace the inline
matchCaseIdentParts block in LensesGenerator.fs with a call to the shared helper
- Estimated effort: ~30 minutes
- Benefits: Single source of truth for qualified-access case resolution
Implementation Checklist
Analysis Metadata
- Analyzed Files: 3 (
DUCasesGenerator.fs, LensesGenerator.fs, GeneratorHelpers.fs)
- Detection Method: Semantic code analysis
- Commit: 165a7e5
- Analysis Date: 2026-03-07
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.
Analysis of the Myriad plugin generators reveals that the logic for resolving a DU case identifier (optionally fully qualifying it with the parent type name when
RequireQualifiedAccessis present) is duplicated betweenDUCasesGenerator.fsandLensesGenerator.fs.Assignee:
@copilotSummary
DUCasesGenerator.fsdefines a named helper functionresolveCaseIdentthat computes the full case name.LensesGenerator.fsre-implements the exact same logic inline asmatchCaseIdentParts. These should be unified inGeneratorHelpersso both generators share a single implementation.Duplication Details
Pattern: Qualified DU case name resolution
src/Myriad.Plugins/DUCasesGenerator.fs(lines 18–24) — named functionresolveCaseIdentsrc/Myriad.Plugins/LensesGenerator.fs(lines 68–72) — inlinematchCaseIdentPartsCode in
DUCasesGenerator.fs(lines 18–24):Equivalent inline logic in
LensesGenerator.fs(lines 68–72):Impact Analysis
lensesanddusgenerators.Refactoring Recommendations
resolveCaseIdenttoGeneratorHelpersresolveCaseIdent(or rename toresolveDuCaseIdent) tosrc/Myriad.Plugins/GeneratorHelpers.fsDUCasesGenerator.fsmatchCaseIdentPartsblock inLensesGenerator.fswith a call to the shared helperImplementation Checklist
resolveCaseIdenttoGeneratorHelpers.fsDUCasesGenerator.fsto call the shared helperLensesGenerator.fsto call the shared helperAnalysis Metadata
DUCasesGenerator.fs,LensesGenerator.fs,GeneratorHelpers.fs)