Skip to content

fix(java): make Type.Methods Identity.Name and Graph relations deterministic#191

Merged
wzekin merged 1 commit into
mainfrom
fix/java-export-determinism
May 14, 2026
Merged

fix(java): make Type.Methods Identity.Name and Graph relations deterministic#191
wzekin merged 1 commit into
mainfrom
fix/java-export-determinism

Conversation

@wzekin
Copy link
Copy Markdown
Collaborator

@wzekin wzekin commented May 14, 2026

What type of PR is this?

fix

Check the PR title.

  • This PR title match the format: <type>(optional scope): <description>
  • The description of this PR title is user-oriented and clear enough for others to understand.
  • Attach the PR updating the user documentation if the current PR requires user awareness at the usage level. User docs repo

(Optional) Translate the PR title into Chinese.

(Optional) More detailed description for this PR(en: English/zh: Chinese).

en:
Two sources of non-determinism in Java IPC parsing surfaced as method-name flapping in Type.Methods[k].Name and reordered Graph.*.References between runs:

  1. exportSymbol stored the new *Identity in visited with the bare method name and only updated id.Name to the prefixed form (Receiver.method or Receiver::method) after recursing into the receiver. The receiver's SKStruct branch iterates its receivers[R] map and value-copies *mid into Type.Methods[k]; if that recursion landed on the very method that started the chain, it captured the still-bare name. Which method flapped per Type depended on Go map iteration order. Fix: pre-compute the prefixed Identity.Name for SKMethod/SKFunction in non-Cpp languages before inserting into visited, so cyclic visits read the final name.

  2. BuildGraph fills Node.References/Dependencies/Implements/Inherits/ Groups while iterating pkg.Functions/Types/Vars maps, so insertion order varied. Sort those slices by (Identity.Full(), Line, Kind) at the end of BuildGraph to make JSON byte-stable.

zh(optional):

(Optional) Which issue(s) this PR fixes:

(optional) The PR that updates user documentation:

…inistic

Two sources of non-determinism in Java IPC parsing surfaced as method-name
flapping in `Type.Methods[k].Name` and reordered `Graph.*.References` between
runs:

1. exportSymbol stored the new *Identity in `visited` with the bare method
   name and only updated `id.Name` to the prefixed form (`Receiver.method`
   or `Receiver::method`) after recursing into the receiver. The receiver's
   SKStruct branch iterates its `receivers[R]` map and value-copies `*mid`
   into `Type.Methods[k]`; if that recursion landed on the very method that
   started the chain, it captured the still-bare name. Which method flapped
   per Type depended on Go map iteration order. Fix: pre-compute the
   prefixed Identity.Name for SKMethod/SKFunction in non-Cpp languages
   before inserting into `visited`, so cyclic visits read the final name.

2. BuildGraph fills `Node.References/Dependencies/Implements/Inherits/
   Groups` while iterating `pkg.Functions/Types/Vars` maps, so insertion
   order varied. Sort those slices by (Identity.Full(), Line, Kind) at the
   end of BuildGraph to make JSON byte-stable.

Adds TestRepository_BuildGraph_Deterministic which marshals the localsession
fixture 5x and asserts byte-equality.

End-to-end: running `abcoder parse java testdata/java/4_full_maven_repo` 8x
now produces byte-identical output; previously every run differed.
@wzekin wzekin merged commit 9982ee1 into main May 14, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants