mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-11-14 21:13:11 +08:00
A Java call written through a type's static field, Consts.HELPER.go() or Holder.SHARED.run(), was resolved by the method's name alone: the receiver Type.FIELD said nothing of its type, so the call went to a same-named method of whatever class the name matcher found, and a field of a library class (Intent.ACTION_VIEW.equals(...), System.out.print()) could reach a project method of that name. An interface's constants were not indexed at all (neither engine read a constant_declaration), so a constant a type declares in an interface, or inherits from one, had no declaration to read. A Java Type.FIELD.m() (Outer.Inner.FIELD.m(), a package written in front) now finds the type as the calling file names it (javaTypeRef), then the field, the type's own or one it inherits (five levels up), and calls the method on the value the field's declaration gives it, read with the field's own file's imports: an enum constant's own override, else the enum's method; the method of the anonymous class the field is initialized with (a CREATOR's createFromParcel); the class a new X(...) initializer builds; else the type the declaration writes. A Kotlin object's INSTANCE or Companion reaches the object's member. A library owner, or a field of a library type, links nothing. A receiver whose head is a local or a field links as before. Both engines index an interface's constant_declaration as a static final constant. Validation: - java-static-field-receivers.test.ts: 9 tests, 7 fail on main60b0d7a9(two already pass there: a field typed by its own declaration and an anonymous class's method), all pass here. - Kernel parity (java), 0 files with diffs: Torture.java 1/1, TortureRecord.java 1/1, jextract 218/218, spring-modulith 682/682, SystemUI 1141/1141, okhttp 71/71, Minestom 1859/1894 (deferrals are main's). - A/B against main60b0d7a9, sites added/removed/retargeted (conf-only): Minestom +26003/-8/122 (751; 12,584 interface constants now indexed, 409 calls typed), spring-ai +14/-21/786 (823; 719 enum constants' own overrides), kestra +27/-273/14 (37), playframework +5/-1/0 (21), SystemUI 0/-11/0 (2), spring-modulith +5/-3/4 (26), jextract +1/-9/6 (1); okhttp, nowinandroid, mihon, click, gin, serilog identical. The removed sites are guesses on library fields and methods (kestra's HttpStatus.X.getCode() x180). - Cost (median of 3 interleaved): SystemUI CPU 92.0 -> 93.7 s, wall 59.4 -> 58.6 s; Minestom CPU 46.7 -> 56.4 s, wall 17.5 -> 19.4 s, as its graph grows by the generated registries' 12,584 interface constants (29% more nodes, 30% more edges). Reimplements #1949 by @mixxer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
149 lines
3.6 KiB
Java
149 lines
3.6 KiB
Java
/**
|
|
* Java torture fixture — exercises every Java extraction path the kernel
|
|
* ports: package namespace, imports, javadoc, annotations, inheritance,
|
|
* fields/constants, enums, anonymous classes, method references, static
|
|
* member reads, fluent chains, Lombok synthesis, value refs + shadowing.
|
|
*/
|
|
package com.example.torture;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import static java.util.Objects.requireNonNull;
|
|
import com.example.other.OtherClass;
|
|
import lombok.Data;
|
|
|
|
/** Javadoc for the service. */
|
|
@Service
|
|
@Component("torture")
|
|
public class TortureService extends BaseService implements Runnable, AutoCloseable {
|
|
/** A shared constant table (value-ref target). */
|
|
public static final Map<String, Integer> RETRY_LIMITS = Map.of("a", 1);
|
|
private static final String API_BASE = "https://example.test";
|
|
protected int count = 0;
|
|
private final List<String> names;
|
|
int packagePrivate, secondDeclarator;
|
|
/** Field initializers — walked scoped to the field (#693). */
|
|
private final Runnable fieldLambda = () -> helper(RETRY_LIMITS);
|
|
private final Runnable fieldAnonClass = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
helper(RETRY_LIMITS);
|
|
}
|
|
};
|
|
private final Runnable fieldMethodRef = TortureService::compute;
|
|
private static final List<Runnable> FIELD_TABLE = List.of(TortureService::compute);
|
|
|
|
/** Ctor javadoc. */
|
|
public TortureService(List<String> names) {
|
|
this.names = requireNonNull(names);
|
|
register(this::onEvent);
|
|
queue(TortureService::compute);
|
|
queue(OtherClass::handle);
|
|
Runnable r = () -> helper(RETRY_LIMITS);
|
|
executor.submit(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
helper(RETRY_LIMITS);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
@Deprecated
|
|
public void run() {
|
|
Config cfg = ConfigLoader.getInstance().load();
|
|
this.registry.lookup("x");
|
|
helper(Direction.UP);
|
|
String base = API_BASE;
|
|
int max = Limits.MAX_VALUE;
|
|
new StringBuilder(16).append(base);
|
|
}
|
|
|
|
private static Config helper(Object arg) {
|
|
return new Config();
|
|
}
|
|
|
|
private void onEvent() {}
|
|
private static void compute() {}
|
|
|
|
public void shadowed() {
|
|
String API_BASE = "local"; // shadows the class constant
|
|
log(API_BASE);
|
|
}
|
|
|
|
enum Direction {
|
|
UP,
|
|
DOWN;
|
|
|
|
Direction opposite() {
|
|
return this == UP ? DOWN : UP;
|
|
}
|
|
}
|
|
|
|
enum Step {
|
|
NEXT(1) {
|
|
@Override
|
|
int apply(int at) {
|
|
return clamp(at + size);
|
|
}
|
|
},
|
|
BACK(-1) {
|
|
@Override
|
|
int apply(int at) { return at + size; }
|
|
};
|
|
|
|
final int size;
|
|
|
|
Step(int size) { this.size = size; }
|
|
|
|
abstract int apply(int at);
|
|
|
|
static int clamp(int at) { return Math.max(0, at); }
|
|
}
|
|
|
|
interface Listener {
|
|
void onChange(TortureService svc);
|
|
}
|
|
}
|
|
|
|
@Data
|
|
class LombokBean {
|
|
private String name;
|
|
private boolean isActive;
|
|
private final int id;
|
|
private static int counter;
|
|
private String toString; // taken: no synthetic toString field collision
|
|
|
|
public String getName() { return name; } // explicit getter — never overridden
|
|
}
|
|
|
|
@lombok.Getter
|
|
@lombok.extern.slf4j.Slf4j
|
|
@Builder
|
|
class LombokBuilderBean {
|
|
private List<String> items;
|
|
}
|
|
|
|
interface Shape extends Comparable<Shape>, Cloneable {
|
|
double area();
|
|
}
|
|
|
|
@interface Marker {
|
|
String value() default "";
|
|
}
|
|
|
|
class DottedAnon {
|
|
Api.Listener listener = new Api.Listener<String>() {
|
|
public void on() {}
|
|
};
|
|
Object plain = new java.util.concurrent.Callable<Integer>() {
|
|
public Integer call() { return 1; }
|
|
};
|
|
}
|
|
interface TortureConsts {
|
|
int MAX = 10;
|
|
Helper HELPER = new Helper();
|
|
String NAME = "x", OTHER = "y";
|
|
Runnable TASK = new Runnable() { public void run() { go(); } };
|
|
}
|