Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

292 lines
10 KiB
Go

package languages
import (
"testing"
"github.com/zzet/gortex/internal/graph"
)
// refEdge finds the first edge with the given kind, target, and
// (optional) ref_context. ref_context == "" matches any (or no) ref_context.
func refEdge(edges []*graph.Edge, kind graph.EdgeKind, to, useKind string) *graph.Edge {
for _, e := range edges {
if e.Kind != kind || e.To != to {
continue
}
if useKind == "" {
return e
}
if e.Meta != nil {
if uk, _ := e.Meta["ref_context"].(string); uk == useKind {
return e
}
}
}
return nil
}
// hasRefTo reports whether any edge of any kind targets unresolved::<name>
// with the given ref_context — used by negative assertions.
func hasUseKindTo(edges []*graph.Edge, to, useKind string) bool {
for _, e := range edges {
if e.To != to || e.Meta == nil {
continue
}
if uk, _ := e.Meta["ref_context"].(string); uk == useKind {
return true
}
}
return false
}
// TestJavaRefForm_Instantiation pins `new Foo()` / `new Foo[]` /
// `new Outer.Inner()` → EdgeInstantiates (ref_context=instantiate), and
// the generic arg of `new ArrayList<Request>()` → Request as a
// generic_arg reference (handled by the type_arguments walker, not the
// instantiation case).
func TestJavaRefForm_Instantiation(t *testing.T) {
src := `package app;
public class Factory {
void build() {
Foo f = new Foo();
Foo[] arr = new Foo[3];
Outer.Inner oi = new Outer.Inner();
java.util.List<Request> reqs = new java.util.ArrayList<Request>();
}
}
`
_, edges := runJavaExtract(t, "app/Factory.java", src)
if e := refEdge(edges, graph.EdgeInstantiates, "unresolved::Foo", "instantiate"); e == nil {
t.Errorf("expected EdgeInstantiates -> Foo (ref_context=instantiate)")
} else if e.Origin != graph.OriginASTInferred {
t.Errorf("instantiate Origin = %q, want OriginASTInferred", e.Origin)
}
if refEdge(edges, graph.EdgeInstantiates, "unresolved::Inner", "instantiate") == nil {
t.Errorf("expected EdgeInstantiates -> Inner for `new Outer.Inner()`")
}
if refEdge(edges, graph.EdgeInstantiates, "unresolved::ArrayList", "instantiate") == nil {
t.Errorf("expected EdgeInstantiates -> ArrayList for `new java.util.ArrayList<>()`")
}
if refEdge(edges, graph.EdgeReferences, "unresolved::Request", "generic_arg") == nil {
t.Errorf("expected EdgeReferences -> Request (generic_arg of new ArrayList<Request>())")
}
}
// TestJavaRefForm_Inheritance pins `extends Foo` / `implements Bar, Baz`
// → EdgeReferences (ref_context=inherit), stamped OriginASTResolved so the
// cross-package guard never reverts them.
func TestJavaRefForm_Inheritance(t *testing.T) {
src := `package app;
public class Worker extends Base implements Runnable, Closeable {
}
`
_, edges := runJavaExtract(t, "app/Worker.java", src)
for _, want := range []string{"Base", "Runnable", "Closeable"} {
e := refEdge(edges, graph.EdgeReferences, "unresolved::"+want, "inherit")
if e == nil {
t.Errorf("expected EdgeReferences -> %s (ref_context=inherit)", want)
continue
}
if e.Origin != graph.OriginASTResolved {
t.Errorf("inherit -> %s Origin = %q, want OriginASTResolved (else cross_pkg_guard reverts it)", want, e.Origin)
}
}
}
// TestJavaRefForm_CastAndInstanceof pins `(Foo) x`, `x instanceof Foo`,
// and the pattern `x instanceof Foo f` → EdgeReferences (ref_context=cast),
// OriginASTResolved.
func TestJavaRefForm_CastAndInstanceof(t *testing.T) {
src := `package app;
public class C {
void m(Object o) {
Foo a = (Foo) o;
boolean b = o instanceof Bar;
if (o instanceof Baz z) {}
}
}
`
_, edges := runJavaExtract(t, "app/C.java", src)
for _, want := range []string{"Foo", "Bar", "Baz"} {
e := refEdge(edges, graph.EdgeReferences, "unresolved::"+want, "cast")
if e == nil {
t.Errorf("expected EdgeReferences -> %s (ref_context=cast)", want)
continue
}
if e.Origin != graph.OriginASTResolved {
t.Errorf("cast -> %s Origin = %q, want OriginASTResolved", want, e.Origin)
}
}
}
// TestJavaRefForm_StaticAccess pins `Foo.CONST`, `Foo.class`, and
// `Foo.staticMethod()` whose scope is a Capitalized type → EdgeReferences
// (ref_context=static_access). A `@Foo` annotation also references Foo.
func TestJavaRefForm_StaticAccess(t *testing.T) {
src := `package app;
@Component
public class C {
void m() {
int x = Constants.MAX;
Class<?> c = Foo.class;
String s = Helper.format();
}
}
`
_, edges := runJavaExtract(t, "app/C.java", src)
for _, want := range []string{"Constants", "Foo", "Helper"} {
if refEdge(edges, graph.EdgeReferences, "unresolved::"+want, "static_access") == nil {
t.Errorf("expected EdgeReferences -> %s (ref_context=static_access)", want)
}
}
// @Component annotation → reference to Component.
e := refEdge(edges, graph.EdgeReferences, "unresolved::Component", "static_access")
if e == nil {
t.Errorf("expected EdgeReferences -> Component for @Component annotation")
} else if e.Origin != graph.OriginASTResolved {
t.Errorf("annotation ref Origin = %q, want OriginASTResolved", e.Origin)
}
}
// TestJavaRefForm_NoFalsePositives pins the capitalization / shadow
// gates: a bare call `bar()`, an instance call `obj.method()`, a
// primitive (`int`), and `this.x` must emit no reference-form edge.
func TestJavaRefForm_NoFalsePositives(t *testing.T) {
src := `package app;
public class C {
int field;
void m(Object obj) {
bar();
obj.method();
int n = 0;
this.field = n;
String name = lower.value;
}
}
`
_, edges := runJavaExtract(t, "app/C.java", src)
// No reference-form edge to a lowercase / primitive / this target.
for _, e := range edges {
if e.Meta == nil {
continue
}
uk, _ := e.Meta["ref_context"].(string)
switch uk {
case "instantiate", "cast", "inherit", "static_access", "generic_arg":
to := e.To
// Strip the unresolved:: prefix for the check.
const p = "unresolved::"
if len(to) > len(p) && to[:len(p)] == p {
to = to[len(p):]
}
if to == "" {
continue
}
c := to[0]
if c < 'A' || c > 'Z' {
t.Errorf("reference-form edge to non-Capitalized target %q (ref_context=%s) — capitalization gate leaked", e.To, uk)
}
}
}
// Specific negatives.
if hasUseKindTo(edges, "unresolved::bar", "static_access") || hasUseKindTo(edges, "unresolved::bar", "cast") {
t.Errorf("bare call bar() emitted a reference-form edge")
}
if hasUseKindTo(edges, "unresolved::method", "static_access") {
t.Errorf("instance call obj.method() emitted a static_access reference")
}
if hasUseKindTo(edges, "unresolved::obj", "static_access") {
t.Errorf("instance receiver obj emitted a static_access reference")
}
for _, prim := range []string{"int", "field", "name", "value", "lower"} {
for _, uk := range []string{"instantiate", "cast", "inherit", "static_access", "generic_arg"} {
if hasUseKindTo(edges, "unresolved::"+prim, uk) {
t.Errorf("primitive/lowercase %q emitted a %s reference-form edge", prim, uk)
}
}
}
}
// TestJavaRefForm_GenericArgs pins that the element types of a
// `type_arguments` node are emitted as generic_arg references
// (EdgeReferences, OriginASTResolved) in *every* position, not just the
// expression positions. The declaration-position passes canonicalize the
// annotation to its outer/wrapped type and drop the remaining element
// types, so without the type_arguments walker `Foo` in `Map<String, Foo>`
// is edge-less. This covers field, parameter, return, local, nested, and
// instantiation/cast/inherit positions, and confirms String / wildcards /
// primitives in the arg list contribute nothing.
func TestJavaRefForm_GenericArgs(t *testing.T) {
src := `package app;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class Svc<T extends Bound> extends Base<Sup> implements Sink<Iface> {
private Map<String, FieldT> fieldMap;
private Cache<FieldU> fieldCache;
public Optional<RetT> getOpt(List<ParamT> items, Map<String, List<NestT>> nested) {
Map<String, LocalT> local = build();
Repository<WidgetT> repo = make();
List<NewT> made = new java.util.ArrayList<NewT>();
Object o = (Holder<CastT>) made;
boolean b = o instanceof Box<TestT>;
List<? extends WildLow> wild = wild();
List<Integer> nums = null;
return null;
}
}
`
_, edges := runJavaExtract(t, "app/Svc.java", src)
// Every element type, regardless of position, must surface as a
// generic_arg EdgeReferences (OriginASTResolved).
wantArgs := []string{
"FieldT", // field Map<String, FieldT>
"FieldU", // field Cache<FieldU>
"RetT", // return Optional<RetT>
"ParamT", // param List<ParamT>
"NestT", // nested param Map<String, List<NestT>>
"LocalT", // local Map<String, LocalT>
"WidgetT", // local Repository<WidgetT>
"NewT", // new ArrayList<NewT>()
"CastT", // (Holder<CastT>) cast
"TestT", // instanceof Box<TestT>
"Sup", // extends Base<Sup>
"Iface", // implements Sink<Iface>
}
for _, want := range wantArgs {
e := refEdge(edges, graph.EdgeReferences, "unresolved::"+want, "generic_arg")
if e == nil {
t.Errorf("expected EdgeReferences -> %s (ref_context=generic_arg)", want)
continue
}
if e.Origin != graph.OriginASTResolved {
t.Errorf("generic_arg -> %s Origin = %q, want OriginASTResolved", want, e.Origin)
}
}
// Wildcard bound type (`? extends WildLow`) is also an element mention.
if refEdge(edges, graph.EdgeReferences, "unresolved::WildLow", "generic_arg") == nil {
t.Errorf("expected EdgeReferences -> WildLow (generic_arg of `? extends WildLow`)")
}
// `String` is treated as a primitive by isJavaPrimitive (same gate the
// declaration-position passes use), so a `Map<String, …>` key must NOT
// produce a generic_arg reference.
if hasUseKindTo(edges, "unresolved::String", "generic_arg") {
t.Errorf("String must not be emitted as a generic_arg reference (primitive gate)")
}
// A boxed type that is *not* on the primitive list (Integer) is a real
// type reference and must surface, confirming the gate is the same one
// the type-position edges use rather than an over-broad drop.
if refEdge(edges, graph.EdgeReferences, "unresolved::Integer", "generic_arg") == nil {
t.Errorf("expected EdgeReferences -> Integer (generic_arg of List<Integer>)")
}
}