Skip to content

THE LINEAGE EXTRACTOR treats any class_start group 2 as an inheritance parent, even when group 1/2 are alternation-exclusive (not name+parent) #1983

Description

@squid-protocol

Summary

detector.py's "THE LINEAGE EXTRACTOR" (~line 1520-1523) unconditionally treats a class_start match's capture group 2 as an inheritance parent whenever the pattern has 2+ groups:

if rule_name == "class_start" and pattern.groups >= 2:
    extracted_parents.extend(m.group(2).strip() for m in matches if m.group(2))

This is correct for the common shape (class Foo extends Bar -> group1=Foo name, group2=Bar parent), but several languages' class_start regexes use group 1 and group 2 as mutually-exclusive alternation branches instead (the name lands in EITHER group 1 OR group 2 depending on which branch of the pattern fired -- _resolve_class_start_match's own docstring already documents this shape for "Fortran/Lua/ABAP-shaped patterns"). For those, group 2 is never really "the parent of group 1" -- it's an alternative NAME capture for a differently-shaped declaration that has no name at all in group 1 for that match.

Confirmed instances

  • fortran (already shipped, status: production): class_start = (?:MODULE|INTERFACE|SUBMODULE)\s+(NAME1)|TYPE\s+(NAME2) -- group 1 fires for MODULE/INTERFACE/SUBMODULE, group 2 fires for TYPE, never both. A bare TYPE foo declaration's own name (group 2) gets swept into extracted_parents and shows up as that file's parent_entity metadata -- not really "foo's parent," just foo's own name being double-counted as if it were a lineage relationship.
  • dockerfile (added in the dockerfile has no named class (build-stage) extraction -- class_start regex captures the FROM keyword, not the stage alias #1974 fix): class_start = FROM image AS (ALIAS)|FROM (BARE_IMAGE) -- same shape. A bare FROM <image> (no AS alias) sweeps the base image reference into extracted_parents. Confirmed empirically: syscall.Dockerfile's parent_entity field is literally debian:${BASE_DEBIAN_DISTRO}-slim, identical to its own (only) class_data.class_name value.

Why this isn't blocking #1974

This is a pre-existing, already-in-production behavior pattern (confirmed live for fortran today), not something #1974 introduced -- #1974 just makes dockerfile the second language to exhibit it. It's also not obviously wrong for dockerfile's specific case (a Dockerfile stage's base image is loosely a real "parent" of that stage, image-inheritance-wise) -- more a case of an accidental side effect nobody explicitly designed than a clear defect.

Suggested fix (future work, not urgent)

Give _CLASS_START_NAMED_EXTRACTION_LANGS languages an explicit, opt-in way to mark their class_start pattern as "alternation-shaped" (name-OR-name, not name-then-parent) -- mirroring how _resolve_class_start_match already distinguishes these shapes for the named-extraction path -- and have THE LINEAGE EXTRACTOR consult the same flag instead of a blanket pattern.groups >= 2 check. Low priority: the current behavior isn't causing incorrect class extraction (that path already handles the alternation correctly via _resolve_class_start_match), only a secondary, cosmetic-ish parent_entity metadata field.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugUnintended behavior or logic failure in the enginecore-engineModifications to the central physics and parsing enginepriority: lowUI tweaks, documentation, and minor optimizations

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions