Skip to content

Duplicate Code: Namespace-Wrapping Boilerplate Repeated Across All Three Generator Modules #280

Description

@github-actions

Analysis of commit 710bd94

Assignee: @copilot

Summary

All three generator modules (FieldsGenerator, DUCasesGenerator, LensesGenerator) repeat identical 2–4 line blocks that look up the configured namespace from config and wrap a nested module in a SynModuleOrNamespace. If the key name, default value, or isRecursive flag ever needs to change, all three sites must be updated consistently.

Duplication Details

Pattern: Namespace lookup + SynModuleOrNamespace.CreateNamespace wrapping

  • Severity: Medium
  • Occurrences: 3 (one per generator)
  • Locations:
    • src/Myriad.Plugins/DUCasesGenerator.fs (lines 120–124)
    • src/Myriad.Plugins/FieldsGenerator.fs (lines 138–142)
    • src/Myriad.Plugins/LensesGenerator.fs (lines 192–195)

DUCasesGenerator (lines 120–124):

let info = SynComponentInfo.Create recordId
let mdl = SynModuleDecl.CreateNestedModule(info, declarations)
let dusNamespace = GeneratorConfig.getOrDefault "namespace" "UnknownNamespace" config
SynModuleOrNamespace.CreateNamespace(Ident.CreateLong dusNamespace, isRecursive = true, decls = [mdl])

FieldsGenerator (lines 138–142):

let info = SynComponentInfo.Create recordId
let mdl = SynModuleDecl.CreateNestedModule(info, decls)
let fieldsNamespace = GeneratorConfig.getOrDefault "namespace" "UnknownNamespace" config
SynModuleOrNamespace.CreateNamespace(Ident.CreateLong fieldsNamespace, isRecursive = true, decls = [mdl])

LensesGenerator (lines 192–195):

let typeNamespace = GeneratorConfig.getOrDefault "namespace" "UnknownNamespace" config
// ...
SynModuleOrNamespace.CreateNamespace(Ident.CreateLong typeNamespace, isRecursive = true, decls = [synModule])

Impact Analysis

  • Maintainability: Three sites to update if the config key "namespace", default "UnknownNamespace", or isRecursive semantics change.
  • Bug Risk: A fix or change applied to one generator but not the others creates inconsistent behaviour across generator outputs.
  • Code Bloat: Minor but represents avoidable copy-paste between modules that already share GeneratorHelpers and GeneratorConfig.

Refactoring Recommendations

  1. Add a helper to GeneratorHelpers or GeneratorConfig

    • Add a small helper such as:
      /// Wraps `decls` in a recursively-open namespace read from the "namespace" config key.
      let wrapInNamespace (config: (string * obj) seq) (decls: SynModuleDecl list) : SynModuleOrNamespace =
          let ns = GeneratorConfig.getOrDefault "namespace" "UnknownNamespace" config
          SynModuleOrNamespace.CreateNamespace(Ident.CreateLong ns, isRecursive = true, decls = decls)
    • Estimated effort: 30 minutes
    • Benefits: Single point of change for the namespace config key and default; consistent behaviour across all generators.
  2. Update all three call sites

    • Replace the repeated 2–4 line blocks with a single call to the new helper.

Implementation Checklist

  • Review duplication findings
  • Add wrapInNamespace (or equivalent) helper to GeneratorHelpers.fs or GeneratorConfig.fs
  • Update DUCasesGenerator.fs to use the helper
  • Update FieldsGenerator.fs to use the helper
  • Update LensesGenerator.fs to use the helper
  • Run existing tests to verify no functionality broken

Analysis Metadata

  • Analyzed Files: 3 (DUCasesGenerator.fs, FieldsGenerator.fs, LensesGenerator.fs)
  • Detection Method: Semantic code analysis
  • Commit: 710bd94
  • Analysis Date: 2026-03-22

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions