Skip to content

fix(java): resolve record accessor calls, and never bind a call to data - #2295

Merged
DeusData merged 16 commits into
DeusData:mainfrom
MopicMP:fix/java-record-accessor-calls
Oct 30, 2026
Merged

DeusData merged 16 commits into
DeusData:mainfrom
MopicMP:fix/java-record-accessor-calls

Conversation

@MopicMP

@MopicMP MopicMP commented Sep 23, 2026

Copy link
Copy Markdown

Written by an AI agent (Claude Code) working for @MopicMP, who signed off the
commit and answers for it.

A Java record accessor call binds to an unrelated field

p.x() on a record ends up as a CALLS edge into some other class's private
field named x.

A record's accessors are implicit, so record Point(double x, double y, double z) declares no x() anywhere in the source, and extraction emits no node for
one. The call has nothing to resolve to, falls through to cbm_registry_resolve,
and the short-name registry hands back the first x in the project — typically
a private field of a class that has nothing to do with the receiver.

Two answers invert:

  • the accessor reports no callers, because it has no node at all. I nearly
    deleted a live method on that answer;
  • the unrelated field reports every record read in the project as its caller.

How much of the graph this is

Two indexed Java trees, v0.10.8 release binary, mode=fast, Windows 11 x86_64:

project CALLS edges target is a Variable or Field
631-file Minecraft mod 2 444 278 (11.4%)
3 000-file Minecraft mod 29 509 2 649 (9.0%)

Counted with MATCH (a)-[:CALLS]->(b) WITH b.label AS kind, count(*) AS n RETURN kind, n. moderate and full resolve the same way, and so does the
v0.11.0 release binary.

The change, in two parts

Extraction emits the accessors (internal/cbm/extract_defs.c). One Method
definition per record component, skipped when the record declares that accessor
itself (JLS §8.10.3 allows the override). The record's own API becomes visible:
the accessor gets a node, and p.x() resolves to it.

A Java call may not bind to data (src/pipeline/registry.c, both call
sites). A Java call expression never names data — p.x() is a method
invocation whatever x spells elsewhere in the tree — so a CALLS bind whose
target is a Variable or a Field is a spelling collision and is dropped.
This follows cbm_go_suppress_bare_field_ref: a pure, label-keyed,
language-gated predicate, called from pass_calls.c and pass_parallel.c so
the sequential and parallel resolvers stay identical.

Java-gated deliberately: the veto is sound only where no callable name can be
anything but a method. Kotlin properties hold function values (val f: () -> Unit; f()) and C has function pointers, so both legitimately call through data.

Both halves are needed. The first makes the right target exist; the second
stops the wrong one being written where the right one is not reachable.

Measured

On the 631-file tree, indexed with this build: 2 103 CALLS edges, every one
into a Method (1 841) or a Class (262). No Variable, no Field — down
from 278.

A separate gap this uncovered, not fixed here

Java cross-file type resolution appears to stop working when the project has
more than one source root. Same four files, two layouts:

  • one root (src/com/x/...): where.x() and where.z() bind to Point.x /
    Point.z across files and across packages, with an unrelated Spring.x
    field present;
  • two roots (src/main/java/... plus src/client/java/..., the Gradle/Fabric
    shape): the same calls do not bind at all. A hand-written public double x()
    in the record does not bind either, so it is not about the implicit accessor
    — everything that binds in that layout binds by short name.

I have a four-file reproduction and can open a separate issue for it; it looked
like a different defect from this one, so I kept it out of this PR.

Tests

  • tests/test_registry.c — java_call_never_binds_data_member: the predicate,
    including the keeps (Method/Function/Class, other languages, NULL).
  • tests/test_call_reference_contract.c —
    call_java_record_accessor_binds_the_record: end to end through the indexing
    path. The accessor call binds to the record; no CALLS into the unrelated
    field; a builder method x(int) declared beside its own x field keeps its
    edge; the genuine static call in the same method still lands.

Built and run with gcc 15.2.0 on Debian (WSL2): scripts/test.sh, plus
clang-format clean on every changed file.

A record's accessors are implicit, so `record Point(double x, double y,
double z)` declares no `x()` and extraction emitted no node for one. The call
`p.x()` had nothing to resolve to, fell through to the short-name registry,
and bound to the first `x` in the project — typically an unrelated class's
private field. Measured on two indexed Java trees, that was 278 of 2444 and
2649 of 29509 CALLS edges.

Extraction now emits one Method definition per record component, skipping any
accessor the record declares itself (JLS 8.10.3), so the accessor has a node
and the call resolves to it.

And a Java call may no longer bind to a Variable or a Field. A Java call
expression never names data, so such an edge is a spelling collision, not a
call. The guard follows cbm_go_suppress_bare_field_ref — a pure, label-keyed
predicate — and is called from both pass_calls.c and pass_parallel.c so the
sequential and parallel resolvers stay identical. Java-gated: Kotlin
properties hold function values and C has function pointers, so both
legitimately call through data.

Signed-off-by: MopicMP <obshiq123@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@MopicMP
MopicMP requested a review from DeusData as a code owner September 23, 2026 20:45
@github-actions

Copy link
Copy Markdown

Thanks for opening this — it has been seen, and it is queued.

This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence.

Current review status: working through a backlog. 0.9.1-rc.1 is out, so the release freeze that held reviews is over — but it left a large queue of open pull requests behind it, and we are reading through them oldest-first. The background is in discussion #1144.

What that means for this PR, concretely:

  • It will not be closed for inactivity. No stale bot touches pull requests here.
  • It may still sit a while before a human reads it. That is on us, not on you.
  • Older PRs are read first, so a recent one is not being skipped — it is behind a queue.

Things that will genuinely speed it up whenever review does happen:

  • Keep it rebased on main — the tree is moving quickly right now, and a conflicting branch cannot be reviewed as the diff you intended.
  • Get CI green, or say which failures you believe are pre-existing.
  • Keep the change to one claim. Bundled features and refactors get split before they get merged, which costs you a round trip.
  • Every commit needs a sign-off (git commit -s) — CI enforces DCO.

If this fixes a bug, a reproduction we can run is worth more than a description of the symptom.

Thanks for contributing, and sorry in advance for the wait.

@MopicMP

MopicMP commented Sep 24, 2026

Copy link
Copy Markdown
Author

Written by an AI agent (Claude Code) working for @MopicMP.

The only red here is test / test-windows-guards, and it is the failure mode tracked in #2057: tests/windows/test_daemon_stability.py, section_cold_storm — "cold-storm client 0 failed (racing daemon spawn): CBM daemon is active or starting but could not accept this client within 30000 ms". ci-ok is red only because it aggregates that leg.

Of the last 61 PR-workflow runs that ran this guard, it was green 56 times and red 5. All five reds are that same section, and four of them are on branches that cannot reach it:

branch job
codex/fix-1593-trace-filter 107192083571
fix/test-daemon-bootstrap-sync 106553770612
fix/1696-bench-runtime-isolation 106294337609
fix/hook-augment-worktree-test 106468158849
fix/java-record-accessor-calls (this PR) 107379415128

Everything else is green: all nine test-unix shards, both Windows shards, TSan, MSan, LSan, lint, lint-mem, CodeQL, the security and license gates, and DCO. This diff touches definition extraction, one pure label predicate, and CALLS edge emission — it has no path to daemon startup or client rendezvous.

Could a maintainer re-run that job? I have no permission to re-run it from here. Happy to rebase instead if you would rather see a fresh run of the whole leg.

@DeusData

Copy link
Copy Markdown
Owner

Thanks for the careful flake analysis, @MopicMP, and sorry for the wait. You're right that test-windows-guards (section_cold_storm) is the known #2057 race and not your change. A plain re-run would re-test the old merge commit from 23 September, so we've updated the branch from our side instead, and CI will run fresh against current main. No rebase is needed from you. We've already built and tested the merge result locally: it merges cleanly, and extraction, pipeline, registry, the Java LSP suites and call_reference_contract all pass (1209 tests), including your java_call_never_binds_data_member and call_java_record_accessor_binds_the_record. It merges once CI is green. Thanks for the record-accessor fix and for keeping calls from binding to data members.

Aerox912 pushed a commit to Aerox912/codebase-memory-mcp that referenced this pull request Sep 30, 2026
…ex, not one poll

watcher_poll_only_watched_projects failed on the macOS LSan job of PR
DeusData#2295, whose diff was Java-only, with
`FAIL tests/test_watcher.c:2971: index_call_count == 0, expected 1`
(8211 passed, 1 failed). The LSan report that followed points into the
aborted test body (watcher and store never freed after the early FAIL):
a consequence, not a separate leak.

The assert expected ONE touch+poll after a dirty change to reindex
exactly once. That needs every git probe of the poll to succeed. A poll
whose git spawn is refused under runner load is a fail-closed no-op by
design (DeusData#937: the baseline stays uncommitted and the next poll retries),
and that path returns without a log line. This is the same test race
that DeusData#2376 fixed in watcher_unwatch_drains_pending_free and
watcher_sustained_failure_logs_once_issue2015, not a production defect.
Holding one exhausted spawn with
cbm_subprocess_force_spawn_eagain_for_testing at that poll reproduces
the CI output exactly: watch, baseline, then
`FAIL tests/test_watcher.c:2971: index_call_count == 0, expected 1 == 1`,
with no watcher.changed and no watcher.git.failed.

The old test was also partly inert. The Go original (TestPollAllOnlyWatched,
from the DeusData#49 fix that replaced scan-all with an explicit watch list)
registered BOTH projects in the store and asserted that the unwatched
one gets no watcher state. The C port dropped the store registration, so
nothing let the watcher learn about B, and the B half could not fail.

The test now:
- registers A and B in the store, and watches only A;
- asserts that the baseline poll indexes nothing and does not adopt B;
- makes both worktrees dirty (a dirty change, not a commit, so a late
  baseline still sees it);
- polls until A's reindex has happened, asserting after EVERY poll that B
  has no watcher state (cbm_watcher_index_failure_count == -1), was never
  reindexed, and that the watch count is still 1;
- asserts that A was reindexed exactly once.
No timer or deadline decides the verdict. A watcher that never reindexes
A hangs, which the runner reports as a failure, never a pass.

Evidence (macOS arm64, ASan/UBSan test-runner, CBM_SANITIZED, so one
exhausted spawn = 10 injected refusals), with temporary injection that
has since been removed:
- CI-shaped (baseline OK, first change poll refused): consumed=10 at
  loop poll 1, watcher.changed at loop poll 2, PASS.
- Heavy (baseline poll plus loop polls 1-3 refused): loop poll 4 takes
  the baseline, poll 5 reindexes A; loop polls=5 watched=1 other=0, PASS.
- Mutation, the pre-DeusData#49 scan-all (poll_once adopts every stored project):
  `FAIL tests/test_watcher.c:3001: cbm_watcher_index_failure_count(w,
  "projB-ow") == 0, expected -1 == -1`, both unforced and with the heavy
  refusals (A's and B's baseline spawns both refused). The other 82
  watcher tests stay green under that mutation, so this is the only
  test guarding DeusData#49.
Final tree: build/c/test-runner watcher, 5/5 runs, 83 passed each.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData DeusData added bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges priority/high Needs near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker. labels Oct 19, 2026
@DeusData

Copy link
Copy Markdown
Owner

Thanks again for the record-accessor fix. The last maintainer update records passing local tests and says no rebase is needed. The remaining landing decision is still on the maintainer side; no new changes are requested in this sweep.

@MopicMP

MopicMP commented Oct 20, 2026

Copy link
Copy Markdown
Author

Written by an AI agent (Claude Code) working for @MopicMP.

Thanks for the update. Two things I noticed while checking where this stands:

  • The only red on the last run (from your 27 September merge) is test / test-lsan-macos, and it is not this change: tests/test_watcher.c:2971 (watcher_poll_only_watched_projects) failed, and the leak report comes from that aborted test's store_open_internal → sqlite allocations. No frame touches extract_defs.c or registry.c; ci-ok is red only through that leg.
  • GitHub now reports the branch as conflicting with main: since that merge, main has had dozens of commits in extract_defs.c, pass_calls.c, pass_parallel.c and registry.c.

I can resolve the conflicts and push to the branch, with the full suite rerun first, or leave it to you as with the last merge — whichever is easier on your side.

@DeusData

DeusData commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Thanks for checking this and offering to handle the update. Maintainer edits are enabled on this PR, so I will handle the scoped conflict resolution and validation directly on this branch; no additional changes are needed from you for that update. I will follow up with what changed and the test results. Thank you again for the contribution.

Preserve the current C/C++ field-binding policy while integrating the Java
record accessor change. Handle varargs record components with array return
types and reject data targets before sequential LSP call emission, matching
the parallel path. Add focused regressions for both cases.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Thank you for the Java record accessor fix and the regression coverage! I added maintainer commit 321dcb63f9a4b7ef2e5cc196bd8393a186df5c99 to finish two related edge cases: varargs record components now produce array-typed accessors, and sequential Java call resolution applies the same data-target guard as the parallel path.

I also merged current main and resolved the conflicts while preserving its C/C++ callable-field behavior. The new regressions failed before the fixes and again with the production changes reverted; all 694 affected tests passed on the integrated tree. Required GitHub CI is now the remaining merge gate. Thanks again for getting this improvement started!

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Thanks again, @MopicMP, for the Java record-accessor work! I merged the latest main in e2660c4 because another merged change touched the shared extraction code and tests. The merge was conflict-free and the Java fix has an identical patch ID. Fresh required GitHub CI will now check the combined head before merge.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Thank you for the Java record accessor work! I added a small follow-up fix so comments inside an otherwise empty accessor parameter list do not create a duplicate implicit accessor. The regression tests cover both block and line comments, retain the explicit method source span, and check that a real-parameter overload still keeps its implicit accessor.

The fix passed all 503 extraction and call-reference contract tests on macOS; reverting the production change reproduced the regression with the same tests. I also refreshed the branch with main so it picks up the shared CI repairs. Fresh GitHub checks will verify the combined branch. Thanks again for the contribution!

@DeusData

Copy link
Copy Markdown
Owner

Thank you again for the Java accessor fix. The October updates record the maintainer integration and the varargs, sequential-path, and comment-parameter regressions as completed. No repeat contributor update is needed. Sorry for the delay in the remaining maintainer follow-up—I’ll follow up soon.

A record's implicit accessors are members the compiler writes and the
source never spells. Their nodes now carry the property generated=record,
and every registry registration path files them in the exact
(qualified-name) map only, never in the short-name index. The Java
type-aware resolver still binds p.y() on a Point to Point.y; a call such
as v.y() on a type from outside the project no longer binds the accessor
through a unique_name / suffix_match / field_type_hint / fuzzy guess.

- extract_defs.c: each implicit accessor carries extra_props
  generated=record (key CBM_PROP_GENERATED, cbm.h).
- registry.c: cbm_registry_add_qn_only, and the pure predicates
  cbm_def_props_generated / cbm_node_props_generated.
- pass_definitions.c, pass_parallel.c, pipeline_incremental.c: the three
  registration sites route a generated member to the exact map only.
- pipeline_delta.c: the incremental preseed proxy keeps the mark, so an
  incremental re-index registers the member exactly as a full one does
  (the proxy carried only a few properties and the accessor came back
  into the short-name index).

Tests: pipeline_java_record_accessors_generated_qn_only (sequential,
parallel and incremental venues) and two registry unit tests.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The import resolver's symbol-name fallback tries the trailing segments of
an import path that names no project symbol, and a package segment that
merely spells a record accessor bound the import to it. On elasticsearch,
`import javax.crypto.spec.PBEKeySpec` bound a record's spec() accessor,
and `new PBEKeySpec(...)`, annotations and type uses then followed the
import onto it: 6,302 IMPORTS edges into accessors, plus CALLS, USAGE,
DECORATES and THROWS through the import map.

A generated member is registered by qualified name only, and no Java
import can name an instance accessor, so the fallback now skips it exactly
as it skips a Python def-local (DeusData#1548).

The record pipeline fixture gains an import whose package segment spells
an accessor. Without the change it fails in the sequential, parallel and
incremental venues: an IMPORTS edge into Point.y, and make() -> Point.y.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
When a JVM LSP callee has no exact node and no Class.method tail match,
cbm_pipeline_lsp_target_node takes the one project callable with that
leaf name. A record accessor became such a callable: on elasticsearch
`Objects.nonNull(x)` (37 CALLS) and `filter(Objects::nonNull)` (230
CALL_REFERENCE) bound a test record's nonNull() accessor.

A generated member is registered by qualified name only. It still joins
through its owner's Class.method tail, but the leaf-name fallback no
longer considers it, either as the unique callable or as a rival that
makes a same-named project callable ambiguous, so every other bind is
decided exactly as before the accessors existed.

The record pipeline fixture gains a record Seen(boolean nonNull) with
`Objects.nonNull(o)` and `filter(Objects::nonNull)` callers. Without the
change it fails in the sequential, parallel and incremental venues.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Thank you again, @MopicMP, for this fix and for the care that went into it. You found the real cause (a record's accessors had no node, so p.x() fell through to a project-wide name guess and landed on unrelated fields), fixed both halves, kept the sequential and parallel resolvers identical, and measured the damage on real trees. That made the remaining work here small.

Since you opened the PR we settled the design for members the compiler writes but the source never spells (record accessors now, Lombok members later): they are Method nodes marked with the property generated, and they are registered by qualified name only, so only a resolver that knows the owner type can bind them and no name guess can land on them. Your data-call veto lands with it unchanged. We pushed three commits and a merge of main on top of your branch to bring the PR in line with that:

  1. 729ce33 fix(java): register generated record accessors by qualified name only. The accessors you emit now carry generated=record. All three registry paths (sequential, parallel, and the registry rebuilt during an incremental re-index) keep them out of the short-name index, so p.y() on a Point still binds Point.y through the Java type resolver, while v.y() on a type from outside the project no longer binds the accessor by name. The incremental path rebuilds its registry from lightweight node proxies; those now keep the generated mark, so a re-index treats an accessor exactly like a full index does.

  2. 6c52e82 fix(java): no import resolves to a generated record accessor. When an import names nothing in the project, the import resolver tries the trailing segments of the import path, and a package segment that merely spells an accessor bound the import to it. On elasticsearch, import javax.crypto.spec.PBEKeySpec bound a record's spec() accessor, and every use of PBEKeySpec then followed the import onto it. The fallback now skips generated members, exactly as it already skips Python function locals.

  3. 679d1e1 fix(java): a JVM leaf-name fallback never picks a generated accessor. When the Java resolver names a callee that is not in the project and no Class.method match exists, the pipeline falls back to the single project method with that name. On elasticsearch, Objects.nonNull(x) and filter(Objects::nonNull) bound a test record's nonNull() accessor that way. Generated members are now left out of that fallback; they still bind through their own record type.

  4. 1d4bcc9 Merge origin/main, which brings the branch up to date. It merged without conflicts.

Each commit comes with tests that run one record fixture through the sequential, parallel and incremental indexing paths, plus small unit tests for the registry helpers. Each test failed before its change for the reason it names, and your veto's tests fail when the veto is switched off, so they really bind. On a full index of elasticsearch, Java calls into fields and variables go from 42,900 to 0, 8,363 accessors appear as generated Method nodes, and every one of the 6,033 calls that now reach them comes from the type-aware resolver, none from a name guess.

Please pull before pushing again, so these commits are not lost. Thanks again for the contribution, and for your patience with the review queue!

Windows headers define near and far as empty macros, so the locals named
near and far in the generated-accessor pipeline test did not compile on
the Windows leg. Rename them to near_m and far_m; the node names stay.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Sorry, @MopicMP, one more small commit from our side. The test we added for the generated accessors named two locals near and far, and the Windows headers define both as empty macros, so the test file did not compile on the Windows leg. 8f36ea6 renames them to near_m and far_m; the node names and every assertion stay the same, and your changes are untouched. Please pull before pushing again.

Conflict in src/pipeline/pass_calls.c: DeusData#2305 moved the inline LSP-target
emission of resolve_single_call into calls_emit_lsp_target() and added
the unresolved-call evidence around emit_classified_edge. The Java
data-member veto of this branch is ported into that structure:

- calls_emit_lsp_target: the veto runs once the target node is known,
  before the resolution, the evidence and any spawn or edge. It returns
  true (handled), so as before no edge is emitted and no registry
  fallback runs after it.
- resolve_single_call: the veto stays in front of main's
  candidate_qn/calls_emitted bookkeeping, matching the parallel
  resolver, whose veto also precedes that bookkeeping.

pass_parallel.c and the remaining files merged cleanly.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Thanks again @MopicMP for this PR - the record accessor work is careful and well tested, and it keeps holding up as main moves underneath it.

We merged current main into your branch once more (merge commit 2aaef23). Main had just landed #2305, which moved the LSP-target part of the sequential call resolver in src/pipeline/pass_calls.c into a new helper, calls_emit_lsp_target(), and added unresolved-call bookkeeping around the final edge emission. That collided with this PR's Java data-member check in two places. Here is exactly what we did:

  1. Inside calls_emit_lsp_target(): the check now runs as soon as the target node is known, before anything is recorded or emitted. It reports the call as handled, so, just as before, no CALLS edge is created and no name-based fallback runs after it.
  2. At the end of resolve_single_call(): the check stays right before main's new bookkeeping. The parallel resolver (pass_parallel.c) uses the same order, so the two resolvers still agree.

Nothing else changed: every other file merged cleanly with your changes intact. The Java, pipeline, registry, call-reference, Kotlin, extraction, parallel and incremental suites all pass locally. call_java_static_import_does_not_call_field_sequential still fails if the check is taken out of the new helper, so your test still guards it.

If you push to this branch again, please pull first so this merge commit is kept. Thanks a lot for your patience with all the moving parts here!

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Thank you again, @MopicMP, for your patience with this one. Two pull requests merged into main a few minutes ago (#2754 and #2090), and they touch src/pipeline/pass_parallel.c, pipeline.h and registry.c, which this pull request also changes. So we merged current main into your branch once more (one merge commit, 7ee3124; it merged cleanly and your own change is untouched), checked that the merged files still compile, and started a fresh CI run. We will merge as soon as the required checks are green. Please pull before pushing again so the merge commit is kept.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Thank you for your patience, @MopicMP. A pull request that merged into main a few minutes ago (#2769) changes internal/cbm/cbm.h and extract_defs.c, which this pull request also changes, so the CI run in progress here could no longer vouch for today's main. We merged current main into your branch once more (one merge commit, 32bd1d3; it merged cleanly and your own change is untouched) and started a fresh run. We will merge once the required checks are green. Please pull before pushing again.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Thank you for your patience, @MopicMP. A pull request that merged into main a few minutes ago (#2418) changes src/pipeline/pass_definitions.c, which this pull request also changes, so the CI run in progress here could no longer vouch for today's main. We merged current main into your branch once more (one merge commit, d1a96df; it merged cleanly and your own change is untouched) and started a fresh run. We will merge once the required checks are green. Please pull before pushing again.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

Copy link
Copy Markdown
Owner

Thank you for your patience, @MopicMP. A pull request that merged into main tonight (#2601) changes src/pipeline/pipeline_incremental.c, which this pull request also changes, so CI on this branch could no longer vouch for today's main. We merged current main into your branch once more (one merge commit, bff6ce9; it merged cleanly and your own change is untouched) and started a fresh run. We will merge once the required checks are green. Please pull before pushing again.

@DeusData
DeusData merged commit edb4a6e into DeusData:main Oct 30, 2026
26 checks passed
@DeusData

Copy link
Copy Markdown
Owner

Merged as edb4a6e - thank you, @MopicMP! Calls to Java record accessors now resolve to the accessor methods, and a call is never bound to a data member any more, in both the sequential and the parallel resolver. Thank you for the careful, well-tested change, and for your patience while main kept moving under it - this one went through more refreshes than most, and every time your tests made it easy to confirm nothing had shifted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working parsing/quality Graph extraction bugs, false positives, missing edges priority/high Needs near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants