Skip to content

[duplicate-code] Duplicate Code Pattern: DIFC Label Type Structural Duplication #2002

@github-actions

Description

@github-actions

Part of duplicate code analysis: #2001

Summary

internal/difc/labels.go contains two parallel label types — SecrecyLabel and IntegrityLabel — that share nearly identical boilerplate across their constructors, flow-check methods, and Clone() implementations. The only meaningful differences are the type names and the checkSubset boolean / label-type string passed to the shared checkFlowHelper. Every structural change to the pattern must be applied twice.

Duplication Details

Pattern: Nil-guard extraction before checkFlowHelper call

  • Severity: Medium
  • Occurrences: 4
  • Locations:
    • internal/difc/labels.go lines ~173–182 (SecrecyLabel.CanFlowTo)
    • internal/difc/labels.go lines ~275–285 (SecrecyLabel.CheckFlow)
    • internal/difc/labels.go lines ~315–324 (IntegrityLabel.CanFlowTo)
    • internal/difc/labels.go lines ~328–338 (IntegrityLabel.CheckFlow)
  • Duplicated block (6 lines × 4 = 24 lines):
    var srcLabel, targetLabel *Label
    if l != nil {
        srcLabel = l.Label
    }
    if target != nil {
        targetLabel = target.Label
    }

Pattern: Structurally identical Clone() methods

  • Occurrences: 2
  • Locations:
    • internal/difc/labels.go lines ~287–292 (SecrecyLabel.Clone)
    • internal/difc/labels.go lines ~340–345 (IntegrityLabel.Clone)
  • Duplicated block (5 lines × 2 = 10 lines):
    if l == nil || l.Label == nil {
        return New(Type)Label()
    }
    return &(Type)Label{Label: l.Label.Clone()}

Pattern: Identical constructors

  • Occurrences: 4 (NewSecrecyLabel, NewIntegrityLabel, NewSecrecyLabelWithTags, NewIntegrityLabelWithTags)
  • Each delegates to NewLabel() / newLabelWithTags() with no variation except the return type.

Total structural duplication: ~36 lines across 10 near-identical code blocks.

Impact Analysis

  • Maintainability: Any change to the nil-guard extraction, Clone guard, or constructor logic must be applied to both SecrecyLabel and IntegrityLabel. The existing checkFlowHelper already consolidates the core algorithm; the remaining duplication is the boilerplate adapter code around it.
  • Bug Risk: Low-to-medium — if a nil-guard rule changes (e.g., add a check for l.Label == nil), it is easy to update one and miss the other.
  • Code Bloat: ~36 lines that could be reduced by ~50%.

Refactoring Recommendations

  1. Extract a generic extractLabels helper (or inline helper per file):

    func extractLabels[T interface{ GetLabel() *Label }](src, target T) (*Label, *Label) {
        var s, t *Label
        // use reflect or interface method to unwrap
        ...
    }

    However, Go generics cannot easily express "nil receiver returns nil", so a simpler option is:

  2. Add a getLabel() method on both types and use it to consolidate the nil-guard:

    func (l *SecrecyLabel) getLabel() *Label {
        if l == nil { return nil }
        return l.Label
    }
    func (l *SecrecyLabel) CanFlowTo(target *SecrecyLabel) bool {
        ok, _ := checkFlowHelper(l.getLabel(), target.getLabel(), true, "Secrecy")
        return ok
    }

    Same for IntegrityLabel. This eliminates the 4 nil-guard blocks (24 lines → 4 one-liners).

  3. Simplify Clone() using the same getLabel() pattern:

    func (l *SecrecyLabel) Clone() *SecrecyLabel {
        if l.getLabel() == nil { return NewSecrecyLabel() }
        return &SecrecyLabel{Label: l.Label.Clone()}
    }

Implementation Checklist

  • Add getLabel() *Label method to SecrecyLabel and IntegrityLabel
  • Refactor all 4 nil-guard extraction blocks to use getLabel()
  • Refactor both Clone() methods to use getLabel()
  • Run make test to verify no regressions
  • Run make lint to ensure code style compliance

Parent Issue

See parent analysis report: #2001
Related to #2001

Generated by Duplicate Code Detector ·

  • expires on Mar 23, 2026, 3:07 AM UTC

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions