Skip to content

J_PARAM_IN/J_PARAM_OUT declare a var property the projection never writes #249

Closed

Description

@rahlk

Problem

V2SchemaCatalog declares a var property on both interprocedural SDG relationship types:

r.add(rel("J_PARAM_IN",  body, body, new P().put("var", "string").done()));
r.add(rel("J_PARAM_OUT", body, body, new P().put("var", "string").done()));

and V2GraphProjector emits both with RowBuilder.props() — no properties at all. So the
declaration promises a property no edge carries. Same defect as codeanalyzer-python#195, found
while fixing that one; verified against 3.1.1's own dataflow-test fixture.

The consequence is not cosmetic. A Cypher predicate written against the declaration lands in
three-valued logic on real data: all(r IN relationships(p) WHERE r.var <> $v) evaluates to null
on any path crossing a call boundary, so the path is silently excluded and the result is
indistinguishable from a genuine "no flow".

The variable is known at emit time and is already computed: SdgVertices.addActualsAndEdges binds
each actual_in:i to callee.getParameters().get(formalIndex), and each actual_out to the
callee's @formal_out. JIdEdge simply has nowhere to carry it.

Scope boundary

JIdEdge, SdgVertices, V2GraphProjector and their tests. Python took the same direction
(write it, in both projections) in codeanalyzer-python#196. Not the summary edges, which share
JIdEdge but bind no formal. Not the body-node / parameter id gap, which is a separate child of
codellm-devkit/.github#56.

Goals

  • JIdEdge.var, carried into analysis.json on param_in / param_out
  • SdgVertices sets it: the bound parameter's name on param_in, $ret on param_out
  • V2GraphProjector writes it on J_PARAM_IN / J_PARAM_OUT
  • A test asserts the property is on every emitted edge of those types, not some
  • summary edges keep the bare shape (var absent, never null-serialized)

Caveats and known risks

  • New property downstream consumers may key on; graphs emitted by 3.1.1 and earlier will not have
    it, so a consumer predicate still has to tolerate its absence for a generation.
  • JIdEdge is shared with summary. Gson is configured without serializeNulls, so an unset
    var is omitted rather than written as null — verify that holds for the summary lists.
  • The divergence is invisible to any test that counts edges or checks endpoints. Only a test that
    reads properties off emitted edges can see it.

Definition of done

  • Catalog and projector agree for both relationship types, asserted against emitted rows rather
    than by reading the two files.
  • Every param_in / param_out edge in the dataflow-test L4 output carries a non-empty var.
  • Full ./gradlew test green.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions