Repository navigation
Conversation
When the Java resolver resolves a call's receiver to a type outside the project (a JDK package, or a package no project file declares), the call gets strategy lsp_external. Both pipeline paths (pass_calls.c and pass_parallel.c) then look the target up strictly by QN through cbm_pipeline_java_external_target and skip the registry's name guess, so no edge is created to an unrelated project method of the same name. This is the rule the Rust path follows since DeusData#2053. Positive proof only: a receiver of unknown type keeps the existing guess, and a seeded JDK type that lacks the called method stays no_method_match. Type variables (T, ID) are never taken for package-qualified types. A package counts as the project's when any registry layer holds a project type in it (the layer above the shared registry is a per-file overlay), and a path-derived spelling counts as the project's also for a file at the repository root. java_receiver_is_external memoizes its answer per package. The sequential path now builds the Java cross registry, as the parallel path does, so the gate applies on both. Tests: java_typed_calls (external receivers get no edge; a project receiver keeps its edge, and so does one whose type is missing from a project package), parallel_java_external_target_contract. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Timur Nizametdinov <7229951+tfactor2@users.noreply.github.com>
|
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. What that means for this PR, concretely:
Things that will genuinely speed it up whenever review does happen:
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. |
DeusData
left a comment
There was a problem hiding this comment.
Thank you very much for this, @tfactor2. It is a careful and well-reasoned change, and it removes a whole class of fabricated edges that has bothered us for a long time. We measured it properly before replying, and the numbers are very good.
What we measured. We merged the PR head (0ec6967) onto current main and indexed 15 open-source Java repositories with and without it on the parallel resolver, plus 6 of them on the sequential one. We hand-judged a stratified sample of the changed edges against the source.
- Parallel, 15 repos: CALLS 749,216 → 665,992, i.e. −83,225 (−11.1 %), with 1 edge added. About 96 % of the sampled removals were wrong edges, for example:
Thread.sleep,Calendar.getInstanceandMap.getbound to same-named project methods;new Date()/new ArrayList<>()bound to apom.xmlelement;String.formatbound to a projectformat.
The remaining ~3–4 % were calls on a JDK interface type whose project implementation happened to be the guessed target (ParameterizedType.getOwnerType()→Utils.ParameterizedTypeImpl.getOwnerType). That trade-off is a broader design question on our side; nothing for you to change here.
- Sequential, 6 repos: CALLS −5,079 / +680. The additions come from the new Tier-2 registry line for small repositories and were correct in every sampled case: calls on project interfaces now reach the interface method, and constructor calls reach the constructor.
Two small requests before we merge:
1. Own package (and the file's own types) before java.lang. java.lang is an implicit on-demand import (JLS §7.3), and an on-demand import never shadows a type of the compilation unit's own package (§6.4.1, §7.5.2). The resolver checks java.lang first. Before this PR, that wrong first answer was harmless because the textual fallback still found the project class. Now it marks the receiver as external and the edge is dropped. Minimal repro (both resolver paths, with 50+ files so the shared registry is built):
// src/main/java/com/acme/protogen/Enum.java
package com.acme.protogen;
public class Enum {
public Enum(Class<?> cls, String parent) {}
}
// src/main/java/com/acme/protogen/Message.java
package com.acme.protogen;
public class Message {
public void addNestedEnum(Class<?> cls) {
Enum e = new Enum(cls, "parent"); // expected: CALLS -> com.acme.protogen.Enum constructor
}
}On main this produces addNestedEnum -> com.acme.protogen.Enum.Enum. With the PR the edge is gone, because Enum resolves to java.lang.Enum and is classified as external. The same shape occurs in Netflix/conductor (protogen.Enum). Project classes named Process, Module, Record, Override and so on are affected the same way. Could you move the own-package lookup ahead of java.lang in the type-name resolution and add a test like the one above?
2. PR description. Please restate the numbers for this PR alone. As far as we can tell, the current figures include the follow-ups you mentioned for #2382 and #2662. Please also call out the pass_lsp_cross.c line that builds the Java shared registry on the sequential path, or split it into its own commit. It is a good change, but it is a behaviour change for every repository of 50 files or fewer, and reviewers should see it as such.
Thanks again; we are looking forward to merging this.
What does this PR do?
Fixes #2660. When the Java resolver knows a receiver's type by its package-qualified name, and no project type lives in that package (JDK, libraries), the call gets
lsp_external. Both pipeline paths then look it up strictly by QN, never by name (as Rust does since #2339).Unknown types, and types missing from a project package, keep the existing guess. The sequential path now builds the Java cross registry too, so both paths agree.
Known gap:
List.getandList.isEmptystill get a guessed edge.On a 3,178-file Spring service, this and the follow-ups for #2382 and #2662 remove 126 of 821 sampled edges; 12 of 15 checked were wrong, none right.
Checklist
git commit -s)maintoo.make teststops earlier at the version-metadata contract, as onmain.lint-no-suppress,lint-memory-corepass; cppcheck and clang-format not installed herejava_typed_calls(fails onmain),parallel_java_external_target_contract🤖 Generated with Claude Code