Skip to content

[finding][lint] After #6381 converged the view ladder, two SMALLER helpers are still triplicated across the same view-walking rules — collectionEntries and the objectName -> object -> data.object binding ladder #6662

Description

@os-project-manager

Filed unassigned from #6381 / PR #6657. Record only — no commitment to a fix.
Observation class: nothing a user hits today. All copies agree, and the PR that
found them deliberately did not fold them in, for reasons given below.

Facts, measured at 3e028ce37 (the #6381 branch, post-convergence)

#6381 converged the "views[] entry to its real form/view sites" descent onto
one shared walker (packages/lint/src/view-walk.ts). Two smaller helpers used by
the very same rules were left at three copies each.

1. collectionEntries — 3 copies. Coerces a collection authored either as an
array or as a name-keyed map into records carrying their config path.

file line
validate-form-layout.ts 81
validate-translatable-sections.ts 143
validate-visibility-predicates.ts 290

Semantically identical. Not byte-identical: the visibility copy open-codes
!!v && typeof v === 'object' && !Array.isArray(v) inline where the other two
call a local isRec. Each carries its own docblock making the same argument
(findings are edit targets, so a map-shaped collection must not report a
synthetic index) — validate-form-layout.ts:76 even says out loud "Same helper,
same reasoning as validate-visibility-predicates.ts and
validate-translatable-sections.ts", i.e. the duplication is already
acknowledged in-tree.

2. The view binding ladder objectName -> object -> data.object — 3 copies.
Byte-identical bodies, two different names:

file line name
validate-form-layout.ts 142 boundObject
validate-translatable-sections.ts 130 viewObjectName
validate-translation-references.ts 347 viewObjectName

The card that spawned this (#6381) named the binding resolution as "three
spellings" and correctly excluded lint-view-refs.ts's deeper ladder
(name -> id -> object -> list.data.object -> form.data.object) as reasoned
difference rather than drift. These three are the other kind: the same four
lines, three times.

Note what does NOT differ: only the base ladder is duplicated. How each rule
composes it differs on purpose (form-layout falls back to the container;
translatable-sections falls back to the container and then to the default
list's binding), and #6657 preserved that deliberately.

Why #6657 did not fold them in

Two reasons, both worth keeping on the record:

  1. Scope. lint: 视图容器阶梯遍历在 packages/lint 内已有三份实现,彼此按不同判据取舍 #6381's ruling scoped the work to "one shared implementation of
    the descent". A refactor whose entire evidentiary claim is "verdicts are
    byte-identical" is worth more when its diff is exactly the thing it claims to
    have merged.
  2. One of the three binding copies is in a file that is currently off-limits.
    validate-translation-references.ts holds collectViewRecord, and lint: collectViewRecord 的 listViews/formViews 分支收「map key + 内层 name」两种拼写,而组装器只认 map key —— 冲突改名时两者恰好相反 #6422 is
    held in the maintainer decision box
    with that file as its subject. Any
    convergence that reaches all three copies has to touch it. Folding two of
    three would reproduce the exact shape lint: 视图容器阶梯遍历在 packages/lint 内已有三份实现,彼此按不同判据取舍 #6381 exists to prevent — the next
    author fixes one copy and leaves another behind.

So the natural window for this is after #6422 is decided, at which point the
descent, the binding ladder and collectionEntries can move together, in one
pass over the same set of files.

Why record it at all

#6381's own signal argument applies unchanged: the ladder there was found broken
in two different files in two consecutive issues, and the copy count was the
evidence a single source was owed. These two helpers have the same copy count
and the same consumer set. Recording them now means the next person to open one
of these files sees the other two, which is the cost this class of finding is
about.

Refs: #6381 / PR #6657 (the descent, converged), #6422 (held — blocks the
binding-ladder half), #6248 / #6251 / #6128 (the two-time hole that made the
case), #3583 (page-walk.ts, the shared-walker precedent).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions